Skip to content

403 Forbidden on /oauth/check_token #28

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
yalmuhaidib opened this issue Jul 19, 2015 · 11 comments
Closed

403 Forbidden on /oauth/check_token #28

yalmuhaidib opened this issue Jul 19, 2015 · 11 comments
Labels

Comments

@yalmuhaidib
Copy link

after acquiring a token from /oauth/token, I want to check if the token is valid or not by calling /oauth/check_token path

curl -X POST -H "Authorization: Basic Y2xpZW50YXBwOjEyMzQ1Ng==" -H "Cache-Control: no-cache" -H "Postman-Token: ca8f304d-06d0-daaa-72eb-df224c3993e1" 'http://localhost:8080/oauth/check_token?token=b4db8484-3ff6-46ca-b8a7-417830042b79'

tried with GET also and got the same error response:

{
  "timestamp": 1437301882689,
  "status": 403,
  "error": "Forbidden",
  "message": "Access is denied",
  "path": "/oauth/check_token"
}

spring configures the mapping

2015-07-19 13:32:44.731  INFO 11989 --- [ost-startStop-1] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped "{[/oauth/check_token],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.Map<java.lang.String, ?> org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint.checkToken(java.lang.String)

how I can check the token validity?

@mariubog
Copy link
Contributor

Look here:
https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.java

The default setting is private String checkTokenAccess = "denyAll()";

So maybe try in AuthorizationServerConfiguration

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
{
   oauthServer.checkTokenAccess("isAuthenticated()");    
}

and authenticate yourself, or "permitAll()" if you wish and let anybody use it

@sridhar1982
Copy link

@mariubog I tried what you suggested. It did not work either. possible I am doing my curl wrong

curl -X POST -H "Authorization: BEARER d69b97b6-4051-4c13-b781-d4e777435397" -H "Cache-Control: no-cache" -H "Postman-Token: ca8f304d-06d0-daaa-72eb-df224c3993e1" 'http://localhost:9001/oauth/check_token?token=d69b97b6-4051-4c13-b781-d4e777435397'

NOTE: I used BEARER with same token I got back from http://localhost:9001/oauth/token.

I get the following errror which is different than one above

{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}.

I used

@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
{
   oauthServer.checkTokenAccess("isAuthenticated()");    
}

any help here is much appreciated

@mariubog
Copy link
Contributor

If all permitted ("permitAll()") :
curl -X POST http://localhost:8080/oauth/check_token -d "token=40ec1ebd-a6a6-4b1c-a506-a9dcf291a056"
Notice that it returns some sensitive data so preferably use below.

If authentication required ("isAuthenticated()") :
curl -X POST http://localhost:8080/oauth/check_token -vu clientapp:123456 -d "token=12702db1-723b-4d65-92b9-ede3bae05ac7"

About -vu clientapp:123456
-v makes it verbose
-u allows you to provide authentication data username and password and this time you authenticate against Oauth server not web security of the application, so you provide client and secret. I think it is worth mentioning.

It works assuming that you use Roy's example.Obviously you replace above token strings with your tokens.

Good luck.

@sridhar1982
Copy link

@mariubog
Thanks. this helped a lot.
Upon

curl -X POST -k -vu clientapp:123456 http://localhost:9001/oauth/token -H "Accept: application/json" -d "password=spring&username=roy&grant_type=password&scope=read%20write&client_secret=123456&client_id=clientapp"

I get

{"access_token":"e9e41273-a36c-4178-a450-0fb2699d3ec9","token_type":"bearer","refresh_token":"bf0f4260-7e80-43af-9706-cdc864bf4c6c","expires_in":43199,"scope":"read write"}

upon this

curl -X POST http://localhost:9001/oauth/check_token -d "token=e9e41273-a36c-4178-a450-0fb2699d3ec9"

I get

{"aud":["restservice"],"exp":1437578526,"user_name":"roy","authorities":["ROLE_USER","ROLE_ADMIN"],"client_id":"clientapp","scope":["read","write"]}

why is expires_in in the first call above and exp in the second call different. (I assume they are expiration times for tokens.) what units (seconds?) are expressed?

Also how to exchange refresh token for access token expiry to get new access token?

Thank you very much for help

@yalmuhaidib
Copy link
Author

I've used

oauthServer.checkTokenAccess("isAuthenticated()"); 

and it's working, but I agree with sridhar1982 on what he is asking:
why is expires_in and exp are different?

expires_in is expressed in seconds, I've changed the ClientDetailsServiceConfigurer access Token Validity to 60 sec..

.accessTokenValiditySeconds(60);

but still getting exp as a static number

@sridhar1982
Copy link

@yalmuhaidib: how did you change the access Token validity to 60 sec. can you give the code snippet here. Also any idea on how to change the validity time for refresh token ?

@yalmuhaidib
Copy link
Author

@sridhar1982,
just override the configure for ClientDetailsServiceConfigurer

AuthorizationServerConfiguration extends
            AuthorizationServerConfigurerAdapter {

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            // @formatter:off
            clients
                .inMemory()
                    .withClient("clientapp")
                        .authorizedGrantTypes("password", "refresh_token")
                        .authorities("USER")
                        .scopes("read", "write")
                        .resourceIds(RESOURCE_ID)
                        .secret("123456")
                        .accessTokenValiditySeconds(60);
            // @formatter:on
        }

@yalmuhaidib
Copy link
Author

I've checked sping code, the /check_token endpoint mapping, and it's using DefaultAccessTokenConverter.convertAccessToken method to return the response, this method is not calculating the difference in seconds

public Map<String, ?> convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
        Map<String, Object> response = new HashMap<String, Object>();
        /*omitted irrelevant lines */

        if (token.getExpiration() != null) {
            response.put(EXP, token.getExpiration().getTime() / 1000);
        }

           /*omitted irrelevant lines */

        return response;
    }

while in /oath/token endpoint it's using jackson serializer OAuth2AccessTokenJackson2Serializerand it's subtracting the date and converting it to seconds:

if (expiration != null) {
            long now = System.currentTimeMillis();
            jgen.writeNumberField(OAuth2AccessToken.EXPIRES_IN, (expiration.getTime() - now) / 1000);
        }

@sridhar1982
Copy link

any input on how to set expiry for refresh token and how to exchange refresh token for a new access token once an access token is expired?

and what is the practical difference between using oauthServer.checkTokenAccess("isAuthenticated()") and oauthServer.checkTokenAccess("permitAll()");

@yalmuhaidib
Copy link
Author

@sridhar1982, the refresh token does not have expiry, it's used to acquire a new access token..
"The refresh token which can be used to obtain new access tokens using the same authorization grant"
from Spring docs OAuth2AccessToken

now how to use it, check the README in this projects (search for refresh_token)

isAuthenticated and permitAll is Spring Security EL for expression support

"permitAll Always evaluates to true" so any request on /check_token will be permitted even anonymous
"isAuthenticated() Returns true if the user is not anonymous" so /check_token is allowed if the user is authenticated with the server (you will see that the user has a session JSESSIONID)

I'm closing this issue as it's solved..

@audtjddld
Copy link

thanks for all :)

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

No branches or pull requests

5 participants