Loss of session data after log in
Amable-Valdes opened this issue · comments
Hello everyone!
I'm afraid I have a problem that I'm not able to solve. You will see: I have a development in which I save data in the user's session before log in through SAML. Once I log in on the IdP successfuly, the session changes and I lose my important old data :(
I've made a sketch to show you what I want to achieve:
Before log in I have a sessionid with the value "kvdtu6ctgiau6oz8ru7qayokny733iag" (this session would have my data X, Y and Z). After successfully log in, I have a sessionid with the value "v5lkheyoqvfsxkclmt54g4pqyh2wwzoq", a session which the user's information from the IdP, but having lost all the data that was there before...
I have tested it with django 2.2.24 (project requisites...) and djangosaml2 v0.19, v0.40 and v1.0.0, all with the same result: the lost of the session old data.
Is this a feature? Do you know how I could keep my information safe and recover it after log in? Could I solve this with a djangosaml2 configuration?
We have a specialized cookie (samesite resistant) here
https://github.com/IdentityPython/djangosaml2/blob/master/djangosaml2/middleware.py
as we can read it, we use this cookie
https://github.com/IdentityPython/djangosaml2/blob/master/djangosaml2/views.py
here we authenticate the user after a succesfull saml2 authentication
https://github.com/IdentityPython/djangosaml2/blob/master/djangosaml2/views.py#L553
from that line to the like 577 you can inspect with a debugger what's wrong with your setup
let us know
One possible problem could be that SESSION_COOKIE_SECURE
is not set to True by default in django. As djangosaml2 reuses this variable, by default the cookie will be sent with SameSite=None and Secure=False, leading to denial by recent browsers (you can check this in the Network-Tab of a Inspector for the ACS-Response).
I'd suggest a warning to be issued iff SESSION_COOKIE_SECURE
is not set to True
This aspect is covered in the docs, here
https://github.com/IdentityPython/djangosaml2/blob/master/docs/source/contents/setup.rst#samesite-cookie
However I believe that your proposal is interesting, would you like to push a contribution and enable the warning message if the cookie is not secured?
I'm sorry to be late. 3 interesting weeks jejeje
Sadly, i couldn't debug the problem because the software i'm implementing is encapsulated on docker and i can't run it on local. I could attach to the process and debug it that way, but i tried other solution (that i will explain later) and it worked for now so was not needed.
First of all, I checked the code (djangosaml2/middleware.py) and everything seems fine. I didn't really find the problem this way. I thought maybe it was because I'm using an older version of djangosaml2, but I checked the same middleware in v1.0 and it seems the same...
I tried different settings: SESSION_COOKIE_SECURE was True and I had my own SAML_SESSION_COOKIE_NAME as the documentation explains, but it keeps losing data after the login.
In the end I decided to be creative; with the middleware code and some documentation from the internet (https://stackoverflow.com/questions/3862888/different-sessions-for-admin-and-applications-in-django) I created my own cookie where I save all the data I wanted to preserve after the login:
class CustomMiddleware(SessionMiddleware):
def process_request(self, request):
engine = import_module(settings.SESSION_ENGINE)
session_key = request.COOKIES.get("my_custom_session_id", None)
request.my_custom_session = engine.SessionStore(session_key)
def process_response(self, request, response):
try:
accessed = request.my_custom_session.accessed
modified = request.my_custom_session.modified
except AttributeError:
pass
else:
if accessed:
patch_vary_headers(response, ('Cookie',))
if modified or settings.SESSION_SAVE_EVERY_REQUEST:
if request.my_custom_session.get_expire_at_browser_close():
max_age = None
expires = None
else:
max_age = request.my_custom_session.get_expiry_age()
expires_time = time.time() + max_age
expires = cookie_date(expires_time)
if response.status_code != 500:
request.my_custom_session.save()
response.set_cookie("my_custom_session_id",
request.my_custom_session.session_key, max_age=max_age,
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
path=settings.SESSION_COOKIE_PATH,
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None)
return response
That way, it worked for me; the sessionid of my_custom_session is not deleted and there are two cookies on the app: my_custom_session (where I can access all the data before and after the login) and the cookie defined in SAML_SESSION_COOKIE_NAME (where I have the login details of the user) .
If someone reading me has this problem, I solved it this way, but this is like killing a fly with a sledgehammer... Give me some time and I'll try in my spare time to replicate this problem in a simpler project to debug it, share it and find a better solution. I'm also sorry that I can't share the code for this project because it's a company software code and I can't share it.