Spring 6: Problem Storing Session Attributes and invalidate Session - spring

While migrating to spring 6 and spring boot 3, we have two problems:
The session attributes are not stored in the database anymore
The session is not invalidated correctly on logoff.
In Spring 5 we have a persistent session (session.store-type: jdbc). When we create a session on successful login with getSession(true) and store the corresponding username, it is saved to the database.
In spring_session we find one entry
In spring_session_attributes we find an entry for the stored attribute a one for the SPRING_SECURITY_CONTEXT.
The request returns with a cookie and the browser uses this cookie for the next request.
When we invalidate the session, all content is removed from the database and the request returns an empty cookie so that the cookie is also cleared in the browser.
This behavior is absolutely correct.
In Spring 6 however the behavior is different.
If we use http.securityContext { ctx -> ctx.requireExplicitSave(false) } in our configuration, the session is stored in the DB but we only see the SPRING_SECURITY_CONTEXT attribute and not our username attribute.
When we invalidate the session, it is not removed from the database, the browser’s cookie is not cleared and the session is still valid.
If we use http.securityContext { ctx -> ctx.requireExplicitSave(true) } all session attributes are stored and the persistent session is removed on logoff. However, if we have multiple requests at the same time, we see these errors in the log file:
ERROR: duplicate key value violates unique constraint "pk_spring_session_attributes"
Detail: Key (session_primary_id, attribute_name)=(bc7114b1-3149-4c7b-8c23-b1023f51a8b9, SPRING_SECURITY_CONTEXT) already exists.
These requests fail with http status 500.
We have found this documentation about changed in session handling (https://docs.spring.io/spring-security/reference/migration/servlet/session-management.html) but it does not apply. We do not change the security context. We just use it to set the authentication-Property.
We tried saving the context, but it didn't solve the problem – specially not the problem with the duplicate keys.
What are we missing?
Are there more changed to spring-session-jdbc that we’ve overlooked?

Related

when a request session is generated in weblogic how session id is determined

When a session is invalidated in a web app, if i make to that app a new request with the invalidated jsessionid in cookie, what will be the new session's id? As i inspect, a new session is generated but the session id remains same. I couldn't give a explanation to this. Is there such a convention to keep jsessionid in cookie and give that value to newly created session or am i doing something wrong? :)
The Scenario.
I have 2 webapps on same weblogic. The WLCookie name for these apps are same.
When user enters in appA i am making a asynchronous call to appB's logout servlet where the appB's session is invalidated.
when user clicks a link in appA which refers to appB, i am creating a new session in appB and when i check for the sessionid in cookie it still remains same which is first created in appA.
As i know, two webapps on same weblogic does not share their session's if not configured but although i invalidated appB's session from outside why newly created session has still the same session id?
Thanks.
Do not confuse jsessionid with sessions. jsessionid is unique per container instance, where as session is per app. So, the session data won't propagate from AppA to AppB, just because the share the same jsessionid.

how do i change the default behavior of session storing in the database

I enabled to store session data in the database and on every page refresh a new record gets inserted and ends up filling the session table with many rows. How can i just set it to insert a record only if no entry exists for its ip and update an existing ip?
Sessions have a timeout which you can set in the config.php file (i.e $config['sess_expiration'] = 7200 ). Once that time has reached, they expire and are deleted (through the session garbage collection mechanism).
. How can i just set it to insert a record only if no entry exists for its ip
It dosent create a new session record for each update, it simply adds/remove data from the existing session record for the given IP and user agent if the option is selected (unless the session has expired in which case it creates a new record). Codeigniter has a builtin garbage collection mechanism which will eventually (if not instantly) delete the expired session.
and update an existing ip?
Why would it update an existing ip and override its session data? that makes no sense. You could end up overwriting session data of a user who is currently using the session. If a user has stopped using the system, the session will evnetually expire and be deleted.
According to codeigniter session class page:
When a page is loaded, the session class will check to see if valid
session data exists in the user's session cookie. If sessions data
does not exist (or if it has expired) a new session will be created
and saved in the cookie. If a session does exist, its information will
be updated and the cookie will be updated. With each update, the
session_id will be regenerated.

