Amit Mahajan
Amit Mahajan

Reputation: 915

Spring security 6 same site issue

I am trying to use spring security saml with spring boot 3 and spring security 6. I have a UI service running in separate domain and it need to authenticate with the SAML service.

Unfortunately as the domain is different even after specifying @CrossSite attribute to new domain, the session cookies are not sent as part of API calls from the UI service after authentication.

I tried setting below SameSite Bean but it is not working.

Steps to reproduce:

For example please consider below Spring Security Samples for SAML service
SAML Service -> https://github.com/spring-projects/spring-security-samples/tree/6.3.x/servlet/spring-boot/java/saml2/login

Add one additional API in above service that works when session is valid.

Add a simple react app (npm create react app) and add a axios call to get some API response from above new api. Call this axios and get response from session.

This example works fine for same domain. Both Spring security and React app are in same domain like localhost. If we change spring security domain to different hostname (under hosts file) and try the same this fails.

Added below config in SecurityConfig.java

I tried setting below bean for same site but it is not working, tried all Lax, None, Null: (form this article https://jstobigdata.com/spring-security/controlling-sessions-with-spring-security/)

@Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();
        serializer.setCookieName("JSESSIONID");
        serializer.setCookiePath("/");
        serializer.setUseSecureCookie(true);
        serializer.setSameSite("Strict"); // default is Lax
        serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
        return serializer;
    }

Login in one tab to spring security project and open react app in another tab. Check the difference when domain is same vs when it is different in the 2 apps.

Upvotes: 0

Views: 184

Answers (1)

ch4mp
ch4mp

Reputation: 12564

The setDomainNamePattern in your question won't make the session cookie "cross-site". As explained in Spring Session documentation from which the blogger you quote copied his conf, it sets the domain with a different value depending the app being deployed on a "real" domain or on localhost (or whatever you put in your host file). But that remains a single domain.

Also, you should be careful when raising the secure flag as this will require the app to be served with SSL (which you might not be doing on localhost).

Session cookies are flagged with SameSite for security reasons. The default value is Lax and the only other acceptable value for a session cookie is Strict. This means that browsers won't attach a session cookie to requests sent to another domain, and you can't change this behavior with CORS configuration, like you were doing before completely rewriting your question, or by trying to set the cookie domain like you are now trying.

With CORS config the server asks user agents (browsers) to allow cross-origin requests (REST requests to a different host or port than the one from which the HTML page originated), not to ignore the SameSite policy for cookies (which would be a major security issue).

You may have some cross-origin requests authorized with a SameSite=Lax session cookie, but only at the condition that the other origins share the same-site.

For more background about the difference between same-site and same-origin, see this excellent and synthetic Google article.

If your front and back ends origins do not satisfy same-site policy, you have no other choice than to use a proxy. That way, from the browser point of view, all requests will have the same-origin (the reverse proxy), and as a consequence, the same-site. This will remove the need for CORS configuration and Spring session cookie will be attached to your UI REST requests. And this even if session & CSRF cookies are explicitly configured with SameSite=Strict.

Upvotes: 0

Related Questions