How to logout oauth2 client in Spring?
Solution 1
You can delete the refresh token as well as access token from database to save space.
@PostMapping("/oauth/logout")
public ResponseEntity<String> revoke(HttpServletRequest request) {
try {
String authorization = request.getHeader("Authorization");
if (authorization != null && authorization.contains("Bearer")) {
String tokenValue = authorization.replace("Bearer", "").trim();
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
tokenStore.removeAccessToken(accessToken);
//OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(tokenValue);
OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
tokenStore.removeRefreshToken(refreshToken);
}
} catch (Exception e) {
return ResponseEntity.badRequest().body("Invalid access token");
}
return ResponseEntity.ok().body("Access token invalidated successfully");
}
The URL to logout will be : http://localhost:9999/oauth/logout Also, pass the access token in the Authorization header, as
Authorization: Bearer 0cb72897-c4f7-4f01-aed9-2f3f79a75484
where, 0cb72897-c4f7-4f01-aed9-2f3f79a75484 is the access token.
Since, its Spring security, don't forget to bypass /oauth/logout url from authorize access, as
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/hello", "/oauth/logout");
}
Hope, it will solve your logout problem in Springboot2+Oauth2. Its working for me.
Solution 2
Add following code snippet to your ClientApplication class. This will also clear your session details.
Replace below code with the configure method of your web security adapter class.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers( "/login**", "/webjars/**", "/error**").permitAll()
.anyRequest()
.authenticated()
.and().logout().invalidateHttpSession(true)
.clearAuthentication(true).logoutSuccessUrl("/login?logout").deleteCookies("JSESSIONID").permitAll().and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
Solution 3
You probably want to use the Spring Security built-in support for the /logout endpoint which will do the right thing (clear the session and invalidate the cookie). To configure the endpoint extend the existing configure() method in our WebSecurityConfigurer:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.and().logout().logoutSuccessUrl("/").permitAll();
}
gstackoverflow
Updated on June 15, 2022Comments
-
gstackoverflow almost 2 years
I have the simplest oauth2 client:
@EnableAutoConfiguration @Configuration @EnableOAuth2Sso @RestController public class ClientApplication { @RequestMapping("/") public String home(Principal user, HttpServletRequest request, HttpServletResponse response) throws ServletException { return "Hello " + user.getName(); } public static void main(String[] args) { new SpringApplicationBuilder(ClientApplication.class) .properties("spring.config.name=application").run(args); } }
I also have the following
application.yml
:server: port: 9999 servlet: context-path: /client security: oauth2: client: client-id: acme client-secret: acmesecret access-token-uri: http://localhost:8080/oauth/token user-authorization-uri: http://localhost:8080/oauth/authorize resource: user-info-uri: http://localhost:8080/me logging: level: org.springframework.security: DEBUG org.springframework.web: DEBUG
It is the full code. I don't have any additional source code. It works properly.
But now I want to add a logout feature. I've added an endpoint but it doesn't work. I tried to do the following:
@RequestMapping("/logout") public void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); authentication.setAuthenticated(false); new SecurityContextLogoutHandler().logout(request,response,authentication); SecurityContextHolder.clearContext(); request.logout(); request.getSession().invalidate(); }
But I am still logged in and can access
/
url and it responds to me with the username.Can you help me fix this issue?
Update
I tried the approach described here https://spring.io/guides/tutorials/spring-boot-oauth2/#_social_login_logout :
@EnableAutoConfiguration @Configuration @EnableOAuth2Sso @Controller public class ClientApplication extends WebSecurityConfigurerAdapter { private Logger logger = LoggerFactory.getLogger(ClientApplication.class); @RequestMapping("/hello") public String home(Principal user, HttpServletRequest request, HttpServletResponse response, Model model) throws ServletException { model.addAttribute("name", user.getName()); return "hello"; } @Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.antMatcher("/**") .authorizeRequests() .antMatchers( "/login**", "/webjars/**", "/error**").permitAll() .anyRequest() .authenticated() .and().logout().logoutSuccessUrl("/").permitAll() .and() .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); // @formatter:on } public static void main(String[] args) { new SpringApplicationBuilder(ClientApplication.class) .properties("spring.config.name=application").run(args); } }
and on FE I wrote:
<script type="text/javascript"> $.ajaxSetup({ beforeSend: function (xhr, settings) { if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE') { if (!(/^http:.*/.test(settings.url) || /^https:.*/ .test(settings.url))) { // Only send the token to relative URLs i.e. locally. xhr.setRequestHeader("X-XSRF-TOKEN", Cookies.get('XSRF-TOKEN')); } } } }); var logout = function () { $.post("/client/logout", function () { $("#user").html(''); $(".unauthenticated").show(); $(".authenticated").hide(); }); return true; }; $(function() { $("#logoutButton").on("click", function () { logout(); }); }); </script>
and
<input type="button" id="logoutButton" value="Logout"/>
But it still doesn't work. It results in the following behavior:
Post
http://localhost:9999/client/logout
redirects to thehttp://localhost:9999/client
but this page doesn't existsource code on gitub:
client - https://github.com/gredwhite/logour_social-auth-client (uselocalhost:9999/client/hello
url)
server - https://github.com/gredwhite/logout_social-auth-server