OpenID Connect Logout Options with Spring Boot
This tutorial demonstrates the logout options you have when developing Spring applications and helps you pick the right one for you!
OpenID Connect Logout Options with Spring Boot
This tutorial demonstrates the logout options you have when developing Spring applications and helps you pick the right one for you!
Soumya D
I am getting below issue with same code, please help:
Field clientRegistrationRepository in com.test.spring.okta.sso.SecurityConfiguration required a bean of type âorg.springframework.security.oauth2.client.registration.ClientRegistrationRepositoryâ that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
The following candidates were found but could not be injected:
- Bean method âclientRegistrationRepositoryâ in âOAuth2ClientRegistrationRepositoryConfigurationâ not loaded because OAuth2 Clients Configured Condition registered clients is not available
I am trying to implement a custom logoutSuccessHandler that logs the logout:
@Component
public class myLogoutHandler extends SimpleUrlLogoutSuccessHandler {
@Value( "${okta.oauth2.postLogoutRedirectUri}" )
private String postLogoutRedirectUri;
@PostConstruct
public void init() {
logger.info(postLogoutRedirectUri);
super.setDefaultTargetUrl(postLogoutRedirectUri);
}
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
if (authentication != null) {
logger.info("Logging out user " + authentication.getPrincipal().toString() );
} else {
logger.info("Logout after session expiration");
}
super.onLogoutSuccess(request, response, authentication);
}
}
I Autowire this in the SpringSecurityConfig and set it as the logoutSuccessHandler:
@Autowired
private myLogoutHandler logoutSuccessHandler;
...
.and().logout().logoutSuccessHandler(logoutSuccessHandler)
The Component is properly configured with my redirectURL (I see the log entry), and when I submit a form with action â/logoutâ, I get logged out, but there is no log entry. Several questions:
OK, the correct answer is #2, there is an easier way to do this:
@Component
public class myLogoutHandler implements LogoutHandler {
private static final Logger log = LogManager.getLogger(myLogoutHandler.class);
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
if (authentication != null) {
String username = "unknown";
if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
username = springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof DefaultOidcUser) {
DefaultOidcUser user = (DefaultOidcUser) authentication.getPrincipal();
username = user.getName();
} else if (authentication.getPrincipal() instanceof String) {
username = (String) authentication.getPrincipal();
}
log.info("Logging out user " + username );
} else {
log.info("Logout after session expiration");
}
}
}
And in SpringSecurityConfig:
.addLogoutHandler(logoutHandler)
Hi @jeffemandel!
Iâm not sure Iâm following the question and example correctly, so Iâll try to fill in some background, but if I missed the mark or didnât answer your question, please let me know.
As mentioned in the blog post there are two different ways to âlog outâ of an OIDC application.
The 2nd option will log out of ALL applications, so if you are doing some sort of SSO, or social login, this might not be what you want.
I like to think about the two options similar to a social auth, think about how you could âLogin with GitHubâ to a 3rd party application. The 3rd party application wouldnât be allowed to log you out of GitHub, but you could still log out of that 3rd party application.
If you only have a single application, then you may want to log out of the IdP as well
Itâs not clear what your myLogoutHandler
does other than ad a log message?
A quick note about logging, Spring Securityâs log is sparse by default, if you need more info you would need to turn up the log levels under org.springframework.security
.
Can you describe your use case a bit more, maybe I can give more specific advice?
How can I logout from custom filter ?
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono {
var uri = URI.create(âhttp://localhost:8080/logoutâ)
val modifiedRequest = exchange
.request
.mutate()
.uri(uri)
.build();
val modifiedExchange = exchange
.mutate()
.request(modifiedRequest)
.build()
modifiedExchange.attributes[ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR] = uri
return chain.filter(modifiedExchange)
}
Hi @rahul6941!
Iâm not sure Iâm following your example code. However, registering the logout handler for a reactive app would look something like:
// httpSecurity is a ServerHttpSecurity
// inject the ReactiveClientRegistrationRepository (repository)
OidcClientInitiatedServerLogoutSuccessHandler logoutSuccessHandler = new OidcClientInitiatedServerLogoutSuccessHandler(repository);
logoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}/your/path/here");
httpSecurity.logout().logoutSuccessHandler(logoutSuccessHandler);
This should be the same for Spring Cloud Gateway or any other reactive Spring Boot app.
Let me know if I didnât answer your question!
How can I logout from filter ? in other words I need to implement force logout through programmatically
Can you provide more context of how/when you are logging out? Are you just trying to end the current session? see:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/WebSession.html#invalidate--
Or are you trying to end the remote session (an RP Initiated logout?)
Issue: Spring Boot/Security is not redirecting to Okta logout URL
Description: I tried Logout sample application as given in OpenID Connect Logout Options with Spring Boot , it is working as expected.
But with the same configurations, we are unable to logout from Okta in our main/ organizationsâ Application.
Expected Flow:
Step 1 - On logout button click, UI calls ââŚ/testbootapp/logoutâ â Spring Security by default handles logout Spring Boot logout
Step 2 - âOidcClientInitiatedLogoutSuccessHandlerâ is configured in SpringBoot application, this should redirect to Okta logout URL
--- Here, in our application Spring Security is not redirecting to Okta logout URL
Implementation Details:
After enabling spring security logs in our application, we saw that âo.s.s.web.DefaultRedirectStrategyâ does not generate Okta logout URL, instead redirects to applications root
Our Application:
Jul 21 2022 12:47:16 PM IST DEBUG o.s.s.w.a.l.SecurityContextLogoutHandler -Invalidated session 280BDF27CFF81149D6C829EF2ADAC9DF
Jul 21 2022 12:47:16 PM IST DEBUG o.s.s.web.DefaultRedirectStrategy -Redirecting to /testbootapp/
Sample application given in blog:
2022-07-21 11:25:20.230 DEBUG 7382 â [nio-8080-exec-5] o.s.s.w.a.l.SecurityContextLogoutHandler : Invalidating session: C54C40030C14B14F9F03250B769D2E99
2022-07-21 11:25:20.231 DEBUG 7382 â [nio-8080-exec-5] o.s.s.web.DefaultRedirectStrategy : Redirecting to âhttps://dev-.oktapreview.com/oauth2/default/v1/logout?id_token_hint=&post_logout_redirect_uri=https://twitter.com/â
A couple of ideas to try:
Reduce the complexity of your configuration until you narrow down what is the cause.
For example, temporarily remove the httpBasic
filter
If that doesnât help, add a breakpoint in the OidcClientInitiatedLogoutSuccessHandler
class and step through to see what condition is getting triggered.
While debugging we saw that: org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler#determineTargetUrl method is called
1- With httpBasic
âauthenticationâ parameter is an instance of org.springframework.security.authentication.UsernamePasswordAuthenticationToken, while the expected type is: org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken
2- After removing httpBasic
âauthenticationâ parameter is null, while the expected type is: org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken
A Filter Chain is executed and it is unclear what determines authentication object type, how to debug further?
For your #1, are you logging in with OAuth or basic auth?
hi okta Dev community,
I created a local spring boot app and integrated with okta having Authorization code grant type. When i access the api, it redirects to okta login page and after successful authentication, i am able to access to api. Till here everyting is good.
Now I want to log out from okta and redirect to okta login page. I found below api for this -
GET https://${baseUrl}/logout?id_token_hint=${id_token}
Now my problem is how can i get this id_token in my local spring boot app. I tried several docs, but no luck. Please help.
You shouldnât need to call that API directly. Spring Security will handle it automatically when configured.
Take a look at the example code in this post related to the logoutSuccessHandler()
method.
If that doesnât help, can you share more details about your application?
hi @bdemers , Thanks you for your article and advice. it was great help
hi @bdemers and okta dev team,
we have a legacy spring web app**(its not spring boot app)** . we are trying to login- authenticate via OKTA sign in page.
Currently, we can login in the application using credentials but now we want to authenticate via okta sign in page (grant type - authorization code). It means when we access the login page, it should redirect to okta sign page and then it should allow for app access.
Can you please provide reference/documentation for the same?
hi @bdemers and okta dev team,
In the above example we are using a single post redirect url. Is it possible to make is dynamic.
For example, call a custom logout api in the controller and and get the redirect url as query parameter and pass to oidcLogoutSuccessHandler to logout from okta and do the redirect.
Hi @ajay.surendrakumar !
Sorry I missed your previous question.
Iâm not 100% what you are asking, but my general suggestion is if you are not on a current/supported version of spring (or other framework) is to handle the OAuth bits in another service (Spring Cloud Gateway, OAuth2-Proxy, etc.)
If those links donât help, let us know!
hi @bdemers , Thanks for the links . I will go through them.
Currently we are trying to logout via controller and redirect to query parameter.
I have created a custom controller
@GetMapping(â/customLogoutâ)
public void logoutPage (HttpServletRequest request, HttpServletResponse response, @RequestParam(âredirectUrlâ) String redirectUrl {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null){
new SecurityContextLogoutHandler().logout(request, response, auth);
}
response.redirect(redirectUrl);
}
This donât logs out from okta. Kindly help on this.