Search code examples
spring-bootoauth-2.0microservicesspring-security-oauth2

Log Out does not work correctly in Spring Security OAuth2


There are a Zuul gateway as Spring-Security-OAuth2 client and Authorization Server. Those are located here

The part of Zuul config:

http
                .csrf()
                .disable()
                .headers().cacheControl().disable()
             .and()
                .headers()
                .cacheControl()
                .disable()
                .frameOptions()
                .sameOrigin()
             .and()
                .httpBasic().disable()
                .authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
                .mvcMatchers("/uaa/**", "/login**", "/favicon.ico", "/error**").permitAll()
                .anyRequest().authenticated()
             .and()
                .logout()
                .logoutSuccessUrl("/app/Index.jsp")
                .logoutRequestMatcher(new AntPathRequestMatcher("/reza"))
                .addLogoutHandler(ssoLogoutHandler);

And the SsoLogoutHandler class of Zuul application as Spring-Security-OAuth2 client:

@Component
public class SSOLogoutHandler implements LogoutHandler {
    @Override
    public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
        Object details = authentication.getDetails();

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

        RestTemplate restTemplate = new RestTemplate();

        String url = "http://192.168.10.97:9191/uaa/token/revoke?token=" + token;

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<Object> requestEntity = new HttpEntity<Object>(headers);

        ResponseEntity<Boolean> result = restTemplate.exchange(url, HttpMethod.GET, requestEntity, new ParameterizedTypeReference<Boolean>() {
        });
    }
}

and the RevokeTokenController config class of Authorization Server:

@RestController
public class RevokeTokenController {

    @Autowired
    private TokenStore tokenStore;

    @RequestMapping(method = RequestMethod.GET, value = "/token/revoke")
    @ResponseBody
    public Boolean revoke(String token) throws Exception {
        OAuth2AccessToken tokenObj = tokenStore.readAccessToken(token);
        tokenStore.removeAccessToken(tokenObj);
        tokenStore.removeRefreshToken(tokenObj.getRefreshToken());
        return true;
    }


}

In order to above configuration that you see, SsoLogoutHandler of client calls as restTemplate to RevokeTokenController of Authorzation Server to log out, Token and Refresh Token are removed but the client again requests as /uaa/authorize... to get new access token and log out is not happen.

Where is wrong? I want to log out after removing both Token and Refresh Token instead of getting again the Access Token. Another hand I want to redirect to login page after removing the token.

Update:

I was deep into the client request after removing the token, the client requests like .../uaa/authorize?client_id=..., so the location attribute of its response is .../gateway/login?code=[code], because of the code, the client is not redirected to login page.


Solution

  • I have solved the problem by two logout endpoints in both Gateway and UAA, in that way first, by the /logout endpoint, the request is redirected to Gateway for logging out, so the its own logoutSuccessUrl is /uaa/logout endpoint of UAA, in order to these endpoints, both the logout of Gateway and UAA are happen.

    like this:

    In the Gateway

    .and()
          .logout()
          .logoutSuccessUrl("/uaa/logout")
          .logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
    

    and the part of UAA config is:

    .and()
          .logout()
          .logoutSuccessUrl("/login")
          .logoutRequestMatcher(new AntPathRequestMatcher("/logout"));