reza ramezani matin
reza ramezani matin

Reputation: 1474

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.

Upvotes: 0

Views: 1664

Answers (2)

reza ramezani matin
reza ramezani matin

Reputation: 1474

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

Upvotes: 1

Milan Kamboya
Milan Kamboya

Reputation: 506

I would suggest to move your token revocation logic in SSOLogoutHandler and then redirect to login page from there instead of calling separate API call.

Because if something fails to execute token revocation logic due API call then that token will be there and you have to separately handle those tokens later on which will be more complex.

In this particular case, if autowire for TokenStore does not work then register/create a bean of SSOLogoutHandler in one of the connfiguration file and provide TokeStore dependancy from there for SSOLogoutHandler.

Upvotes: 0

Related Questions