Spring Security SAML Extension with Azure AD: SingleLogout problem - spring

I have two web applications configured as SAML Service Providers, using version 1.0.10 of the Spring Security SAML extension. The identity provider is Azure AD.
Single sign-on across both applications works fine. The problem is with single logout (SLO). If I'm logged into both apps in two different browser tabs, and then initiate a logout from one app, that app is logged out as expected, but the logout of the other app fails.
With debug logging enabled, this is the output I get for the second app:
DEBUG [org.springframework.security.web.FilterChainProxy] - Securing GET /saml/SingleLogout?SAMLRequest=lZJfb5swFMW%2fCuLdYGPzxxZBypYtQ20aqVlbaS%2bRgUuKBjbFJs3HLwT1IdJUaW%2f2lY9%2b51yf1Miu7cW9PunRPsLbCMY6%2bWblHmscFoREGHHGJGJJTBHnCUYhl1SWUU1rWrrOMwym0WrlBh52ndyYEXJlrFR2GuEgQAQjQn8TKjATAfcinvxxnc1EaZS0V%2bWrtb0Rvt%2fKcYDW6wcwMJybUnql9sa%2f%2ftN03UklT9CBsv5s2D806tTC4tp1HrTdq%2f2wri0Mt1h2g710rTLimnjljoMSWprGCCU7MMKW4rDe3YspiOgHbXWpWzdLr5GGRfq1SJrJ6BzJzT4jGWu890ZV%2bt14CqwfSYkZqUrEo4IiFsoKceAFimKQAS4JgwT81F%2bYWfowMfKN81MPnbRfw%2bdJU6H6%2blT0868YO63L%2fU%2fnYfwcbrvzcWe%2f3R2L%2fO7Hmv%2b6BPtX%2fXLenrakfvveRo8o3B4anfqLvyxdOnQAM1chVxVcsiMNaREDo6jmkiBWQ4SSuJYowFUZTgcSYJz6%2f1B%2bDm8qmX0A&Signature=H2iMTbizxEM8ooIUfV%2fyZ8zZfkK8J9CXbVako2sPk9EUw1xjRUXfaCUbO3gpsjKvUD61UHEbpOexnMhCtqCJnItC81hIVp9dI2%2bSGqJ3%2fIYFtxDMqVAsP%2fxsEZpL%2f15OkZ0rj0n1nAiU7dT3xC0K5TDtjUWciKqbt0MkJgvKyvkZyjZGjhclfTGo4AJQrEkBVxkw8%2b2Evwgmxpk0taOfhq9sHaiRLzvVAxhCse9GZhbQehxyxtWWNDYt8Ks7JJJR5UDfdszX4E5J2576seSxvop3EeJLlULjjNm3FJZcXoKKAXzA%2bfHqYBYFD9rIyuEXaJsFEC0p8SSAHwKgDOq3PA%3d%3d&SigAlg=http%3a%2f%2fwww.w3.org%2f2001%2f04%2fxmldsig-more%23rsa-sha256
DEBUG [org.springframework.security.web.context.SecurityContextPersistenceFilter] - Set SecurityContextHolder to empty SecurityContext
DEBUG [org.springframework.security.web.FilterChainProxy] - Securing GET /saml/SingleLogout?SAMLRequest=lZJfb5swFMW%2fCuLdYGPzxxZBypYtQ20aqVlbaS%2bRgUuKBjbFJs3HLwT1IdJUaW%2f2lY9%2b51yf1Miu7cW9PunRPsLbCMY6%2bWblHmscFoREGHHGJGJJTBHnCUYhl1SWUU1rWrrOMwym0WrlBh52ndyYEXJlrFR2GuEgQAQjQn8TKjATAfcinvxxnc1EaZS0V%2bWrtb0Rvt%2fKcYDW6wcwMJybUnql9sa%2f%2ftN03UklT9CBsv5s2D806tTC4tp1HrTdq%2f2wri0Mt1h2g710rTLimnjljoMSWprGCCU7MMKW4rDe3YspiOgHbXWpWzdLr5GGRfq1SJrJ6BzJzT4jGWu890ZV%2bt14CqwfSYkZqUrEo4IiFsoKceAFimKQAS4JgwT81F%2bYWfowMfKN81MPnbRfw%2bdJU6H6%2blT0868YO63L%2fU%2fnYfwcbrvzcWe%2f3R2L%2fO7Hmv%2b6BPtX%2fXLenrakfvveRo8o3B4anfqLvyxdOnQAM1chVxVcsiMNaREDo6jmkiBWQ4SSuJYowFUZTgcSYJz6%2f1B%2bDm8qmX0A&Signature=H2iMTbizxEM8ooIUfV%2fyZ8zZfkK8J9CXbVako2sPk9EUw1xjRUXfaCUbO3gpsjKvUD61UHEbpOexnMhCtqCJnItC81hIVp9dI2%2bSGqJ3%2fIYFtxDMqVAsP%2fxsEZpL%2f15OkZ0rj0n1nAiU7dT3xC0K5TDtjUWciKqbt0MkJgvKyvkZyjZGjhclfTGo4AJQrEkBVxkw8%2b2Evwgmxpk0taOfhq9sHaiRLzvVAxhCse9GZhbQehxyxtWWNDYt8Ks7JJJR5UDfdszX4E5J2576seSxvop3EeJLlULjjNm3FJZcXoKKAXzA%2bfHqYBYFD9rIyuEXaJsFEC0p8SSAHwKgDOq3PA%3d%3d&SigAlg=http%3a%2f%2fwww.w3.org%2f2001%2f04%2fxmldsig-more%23rsa-sha256
DEBUG [org.springframework.security.saml.SAMLLogoutProcessingFilter] - Delegating logout processing to super class...
DEBUG [org.springframework.security.saml.SAMLLogoutProcessingFilter] - Processing SAML logout message
DEBUG [org.springframework.security.saml.processor.SAMLProcessorImpl] - Retrieving message using binding urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
INFO [org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule] - Validation of request simple signature succeeded
INFO [org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule] - Authentication via request simple signature succeeded for context issuer entity ID https://sts.windows.net/00000000-0000-0000-0000-00000000/
INFO [org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule] - SAML protocol message was not signed, skipping XML signature processing
DEBUG [org.springframework.security.saml.util.SAMLUtil] - Found endpoint org.opensaml.saml2.metadata.impl.SingleLogoutServiceImpl#76b927ad for request URL https://server.com:443/app2/saml/SingleLogout?SAMLRequest=lZJfb5swFMW%2fCuLdYGPzxxZBypYtQ20aqVlbaS%2bRgUuKBjbFJs3HLwT1IdJUaW%2f2lY9%2b51yf1Miu7cW9PunRPsLbCMY6%2bWblHmscFoREGHHGJGJJTBHnCUYhl1SWUU1rWrrOMwym0WrlBh52ndyYEXJlrFR2GuEgQAQjQn8TKjATAfcinvxxnc1EaZS0V%2bWrtb0Rvt%2fKcYDW6wcwMJybUnql9sa%2f%2ftN03UklT9CBsv5s2D806tTC4tp1HrTdq%2f2wri0Mt1h2g710rTLimnjljoMSWprGCCU7MMKW4rDe3YspiOgHbXWpWzdLr5GGRfq1SJrJ6BzJzT4jGWu890ZV%2bt14CqwfSYkZqUrEo4IiFsoKceAFimKQAS4JgwT81F%2bYWfowMfKN81MPnbRfw%2bdJU6H6%2blT0868YO63L%2fU%2fnYfwcbrvzcWe%2f3R2L%2fO7Hmv%2b6BPtX%2fXLenrakfvveRo8o3B4anfqLvyxdOnQAM1chVxVcsiMNaREDo6jmkiBWQ4SSuJYowFUZTgcSYJz6%2f1B%2bDm8qmX0A&Signature=H2iMTbizxEM8ooIUfV%2fyZ8zZfkK8J9CXbVako2sPk9EUw1xjRUXfaCUbO3gpsjKvUD61UHEbpOexnMhCtqCJnItC81hIVp9dI2%2bSGqJ3%2fIYFtxDMqVAsP%2fxsEZpL%2f15OkZ0rj0n1nAiU7dT3xC0K5TDtjUWciKqbt0MkJgvKyvkZyjZGjhclfTGo4AJQrEkBVxkw8%2b2Evwgmxpk0taOfhq9sHaiRLzvVAxhCse9GZhbQehxyxtWWNDYt8Ks7JJJR5UDfdszX4E5J2576seSxvop3EeJLlULjjNm3FJZcXoKKAXzA%2bfHqYBYFD9rIyuEXaJsFEC0p8SSAHwKgDOq3PA%3d%3d&SigAlg=http%3a%2f%2fwww.w3.org%2f2001%2f04%2fxmldsig-more%23rsa-sha256 based on location attribute in metadata
DEBUG [org.springframework.security.saml.SAMLLogoutProcessingFilter] - Received logout request is invalid, responding with error
org.springframework.security.saml.SAMLStatusException: No user is logged in
at org.springframework.security.saml.websso.SingleLogoutProfileImpl.processLogoutRequest(SingleLogoutProfileImpl.java:175) ~[spring-security-saml2-core-1.0.10.RELEASE.jar:1.0.10.RELEASE]
at org.springframework.security.saml.SAMLLogoutProcessingFilter.processLogout(SAMLLogoutProcessingFilter.java:181) [spring-security-saml2-core-1.0.10.RELEASE.jar:1.0.10.RELEASE]
at com.tessella.sdb.core.security.authentication.saml.SamlCustomLogoutProcessingFilter.processLogout(SamlCustomLogoutProcessingFilter.java:52) [WebAppSecurity-6.6.0-bugfix_SUPPORT-1608-SNAPSHOT.jar:?]
at org.springframework.security.saml.SAMLLogoutProcessingFilter.doFilter(SAMLLogoutProcessingFilter.java:107) [spring-security-saml2-core-1.0.10.RELEASE.jar:1.0.10.RELEASE]
...
In Azure AD, the Front-channel logout URL for app2 is set as https://server.com/app2/saml/SingleLogout, so it looks like the endpoint is called & the HTTP-Redirect binding is used.
However, in SAMLLogoutProcessingFilter, for the line:
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
auth is returned as null, i.e. there's no existing user session and so the logout fails. I've seen reports of this happening elsewhere with WSO2 as the SAML IdP, when the HTTP POST binding is used, but with Azure AD, my understanding is that this should be a front-channel request using the HTTP-Redirect binding.
Has anyone got Single Logout to work successfully using Azure AD as the IdP with the Spring SAML extension? Are there any configuration changes required either in the SP or IdP?
Any advice on what I need to do would be gratefully received. Thank you.

