Hi Team,
I have been looking for this for some days now. We have spring boot based application(s) using Okta as IDP, using okta spring boot starter - which inject Spring Security 5.1.5. With some efforts, I was able to configure gradle script where in my WAR file now have Spring Security 5.2.0.M4 jars. I am still unable to clear / kill Okta Session - after hitting default logout url. It is configured as link (app/logout) on app's UI - so no XHR - just link. Am I missing anything ?
Vivek
Comment From: jzheaux
Sorry that you are having difficulties, @vekdeq, happy to help.
So that I can understand the issue better, what leads you to believe it is an issue with the Spring Security code? For example, is the redirect to Okta not happening? Specific details will help.
Could you provide a sample that reproduces the issue?
Comment From: vekdeq
Hi Josh,
This is in regards to : gh-5350 - OpenID Connect RP-Initiated Logout issue, which is included as part of this release. I may be doing something wrong - but here is my use case. I have Okta as IDP, Spring boot 2+, Okta - Spring - Boot Starter (which includes Spring Security). I have configured, one app in Okta and I have multiple WARs - representing different functional needs. WARs are deployed to Tomcat app server and Okta Login Page is used for login into app. Even though there are multiple WARs, from end user point of view - it represents separate section in User Portal. So user can log into any of the section - by hitting secure URLs - which is redirected to Okta Login Page - on successful authentication - user is redirected to the page he / she was trying to access. In application, we check if user is logged in or not - by checking Authentication object (SecurityContextHolder.getContext().getAuthentication()) is NOT NULL & the sub in Authentication is matching that of application user session object.
There is nothing specific in WebSecurityConfig - like below
http
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and().logout().clearAuthentication(true)
.deleteCookies().invalidateHttpSession(true).
Here are the needs / questions :
When I logout (I have a link to /logout URL which is default configuration) - its needs to do 2 things a. Kill the Okta Session IDP session. b. Clear Authentication object in my application Security Context.
Both these things are not happening and the issue raised with Okta Boot API - they pointed to Spring Security 5.2.0 release https://github.com/okta/okta-spring-boot/issues/126, which I configured - but still did't work. Please advise.
Vivek
Comment From: jzheaux
@vekdeq Thank you for detailing out some of your configuration - that may have cleared things up for me.
To use OIDC logout, you will need something like:
@Autowired
ClientRegistrationRepository clientRegistrationRepository;
protected void configure(HttpSecurity http) throws Exception {
LogoutSuccessHandler logoutHandler =
new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);
http
// ... other configs
.logout()
.addLogoutHandler(logoutHandler);
}
We are a little behind on our docs, but you can see a sample in the unit tests.
If this doesn't address your issue, would you please post a sample application, for example to GitHub, that can reproduce the issue?
Comment From: vekdeq
Thanks Josh !!
I was aware that I could do it through custom logoutHandler - but I was under impression that with Okta Boot Starter, Okta Java SDK & Okta Auth Java APIs, it will be inbuilt and hence I raised this issue in Okta Support group. Further, I was referring to this documentation, https://developer.okta.com/docs/guides/sign-users-out/springboot/sign-out-of-okta/
As per that, the Okta logout will be available with Spring Security 5.2.0.M release. Hence I was checking with this release. As still the challenge remains - how to get id_token_hint from Authentication object - for which I need to make Authorize api call - for which I need to know id/ pwd - which I don't have it once user is logged in.
Vivek
Comment From: jzheaux
how to get id_token_hint from Authentication object
Have you already taken a look at how OidcClientInitiatedLogoutHandler does it?
https://github.com/spring-projects/spring-security/blob/master/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/web/logout/OidcClientInitiatedLogoutSuccessHandler.java#L86
for which I need to make Authorize api call - for which I need to know id/ pwd
I guess I'm not sure why you need to do those things as the token that was used during login is stored in the Authentication instance.
Comment From: vekdeq
Hi Josh,
Sorry I was busy in few other things. I am going to check above details and will get back to you. Regarding id_token_hint, we don't use token to authenticate / rather - it is Okta hosted Login Page and then I have bearer token in my Authentication Object. I guess for logout, I need other token (may be JWT token). Please correct me if I am wrong.
Vivek
Comment From: jzheaux
then I have bearer token
By bearer token, do you mean as an Authorization header? If so, then I think I'm lost regarding your setup. Would you be willing to problem a sample that demonstrates?
The reason I'm confused is that clients that have a need to logout would typically login using an OAuth 2.0 authorization flow for which Spring Security would preserve the id token in the Authentication for you. It's not as common for, say, a RESTful API that needs an Authorization header to also be the entity performing the logout.
Comment From: vekdeq
Alright - here is our setup: Spring boot based WAR applications deployed on Tomcat with Okta acting as IDP having authentication flow.
api ("com.okta.spring:okta-spring-boot-starter:1.2.1")
api ("com.okta.spring:okta-spring-sdk")
compileOnly apiElements ("com.okta.authn.sdk:okta-authn-sdk-api:1.0.0")
api ("com.okta.authn.sdk:okta-authn-sdk-impl:1.0.0")
Each app have WebSecurityConfig as below;
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests().anyRequest().authenticated() .and().logout().clearAuthentication(true) .deleteCookies().invalidateHttpSession(true); } }
In application interceptor, we check the request is authenticated and retrieve login id for further processing :
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
LOGGER.debug("==== Authentication ===="+authentication);
if (authentication instanceof OAuth2AuthenticationToken) {
String emailId = oktaClient.getUser(authentication.getName()).getProfile().getLogin();
OAuth2AccessToken accessToken = authorizedClientService.loadAuthorizedClient( ((OAuth2AuthenticationToken)authentication).getAuthorizedClientRegistrationId() ,authentication.getName()).getAccessToken(); ---------------------------- This accessToken is of type bearer - which can't work for logout url. Okta support team told us that the id_token_hint value needs to be the one which is available through rest call as below;
https://azdeq.oktapreview.com/oauth2/v1/authorize?response_type=id_token&client_id=xxxx&redirect_url=xxxx&&scope=openid&nonce=abcd&state=authn
We are looking to configure our spring boot layer to take care of logout which will be simple /logout link from UI to kill Okta Session and App Session.
Vivek
Comment From: jzheaux
Just to gather a bit more information, does the following work, @vekdeq, to get the id token:
OAuth2AuthenticationToken authentication = (OAuth2AuthenticationToken) authentication;
OAuth2User user = authentication.getPrincipal();
if (user instanceof OidcUser) { // this should be the case since you are using OIDC
OidcIdToken idToken = ((OidcUser) user).getIdToken();
// ... use token
}
Also, have you had any luck trying to use or borrow OidcClientInitiatedLogoutHandler?
Comment From: vekdeq
Hi Josh,
I tried using OidcClientInitiatedLogoutHandler directly after making some changes to our gradle files to inject spring security 5.2.0.M4. For some reason, I overlooked your earlier post and was thinking to build my custom logout handler and use id_token_hint. But OidcClientInitiatedLogoutHandler should take care of our needs (at least at this time).
So after configuring websecurityconfig to have OidcClientInitiatedLogoutHandler as logoutsuccesshandler, I tested the flow - but it didn't work as expected. It's not killing Okta Session.
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(WebSecurityConfig.class);
@Autowired private ClientRegistrationRepository clientRegistrationRepository;
@Override
protected void configure(final HttpSecurity http) throws Exception {
LogoutSuccessHandler logoutHandler = new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);
http
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and()
.logout()
//.logoutSuccessUrl("xxxx");
.logoutSuccessHandler(logoutHandler);
}
}
My guess is ClientRegistrationRepository - may not be getting set as expected. Do I need set any additional properties currently ? While logoutSuccessUrl - works as expected and network tab shows /logout then xxx URL; but for logoutSuccessHandler - it goes like below;
-- /logout redirects to
----- https://xxx.com/
Can you please help further ?
Comment From: jzheaux
@vekdeq Will you please compare your setup to this test one: https://github.com/spring-projects/spring-security/blob/master/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java#L833
Since it is redirecting to / instead of the end_session_endpoint, I'm guessing that the handler cannot find what it needs in the ClientRegistrationRepository. We'd make progress more quickly if you produced a sample application (like a GitHub repo) that reproduces your issue.
Comment From: vekdeq
Alright !! I figured out - the end_session_endpoint was NULL. It seems Okta starter boot (1.2.1) doesn't support Spring security 5.2.0.M4 yet, hence the ConfigurationMetadata of ProviderDetails of ClientRegistration object is Empty. I guess I need to inject that by some other way (like ur unit test ) or I need to have custom logoutsuccesshandler which will have it predefined. I don't know, if there is any other better way to do it that (like prop file entry). Let me know, if you know better way.
Coming to second issue : How can I configure Spring Security to check with IDP in each request / hit ? The need is as stated initially - we have multiple Apps (WARs) in Web Portals - representing unified user experience as per functional needs. If user navigates across different apps - it is seamless - if he is logged in - where in Authentication Object is available in across all Apps if user if logged in. Now if I logout from App 1 - my Okta & App 1 sessions are killed - but app 2 spring sec & http session is still active. - which is not expected security need. Please guide.
Thanks again !!
Comment From: jzheaux
I'm glad to hear you've resolved your issue, @vekdeq! Nice work.
I'm going to close this issue at this point. Stack Overflow is our preferred platform for handling support requests, as mentioned in the guidelines for contributing.
If you have further questions (it sounds like you might), please ask them on StackOverflow - we as a team watch the spring-security tag, among others, and there are many community members who do the same. Asking your question on StackOverflow also makes it more easily searchable over time.
Of course, if you find a bug or want to make an enhancement request, always feel free to log another GitHub ticket!
Comment From: sai-kopparthi
Dear Josh Cumming,
So I am working on my project and currently using "Okta.spring.boot.starter" for okta login page in my gradle file and trying include this for my logout option.
OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() { OidcClientInitiatedLogoutSuccessHandler successHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository); successHandler.setPostLogoutRedirectUri(URI.create("http://localhost:8080/")); return successHandler; }
But I was not able to import OidcClientInitiatedLogoutSuccessHandler can you help me by any chance on this .
I am not able to this
import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler;
Thanks,
Comment From: vekdeq
Hi,
It is part of spring-security-oauth2-client-5.xxx.jar Below gradle entries should resolve it:
api ("com.okta.spring:okta-spring-boot-starter:1.2.1") api ("com.okta.spring:okta-spring-sdk") compileOnly apiElements ("com.okta.authn.sdk:okta-authn-sdk-api:1.0.0") api ("com.okta.authn.sdk:okta-authn-sdk-impl:1.0.0")
Just check what you need and fine tune it accordingly.
Warm Regards .. * Vivek V. Bedekar*
On Sat, Jul 11, 2020 at 2:30 PM Sai notifications@github.com wrote:
Dear Josh Cumming,
So I am working on my project and currently using "Okta.spring.boot.starter" for okta login page in my gradle file and trying include this for my logout option.
OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() { OidcClientInitiatedLogoutSuccessHandler successHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository); successHandler.setPostLogoutRedirectUri(URI.create("http://localhost:8080/ ")); return successHandler; }
But I was not able to import OidcClientInitiatedLogoutSuccessHandler can you help me by any chance on this .
Thanks,
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-security/issues/7285#issuecomment-657133141, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADZJFEEKMCOH4NXGOYZFAPTR3DKX3ANCNFSM4IN2OU5Q .
Comment From: sai-kopparthi
Hey Vivek, Thanks for the reply I included those in my gradle build. But still I am not able to get import the class "OidcClientInitiatedLogoutSuccessHandler "
Comment From: vekdeq
This class is in spring-security-oauth2-client-5.2.0.RELEASE.jar - check your workspace - I am not sure, if this is in earlier version or not - but check in your jar if class is present. If it is, then it's your gradle dependencies configuration.
Warm Regards .. * Vivek V. Bedekar*
On Sun, Jul 12, 2020 at 2:38 PM Sai notifications@github.com wrote:
Hey Vivek, Thanks for the reply I included those in my gradle build. But still I am not able to get import the class "OidcClientInitiatedLogoutSuccessHandler "
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-security/issues/7285#issuecomment-657279127, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADZJFEFU73HRRZGRGKJUT6LR3IUNPANCNFSM4IN2OU5Q .
Comment From: erycoking
Hi guys, am facing a similar issue with the spring oauth2 authorization server. Once the user signs in for the first time using the authorization code flow, the next time they try to log in they are automatically logged in without filling in the username and password, which is not the desired behavior for me. Is there a way to log them out completely so that they will have to fill in the form again to log in?? please any help would go a long way? I am stuck, I have also posted this question on stack overflow, you can follow this link https://stackoverflow.com/questions/70735327/spring-oauth2-authorization-server-unable-to-logout-users
Comment From: jzheaux
@erycoking, sorry you are having trouble, but please do not cross-post the same message to multiple projects. I'm glad you got some advice from Steve on your StackOverflow question. The team monitors StackOverflow for questions, so it's typically not necessary to also post in GitHub to increase visibility.
In the odd case that you don't see anyone comment on your SO ticket for a few days, it may be worth engaging the team on Gitter. This is preferred over adding comments to closed tickets.
Comment From: erycoking
@jzheaux noted. my apologies.