I'm seeing some strange behaviour when using stateless token-based authentication on a rest API written using Spring Boot.
The client includes a JWT token with each request, and a custom filter I've written that extends GenericFilterBean adds an Authentication object based on the claims in the token to the security context using the following :
SecurityContextHolder.getContext().setAuthentication(authentication);
And clears the context after processing the request by doing :
SecurityContextHolder.getContext().setAuthentication(null);
However when the simple app I've developed performs a range of operations, I sometimes see that the security context isn't being set correctly - sometimes it's null for a request that has supplied a token. The filter is being called correctly, setAuthencation() is also being called, but the request fails authentication, and throws a 403 denied.
If I explicitly turn off any http Session management by setting the session creation policy to STATELESS, this behaviour stops.
Any ideas what could be happening here? Is the security context being shared between threads dealing with requests in some way?
The SecurityContext is used to store the details of the currently authenticated user, also known as a principle. So, if you have to get the username or any other user details, you need to get this SecurityContext first. The SecurityContextHolder is a helper class, which provides access to the security context.
The short answer: At its core, Spring Security is really just a bunch of servlet filters that help you add authentication and authorization to your web application. It also integrates well with frameworks like Spring Web MVC (or Spring Boot), as well as with standards like OAuth2 or SAML.
Interface SecurityContext The security context is stored in a SecurityContextHolder .
The BCryptPasswordEncoder implementation uses the widely supported bcrypt algorithm to hash the passwords.
It seems that the context can be shared, according the official documentation here : http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html
In an application which receives concurrent requests in a single session, the same SecurityContext instance will be shared between threads. Even though a ThreadLocal is being used, it is the same instance that is retrieved from the HttpSession for each thread. This has implications if you wish to temporarily change the context under which a thread is running. If you just use SecurityContextHolder.getContext(), and call setAuthentication(anAuthentication) on the returned context object, then the Authentication object will change in all concurrent threads which share the same SecurityContext instance. You can customize the behaviour of SecurityContextPersistenceFilter to create a completely new SecurityContext for each request, preventing changes in one thread from affecting another. Alternatively you can create a new instance just at the point where you temporarily change the context. The method SecurityContextHolder.createEmptyContext() always returns a new context instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With