OK, so I found the answer. We're using the Apache web server as a reverse proxy in front of the apps, and this was setting same-site on the session cookie to Lax. Since the Logout request was coming from the SAML IdP, the session cookie was being removed. If same-site is set to None instead, the session cookie is attached, and the call to:
SecurityContextHolder.getContext().getAuthentication()
returns the valid authentication credentials.

Related

Facebook Oauth2 authentication not working for spring boot application

I am building a spring-boot application which uses google/facebook oauth2 authentication. The application configurations set are as follows:
#Google
spring.security.oauth2.client.registration.google.clientId=<googleClientId>
spring.security.oauth2.client.registration.google.clientSecret=<googleClientSecret>
spring.security.oauth2.client.registration.google.redirectUri={baseUrl}/oauth2/callback/{registrationId}
spring.security.oauth2.client.registration.google.scope=email,profile
#Facebook
spring.security.oauth2.client.registration.facebook.clientId=<fbClientId>
spring.security.oauth2.client.registration.facebook.clientSecret=<fbClientSecret>
spring.security.oauth2.client.registration.facebook.redirectUri={baseUrl}/oauth2/callback/{registrationId}
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.provider.facebook.authorizationUri=https://www.facebook.com/v13.0/dialog/oauth
spring.security.oauth2.client.provider.facebook.tokenUri=https://graph.facebook.com/v13.0/oauth/access_token
spring.security.oauth2.client.provider.facebook.userInfoUri=https://graph.facebook.com/v13.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250)
For google, this is working well - the application has an authorization rest controller which redirects to the google auth end point. After logging in, I can see a code is returned and sent to a redirect URI {baseUrl}/ouath2/callback/google, which is exchanged for a token which is in turn parsed and used to construct a universal application-level Oauth2 bearer token (for use in my shared APIs etc).
For facebook, I am attempting a similar setup. The initial redirect works, and user is directed to a facebook login page with equivalent client_id / redirect uri parameters set:
https://www.facebook.com/v3.0/dialog/oauth
?response_type=code
&client_id=<fbClientId>
&scope=email+public_profile
&state=<state>
&redirect_uri=https%3A%2F%2F192.168.50.150.nip.io%3A8300%2Foauth2%2Fcallback%2Ffacebook
&ret=login
&fbapp_pres=0
&logger_id=e1036c5a-ac6e-448c-ab8g-655727eae993
&tp=unspecified
&cbt=1643459835928
&ext=1645463198
&hash=AeJog6HeUz9jlsDRQQo
However, when the code is obtained after login and sent to the redirect uri {baseUrl}/ouath2/callback/facebook, there is an error returned when my application attempts to access the FB User Info resource server:
I don't have any traffic capture from my backend to the FB User Info URI, so I can't see exactly what's being sent, but the response I get back is a server error:
[invalid_user_info_response] An error occurred while attempting to
retrieve the UserInfo Resource: Error details: [UserInfo Uri:
https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250),
Error Code: server_error]
Are there any known issues with the graph.facebook.com end points?

Keycloak not logging out the Identity provider after calling the /logout endpoint

I'm trying to use Keycloak (13.0.1) as an identity broker. I have an iOS app that uses keycloak to log in via an OIDC identity provider, and then use the token to access a spring-boot backend.
My issue is that I simply can't get the keycloak logout to also log the user out of the Identity Provider session.
I've spent days googling this and looking at both stackoverflow and the keycloak discourse page and git repo, but I couldn't find an answer to my specific issue.
Using the postman to test, the first time I click "Get New Access Token":
It successfully redirects me to the identity provider login page (I use the keycloak hint to bypass the initial keycloak login page). Pressing the button again will skip the IDP login and give me the token directly. How convenient, or so I thought...
The problem is that when I use keycloak's /logout endpoint to invalidate the refresh token:
And it successfully returns 204, when I click "Get new access token" again, it skips the login form and gives me the token directly, so there is effectively no way to logout the user and then login with a different user. The only way to bypass this is to manually click the "clear all cookies" button.
Here is my IDP configuration:
Also note that, in the keycloak admin guied it is specified that keycloak should be logging out of the IDPs when a logout is triggered, so it doesn't seem like I should be making any special configs:
https://www.keycloak.org/docs/latest/server_admin/#identity-broker-logout
IMPORTANT EDIT:
I marked this question as solved and the solution is correct, but I also needed to turn off the IDP "backchannel logout", because our corporate SSO doesn't like it. Keycloak seems to be able to log out regardless.
It successfully redirects me to the identity provider login page
That redirect is the key. It opens a browser, where Keycloak cookie is created - that is your IdP session. You have to open Keycloak /logout endpoint in the same browser, so Keycloak can clear own Keycloak cookies.
Summary: you have to open/redirect (API call doesn't work) user to the same browser to the logout endpoint (API call doesn't work) as you have used for the login. Of course this may not be case for some special flows, but it should be working for standard Authorization Code (with/without PKCE).

