Skip to content

Incorrect header in useHttpBasicAuthForPasswordFlow #368

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Rzpeg opened this issue Jun 27, 2018 · 13 comments
Closed

Incorrect header in useHttpBasicAuthForPasswordFlow #368

Rzpeg opened this issue Jun 27, 2018 · 13 comments

Comments

@Rzpeg
Copy link

Rzpeg commented Jun 27, 2018

Hello,

When configuring the basic authentication header for password flow you are using "Authentication" and the correct header for the scheme is "Authorization"

const header = btoa(`${this.clientId}:${this.dummyClientSecret}`);
                headers = headers.set(
                    'Authentication',
                    'BASIC ' + header);
@joelmuskwe
Copy link

Has this been sorted yet

jeroenheijmans added a commit to jeroenheijmans/angular-oauth2-oidc that referenced this issue Jul 1, 2018
jeroenheijmans added a commit to jeroenheijmans/angular-oauth2-oidc that referenced this issue Jul 1, 2018
@jeroenheijmans
Copy link
Collaborator

@joelmuskwe Don't think so. I've created a PR to fix things. If you need it right away I suggest making a custom build (or very maybe a http interceptor might give a workaround?), otherwise will have to wait a bit until a bugfix lands.

@vogoltsov
Copy link

vogoltsov commented Jul 21, 2018

I would also suggest changing header value prefix from 'BASIC ' to 'Basic ' as most frameworks check value using a case-sensitive startsWith method.

@jeroenheijmans
Copy link
Collaborator

jeroenheijmans commented Jul 22, 2018

@vogoltsov They do? Which ones? All servers I've worked with are case insensitive I think. Also, IIRC, the RFC specifies that the auth scheme should be treated in a case insensitive manner.

If you have an example server (or reference that it should be case sensitive) then it should probably be changed or made configurable. If so, I think creating a seperate issue would be good too?

@vinliangx
Copy link

Hello,
@jeroenheijmans I'm having the same issue I'm using Spring Security...

org.springframework.security.web.authentication.www.BasicAuthenticationFilter.java // line:175
if (header == null || !header.startsWith("Basic ")) {
...

Thanks,
Vin

@jeroenheijmans
Copy link
Collaborator

@vinliangx Well, oh my, you're right I see the same in the source for latest release of Spring.

I think that might be a bug in Spring though. Looking at RFC 7617 specifically section 2 it's stated that (emphasis mine):

Note that both scheme and parameter names are matched case-insensitively.

Disclaimer: I'm not great at estimating if I was looking at the right spec/rfc, so someone might correct me on this.

On the other hand:

  • Everywhere in that RFC the scheme name is literally "Basic", so it's understandable that implementors use that.
  • This Github issue here noted that the entire header is wrong anyways, so I don't think it would break anything more than it is already broken if we change the casing in angular-oauth2-oidc

so I'll update my PR accordingly.

jeroenheijmans added a commit to jeroenheijmans/angular-oauth2-oidc that referenced this issue Jul 26, 2018
After further discussion and research in manfredsteyer#368 I noticed that even
though RFC 7617 seems to state that:

> Note that both scheme and parameter names are matched
> case-insensitively.

All the examples use "Basic" instead of "BASIC". There is one very
notable framework that checks case *sensitively* for "Basic". Given
that the header was incorrect anyways, we can be sure that changing
this casing won't further break anything, and work around issues for
server side frameworks like Spring.

See: https://tools.ietf.org/html/rfc7617
See: https://github.com/spring-projects/spring-security/blob/5.0.6.RELEASE/web/src/main/java/org/springframework/security/web/authentication/www/BasicAuthenticationFilter.java#L157

Fixes manfredsteyer#368
@jeroenheijmans
Copy link
Collaborator

Note that this code in IdentityServer4 (a notable .NET server side framework) does the StartsWith in a case insensitive manner (AFAICT). It does also follow the RFC in that itself it seems to default to the "Basic" casing for examples and output and soforth.

@vinliangx
Copy link

I read in a few places that should be case insensitive, so the issue may go to Spring Framework, but I figure it would be easier to here. Meanwhile I did a workaround with a filter to modify the request in my service so everything goes smoothly from the web app.

I think this change won't cause major issues to anyone.

Thanks @jeroenheijmans!

@jeroenheijmans
Copy link
Collaborator

@vinliangx Nice, good to hear you found a workaround. It might be worth sharing here so others can use it too while the issue remains unfixed.

@vinliangx
Copy link

vinliangx commented Jul 26, 2018

This is the workaround I've implemented for Spring Security:

The filter

import org.springframework.web.filter.OncePerRequestFilter;

@Component
public class BasicAuthHeaderFilter extends OncePerRequestFilter {
   @Override
   protected void doFilterInternal(HttpServletRequest request, 
                                                     HttpServletResponse response, 
                                                     FilterChain chain) throws ServletException, IOException {
      HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {
                @Override
                public String getHeader(String name) {
                    String header = super.getHeader(name);                    
                    if (header == null && name.equalsIgnoreCase("authorization")){
                        header = super.getHeader("authentication");
                    }
                    if (header != null && header.toLowerCase().startsWith("basic")) {
                        return header.replaceAll("^[Bb][Aa][Ss][Ii][Cc]", "Basic");
                    }
                    return header;
                }
       };
      chain.doFilter(requestWrapper, response);
   }
}

Registering the Filter:

import org.springframework.boot.web.servlet.FilterRegistrationBean;

@Bean
public FilterRegistrationBean<BasicAuthHeaderFilter> filterFilterRegistrationBean(BasicAuthHeaderFilter filter) {
    FilterRegistrationBean<BasicAuthHeaderFilter> reg = new FilterRegistrationBean<>(filter);
    reg.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return reg;
}

Thanks again @jeroenheijmans

@jeroenheijmans
Copy link
Collaborator

FYI: I just got a notification that this was changed in spring-security, slated for milestone "5.0.8". That might make the workaround unneeded.

@ThePinkPanther
Copy link

Changing the server side implementation for the sake of fixing a client because of a stupid mistake in the library is the most retarded solution I have ever seen. Seriously, if library requires you to hack either your server side app or client you should not use this library in the first place.

@jeroenheijmans
Copy link
Collaborator

Careful please with your choice of words @ThePinkPanther, it sounds pretty hostile. We're just internet strangers trying to be helpful.

About the solution, I think (as indicated by the fact that Spring fixed this on their end) that the server side implementation was the one that had a bug, because it didn't follow the spec originally with a case sensitive comparison.

In any case, it won't hurt anyone if you opt to use another library for client side auth. To each their own! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants