Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: OAuth 2 - RC3 - client_id

  1. #1
    Join Date
    Oct 2012
    Posts
    7

    Default OAuth 2 - RC3 - client_id

    I'm on a quest to upgrade our OAuth version from M3 to RC3.

    My current snag is:

    When I punch in the user credentials and then drive /oauth/token (which we override to /access_token) the client_id seems to be getting wacked or not picked up.

    Here is my auth server:
    Code:
      <oauth:authorization-server   authorization-endpoint-url="/authorize" 
          							client-details-service-ref="jdbcClientDetailsService" 
          							token-services-ref="oAuth2ProviderTokenServices" 
          							user-approval-page="/token/confirm_access" 
          							user-approval-handler-ref="oL2ApprovalHandler"
          							token-endpoint-url="/access_token">
      	<oauth:authorization-code/>
      	<oauth:implicit/>
      	<oauth:refresh-token/>
      	<oauth:client-credentials/>
      	<oauth:password/>
      </oauth:authorization-server>
    http://localhost:8080/oauth/access_t...code=ROLE_USER


    After this GET request I would assume that the client_id pulled in TokenEndPoint would be 'FOO', but it ends up to be the username I punched into the form.

    Using the FROM and M3 all is well. I did see a similar post but I don't know if this was related.

    Any help would be great! Sorry if a little vague as this just sounds like a WTH?! =)

  2. #2
    Join Date
    Jun 2005
    Posts
    4,232

    Default

    I'm not really following 100% what you did here. The token endpoint is secured with Basic auth and the credentials should be the client id and secret, so where was the "form" you were talking about? Your client should be POSTing to the token endpoint and the query you show is a GET (I assume), with way more in it than I would expect (you need grant_type and code, and maybe redirect_uri, but that's it) and the code doesn't look like a valid authorization code.

    Does it work before you change the endpoint urls?

  3. #3
    Join Date
    Oct 2012
    Posts
    7

    Default

    Quote Originally Posted by Dave Syer View Post
    I'm not really following 100% what you did here. The token endpoint is secured with Basic auth and the credentials should be the client id and secret, so where was the "form" you were talking about? Your client should be POSTing to the token endpoint and the query you show is a GET (I assume), with way more in it than I would expect (you need grant_type and code, and maybe redirect_uri, but that's it) and the code doesn't look like a valid authorization code.
    Thanks for the response Dave. Sorry about the details as I've been sort of pounding my head on the migration.

    Quote Originally Posted by Dave Syer View Post
    Does it work before you change the endpoint urls?
    No. I had to hunt down that the url wasn't get set in RC2 and hence I'm using RC3.

    Here is my work flow (which has been working with M3):

    My little test client makes this request:

    http://localhost:8080/oauth/access_t...code=ROLE_USER

    This obviously fails because there is no Basic Auth that has been preformed.

    Then I'm rediected to my setup page that asks the me to Auth. Once I've Auth, then I attempt to get a Token.

    I've added grant_type and the redirect is there.

    Here I executed a stack trace in my jdbcClientDetailsService
    'loadClientByClientId(JdbcClientDetailsService.jav a:35),org.springframework.security.oauth2.provider .endpoint.TokenEndpoint.getAccessToken(TokenEndpoi nt.java:79), sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method),'

    This is what's driving me crazy. The client_id I would except to be FOO, but the client_id ends up being my basic auth loginID.

    There is something really stupid going on. I was thinking about tearing up the oauth.jar and dumping out the Request params but how client_id is becoming the basic auth id is beyond me.

    Thanks again for all your help.

  4. #4
    Join Date
    Jun 2005
    Posts
    4,232

    Default

    No one should be asking the token endpoint for an authorization code - that comes from the authorization endpoint and always has done. So your client is doomed to fail anyway because of that, but then because you entered that URL in a browser (I guess) it is prompting you for basic auth credentials and you are entering user credentials, not client credentials. The realm in the basic auth should alert you to the fact that the 401 response requires client credentials to be presented.

  5. #5
    Join Date
    Oct 2012
    Posts
    7

    Default

    Quote Originally Posted by Dave Syer View Post
    No one should be asking the token endpoint for an authorization code - that comes from the authorization endpoint and always has done. So your client is doomed to fail anyway because of that, but then because you entered that URL in a browser (I guess) it is prompting you for basic auth credentials and you are entering user credentials, not client credentials. The realm in the basic auth should alert you to the fact that the 401 response requires client credentials to be presented.
    Doom and Gloom baby!

    Had to go back and double check the spec because my translation here is terrible.

    From the Client I'm submitting a Authorization Code and Redirect URL. The 'client_id' for which you see in that URL (FOO) is what I would expect TokenEndPoint to grab and submit to loadClientByClientId when it is reached. However, like I have stated, the ClientID being grabbed is the Basic Auth ID. These two, Basic Auth ID and Client ID, are not the same...and they were certainly not the same when we used Spring OAuth V1 M3.

    Code:
    ublic ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal,
                            @RequestParam("grant_type") String grantType, @RequestParam Map<String, String> parameters) {
     
                    if (!(principal instanceof Authentication)) {
                            throw new InsufficientAuthenticationException(
                                            "There is no client authentication. Try adding an appropriate authentication filter.");
                    }
     
                    Authentication client = (Authentication) principal;
                    if (!client.isAuthenticated()) {
                            throw new InsufficientAuthenticationException("The client is not authenticated.");
                    }
                    HashMap<String, String> request = new HashMap<String, String>(parameters);
                    String clientId = client.getName();
                    request.put("client_id", clientId);
    So in here when client_id is pulled from the request, it's not the client id. It's the Basic Auth ID.

    Any suggestions here expect DOOM or RTFM? Really stumped on this one. Log out the Params see if something is getting wack? Like I was saying, I'm sure I missed something while trying to migrate from M3 to RC3. Splitting the packages up and then M5 being a train wreck just sucked.

    Thanks for any help Dave.

  6. #6
    Join Date
    Jun 2005
    Posts
    4,232

    Default

    I don't think we are on the same page here regarding the operation of the /token endpoint. It has to be authenticated, so you must send the client secret if there is one. Per the spec, your client should send its id (and secret) as part of the Basic authorization header. If you don't like that (I think it wasn't the default in older milestones) you can add a ClientCredentialsTokenEndpointFilter to the endpoint instead of the <http-basic/> filter.

  7. #7
    Join Date
    Oct 2012
    Posts
    7

    Default

    Dave thanks for the suggestion. Here is a stack trace to help (I hope)

    Code:
      <security:http pattern="/access_token" authentication-manager-ref="authenticationManager">
    	<security:intercept-url pattern="/access_token" access="ROLE_USER" />
    	<security:custom-filter ref="customClientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
    	    <security:form-login authentication-success-handler-ref="customSavedRequestAwareAuthenticationHandler" authentication-failure-handler-ref="customSimpleUrlAuthenticationFailureHandler" login-page="/index.jsp" login-processing-url="/login.do" />
        <security:logout logout-success-url="/index.jsp" logout-url="/logout.do"/>
    </security:http>
    DEBUG [http-8080-5] (CustomSavedRequestAwareAuthenticationSuccessHandl er.java:79) - login = [Login]
    DEBUG [http-8080-5] (CustomSavedRequestAwareAuthenticationSuccessHandl er.java:79) - j_username = [jasonmcdonald]
    ..
    ...
    DEBUG [http-8080-5] (FilterChainProxy.java:337) - /access_token?response_type=code&client_id=FOO&gran t_type=authorization-code&redirect_uri=http://localhost:8080/FOO/setup-oauth.jsp&code=ROLE_USER at position 4 of 10 in additional filter chain; firing Filter: 'CustomClientCredentialsTokenEndpointFilter'
    DEBUG [http-8080-5] (CustomClientCredentialsTokenEndpointFilter.java:3 6) - JASON:requiresAuthentication:response_type = [code]
    DEBUG [http-8080-5] (CustomClientCredentialsTokenEndpointFilter.java:3 6) - JASON:requiresAuthentication:grant_type = [authorization-code]
    DEBUG [http-8080-5] (CustomClientCredentialsTokenEndpointFilter.java:3 6) - JASON:requiresAuthentication:redirect_uri = [http://localhost:8080/FOO/setup-oauth.jsp]
    DEBUG [http-8080-5] (CustomClientCredentialsTokenEndpointFilter.java:3 6) - JASON:requiresAuthentication:client_id = [FOO]
    DEBUG [http-8080-5] (CustomClientCredentialsTokenEndpointFilter.java:3 6) - JASON:requiresAuthentication:code = [ROLE_USER]
    …..
    ….
    Obviously at this point the client_id = FOO.
    ….
    DEBUG [http-8080-5] (AbstractSecurityInterceptor.java:215) - Authorization successful
    DEBUG [http-8080-5] (AbstractSecurityInterceptor.java:227) - RunAsManager did not change Authentication object
    DEBUG [http-8080-5] (FilterChainProxy.java:323) - /access_token?response_type=code&client_id=FOO&gran t_type=authorization-code&redirect_uri=http://localhost:8080/FOO/setup-oauth.jsp&code=ROLE_USER reached end of additional filter chain; proceeding with original chain
    DEBUG [http-8080-5] (DispatcherServlet.java:819) - DispatcherServlet with name 'oauth' processing GET request for [/oauth/access_token]
    DEBUG [http-8080-5] (AbstractHandlerMethodMapping.java:209) - Looking up handler method for path /access_token
    DEBUG [http-8080-5] (AbstractHandlerMethodMapping.java:219) - Did not find handler method for [/access_token]
    DEBUG [http-8080-5] (AbstractHandlerMethodMapping.java:209) - Looking up handler method for path /access_token
    DEBUG [http-8080-5] (AbstractHandlerMethodMapping.java:216) - Returning handler method [public org.springframework.http.ResponseEntity<org.spring framework.security.oauth2.common.OAuth2AccessToken > org.springframework.security.oauth2.provider.endpo int.TokenEndpoint.getAccessToken(java.security.Pri ncipal,java.lang.String,java.util.Map<java.lang.St ring, java.lang.String>)]
    DEBUG [http-8080-5] (AbstractBeanFactory.java:245) - Returning cached instance of singleton bean 'oauth2TokenEndpoint'
    DEBUG [http-8080-5] (DispatcherServlet.java:902) - Last-Modified value for [/oauth/access_token] is: -1
    DEBUG [http-8080-5] (WebContentInterceptor.java:145) - Looking up cache seconds for [/access_token]
    DEBUG [http-8080-5] (WebContentInterceptor.java:157) - Applying default cache seconds to [/access_token]
    DEBUG [http-8080-5] (JdbcClientDetailsService.java:57) - Looking up ClientID:jasonmcdonald

    After this point you can see I am authorized and the client_id is no longer FOO, but it is my Login name from the BASIC Auth.

    Anything glaring? Maybe something else I can try or dig up to help you help me figure out WTH I'm doing wrong.

    Thanks for the speedy response.

    Jason

  8. #8
    Join Date
    Oct 2012
    Posts
    7

    Default

    Dave here is a question:

    Code:
         @RequestMapping
            public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal,
                            @RequestParam("grant_type") String grantType, @RequestParam Map<String, String> parameters) {
     
                    if (!(principal instanceof Authentication)) {
                            throw new InsufficientAuthenticationException(
                                            "There is no client authentication. Try adding an appropriate authentication filter.");
                    }
     
                    Authentication client = (Authentication) principal;
                    if (!client.isAuthenticated()) {
                            throw new InsufficientAuthenticationException("The client is not authenticated.");
                    }
                    HashMap<String, String> request = new HashMap<String, String>(parameters);
                    String clientId = client.getName();
                    request.put("client_id", clientId);
    
                   getAuthorizationRequestManager().validateParameters(parameters,
                                    getClientDetailsService().loadClientByClientId(clientId));
    Shouldn't the clientId be pulled from the RequestParam and not the Principal when you are trying to loadClientByClientId?

  9. #9
    Join Date
    Jun 2005
    Posts
    4,232

    Default

    In a word, no.

    I don't think you understood my last point. Your /access_token endpoint should not be protected by a <form-login/>. It looks like you have a custom filter in there, so that's a start, and I assume it's a version of ClientCredentialsTokenEndpointFilter, but you didn't say exactly. If it is then you would need to send the client_secret as a request parameter (and note that it is bad practice to do this as a query parameter because your logs will contain secrets in plain text).

    Additionally, your request should not contain a response_type, and it looks to me like the authorization code (ROLE_USER) must be wrong.

  10. #10
    Join Date
    Oct 2012
    Posts
    7

    Default

    If I want to just bypass the Basic Auth (for now), all I would have to do is:

    Using my CustomClientCredentialsTokenEndpointFilter.java which extends ClientCredentialsTokenEndpointFilter.java

    implement attemptAuthentication
    Code:
    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(clientId,
                                    clientSecret);
     
                    return this.getAuthenticationManager().authenticate(authRequest);
    and just fake out the client secret for now.

    Correct? I think I get what you are saying now, and yeah this was not mandated with M3.

    Thanks for the patiences.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •