I am trying to use Spring Boot SAML2 + Spring Session to secure my web application (to be deployed on K8S). Everything is fine without spring-session-data-rest or spring-session-hazelcast. It can authenticate with Okta and redirect back to the requested page after authentication. Also, I can use either opensaml3 or opensaml4.
However, when I tried to use either spring-session-data-rest or spring-session-hazelcast (just 1 instance, no cluster yet), it would not redirect back to the requested page. Also, it'd fail with opensaml4 with exception: "The response contained an InResponseTo attribute [] but no saved authentication request was found". There's some mentioning about opensaml3 going EOL so I want to make it work with opensaml4.
Here's a sample application to demonstrate my case https://github.com/simonckw/redis-saml2/tree/redis. Have I missed anything? Have anyone got a working sample with this setup? Help is much appreciated.
p.s. I've traced into HttpSessionRequestCache.java, invoked from SavedRequestAwareWarpper.java. Without spring-session-data-rest or spring-session-hazelcast, the saved request can be retrieved but not when either spring-session-data-rest or spring-session-hazelcast is enabled. It also seems to me that the InResponseTo exception could be related too. My Redis setup should be fine. Here's the session data written into Redis:
- "spring:session:sessions:expires:7c1858d1-0ea7-4a7a-8523-2abf89137771"
- "spring:session:expirations:1654439580000"
- "spring:session:sessions:expires:58a584d3-625e-4e0a-bef5-3aaff485ad93"
- "spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:[email protected]"
- "spring:session:sessions:7c1858d1-0ea7-4a7a-8523-2abf89137771"
- "spring:session:sessions:58a584d3-625e-4e0a-bef5-3aaff485ad93"
127.0.0.1:6379> hkeys spring:session:sessions:7c1858d1-0ea7-4a7a-8523-2abf89137771
- "sessionAttr:SPRING_SECURITY_SAVED_REQUEST"
- "lastAccessedTime"
- "maxInactiveInterval"
- "creationTime"
- "sessionAttr:org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository.SAML2_AUTHN_REQUEST"
127.0.0.1:6379> hkeys spring:session:sessions:58a584d3-625e-4e0a-bef5-3aaff485ad93
- "maxInactiveInterval"
- "creationTime"
- "lastAccessedTime"
- "sessionAttr:SPRING_SECURITY_CONTEXT"
- "sessionAttr:SPRING_SECURITY_LAST_EXCEPTION"
The problem is that Spring Session is setting
SameSite=Lax
for itsSESSION
cookie. Your servlet container isn't setting that onJSESSIONID
(when you're not using Spring Session).Because the SAML response is being POSTed from Okta's page, the browser will not send the cookie, so Spring doesn't think it has a session in which to find the authentication request. It uses that saved request to reconcile the
InResponseTo
attribute.You can work around this by removing
SameSite
from the cookie. Create a bean like this:Alternatively, you could explicitly specify
None
, but then you would have to also set theSecure
attribute.Note: Chrome is supposed to default to
Lax
whereSameSite
isn't specified. In reality, it doesn't do that ifHttpOnly
is set. Safari and Firefox don't even seem to care aboutHttpOnly
.This problem is discussed here.