11

In logout controller I tryed to write a lot of combination of code. Now I have this:

final Authentication auth = SecurityContextHolder.getContext().getAuthentication();

if (auth != null) {
    new SecurityContextLogoutHandler().logout(request, response, auth);
}

SecurityContextHolder.getContext().setAuthentication(null);
auth.setAuthenticated(false);

But after provided code execution token still valid.

What do I wrong? How to revoke token eventually?

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
gstackoverflow
  • 36,709
  • 117
  • 359
  • 710

5 Answers5

9

The class you're looking for is DefaultServices, method revokeToken(String tokenValue).

Here an exemple of a controller that revokes token, and here the oauth2 configuration with the DefaultServices bean.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
raonirenosto
  • 1,507
  • 5
  • 19
  • 30
  • 4
    @raonirenosto, I've run into problems with autowiring a class with Spring been proxy using your example. I had to change DefaultTokenServices to ConsumerTokenServices (which is an interface) for it to work. But thanks for suggesting using DefaultTokenServices.revokeToken(). – vutbao Jul 09 '15 at 12:03
  • Since I last saw, Spring Oauth has changed many classes. I guess the framework is more stable now than the time I wrote this example. – raonirenosto Jul 09 '15 at 13:20
  • 10
    Both links do not exist anymore :( – Ondřej Stašek Oct 01 '19 at 07:57
9

If you need to revoke a token for another user than the current one (E.g. an admin wants to disable a user account), you can use this:

Collection<OAuth2AccessToken> tokens = tokenStore.findTokensByClientIdAndUserName(
                                                           "my_oauth_client_id", 
                                                           user.getUsername());
for (OAuth2AccessToken token : tokens) {
  consumerTokenServices.revokeToken(token.getValue());
}

With tokenStore being an org.springframework.security.oauth2.provider.token.TokenStore and consumerTokenServices being a org.springframework.security.oauth2.provider.token.ConsumerTokenServices

Wim Deblauwe
  • 25,113
  • 20
  • 133
  • 211
  • when doing this its showing "Cannot make a static reference to the non-static method revokeToken(String) from the type ConsumerTokenServices". – Mohammedshafeek C S Mar 11 '18 at 10:15
  • Mohammed Shafeek, you must be calling the method revokeToken using the classname instead of using the name of the object instantiated from the class ConsumerTokenServices – Abu Sulaiman May 09 '18 at 19:37
0

the thread is a bit old but for JWTToken users this is not working as the tokens are not stored. So another option is to use a filter. 1 create a method for admin to lock/unlock a user on your database. 2 use a filter and if the method needs authentication check if the user is active or not

exemple :

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if(authentication != null
            &&  authentication.getName() != null
            && !authentication.getName().equalsIgnoreCase("anonymousUser")) {
        UserModel user = userService.getUser(authentication.getName());
        if(user != null && !user.isActivated())
            throw new SecurityException("SECURITY_USER_DISABLED");
    }
    chain.doFilter(request, response);
}

On client side just intercept this error and disconnect user hope this helps someone.

mcfly
  • 774
  • 1
  • 8
  • 18
0

Simple example of token revocation for current authorized user using DefaultTokenServices:

  1. Need Bean for Default token store

    @Bean 
    public DefaultTokenServices tokenServices() {
         DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
         defaultTokenServices.setTokenStore(tokenStore());
         defaultTokenServices.setSupportRefreshToken(true);
         return defaultTokenServices;
    }
    
  2. Then you can write your own controller

    @RestController
    @RequestMapping("/user")
    public class UserApi {
    
    @Autowired
    private DefaultTokenServices tokenServices;
    
    @Autowired
    private TokenStore tokenStore;
    
    @DeleteMapping("/logout")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void revokeToken() {
        final OAuth2Authentication auth = (OAuth2Authentication) SecurityContextHolder
                .getContext().getAuthentication();
        final String token = tokenStore.getAccessToken(auth).getValue();
        tokenServices.revokeToken(token);
    }
    }
    
Abhishek
  • 3,348
  • 3
  • 15
  • 34
lukascode
  • 138
  • 1
  • 7
  • Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.provider.token.TokenStore' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} – Ondřej Stašek Oct 01 '19 at 08:37
-2

Autowire the DefaultTokenServices then use this code:

String authHeader = request.getHeader("Authorization");
String tokenValue = authHeader.replace("bearer", "").trim();
tokenService.revokeToken(tokenValue);
tokenService.setAccessTokenValiditySeconds(1);
tokenService.setRefreshTokenValiditySeconds(1);

Just try the code to revoke the access token.

Jiri Tousek
  • 12,211
  • 5
  • 29
  • 43
  • 1
    Someone should kindly explain why this answer was downvoted. Why is this not advisable? – Olantobi Sep 21 '17 at 16:45
  • 4
    @Olantobi Because changing the token validity time this way changes the token validity for the whole application, not just one token. – Mikk Dec 27 '17 at 17:26