Spring security OAuth2 - invalidate session after authentication

Understanding that the question is a bit old, I hope that the following could be helpful for those who search for the correct answer for the question

OP asked not about tokens invalidation, but how to invalidate httpSession on Spring OAuth2 server right after user authentication successfully passed and a valid access_token or authorization_code (for subsequent getting of access_token) returned to a client.

There is no out-of-the-box solution for this use-case still. But working workaround from the most active contributor of spring-security-oauth, Dave Syer, could be found here on GitHub

Just copy of the code from there:

@Service
@Aspect
public class SessionInvalidationOauth2GrantAspect {

    private static final String FORWARD_OAUTH_CONFIRM_ACCESS = "forward:/oauth/confirm_access";
    private static final Logger logger = Logger.getLogger(SessionInvalidationOauth2GrantAspect.class);

    @AfterReturning(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")
    public void authorizationAdvice(JoinPoint joinpoint, ModelAndView result) throws Throwable {

        // If we're not going to the confirm_access page, it means approval has been skipped due to existing access
        // token or something else and they'll be being sent back to app. Time to end session.
        if (!FORWARD_OAUTH_CONFIRM_ACCESS.equals(result.getViewName())) {
            invalidateSession();
        }
    }

    @AfterReturning(value = "within(org.springframework.security.oauth2.provider.endpoint..*) && @annotation(org.springframework.web.bind.annotation.RequestMapping)", returning = "result")
    public void authorizationAdvice(JoinPoint joinpoint, View result) throws Throwable {
        // Anything returning a view and not a ModelView is going to be redirecting outside of the app (I think). 
        // This happens after the authorize approve / deny page with the POST to /oauth/authorize. This is the time
        // to kill the session since they'll be being sent back to the requesting app.
        invalidateSession();
    }

    @AfterThrowing(value = "within(org.springframework.security.oauth2.provider.endpoint..*) &&  @annotation(org.springframework.web.bind.annotation.RequestMapping)", throwing = "error")
    public void authorizationErrorAdvice(JoinPoint joinpoint) throws Throwable {
        invalidateSession();
    }

    private void invalidateSession() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        HttpSession session = request.getSession(false);
        if (session != null) {
            logger.warn(String.format("As part of OAuth application grant processing, invalidating session for request %s", request.getRequestURI()));

            session.invalidate();
            SecurityContextHolder.clearContext();
        }
    }

}

add pom.xml

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
</dependency>

Another solution could be to set session time out to some very small value. The simplest way to achieve that is put the following to application.yml config:

server:
  session:
    timeout: 1

But it's not ideal solution as the minimum value could be provider is 1 (zero is reserved for infinite sessions) and it is in minutes not in seconds


From what I understand, you are trying to programmatically logout after you have undertaken certain set of actions. Probably you should look into the SecurityContextLogoutHandler and see how it works. There is a method for logout there. I think calling it as an advice will solve your problem.

public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
      Assert.notNull(request, "HttpServletRequest required");
      if (invalidateHttpSession) {
          HttpSession session = request.getSession(false);
          if (session != null) {
              session.invalidate();
          }
      }

      SecurityContextHolder.clearContext();
  }

First: in your configuration declare bean with token store for oauth

@Bean
@Primary
public TokenStore tokenStore() {
    return new InMemoryTokenStore();
}

For controller approach we made the following class

@Controller
 public class TokenController {

    @RequestMapping(value = "/oauth/token/revoke", method = RequestMethod.POST)
    public @ResponseBody void create(@RequestParam("token") String value) {
        this.revokeToken(value);
    }

    @Autowired
    TokenStore tokenStore;

    public boolean revokeToken(String tokenValue) {
        OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
        if (accessToken == null) {
            return false;
        }
        if (accessToken.getRefreshToken() != null) {
            tokenStore.removeRefreshToken(accessToken.getRefreshToken());
        }
        tokenStore.removeAccessToken(accessToken);
        return true;
    }
}

If you don't wan't to use this approach you can grab current user's token autowiring Principal:

    OAuth2Authentication authorization = (OAuth2Authentication) principal;
    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authorization.getDetails();
    String token = details.getTokenValue();

Or even autowiring OAuth2Authentication:

    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
    String token = details.getTokenValue();