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.
Related
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.
I wanna refactor a monolithic spring boot application basically a web app with login and functionalities for customers. We already have a Security implementation which works with a session id stored as a cookie but I dont have much knowledge about it at all and im completetly new to this topic. It seems JWT is a better solution for Microservices because of an independent authentication service.
So my questions are:
is it alot of work to create a JWT authentication service and exchange the session id implemenation? (since im doing it for my bachelor thesis and have a clear deadline)
can I stay at the session ids while using microservices?
are there maybe other ways to implement authentication?
is it alot of work to create a JWT authentication service and exchange
the session id implemenation? (since im doing it for my bachelor
thesis and have a clear deadline)
This question is hard to answer, as it depends how tightly coupled your particular implementation is. It's certainly not trivial.
can I stay at the session ids while using microservices?
Yes, but you need to figure out how to federate sessions across the microservices (i.e. how to get the information in the session from one service to the other). Overall, this represents a risk of tight coupling between services, so I'd recommend treating this as a transitionary step only.
are there maybe other ways to implement authentication?
As many as the day is long. That being said, without specific reason to do otherwise, I generally prefer to stick to the middle of the road.
Typical user sessions is not recommended in microservices.You should use Stateless architecture and tokens (Tokens stored in database or JWT).
It's better to use Spring Boot OAuth2.
You should implement an Authorization server and Resource servers with Spring Boot.
Authorization server:
Choose the token storage method (JWT,Jdbc,...)
Configure client details
Add a RESTful Api for user info or enable /oauth/check_token api.(Called by Resource servers)
Resource servers:
Set user-info-uri or token-info-uri in Spring boot OAuth2 properties.
Extends ResourceServerConfigurerAdapter class for securing url mappings.
I have application that I want to divide into micro-services to increase overall performance on high load. Overall structure I plan to create like this:
Web -> Authorization Server -> Eureka + Zulu -> Spring boot Micro-services
Since my previous application was monolith I used Spring boot + Spring security and had no problem while logging things like #CreatedBy #LastModifiedBy - I laso use Aspects to log every action in app and track who made the changes. Now since I don't have session across microservicies I don't know what to do - I do need to log the action owners - log who is doing what.
Can someone tell me how can I maintain the logging possibilities in my new structure. Maybe there is some ready made patters or maybe I need to make some changes in my structure?
How are you dealing with authorization? If the web component calls the authorization server with an authentication token, that token should be forwarded when calling microservices. Every microservice should be stateless (so, no session is ever stored), and that token should contain information about the user so each microservice can access it and authenticate requests.
If you could specify what you mean by Authorization Server, I'll be glad to explain in greater detail.
I have a single grails (3.3.5) web server, and I am interested in improving the availability and I'd like to add another server and put a load balancer in front of it.
Rather than share sessions between servers, or use sticky sessions, i'd like to know if there is a good way to have a session-less front-end server. I don't use sessions for anything other than using spring-security to validate the session token that it is using to identify the user.
I'd like to find a token based authentication system suitable for the front-end such that the token is safe and sufficient for identifying the current user.
I've seen the grails-spring-security-rest plugin which looks promising, but it seems like everyone is using it for back-end rest api calls. Is it also suitable for front-end authentication when you aren't storing application data in the webapp session?
If you don't use the session objects in your controller then tomcat will not create any sessions for you.
Also you can define your controllers to be
static singleton = true
then they will be instantiated not on per-request basis.
Now, if you still want to use sessions, you can use something like Cookie Sessions and keep your data inside the cookies instead of tomcat's memory.
I haven't used the grails-spring-security-rest, but you should be able to tweak spring-security-core to be session-less. You should set scr.allowSessionCreation to false and use remember-me.
Since Grails is built on Spring Boot, you can access all the features of Spring Session (https://docs.spring.io/spring-session/docs/2.0.x/reference/html5/), which includes the ability to share session data between server instances with some data store instead of keeping it in memory.
In those docs you'll find this pointer to a guide with a Grails 3.1 example that uses Redis as the store. https://github.com/spring-projects/spring-session/tree/2.0.3.RELEASE/samples/misc/grails3
Is it also suitable for front-end authentication when you aren't storing application data in the webapp session?
Yes, you can use JWT tokens in your front-end. You need to properly configure the security filters of your controllers so that they are not using cookie for authentication but they are looking for JWT.
See : http://alvarosanchez.github.io/grails-spring-security-rest/latest/docs/#_plugin_configuration for configuration of endpoints that should validate JWT tokens.
Have a look at https://github.com/hantsy/angularjs-grails-sample/wiki/3-basic-auth for a stateless example with Angular.
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.