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?
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 the http://localhost:9999/client
but this page doesn't exist
source code on gitub:
client - https://github.com/gredwhite/logour_social-auth-client (use localhost:9999/client/hello
url)
server - https://github.com/gredwhite/logout_social-auth-server
GET /oauth/login/logout. Destroys any authentication cookies associated with the current OAuth session. Once the API calls are made, the logout API removes the OAuthToken cookie and forces users to log in again before invoking any protected API calls.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With