CAS 6.0 and Spring Security: JWT configuration fails on Service Ticket validation

I'm setting up a configuration using CAS 6.0 and Spring Boot with Spring Security so as to shift to JWT. Looking at this guide, I've configured module dependency, CAS Service Registry, and signing and encryption Keys. The flow goes fine:
calling the app at https://localhost:9000/secure/home/test I'm redirected to CAS login,
at https://localhost:8443/cas/login?service=https%3A%2F%2Flocalhost%3A9000%2Flogin%2Fcas I can correctly specify credentials and see TGC in JWT form inside the cookies,
after inserting credentials I'm redirected to https://localhost:9000/login/cas.
Last call has the two query string parameters redirect=true and ticket=[JWT string].
I've set up a filter decoding the token and it works, but then the filter chain hits CasAuthenticationFilter, which sees the ticket parameter and tries to validate it as Service Ticket, failing.
How can it be made aware of jwt, and forward the request to the original URL?
the same question in CAS 5.3.x.
finally I did the following flow:
CAS Server:
set up the cas.properties in cas server, add 'cas.ticket.st.numberOfUses=2' to let service ticket can be used twice. (default value is 1)
Application Server:
set up a filter to decode JWT token, extract service ticket from the key "jti" in JWT token.
set the response status to 302 and redirect to the request url and make the service ticket as query string named "ticket". (note that in this step should not go on the next filter)
the redirect request from #2 should not process in #1's filter then go on the filter chain.
The above flow works. But need more testing to confirm the working fine for web applications and result api service.

SpringBoot 2 SSO with OAM using SAML2

