Springboot 2.5+ with SAML2 Stateless - spring-boot

I've been attempting to setup springboot2.5+ with the new saml2login implementation, but I'm finding it very difficult (due to lack of documentation and old documentation from the spring-security-saml extension) to do it in a stateless manner.
Has anyone been able to get springboot saml2 working stateless? I can't seem to figure out how to get my ACS (Assertion Consumer Service) filter from spring security to return a custom cookie with a redirect instead of a jsessionid.
Any help or insight would be awesome. Right now, I have a hack-y work around where I'm leaving sessions on, but attempting to kill the session right after SSO via SecurityContextHolder.clearContext(), but this is causing other issues.

Related

Scaling Spring Authorization Server on GCP Cloud Run

We are experiencing an issue in production which seems identical to when we restart our dev boxes and try to authenticate using the token that was generated with the previous instance of our SSO Spring Boot App and powered by Spring Authorization Server.
The error is: Wrong nonce
In production, it looks to occur when our SSO app scales up due to a user spike. We could see this happening at a point with high user activity and we would continually get logged out.
Now, of course we do not want all our active users to suddenly have invalid tokens just because a new instances of SSO is added.
This questions also relates to the currently unanswered, but much older question here: Can Spring Security OAuth2 Authorization Server scale horizontally?
Please advise. It is the number 1 most frustrating issue we are having in production right now and we are not quite sure how to proceed. We are not using any In-Memory implementations of classes.
2022-07-12 - Update: The question was asked "How are we storing the session?"
We are storing OAuth2 authorizations, authorization consents and registered clients in MongoDb.
We implemented OAuth2AuthorizationService, OAuth2AuthorizationConsentService and RegisteredClientRepository
Spring Authorization Server is built on Spring Security (see docs Overview) and does require knowledge of Spring Security (see Getting Help).
In particular, you'll want to review the Authentication chapter of Spring Security documentation. Session management falls under this topic, and if you're using (for example) form login or something similar, you'll almost certainly want to add Spring Session to your server to manage distributed sessions.
You are also likely running into an issue on the client side if you are not managing sessions in a database, so once again looking into Spring Session for the client will help alleviate issues such as the nonce error you mentioned. You will also want to look into the OAuth2 Client documentation and review the core interfaces as you will need to be storing your client authorizations in a database as well.
Steve writes a great response above already and I marked it as the answer.
To answer the title of this question:
Yes, Spring Authorization Server can easily be scaled to include multiple instances without suffering from the original misconfiguration issue we were experiencing.
Spring Authorization Server does not have any magic tools to persist a session across instances. It is reliant on session management being configured correctly. We use Spring Session backed by MongoDb for our purpose.
Session validity best practices is probably something that should be addressed and whether some of them should have the same timeout values.
Servlet session timeout
Spring Session timeout (this overrides 1 when present)
Remember me timeout
Token timeout
We are still figuring out / playing with what these values should be and have found no document or article that speak of one best way of doing things.

Spring How to maintain logged in user without spring security

I'm building a simple project management web application and I'm having some problems finding the best practices for storing the current logged user without recurring to spring security.
I was thinking of creating a filter or maybe a interceptor to reduce code but I'm still struggling with how to actually store the user. Is it better to had a specific header to the request or is there a more elegant way to do this?
You can use spring session to maintain the login information in you app in a better way, there are various options available in spring to replace normal HttpSession like Spring Session JDBC.
See Here: https://spring.io/projects/spring-session

Spring Boot w/ KeyCloak and Redis session store

Can someone suggest how to configure a Spring Boot application to authenticate via KeyCloak, and then use Redis as the session store? I've spent a day googling and banging my head on this, and I just don't feel like I'm getting anywhere.
I know how to configure each one independently - i.e. I can make a boot app that auths via KeyCloak, and I can also make a boot app that keeps session in Redis, but I'm not getting them to work together. Is this possible? It seems like it should be. Or is this just not how its supposed to work?
I think my working POC would behave something like this:
start my app
access some resource that forces a login via KeyCloak - access to resource is granted
restart my app
access that same resource but now no login is needed (since session is persisted in Redis)
Thanks for any suggestions.
OK - turns out I'm just not paying attention. I was not using the access/bearer token correctly. There is no need to keep the Spring session around when the bearer token is properly provided in requests.

how to enable distributed session for spring saml project

I am using spring saml to provide authentication service to the user. But I have met an issue.
We need to deploy spring saml to kubenete for cluster management purpose. Unfortunately, spring saml is not using distributed session solution, instead of that, it requires the saml response to land at the same originating server. Spring saml said we need to use sticky session to let saml server send user back to the originating server.
But once we deploy into kubernete, this is very difficult to implement. Kubenete will send user to any pod randomly, also we do not want to use nginx plus for this purpose.
So I thought if we can use distributed session, this will resolve the whole problem. Can anyone tell me how I can use distributed session solution, such as redis, mongo etc with spring saml project?
Thanks
Using distributed HttpSessions, e.g. with Hazelcast and Spring Session will work as well as using sticky sessions.
This will be transparent for Spring SAML, as the replication will be provided automatiacally behind the scenes, so there's no need for changes there.

Container Managed Security, Spring Security and Authentication

I have been looking everywhere on how I can implement Spring Security based on a Container Managed Security Model. In my test case, I am using Tomcat and it's corresponding tomcat-users.xml file. The issue is, I cannot get Spring Security to play well (meaning pass authentication over to Tomcat) to let the app server perform the Authentication and have Spring manage the role based security once someone is authenticated. I am using the latest Spring versions, so it's all Java config as I am just not familiar enough with XML based config. I have read many examples that talk about using a PreAuthenticatedAuthenticationProvider but the examples are poor not to mention the Spring documentation is quite confusing IMHO. I even downloaded the sample preauth code from the Spring Security GIT hub but I still cannot see how the example code is tied to the authentication that Tomcat is performing. When I run the Spring sample code for preauth, it doesn't authenticate with any of the users in my tomcat-users XML file as I deployed my code to Tomcat 8. Wondering if anyone has any ideas on where I can look in order to understand how Spring Security and the authentication performed by Tomcat (container managed) happens?
UPDATE:
It appears I had to start from scratch and simply get the authentication to work with a very simply app created in my IDE. Basically I had a folder that was called secure, one folder that was called unsecure and I mapped the paths according to the Servlet 3 spec to secure and unsecure what I needed. I had to use a web.xml in order to contain the security constraints. Once I tested in both Tomcat 7 and 8, where I tried to hit a secure URL, I was challenged to enter an ID and password. Please note you have to define the path to a login page, mine was a simple JSP. I also had to submit to the j_security_check and also make sure to use the j_username and j_password field names. Once I knew I could hit a secure page, I then started introducing the Spring components. This involved Spring Security, Spring Boot etc. The key was in the WebSecurityConfigurerAdapter. Where I normally would have basic auth or form based security enabled, I removed those and instead used the jee() setting based on the same fluent builder API used to configure your security settings. I left all antmatcher settings in the web.xml, so my WebSecurityConfigurerAdapter was very basic. When you are debugging controllers, you can inject the HttpServletRequest directly in the method and that request contains a userPrincipal request value containing things such as the user ID, and roles. Good luck, hope this helps others because it was painfully long for me to figure out such a simple solution.
See the update for a detailed explanation on my solution.

Resources