JSESSIONID not expired, SPRING_SECURITY_REMEMBER_ME expired - java

So, I have in my application spring security and have introduced remember me functionality when the checkbox is checked in.
I wanted to know what is the exact behavior:
if I set </remember-me> tag and specify for the rememberMeServices tokenValiditySeconds to 20 seconds, shouldn't the session expire and and ask me to log in again?
Do I have to set:
<session-config>
<session-timeout>XX</session-timeout>
</session-config>
So it matches the SPRING_SECURITY_REMEMBER_ME cookie tokenValiditySeconds ?
UPDATE
Does it matter if I've implemented my own PersistentTokenBasedRememberMeServices?
I had to override the default PersistentTokenBasedRememberMeServices coming from spring, because the PersistentRememberMeToken did not have any no-arg constructor, thus unable to use hibernate for that, so what I did I just wrote my own PersistentRememberMeToken, PersistentTokenBasedRememberMeServices (which, by the way, do no have anything special beside me introducing the no-arg constructor in PersistentRememberMeToken, beside that, it's copy paste from spring's source)

Having a remember-me token which is valid for less than the session-timeout will have no effect on your authentication during that session, if that's what you are asking.
Once you are authenticated during a session, your authentication is valid for the duration of that session, unless you log out or the session expires.
The remember-me token is only considered if you are unauthenticated, otherwise it will be ignored.

Related

can we maintain more than one access token for one authentication object(credential) in jdbcTokenStore

I want to maintain more than one access tokens for same credentials of a user is it possible for us to override createAccessToken method of DefaultTokenServices to do that.
All I want is that when an access token for a user expires from one device ,it should not affect the access token of the same user logged in from other device(ie maintain as many access token for a user, as the number of logins of that user)
Can you elaborate bit more on what exactly you need to achieve? Irrespective of client you should be allowed to authenticate concurrently. Spring security allows maximumSessions property to allow multiple sessions
ex:
http
.sessionManagement()
.maximumSessions(2)
.maxSessionsPreventsLogin(true);
Extending DefaultTokenService is very much possible, please refer Spring Boot Oauth2 Extending DefaultTokenServices.

How does Spring Security handle JSESSIONID with various Session Creation and Session Fixation combinations?