How to do custom action before session invalidation (time-out)?

I want to store some information of current session's user when a session is getting invalidated (because of time out). How can I do that?
If this helps, I'm using Spring Security 3.1. So if there is any configuration in Spring I'm having no trouble understanding that.
There is a thing in Spring Security as Session Expiration. When a session expires, a filter catches it and I can have my desired information from it.
However the problem is when a session gets invalidated (because of timeout). Because, for the next request there will be a new session created and I'm not able to have access to the old one. I want to know how I can customize session invalidation ?

symfony 1.4 session without using cookies

I have a Symfony application which use a mysql database to store session data, and uses the SfGuard plugin to manage the authentication.
Despite that symfony allways save the authentication info in a cookie. Is there anyway i can disable cookies and store the authentication info in the database or in memory?
I might need in the future, to have a kind of single sign on feature, where the authentication state will persist between multiple applications, in different domains. Thats why I mostly want to eliminate the need to use cookies.
Thank you for your help.
You do not seem to understand how sessions work.
That cookie that gets sent to the cient is called the session id, and it's unique to the visitor. When he reqests a page from the server that cookie identifies the row in your session table where his data are - no data besides the ID is ever sent to the client.
Without that ID there's no way to pair a request to session data, that's why you could not log in anymore after disabling the cookies. The alternative to the cookie is to pass the session id some other way, like in the url - php can do that automatically, you just need to enable use_trans_sid in the php.ini.
Yes, you can store the authentication info in the database : See here how.

Can i regenerate my own session id in servlet? [duplicate]

Whenever you authenticate, your application should change the session identifier it uses. This helps to prevent someone from setting up a session, copying the session identifier, and then tricking a user into using the session. Because the attacker already knows the session identifier, they can use it to access the session after the user logs in, giving them full access. This attack has been called "session fixation" among other things. How can i change the session id once the user login to the system ?
You're still on the server while you invalidate the session.
//get stuff out of session you want before invalidating it.
currentSession = request.getSession(true);
UserProfile userProfile = (UserProfile) currentSession.getAttribute("userProfile");
//now invalidate it
currentSession.invalidate();
//get new session and stuff the data back in
HttpSession newSession = request.getSession(true);
newSession.setAttribute("userProfile", userProfile);
Get the existing; invalidate it; create a new one ...
1) Get the current Session with HttpServletRequest.getSession();
2) Clear the Session: HttpSession.invalidate();
3) Create a new one: HttpServletRequest.getSession(true);
Talking generally (because this isn't a Java problem at all, it's a general web problem) session fixation arises when session IDs are easy to discover or guess. The main method of attack is when the session ID is in the URL of a page, for example http://example.com/index?sessionId=123. An attacker could setup capture a session and then embed the link in their page, tricking a user into visiting it and becoming part of their session. Then when the user authenticates the session is authenticated. The mitigation for this is to not use URL based session IDs, but instead use cookies
Some web applications will use a cookie session based but set it from the initial URL, for example visiting http://example.com/index?sessionId=123 would see the session id in the url and then create a session cookie from it, setting the id in the session cookie to 123. The mitigation for this is to generate random session ids on the server without using any user input as a seed into the generator.
There's also browser based exploits where a poorly coded browser will accept cookie creation for domains which are not the originating domain, but there's not much you can do about that. And Cross Site Scripting attacks where you can send a script command into the attacked site to set the session cookie, which can be mitigated by setting the session cookie to be HTTP_ONLY (although Safari does not honour this flag)
For Java the general recommendation is
session.invalidate();
session=request.getSession(true);
However at one point on JBoss this didn't work - so you need to check this works as expected within your chosen framework.
Invalidate the current session and the get a new session:
//invalidate the current session
request.getSession().invalidate();
/*
get another session and get the ID (getSession()) will create a session if one does not exist
*/
request.getSession().getId();

Resources