Skip to content

OAuth 2 Logout not working even after upgrade to Spring Sec 5.2.0.M4 #7285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vekdeq opened this issue Aug 20, 2019 · 20 comments
Closed

OAuth 2 Logout not working even after upgrade to Spring Sec 5.2.0.M4 #7285

vekdeq opened this issue Aug 20, 2019 · 20 comments
Assignees
Labels
for: stackoverflow A question that's better suited to stackoverflow.com in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)

Comments

@vekdeq
Copy link

vekdeq commented Aug 20, 2019

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

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 20, 2019
@jzheaux
Copy link
Contributor

jzheaux commented Aug 20, 2019

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?

@jzheaux jzheaux self-assigned this Aug 20, 2019
@vekdeq
Copy link
Author

vekdeq commented Aug 20, 2019

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
okta/okta-spring-boot#126,
which I configured - but still did't work. Please advise.

Vivek

@jzheaux
Copy link
Contributor

jzheaux commented Aug 21, 2019

@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?

@vekdeq
Copy link
Author

vekdeq commented Aug 21, 2019

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

@jzheaux
Copy link
Contributor

jzheaux commented Aug 21, 2019

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.

@vekdeq
Copy link
Author

vekdeq commented Aug 27, 2019

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

@jzheaux
Copy link
Contributor

jzheaux commented Aug 30, 2019

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.

@vekdeq
Copy link
Author

vekdeq commented Aug 30, 2019

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

@jzheaux
Copy link
Contributor

jzheaux commented Aug 31, 2019

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?

@vekdeq
Copy link
Author

vekdeq commented Sep 4, 2019

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//
------ http://xxx.com//oauth2/authorization/okta redirects to
------- https://xxx.com//oauth2/authorization/okta goes to
-------- https://xxx.oktapreview.com/oauth2/v1/authorize?response_type=code&client_id=&scope=openid%20profile%20email&state=emjmYD_lNn4CdJej1Pg1CplQOi1C4QotAGjlQoeys7M%3D&redirect_uri=http://xxx.com//login/oauth2/code/okta
--------- http://xxx.com//login/oauth2/code/okta?code=5dsb7NuCeJBMqTnBkRYm&state=emjmYD_lNn4CdJej1Pg1CplQOi1C4QotAGjlQoeys7M%3D
------- https://xxx.com//login/oauth2/code/okta?code=5dsb7NuCeJBMqTnBkRYm&state=emjmYD_lNn4CdJej1Pg1CplQOi1C4QotAGjlQoeys7M%3D

Can you please help further ?

@jzheaux
Copy link
Contributor

jzheaux commented Sep 5, 2019

@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.

@vekdeq
Copy link
Author

vekdeq commented Sep 5, 2019

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 !!

@jzheaux
Copy link
Contributor

jzheaux commented Sep 6, 2019

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!

@jzheaux jzheaux closed this as completed Sep 6, 2019
@sai-kopparthi
Copy link

sai-kopparthi commented Jul 11, 2020

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,

@vekdeq
Copy link
Author

vekdeq commented Jul 12, 2020 via email

@sai-kopparthi
Copy link

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 "

@vekdeq
Copy link
Author

vekdeq commented Jul 13, 2020 via email

@jzheaux jzheaux added for: stackoverflow A question that's better suited to stackoverflow.com in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 5, 2020
@erycoking
Copy link

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

@jzheaux
Copy link
Contributor

jzheaux commented Jan 26, 2022

@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.

@erycoking
Copy link

@jzheaux noted. my apologies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: stackoverflow A question that's better suited to stackoverflow.com in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)
Projects
None yet
Development

No branches or pull requests

5 participants