I have a J2EE REST-based app using Spring Security 4.0.1.RELEASE. Needless to say, Spring documentation on sessionCreationPolicy and sessionFixation is sparse, aside from targeted questions here on StackOverflow.
I'm using a Java-based config for Spring Security like this:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(secureEnabled=true, prePostEnabled=true, jsr250Enabled=true, order=1)
public class DefaultSecurityBeansConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.sessionFixation().migrateSession()
.and()...; // additional config omitted for brevity
}
}
I'd really just like to know what behavior to expect from Spring, as it relates to JSESSIONID, given all possible combinations of sessionCreationPolicy and sessionFixation.
Possible values in the SessionCreationPolicy enum are ALWAYS, NEVER, IF_REQUIRED, and STATELESS.
Possible values for session fixation are newSession, migrateSession, changeSessionId, and none.
Thank you.
NOTE: What prompted this question is that I am not seeing a new JSESSIONID on every request when I have sessionCreationPolicy set to IF_REQUIRED and sessionFixation set to changeSessionId. A JSESSIONID is correctly created, but is maintained across requests thereafter. I generalized my question about all combinations to hopefully help others in a similar situation with slightly different settings.
It's important to keep in mind that Spring Security doesn't always have full control of the HttpSession. It can create one itself, but it can also be provided a Session object by the container.
For SessionCreationPolicy.IF_REQUIRED, the docs state:
Spring Security will only create an HttpSession if required
In your particular case, you're not seeing a new JSESSIONID for every request for at least 2 possible reasons:
With your current configuration, Spring has the option of creating a Session if it needs one.
SessionCreationPolicy.IF_REQUIRED also appears to allow Spring Security to use the Session it is provided with. Your container might be providing this object if this is the case, and so the session is maintained across multiple requests (as is expected if you're in a session).
If you wanto to disable #1, use SessionCreationPolicy.NEVER:
Spring Security will never create an HttpSession, but will use the HttpSession if it already exists
The only SessionCreationPolicy that will ensure that Spring Security uses NO SESSIONS is SessionCreationPolicy.STATELESS.
As regards SessionFixation, it only comes into play when you have multiple sessions for one user, after authentication. At this point, the SessionCreationPolicy is somewhat irrelevant.
SessionCreationPolicy: used to decide when (if ever) to create a new session
SessionFixation: once you have a session for a user, what to do with the session if the user logs in again
Hope this helps!

Access to sessionid from RealmBase object

Is it possible to access to session id from RealmBase.athenticate method? I need it from my custom realm class in order to store into a database additional info associated to the session and retrieve it during the following requests. I'm using Tomcat 8. Thank you!
No.
Authentication does not require the use of a session, so it's not baked into the API. Authentication is also supposed to be separated from session management, so again it's not baked-into the API.
You might still be able to do this, but it requires some trickery.
Write a Valve that uses a ThreadLocal containing a Request object.
Register the Valve before the AuthenticationValve in the valve chain.
In that Valve, stuff the user's request into the ThreadLocal, then call down the chain.
In your custom Realm, fetch the object from the ThreadLocal.
Always remember to remove the request from the ThreadLocal after the call chain comes back... even if an exception is thrown.

Allow only one session per user

We have a web-application developed using struts2, spring & hibernate.
The application needs a functionality that one user can login from only one browser.
Say if user x, is logged in on pc-1 browser ff, then he cannot be logged in from any other place.
I tried it by implemention session map and store the sessions in global map, but this fails when user logs off and tries to login again.
Even it fails critically if the user does not logs off and session time-outs, but the map is not cleared.
Any better idea to implement this functionality.
We do not want to obstruct the user to login but do not want users to exploit the application by allowing him to share the creditionals and allow multiple users with same login to happen.
Since you are already using Spring, I would recommend you to integrate your application with Spring Security.
Spring security lets you define maximum sessions allowed per user concurrently.
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
If set when user having valid session tries to login again it will inform user that maximum concurrent access is set to 1.
Read more at the reference documentation of Spring Security: v3.2.x, v4.2.x or v5.1.x.
If spring security is not an option for you then:
Use a SessionInterceptor which will check for session validity, if session is valid it will check if user is already logged in to the application (for this you will have to maintain session somewhere for eg database for every successful login), if valid login is found, redirect user again to login page with custom message, or logout already valid session and then redirect him to login again. If you logout earlier session it would mean any successive action in that browser session will have to deal with invalid session.
If case you are also using Servlet in your application then Interceptor wont work for you, in this case you should use a Filter and follow the same steps as detailed above for Interceptor.
The best solution is to log-off user from other session when he logs in in new session. It is often that user would not logoff when closing browser and restricting him from logging in other window would be the pitfall.
Automaticly closing any previous user sessions is good, because in normal usage, it is no problem, but when sharing login and password, no two persons can work simultanously with your application.
At the login give the user a generated ID/cookie (sessionid suffices) stored with the user data. If a user does a request to the server with an old ID/cookie, say that he logged in elsewhere.
The other way round, forbidding the new login attempt, has its drawbacks - as you've experienced.
Create a map.
At the time of logging check that user id is present into that map or not.
If its not exist then put user id into map, at the time of logout remove that user id.
To be honest I would revisit the reasons why you have to restrict a user to a single login. Whilst preventing them from logging in from two different browsers is easy enough - any of the suggestions provided would work - with the Spring Security option being the easiest to implement if you can - they all break down when your user opens a second tab in the same browser. That is considered to be part of the same session.
Maintain user stack in servlet context,as it will be one for web container.perform a check before user getting logged in, if user name found in servlet context redirect him to login page.
All you should do is add a field in database userprofile table saying: alreadyLogin.
If user logins, make it Y. If user logs out, make it N. Now every time when user tries to login from new location, check this value and prevent login if Value is Y.
As many said, you can have a Map<String, User> (static Map or better an attribute in ServletContext) of (sessionId, user) of active users.
When a user tries to login, first check the existence in theMap.values(), and if it is okay add it to theMap.
Instead of removing from theMap on logout, implement a javax.servlet.http.HttpSessionListener, and on sessionDestroyed method, remove the item from it (the parameter of the method gives you the sessionId). This way if a user closes the browser, after session timeout period, it will be removed automatically.
On logout, invalidate the session, so it will be destroyed, and again this listener get executed.
Don't forget adding the listener to your web.xml.

Spring Security Sequence Flow

Can anybody explain me how Spring Security works? The architecture and the main classes or interfaces, I want to have overview about this framework. How Spring security work from the authentication to access control, which classes or interfaces in each stage??? I saw in spring has some annotation like #Secured, how Spring process them and where Spring collects information to do security check?
Well first you should know that exists a spring security filter chain (describe later on here).
When the context is loaded the Authentication Manager populates the Security Context, and this context has all the information about the security policies to use, and how to use them.
When a request is received the flow is:
1) The security interceptor capture it to protect secured resources
2) Asks the Access Decision Manager what to do
3) Then this manager checks if the access should be granted or not (based on a voters principle (based on rules))
4) if so the filter calls the proceed method
5) if not a security exception is thrown
The spring security filter chain is:
1) SecurityContextPersistenceFilter
- if has session access is granted and request goes on
- if not it goes to 2)
2) Logout filter (do nothing if is not a logout request and proceed)
3) UsernameAndPasswordAuthenticationFilter
- extracts the username and the password from request params and passes it to the authenticationManager.authenticate(username, password)
4) The AuthenticationManager performs the authentication based on it policy (ex: Basic, Digest, RSA)
- If authenticated add information to response headers about session id to be remembered by SecurityContextPersistenceFilter as session
- If not a spring security exception is thrown
5) Proceed to ExceptionTranslationFilter if no exception thrown so far do nothing, on the request side does nothing, only performs when responding, the request is then passed to FilterSecurityInterceptor if the resource has no attributes does nothing (base configs)
6) Finally it accesses the secured resource and returns with the exact inverted order
I recomend you to open and check this classes one by one, break points in it, debug them, look ate the stack calls. This way you will understand the security flow.
Plus I encourage you to refer to the documentation if any doubt persists.
Hope I this helps you or someone else.
Cheers
I think that this is too broad for a SO question. I suggest that you read the Spring Security Manual (especially Chapters 5 and 7 which give a good overview of how it all fits together), and come back if you have more specific questions. (And ask them one at a time ...)

Categories

Resources