I am working on a web application of tech stack contains front end ReactJS and backend SpringBoot 2 Microservices. Now it's time for the SSO integration **(single sign on) using the OAM(Oracle Access Manager) using SAML2 **.
I had a discussion with OAM Team and they had given me below details
Entity ID or Issuer ID
OAM Entry Point or OAM SSO URL
X509 Certificate
Assertion consumer URL (ACS URL) which i had given to them to receive SAML Response
online i could find few SSO option with SSOCIRCLE, OKTA, ONEIDENTITY etc but couldn't find any resources with Springboot2 + SSO + OAM.
Please throw some lights or any response on how to start would be greatly appreciated.
You can start with OAM installation:
https://docs.oracle.com/en/middleware/idm/access-manager/12.2.1.4/tutorial-oam-install-oam/
Refer to the following link to understand deployment and usage in application:
https://docs.oracle.com/en/middleware/idm/access-manager/12.2.1.4/tutorial-oam-protect-wlsapp/#deploy-a-sample-application-to-weblogic-server
You have to integrate below flows
Login flow: From your web application (frontend) redirect to the Federation system endpoint (get their login endpoint), this is a browser redirect. Here 2 types of configurations options are available- Either you send the xml Metadata to them when you redirect to their portal OR
These configurations can be set at OAM manually and you only have to do a simple browser redirect. (I have tried the 2nd option).
User enters the credentials in Federation page which gets authenticated by IdP and after successful authentication the SP is notified on ACS login url. So your login url will be basically a callback url which will be called by them and they will be sending a SAML response on that callback api. Once you get a notification on your callback you need to redirect the user to your portal.
For this your callback url should set http response status code as 302 and response.headers.location as the endpoint (along with saml response) where you want the user to redirect. Take care of validating saml signature before redirecting user to your portal.
On your frontend code, you will have to check for the SAML response with windows.location.search.
These steps will redirect user back to SP portal.
Logout flow: when user clicks on SP logout button, execute your logout api and then redirect user to Federation System's logout url, browser redirection, in this case User's session will also terminate at their(SAML) end and they redirect user to SP portal.
Ensure that user's sessions (both) are in sync. For this keep idle timeout and max session timeout same at both ends.
Hope this helps.

Unable to get the Shibboleth IDP login page

I am trying to integrate a Shibboleth IDPV3.4.1 with my SP which is a server called as ClearPass. I am using the Linux platform of the Shibboleth IDP. I configured the relyingparty.xml, attribute-filter.xml, attribute-resolver.xml,ldap.properties, and also the and uploaded the metadata to the /metadata/sp-metadata.xml also updating the metadata-providers.
I am trying to use the password authentication flow with LDAP, however the issue is that I never get the login page when I initiate the SAML transaction from my SP. I get an error saying "Web Login Service -Stale Request". I have attached the screenshot of the error
Stale Request
I attempt to do a resolver test using the
http://shib.nslab.com:8080/idp/profile/admin/resolvertest?requester=https://chandracppm.nslab.com/networkservices/saml2/sp&principal=chandu
requester "https://chandracppm.nslab.com/networkservices/saml2/sp"
principal "chandu"
attributes
0
name "sAMAccountName"
values
0 "chandu"
and I get the attributes from AD in return, which shows the connection to AD is working.
However the authentication page does not appear from the IDP when I try to access the resource in my SP, I only get the Stale request Error.
The error that I see in the logs/idp-process.log is as follows
2018-12-10 19:26:08,222 - 10.23.20.81 - ERROR [org.opensaml.profile.action.impl.DecodeMessage:73] - Profile Action DecodeMessage: Unable to decode incoming request
org.opensaml.messaging.decoder.MessageDecodingException: Shibboleth Authentication Request message did not contain the providerId query parameter.
at net.shibboleth.idp.saml.profile.impl.BaseIdPInitiatedSSORequestMessageDecoder.getEntityId(BaseIdPInitiatedSSORequestMessageDecoder.java:128)
2018-12-10 19:26:08,223 - 10.23.20.81 - WARN [org.opensaml.profile.action.impl.LogEvent:105] - A non-proceed event occurred while processing the request: UnableToDecode
2018-12-10 19:26:08,224 - 10.23.20.81 - DEBUG [org.opensaml.saml.common.profile.logic.DefaultLocalErrorPredicate:143] - No SAMLBindingContext or binding URI available, error must be handled locally
I am new to setting up Shibboleth IDP, not sure what I am missing.
Any inputs would be appreciated
Shibboleth fails to decode the message. This behavior is to be seen if the AuthnReq is being sent to POST endpoint instead of Redirect or vice versa or if any of both endpoints are not configured properly. On UI, the error you will notice for this is "StaleRequest". I got a similar error in idp-process.log file "org.opensaml.messaging.decoder.MessageDecodingException: This message decoder only supports the HTTP GET method". The issue is pertaining to incorrect or misconfigured endpoints.
I was able to get this working by installing an IDP docker image from here
https://docs.google.com/document/d/1qb5XTde1nulCdA_8QUei48CxDj0lQs7ShD622Ze_4II/edit
The authentication flow is working now

Resources