summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2018-04-13 20:58:31 -0400
committerTim Graham <timograham@gmail.com>2018-04-13 20:58:31 -0400
commit9a56b4b13ed92d2d5bb00d6bdb905a73bc5f2f0a (patch)
treeddb311604d1ec31ec09c8ae12e34dadc821f7536 /django
parent13efbb233a9aa2e3f13be863c6616ec0767a0d58 (diff)
Fixed #27863 -- Added support for the SameSite cookie flag.
Thanks Alex Gaynor for contributing to the patch.
Diffstat (limited to 'django')
-rw-r--r--django/conf/global_settings.py4
-rw-r--r--django/contrib/messages/storage/cookie.py1
-rw-r--r--django/contrib/sessions/middleware.py1
-rw-r--r--django/http/cookie.py3
-rw-r--r--django/http/response.py6
-rw-r--r--django/middleware/csrf.py1
6 files changed, 15 insertions, 1 deletions
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 8efa602e1e..befade160f 100644
--- a/django/conf/global_settings.py
+++ b/django/conf/global_settings.py
@@ -461,6 +461,9 @@ SESSION_COOKIE_SECURE = False
SESSION_COOKIE_PATH = '/'
# Whether to use the non-RFC standard httpOnly flag (IE, FF3+, others)
SESSION_COOKIE_HTTPONLY = True
+# Whether to set the flag restricting cookie leaks on cross-site requests.
+# This can be 'Lax', 'Strict', or None to disable the flag.
+SESSION_COOKIE_SAMESITE = 'Lax'
# Whether to save the session data on every request.
SESSION_SAVE_EVERY_REQUEST = False
# Whether a user's session cookie expires when the Web browser is closed.
@@ -537,6 +540,7 @@ CSRF_COOKIE_DOMAIN = None
CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_SECURE = False
CSRF_COOKIE_HTTPONLY = False
+CSRF_COOKIE_SAMESITE = 'Lax'
CSRF_HEADER_NAME = 'HTTP_X_CSRFTOKEN'
CSRF_TRUSTED_ORIGINS = []
CSRF_USE_SESSIONS = False
diff --git a/django/contrib/messages/storage/cookie.py b/django/contrib/messages/storage/cookie.py
index 6a6a301db7..9e0c93e436 100644
--- a/django/contrib/messages/storage/cookie.py
+++ b/django/contrib/messages/storage/cookie.py
@@ -86,6 +86,7 @@ class CookieStorage(BaseStorage):
domain=settings.SESSION_COOKIE_DOMAIN,
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None,
+ samesite=settings.SESSION_COOKIE_SAMESITE,
)
else:
response.delete_cookie(self.cookie_name, domain=settings.SESSION_COOKIE_DOMAIN)
diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py
index 7263b6ac2d..6795354cc5 100644
--- a/django/contrib/sessions/middleware.py
+++ b/django/contrib/sessions/middleware.py
@@ -69,5 +69,6 @@ class SessionMiddleware(MiddlewareMixin):
path=settings.SESSION_COOKIE_PATH,
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None,
+ samesite=settings.SESSION_COOKIE_SAMESITE,
)
return response
diff --git a/django/http/cookie.py b/django/http/cookie.py
index b94d2b0386..5c418d7e35 100644
--- a/django/http/cookie.py
+++ b/django/http/cookie.py
@@ -3,6 +3,9 @@ from http import cookies
# For backwards compatibility in Django 2.1.
SimpleCookie = cookies.SimpleCookie
+# Add support for the SameSite attribute (obsolete when PY37 is unsupported).
+cookies.Morsel._reserved.setdefault('samesite', 'SameSite')
+
def parse_cookie(cookie):
"""
diff --git a/django/http/response.py b/django/http/response.py
index b21b73f247..96c0cae597 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -154,7 +154,7 @@ class HttpResponseBase:
return self._headers.get(header.lower(), (None, alternate))[1]
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
- domain=None, secure=False, httponly=False):
+ domain=None, secure=False, httponly=False, samesite=None):
"""
Set a cookie.
@@ -194,6 +194,10 @@ class HttpResponseBase:
self.cookies[key]['secure'] = True
if httponly:
self.cookies[key]['httponly'] = True
+ if samesite:
+ if samesite.lower() not in ('lax', 'strict'):
+ raise ValueError('samesite must be "lax" or "strict".')
+ self.cookies[key]['samesite'] = samesite
def setdefault(self, key, value):
"""Set a header unless it has already been set."""
diff --git a/django/middleware/csrf.py b/django/middleware/csrf.py
index a3a6eaf62f..10f878834d 100644
--- a/django/middleware/csrf.py
+++ b/django/middleware/csrf.py
@@ -190,6 +190,7 @@ class CsrfViewMiddleware(MiddlewareMixin):
path=settings.CSRF_COOKIE_PATH,
secure=settings.CSRF_COOKIE_SECURE,
httponly=settings.CSRF_COOKIE_HTTPONLY,
+ samesite=settings.CSRF_COOKIE_SAMESITE,
)
# Set the Vary header since content varies with the CSRF cookie.
patch_vary_headers(response, ('Cookie',))