How does spring security maintain authentication info between requests?
Does it use any thing similar to jSessionId or uses an entirely different mechanism.
Further, I see that the AbstractSecurityInterceptor (I mean, any of it's implementations) is responsible for intercepting the incoming request and verify if a request is already authorized using Authentication.isAuthenticated() and then depending on the condition either validate the request or send the Authentication request to an AuthenticationManager Implementation. So, in other words, how does AbstractSecurityInterceptor differentiate between first request and subsequent request.
Spring Security uses a SecurityContextRepository to store and retrieve the SecurityContext for the current security session.
The default implementation is the HttpSessionSecurityContextRepository which utilizes the javax.servlet.http.HttpSession to store/retrieve the SecurityContext.
The underlying servlet container will obtain the correct HttpSession for the incoming request, generally due to a session identifier being passed in a cookie or request parameter. For Spring Security it doesn't matter as that is thus loaded of to the underlying servlet container.
Related
We are running an API on Sping Boot 2.2 and are consequently using Sping Security 5.2. In securing this API with OAuth, we are using the new features built into Spring Security (since the Spring Security OAuth project is now deprecated). We are using opaque tokens and (as indicated by the documentation) have a security config of the following form:
#Configuration
public static class OAuthWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().mvcMatchers("/path/to/api/**").hasAuthority(CUSTOM_SCOPE)
.oauth2ResourceServer().opaqueToken().introspector(opaqueTokenIntrospector());
}
}
Here opaqueTokenIntrospector() is a bean which performs the following tasks:
Send a request to the introspection endpoint to get the full token.
Also send a request to the userinfo endpoint to get additional info about the user from the IDP.
Map some of this additional info into custom spring roles and add these roles to the authenticated user.
The way this configuration is set up, each request to the API comes with two additional requests: one to the introspection endpoint and one to the userinfo endpoint. It would be better to save on some of these if a user performs successive requests to the API.
Is it possible to save the result of the opaqueTokenIntrospector() in the session of the user? This way the whole flow of the bean need only be done once per user, saving on redundant requests.
This is a common requirement when you get beyond basic APIs. Use a claims caching solution, which is an API gateway pattern:
When a token is first received do the lookups and save them into an object:
Token claims
User info claims
App specific claims
Then cache the results against the token, so that subsequent requests with the same token are fast:
Use a thread safe cache - my preference is to use an in memory one
Use the SHA256 hash of the access token as the key
Use the serialized claims as the value
This probably goes beyond Spring's default behaviour, but you can customise it.
I have a Java sample that does this - here are a couple of links, though my sample is quite a complex one:
Custom Authorizer Class
Caching Class
Java Write Up
Basic Spring Security is great as it comes with WebSecurity (preventing malformed URLs) along with setting up authentication and authorization.
As part of authenticating my web request, the digest of the request body needs to be verified against the digest value passed in the http header. Setting up the Spring Security filter, forces my auth filter to process a firewalled request. The firewalled request doesn't seem to expose the request body to the filter.
What is the correct way to set up the Spring Security filter so that I can inspect the request body?
Thanks!
In Spring Security there are many filter classes built in for to be extended and used for specific purposes. As in my experience most of (or all of them) have methods with overloads which have access to,
HttpServletRequest request, HttpServletResponse response
as method arguments, so that those can be used inside the method.
When the filter class is met with any request, these variables are then populated with related data thus the code inside the methods output as expected.
I am not able to find out where and when exactly the authentication manager is executed by spring security. I mean there are certian filters which are executed sequentially as below:
FIRST
- CHANNEL_FILTER
- CONCURRENT_SESSION_FILTER
- SECURITY_CONTEXT_FILTER
- LOGOUT_FILTER
- X509_FILTER
- PRE_AUTH_FILTER
- CAS_FILTER
- FORM_LOGIN_FILTER
- OPENID_FILTER
- BASIC_AUTH_FILTER
- SERVLET_API_SUPPORT_FILTER
- REMEMBER_ME_FILTER
- ANONYMOUS_FILTER
- EXCEPTION_TRANSLATION_FILTER
- SESSION_MANAGEMENT_FILTER
- FILTER_SECURITY_INTERCEPTOR
- SWITCH_USER_FILTER
- LAST
But when exactly authentication provider authenticates the provided username and password, i mean to ask after which these below filters is the authentication provider is executed .
Regards
Jayendra
From Spring Security documentation:
The order that filters are defined in the chain is very important.
Irrespective of which filters you are actually using, the order should
be as follows:
ChannelProcessingFilter, because it might need to redirect to a different protocol
SecurityContextPersistenceFilter, so a SecurityContext can be set up in the SecurityContextHolder at the beginning of a web request, and
any changes to the SecurityContext can be copied to the HttpSession
when the web request ends (ready for use with the next web request)
ConcurrentSessionFilter, because it uses the SecurityContextHolder functionality but needs to update the SessionRegistry to reflect
ongoing requests from the principal
Authentication processing mechanisms - UsernamePasswordAuthenticationFilter, CasAuthenticationFilter,
BasicAuthenticationFilter etc - so that the SecurityContextHolder can
be modified to contain a valid Authentication request token
The SecurityContextHolderAwareRequestFilter, if you are using it to install a Spring Security aware HttpServletRequestWrapper into your
servlet container
RememberMeAuthenticationFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder,
and the request presents a cookie that enables remember-me services to
take place, a suitable remembered Authentication object will be put
there
AnonymousAuthenticationFilter, so that if no earlier authentication processing mechanism updated the SecurityContextHolder,
an anonymous Authentication object will be put there
ExceptionTranslationFilter, to catch any Spring Security exceptions so that either an HTTP error response can be returned or an
appropriate AuthenticationEntryPoint can be launched
FilterSecurityInterceptor, to protect web URIs and raise exceptions when access is denied
So the authentication manager is called at step 4. If you look at the source code of UsernamePasswordAuthenticationFilter you will see something like:
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
// ...
return this.getAuthenticationManager().authenticate(authRequest);
}
I get the currently logged in user by
SecurityContextHolder.getContext().getAuthentication() in server side and do some logging on users.
Here is the question:
Suppose I have three user logged in.
How the server side can identify the user just simply calling SecurityContextHolder.getContext().getAuthentication(); ?
Thanks for your reply.
By default there are 3 important things here:
HTTP session - stores authentication object between requests
Servlet API filter - populates SecurityContextHolder before each request from HTTP session (and stores authentication object back once the request has completed)
ThreadLocal - stores authentication object during request processing
After authentication corresponding SecurityContext object is stored in HTTP session.
Before each request processing special SecurityContextPersistenceFilter is fired. It is responsible for loading of SecurityContext object from HTTP session (via SecurityContextRepository instance) and for injecting SecurityContext object into SecurityContextHolder. Take a look at the source code of SecurityContextPersistenceFilter class for more details. Another important part is that by default SecurityContextHolder stores SecurityContext object using ThreadLocal variable (so you will have a different authentication object per thread).
EDIT. Additional questions:
HTTP session is saved in client's browser and updated between requests. No, HTTP session is stored in server side. It is linked to some user via session coockie (browser send this cookie during each request).
SecurityContext, SecurityContextHolder and SecurityContextRepository are instances in Server side. They are used on server side. But SecurityContextHolder is not an instance, it is a helper class with static methods.
ThreadLocal is a variable storing SecurityContextHolder which stores SecurityContext No, SecurityContext is stored in ThreadLocal variable. SecurityContextHolder is a helper class that may be used to get/set SecurityContext instance via ThreadLocal variable.
If there are three connections, then there will be three SecurityContext object in Server. Yep.
One SecurityContextHolder stores one SecurityContext No, the same static methods of SecurityContextHolder used by all threads to get/set corresponding SecurityContext.
And suppose there are three SecurityContext instances in Server Side, how does it knows which one refers to that corresponding client? ThreadLocal variable has different values for different threads.
For every logged-in user, there will be different sessions. Every session have its own configuration. Therefore, at server side, SecurityContext load data specific to a session. You can visualise data in SecurityContext as a map(key-value) pair.
1) How can i add a custom field in my login form and use that value to navigate to a different page after login. I need a custom authentication provider for authenticating. Can we use spring mvc to tie all this?
2) How can we get hold of HttpSession in auth provider?
1) I guess, you can choose the default behavior by implementing your own AuthenticationSuccessHandler and passing it to <form-login authentication-success-handler-ref="..."/>
2) This is actually not in the vein of the separation of concerns paradigm in Spring Security where the authentication provider populates the Authentication object and another filter persists/populate the authentication in/from the HTTP session. Nevertheless, you can in general have access to the current HTTP request and, therefore a session, from anywhere inside the request processing chain by adding the filter org.springframework.web.context.request.RequestContextListener to your web.xml. Use then ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession() to reach the session from your authentication provider.