1
votes

I have generated access token using SAML extension grant type as mentioned in the below link:

https://docs.wso2.com/display/AM180/Token+API#TokenAPI-ExchangingSAML2bearertokenswithOAuth2(SAMLextensiongranttype)

Step 1: Generate assertion string.

java -jar SAML2AssertionCreator.jar TestSP admin https://localhost:9443/oauth2/token https://localhost:9443/oauth2/token/home/dinusha/nothing/WSO2/API-Manager/saml-oauth/wso2is-5.0.0/rhbepository/resources/security/wso2carbon.jks wso2carbon wso2carbon wso2carbon

This gives me the assertion string. I have set the expiry period as 300 (5 minutes).

Step 2: Fetch access token Using the assertion string and the Base64 encoded string of (consumerKey:ConsumerSecret) I can generate Oauth access token.

curl -k -d "grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer&assertion=<ASSERTION_PROVIDED_BY_CLIENT>&scope=PRODUCTION" -H "Authorization: Basic <ASSERTION_PROVIDED_BY_CLIENT>, Content-Type: application/x-www-form-urlencoded" https://localhost:9443/oauth2/token

Oauth access token and Refresh token are generated. Access token has validity of 3600 (60 minutes).

Now, suppose a user's session is timed out within a time duration of 5 minutes (assertion string expiry time) and the user performs login operation, a new assertion string is generated and the existing access token is removed. However, this new assertion string gives me the same access token as obtained in the previous session. Since the access token is already invalid, it tries to regenerate a new access token using the refresh token. At this step, I am getting an error: "Invalid refresh token". (Logs are provided below). I don't think it's an issue with the authenticity of refresh token, since a new pair of access token should have been generated the second time using the new assertion string.

TID: [-1234] [] [2019-09-24 12:59:02,036] DEBUG {org.wso2.carbon.identity.oauth2.util.OAuth2Util} - Added OAuthTokenReqMessageContext to threadlocal {org.wso2.carbon.identity.oauth2.util.OAuth2Util} TID: [-1234] [] [2019-09-24 12:59:02,036] DEBUG {org.wso2.carbon.identity.oauth2.util.OAuth2Util} - Token type is not set for service provider app with client Id: <client_id>. Hence the default Identity OAuth token issuer will be used. No custom token generator is set. {org.wso2.carbon.identity.oauth2.util.OAuth2Util} TID: [-1234] [] [2019-09-24 12:59:02,039] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} - Valid access token is found in cache for client: <client_id>. Remaining time: 3549358ms {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} TID: [-1234] [] [2019-09-24 12:59:02,040] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} - Enable Access Token renew per request: false {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} TID: [-1234] [] [2019-09-24 12:59:02,040] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} - Enable Access Token renew per request considering OAuthTokenReqMessageContext: false {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} TID: [-1234] [] [2019-09-24 12:59:02,040] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} - Valid access token is found in cache for client: <client_id>. Remaining time: 3549357ms {org.wso2.carbon.identity.oauth2.token.handlers.grant.AbstractAuthorizationGrantHandler} TID: [-1234] [] [2019-09-24 12:59:02,040] DEBUG {org.wso2.carbon.identity.oauth2.util.OAuth2Util} - Cleared OAuthTokenReqMessageContext {org.wso2.carbon.identity.oauth2.util.OAuth2Util} TID: [-1234] [] [2019-09-24 12:59:02,040] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} - Access token issued to client Id: <client_id> username: @carbon.super and scopes: default {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - Executing OAuth client authenticators. {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - Retrieving registered OAuth client authenticator list. {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - Evaluating canAuthenticate of authenticator : BasicOAuthClientCredAuthenticator {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.BasicAuthClientAuthenticator} - Basic auth credentials exists as Authorization header. Hence returning true. {org.wso2.carbon.identity.oauth2.client.authentication.BasicAuthClientAuthenticator} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - BasicOAuthClientCredAuthenticator authenticator can handle incoming request. {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - Authenticator BasicOAuthClientCredAuthenticator can authenticate the client request. Hence trying to evaluate authentication {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.BasicAuthClientAuthenticator} - Authorization header exists. Hence validating whether body params also present {org.wso2.carbon.identity.oauth2.client.authentication.BasicAuthClientAuthenticator} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.BasicAuthClientAuthenticator} - Authenticating client : <client_id> with client secret. {org.wso2.carbon.identity.oauth2.client.authentication.BasicAuthClientAuthenticator} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.util.OAuth2Util} - Client credentials were available in the cache for client id : <client_id> {org.wso2.carbon.identity.oauth2.util.OAuth2Util} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.util.OAuth2Util} - Successfully authenticated the client with client id : <client_id> {org.wso2.carbon.identity.oauth2.util.OAuth2Util} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - Authentication result from OAuth client authenticator BasicOAuthClientCredAuthenticator is : true {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,006] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - Evaluating canAuthenticate of authenticator : PublicClientAuthenticator {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,007] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.PublicClientAuthenticator} - Application with the given client ID <client_id> is not found {org.wso2.carbon.identity.oauth2.client.authentication.PublicClientAuthenticator} TID: [-1234] [] [2019-09-24 12:59:09,007] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.PublicClientAuthenticator} - The Client ID is not present in the request. {org.wso2.carbon.identity.oauth2.client.authentication.PublicClientAuthenticator} TID: [-1234] [] [2019-09-24 12:59:09,007] DEBUG {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} - PublicClientAuthenticator authenticator cannot handle this request. {org.wso2.carbon.identity.oauth2.client.authentication.OAuthClientAuthnService} TID: [-1234] [] [2019-09-24 12:59:09,040] DEBUG {org.wso2.carbon.identity.oauth2.OAuth2Service} - Access Token request received for Client ID <client_id>, User ID null, Scope : [] and Grant Type : refresh_token {org.wso2.carbon.identity.oauth2.OAuth2Service} TID: [-1234] [] [2019-09-24 12:59:09,040] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} - Oauth App validation success for consumer key: <client_id> {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} TID: [-1234] [] [2019-09-24 12:59:09,040] DEBUG {org.wso2.carbon.identity.oauth2.dao.TokenManagementDAOImpl} - Validating refresh token for client: <client_id> {org.wso2.carbon.identity.oauth2.dao.TokenManagementDAOImpl} TID: [-1234] [] [2019-09-24 12:59:09,089] DEBUG {org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler} - Invalid Refresh Token provided for Client with Client Id : <client_id> {org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler} TID: [-1234] [] [2019-09-24 12:59:09,089] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} - Error occurred while validating grant {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception: Persisted access token data not found

    at org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler.validatePersistedAccessToken(RefreshGrantHandler.java:251)
    at org.wso2.carbon.identity.oauth2.token.handlers.grant.RefreshGrantHandler.validateGrant(RefreshGrantHandler.java:79)
    at org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer.issue(AccessTokenIssuer.java:226)
    at org.wso2.carbon.identity.oauth2.OAuth2Service.issueAccessToken(OAuth2Service.java:225)
    at org.wso2.carbon.identity.oauth.endpoint.token.OAuth2TokenEndpoint.issueAccessToken(OAuth2TokenEndpoint.java:300)
    at org.wso2.carbon.identity.oauth.endpoint.token.OAuth2TokenEndpoint.issueAccessToken(OAuth2TokenEndpoint.java:90)
    at sun.reflect.GeneratedMethodAccessor153.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:188)
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:104)
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:204)
    at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:101)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:94)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:249)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153)
    at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:171)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:289)
   at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:209)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:265)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.wso2.carbon.webapp.mgt.filter.AuthorizationHeaderFilter.doFilter(AuthorizationHeaderFilter.java:128)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter.doFilter(ContentTypeBasedCachePreventionFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter(HttpHeaderSecurityFilter.java:124)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.wso2.carbon.identity.context.rewrite.valve.TenantContextRewriteValve.invoke(TenantContextRewriteValve.java:80)
    at org.wso2.carbon.identity.authz.valve.AuthorizationValve.invoke(AuthorizationValve.java:91)
    at org.wso2.carbon.identity.auth.valve.AuthenticationValve.invoke(AuthenticationValve.java:65)
    at org.wso2.carbon.tomcat.ext.valves.CompositeValve.continueInvocation(CompositeValve.java:99)
    at org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve$1.invoke(CarbonTomcatValve.java:47)
    at org.wso2.carbon.webapp.mgt.TenantLazyLoaderValve.invoke(TenantLazyLoaderValve.java:57)
    at org.wso2.carbon.event.receiver.core.internal.tenantmgt.TenantLazyLoaderValve.invoke(TenantLazyLoaderValve.java:48)
    at org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer.invokeValves(TomcatValveContainer.java:47)
    at org.wso2.carbon.tomcat.ext.valves.CompositeValve.invoke(CompositeValve.java:62)
    at org.wso2.carbon.tomcat.ext.valves.CarbonStuckThreadDetectionValve.invoke(CarbonStuckThreadDetectionValve.java:159)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
    at org.wso2.carbon.tomcat.ext.valves.CarbonContextCreatorValve.invoke(CarbonContextCreatorValve.java:57)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1775)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1734)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

