Announcement Announcement Module
No announcement yet.
How to invalidate existing Access/refresh token when logout Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to invalidate existing Access/refresh token when logout

    How to invalidate an existing access token which used to exchange the information between client/server. I don't find any option to
    invalidate or remove the access token. I am using In-Memory implementation of token Services (InMemoryOAuth2ProviderTokenServices).

    I can see there is a method removeAccessToken(String tokenValue) in InMemoryOAuth2ProviderTokenServices class that can be used to remove access token, after extending this class but i am using web browser as a client to access the protected resource and i don't know how to get the tokenValue when using webbrowser since we are not explicitly passing access_token in http request header.

    Please let me know if anybody has any idea about how to invalidate/remove access token.

  • #2
    There is no public API for that in Spring Security OAuth, nor is it really mentioned in the spec as far as I know. You could implement a service endpoint based on your own concrete implementation of OAuth2ProviderTokenServices I guess. What is the use case exactly? Why is it not acceptable to simply let the token time out?


    • #3

      It seems that I have the similar problem. But from side of the consumer.
      So there is the consumer implementation and HttpSessionBasedTokenServices is used for token (get/store/remove).

      But I've implemented the custom TokenServices and it manipulate with DB.
      Store in the DB, get from DD and remove from DB.

      The question is how to force Spring to remove token (call tokenServices.removeToken) if provider return "oAuth authentication failed"

      The sample:
      1 first retrieving of the protected data. In general: get unauthorized token -> get verify - > get access token - >store in DB access token - > retrieve protected data.
      2 second retrieving. For now we have the access token (tokenServices.getToken) and just retrieve protected data.
      3 access token has expired of the provider's side (or whatever else ... but access token is "wrong").
      4 third retrieving. For now we have the access token (tokenServices.getToken) and just retrieve protected data. BUT provider returns "oAuth authentication failed" because of token is invalid. In this case Spring does nothing. Just catch the exception and skip it.(OAuthConsumerContextFilter line 196)
      5 next retrieving is the same as 4 because of wrong token still exists in the DB and "nobody" changes it

      thanks in advance.


      • #4
        I'm not really using OAuth (as opposed to OAuth2) so I can't really be sure, but doesn't the consumer have an API for refreshing an access token? At the very least it would seem you could simply go through the whole flow again and get a new token. So it's a problem for the implementation of the consumer? In the OAuth2 case the Spring Security client support will generally handle re-obtaining or refreshing a token if it gets an error from the existing token. If the OAuth consumer support doesn't do it automatically, I'm sure you could use the available APIs to do it yourself. Feel free to submit a pull request if you have some interesting changes to propose (follow instructions in the README).


        • #5
          thanks for the feedback.
          the problem is that current implementation try to get protected data with token from http session.
          if there is no token in the http session or token is invalid then token is requested from ***TokenService.
          By default it's HttpSessionBasedTokenServices and in my case it's CustomTokenServices.

          And CustomTokenServices returns access token from DB. That is why Spring does not try to get new one.
          And try to get protected data with token which was returned by CustomTokenServices.
          But this access token is wrong (because of expiring ....)

          After second time error... Sprind(OAuthConsumerContextFilter) does nothing.

          And it's question for me how to process this


          • #6
            OAuthConsumerTokenServices has a removeToken() method and it is always called by the OAuthConsumerContextFilter, so I'm not quite sure what your problem is. Maybe your CustomTokenServices doesn't implement that method correctly? If you have more thoughts you could wrote an integration test using the sparklr sample, and/or suggest a change to the filter?


            • #7
              Hm possibly I don't understand the process but as I understand the process is as the following:


               try {
                      request.setAttribute(getAccessTokensRequestAttribute(), new ArrayList<OAuthConsumerToken>(accessTokens.values()));
                      chain.doFilter(request, response);
                    catch (Exception e) {
                        // here we get token from tokenService
                        if (token == null) {
                            token = getTokenServices().getToken(neededResourceId);
                        String verifier = request.getParameter(OAuthProviderParameter.oauth_verifier.toString());
                        if (token == null || (!token.isAccessToken() && verifier == null)) {
                            // try to get UnauthorizedRequestToken
                            token = getConsumerSupport().getUnauthorizedRequestToken(neededResourceId, callbackURL);
                        else if (!token.isAccessToken()) {
                            //we have a presumably authorized request token, let's try to get an access token with it.
                          //authorize the request token and store it.
                            try {
                              token = getConsumerSupport().getAccessToken(token, verifier);
                            finally {
                              // Remove token only here
                        try {
                            //try again
                            if (!response.isCommitted()) {
                              request.setAttribute(getAccessTokensRequestAttribute(), new ArrayList<OAuthConsumerToken>(accessTokens.values()));
                              chain.doFilter(request, response);
                            else {
                              //dang. what do we do now?
                              throw new IllegalStateException("Unable to reprocess filter chain with needed OAuth2 resources because the response is already committed.");
                        catch (Exception e1) {
                            // HERE SPRING DOES NOTHING
                            resourceThatNeedsAuthorization = checkForResourceThatNeedsAuthorization(e1);
                            neededResourceId = resourceThatNeedsAuthorization.getId();
              So if here

              // here we get token from tokenService
              if (token == null) {
              token = getTokenServices().getToken(neededResourceId);

              we get the access token we will not step neither here if (token == null || (!token.isAccessToken() && verifier == null)) { nor here else if (!token.isAccessToken()) {

              That's the case.


              • #8
                I see. So you could definitely make a case for a change to the filter to either inspect the token and find out more about whether it is valid immediately, or try and again if the request fails, removing the existing token. If you want to make the change follow the process in the README.