Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clear cookies for old SESSION_COOKIE_DOMAIN in Django

We recently changed our cookie domain (settings.SESSION_COOKIE_DOMAIN) from domain.com to .domain.com and this is now preventing Safari users from logging in unless they clear their cookies. The problem seeds to the fact that there's sessionid cookies set for both domains.

Is there a way to clear or ignore the original domain or is the only way to advice users to clear cookies?

like image 312
jorilallo Avatar asked Mar 25 '13 21:03

jorilallo


People also ask

How to clear session in Django?

To delete a session or any particular key of that session, we can use del. The output will look like this and don't worry if your cookie didn't delete because we use this method only to delete your data in the Django database and not the session ID and cookie itself.

How do you delete cookies in Python?

delete_cookie method is used to delete a cookie with a specified value.

Where does Django store session data?

Django uses a cookie containing a special session id to identify each browser and its associated session with the site. The actual session data is stored in the site database by default (this is more secure than storing the data in a cookie, where they are more vulnerable to malicious users).

How to handle sessions in Django?

If you want to use a database-backed session, you need to add 'django. contrib. sessions' to your INSTALLED_APPS setting. Once you have configured your installation, run manage.py migrate to install the single database table that stores session data.


1 Answers

This can occur when the SESSION_COOKIE_DOMAIN setting is modified. (You stated that SESSION_COOKE_PATH was changed).

The documentation for SESSION_COOKIE_DOMAIN comes with this warning:

SESSION_COOKIE_DOMAIN

Be cautious when updating this setting on a production site. If you update this setting to enable cross-domain cookies on a site that previously used standard domain cookies, existing user cookies will be set to the old domain. This may result in them being unable to log in as long as these cookies persist.

This would occur if you went from:

SESSION_COOKIE_DOMAIN = None

to

SESSION_COOKIE_DOMAIN = '.domain.com'

As you've stated, there are now two cookies on the client end which will be sent to the server during a request, with both cookies named sessionid. When Django looks at the cookies, it only has access to a Python dictionary, so it only every sees one sessionid cookie rather than both that were sent.

I haven't tested this, but some ideas for fixing the problem may be:

  • Ask the user to delete the appropriate cookies. Depending on the number of users and their skill level, this may not be an reasonable option. Asking them to delete ALL their cookies may be out of the question.

  • Wait for the old cookies to expire. By default, it appears as though the sessionid cookie has a 14 day expiry. Once the old session cookies expire, they will no longer be sent with each request, allowing the new sessionid cookie to take effect.

  • Change the name of the sessionid cookie and write a custom Django middleware to handle both old and new sessionid cookies.

I haven't tested the last point, but it should be possible to change the SESSION_COOKIE_NAME to something other than sessionid. Now, this will prevent existing logged in users from using their existing sessionid cookies, so you'd need to write a custom middleware which was capable of handling both sessionid cookies (for old cookies) and sessionidnew cookies for current logons.

Something like this will work:

from django.utils.importlib import import_module
from django.contrib.sessions import middleware
from django.conf import settings

class MySessionMiddleware(middleware.SessionMiddleware):
    def process_request(self, request):
        engine = import_module(settings.SESSION_ENGINE)
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
        if session_key is None:
            # Look for old cookie in request for auth purposes.
            session_key = request.COOKIES.get('sessionid', None)
        request.session = engine.SessionStore(session_key)

You'd have to replace the SessionMiddleware in settings.py under MIDDLEWARE_CLASSES with this new middleware. Eg: Change 'django.contrib.sessions.middleware.SessionMiddleware' to 'custommiddleware.MySessionMiddleware' where custommiddleware.py is the file with above code and is present in your project root folder (where manage.py file is present)

Once enough time has passed and you're satisfied that all of the old sessionid cookies have expired, you could do the reverse and change back to using sessionid as the preferred cookie name for sessions, eventually removing the specialist code which can handle two different types of sessionid cookie.

like image 174
Austin Phillips Avatar answered Sep 20 '22 19:09

Austin Phillips