Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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

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.

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);
    }
    }
    

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top