TID: [-1234] [] [2019-09-24 12:59:09,090] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} - Invalid Grant provided by the client Id: <client_id> {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} TID: [-1234] [] [2019-09-24 12:59:09,090] DEBUG {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer} - OAuth-Error-Code=invalid_grant client-id=<client_id> grant-type=refresh_token scope= {org.wso2.carbon.identity.oauth2.token.AccessTokenIssuer}

To sum up, my issue is that two assertion strings(as long as the first one is still valid) gives me the same pair of access and refresh token. Any help is very much appreciated. Thanks for reading :)

1
Seems to be a caching issue : "Valid access token is found in cache for client: kQUVSx_rKMDolTrm3m64mX4iNIYa. Remaining time: 3549358ms" . Did you tyy to revoke access token using document specified method and try again ? It should help you to solve this issue. I think issue is difference of times for cache clearing, token expiration and assertion expiration.. Also, please be mindful about logs you put on StackOverflow. This log has exposed your client ID as well as your email for IS server .!Kavindu Dodanduwa

1 Answers

3
votes

This is an expected behavior. Since you are authenticating with the same (user, client-id and scope) set, it will return the previous token if there is an active access token already in the database for the requested (user, client-id and scope) set.

If you need to generate new access token for every token request, you will have to enable RenewTokenPerRequest [1] from the identity.xml. But this config is available in the latest versions only (WSO2 IS 5.8.0 GA, WSO2 IS 5.7.0 WUM, WSO2 APIM 2.6.0 WUM)

Otherwise, you may use self-contained access tokens [2]. It will issue new tokens for every request by design.

One other option is to write a custom OAuthTokenGenerator [3] by extending OauthTokenIssuerImpl class and overriding renewAccessTokenPerRequest() method to return true always.

[1] https://docs.wso2.com/display/IS580/Issuing+New+Tokens+Per+Request

[2] https://docs.wso2.com/display/IS540/Self-contained+Access+Tokens

[3] https://docs.wso2.com/display/IS570/Extension+Points+for+OAuth#ExtensionPointsforOAuth-OAuthTokenGenerator