Package: django-cookieless
Django CookielessEd Crewe - Oct 2019OverviewThis package provides a sessions implementation and decorator class for views to
allow for forms to maintain state without using cookies by posting the session
id between forms, or via urls.Django requires cookies to maintain session, and hence for authorisation.This package is designed to cater for anonymous user session maintenance, without cookies.WARNING : There are security issues with this, since it is not possible to use
CSRF protection without session Cookies to maintain a separate token from that passed via the URL or form posts.However there are cases when forms are used on a public site, where setting cookies is not desirable (due to privacy legislation), since technically they are not required for anonymous users to respond to forms.
So if used, may necessitate requesting permission to set cookies, from the user.Hence this package was devised to allow django to deliver multipage forms, without using cookies.To ameliorate the security implications, a whitelist of allowed domains, can be set in the configuration.Usage can also be restricted to a particular URL.As another safety measure, handling of GET requests can be turned off, so that the encrypted session id is not present in any URLs.Please NOTE: It is not advisable to use this package without some form of the above restrictions being in place.For the purposes of using both cookie based and cookieless sessions together, there is a
custom cookieless_signal(sender=request, created) and a ‘no_cookies’ flag when cookieless sessions are saved.Both cater for hooking up custom code for handling these less secure sessions.The package provides a decorator utility to turn off cookie setting for particular views (which also sets the csrf_exempt flag).The package also handles the case of session handling for anonymous users with cookies disabled in the browser.You can decorate views to prevent them setting cookies, whilst still retaining the use of Sessions.
Usually this is easiest done in the urls.py of your core application …from cookieless.decorators import no_cookies>>> urlpatterns = [
...    path('somewhere/index', no_cookies(views.home)),
...    re_path(r'^somewhere/page/(\d{1,6})$', no_cookies(views.page)),
...]Note that if a number of browser tabs are open on to a site with cookieless, they will each maintain a completely separate session, since
without cookies the session is tied to the session posted from the pages accessed, not the client as a whole.In cases where this is not the desired behaviour, then it can be reduced by using URL rewriting to make any links to open other windows pass session across.
However of course this also means that potentially a session can be shared across browsers, too.InstallationTo install add the package via pip or other build tool, e.g. bin/pip install django-cookielessThen replace the standard Session in the middleware settings:>>> MIDDLEWARE = (
...    'django.middleware.gzip.GZipMiddleware',
...    'django.middleware.common.CommonMiddleware',
...    'django.middleware.transaction.TransactionMiddleware',
...    # 'django.contrib.sessions.middleware.SessionMiddleware',
...    'cookieless.middleware.CookielessSessionMiddleware',
...)The following settings control its behaviour:(see the example settings file)Rewriting the response automatically rather than use manual <% session_token %> <% session_url %>COOKIELESS[‘REWRITE’] = TrueRewrite URLs to add session id for no_cookies decorated views (if False then all page navigation must be via form posts)COOKIELESS[‘USE_GET’] = TrueUse client ip and user agent to encrypt session key, to add some sort of CSRF protection given the standard CSRF has to be disabled without cookies.COOKIELESS[‘CLIENT_ID’] = TrueIf this list is populated then only hosts that are specifically whitelisted are allowed to post to the server. So any domains that the site is served over should be added to the list. However, if no referer is found, the session is reset, which will occur with a page reload. This helps protect against XSS attacks.COOKIELESS[‘HOSTS’] = [‘localhost’, ]Further security option to not find and persist cookie based sessions as cookieless ones since these may be tied to a user or other data. Instead new sessions are created for tying to cookieless data. This reduces the risk of cookieless allowing capture of a user’s session - and hence privilege escalation attacks.COOKIELESS[‘NO_COOKIE_PERSIST’] = TrueFurther security option to only keep a session for accessing a specific URLCOOKIELESS[‘URL_SPECIFIC’] = TrueDelete any cookies that are found for a no_cookies decorated URL (could be ones set by other URLs)COOKIELESS[‘DELETE_COOKIES’] = FalseTestsThe test suite sets up a simple application to test cookies manually, and to run the functional tests against.To run the tests, you may want to install from src (or your branch):bin/pip install -e git+https://github.com/edcrewe/django-cookieless#egg=django-cookielessThen run via:bin/django-admin.py or manage.py test cookieless.tests –settings=cookieless.tests.settings(The package was changed from a namespace package due to the issue with pip
not installing the __init__ for running tests when it does a nspkg.pth file instead)cookieless/decorator.pyBecause the django test browser has some session implementation specific mocking,
it fails to work if used directly against cookieless, so to stop it breaking other tests
cookieless checks to see if the django admin command has been called with the ‘test’ argument and sets settings.TESTING = True, and doesnt decorate with no_cookies if so.To override this automatic disabling setting, just add TESTING = False, to your test settings.Changelog1.2 - 26th Oct 2019Fix breach mitigation test for Python 3 [Ed Crewe]Fix test settings to correct path  [jonespm]Fix content-length and decode  [C.Severance]1.1 - 1st May 2019Rewrite for Python 3 and Django 2.2Remove xteacrypt and use cryptography[Ed Crewe]1.0 - 24th February 2014Test with latest Django 1.6.2Enforce session keys as strings if the session fails to save
Due to the move of the session serializer to JSON in Django 1.6[Ed Crewe]0.9 - 18th August 2013Add protection against breach attack via nonce encryptionhttp://breachattack.com/Added related test[Chris Bailey]Remove line return at end of session id introduced by base64 encoding[Ed Crewe]0.8 - 4th January 2013Clean up some pylintSwitch to base64 encoding to shorten encrypted session ids0.7 - 18th December 2012Add a cookieless_signal to allow custom code to be hooked to cookieless sessionsPass a created flag for cookieless sessions to the signalAdd a no_cookies marker key to cookieless sessions for the same reasonCheck automatic form rewrites to ensure that sessions are not already set manuallyFix tests check of hidden session_id broken by extra space in hidden fieldAdd post method for test class view so test posts don’t throw HttpResponseNotAllowedMake the secret generated by settings options more unique0.6 - 21st November 2012Never use the cookie for session for decorated views since it may break sessions passed by
cookieless means0.5 - 14th November 2012Only rewrite redirect URLs if USE_GET is True and its the same domain0.4 - 9th November 2012Fix issue of not having no_cookies to test in process_request by getting it from urlresolvers
Now we only check for cookie session where we should, and cookies cannot mess with cookieless sessionsMake the deletion of any cookies that are passed on to the URL, an optional featureUse settings.TESTING based on argv to disable, instead of check for servername0.3 - 7th November 2012Turn off cookieless for django test browser - since its hard coded to use
dummy sessions if an alternative session provider is in use -
otherwise cookieless could break other packages testsAdd server name switch to re-enable test browser for cookieless functional testsChange anon user switch to be NO_COOKIE_PERSIST - ie. never use cookie originated sessions - move to process_responseMake session use cookieless post / get first over cookies, if presentDelete request cookies if found in responseRefactor settings to a dictionaryAdd some testsMove fix for non-unicode key to the decrypt method[Ed Crewe]0.2 - 6th November 2012Add COOKIELESS_ANON_ONLY setting to not use cookieless if a user is authorisedUpdate example settingsAdd test suiteDon’t assume request META keys exist so OK with test client etc.Fix session decrypt with wrong secret - generates non-unicode key bug
rather than new sessionAdd SPECIFIC_URL option for extra security for sessions[Ed Crewe]0.1 - 4th November 2012Initial releaseDjango snippets -http://djangosnippets.org/snippets/1540/Basis of middlewareAdd simple crypt of sessionid when used in HTMLCall standard contrib.sessions.Session if not decorated as no_cookiesAdd CSRF exempt decorator too to ensure cookie not set by thatAdd templatetags for users who prefer manual adding of session idsAdd settings options to configure level of security applied,
e.g. whitelist of referers, no URL rewriting etc.[Ed Crewe, julio carlos and Ivscar (snippet), Paul Chakravarti (xteacrypt)]