summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2018-06-11 10:28:52 -0500
committerGitHub <noreply@github.com>2018-06-11 10:28:52 -0500
commit2fd7905a9d4427ea6dbeaff35f44855c824e470d (patch)
treebbbef8a36a0bc6ee07545737f94f7505c5e8d232
parentaaed8d498ae255c27109e0b40736ca93ed7a4093 (diff)
parent34bbcc83ddb9052f803c62eaedbe7308809d9416 (diff)
downloadpyramid-2fd7905a9d4427ea6dbeaff35f44855c824e470d.tar.gz
pyramid-2fd7905a9d4427ea6dbeaff35f44855c824e470d.tar.bz2
pyramid-2fd7905a9d4427ea6dbeaff35f44855c824e470d.zip
Merge pull request #3300 from Pylons/feature/session-samesite-lax
Feature: Default session cookies to SameSite=Lax
-rw-r--r--CHANGES.rst13
-rw-r--r--CONTRIBUTORS.txt4
-rw-r--r--pyramid/session.py31
-rw-r--r--pyramid/tests/test_session.py7
-rw-r--r--setup.py2
5 files changed, 52 insertions, 5 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index de7ad0f8a..aeb7c3f9a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -30,6 +30,13 @@ Features
route_prefix for ``include`` and ``add_route`` calls inside the context.
See https://github.com/Pylons/pyramid/pull/3279
+- Modify the builtin session implementations to support SameSite options on
+ cookies and set the default to ``'Lax'``. This affects
+ ``pyramid.session.BaseCookieSessionFactory``,
+ ``pyramid.session.SignedCookieSessionFactory``, and
+ ``pyramid.session.UnencryptedCookieSessionFactoryConfig``.
+ See https://github.com/Pylons/pyramid/pull/3300
+
Bug Fixes
---------
@@ -59,6 +66,12 @@ Backward Incompatibilities
from a feature removed in Pyramid 1.5 and has had no effect since then.
See https://github.com/Pylons/pyramid/pull/3299
+- Modify the builtin session implementations to set ``SameSite='Lax'`` on
+ cookies. This affects ``pyramid.session.BaseCookieSessionFactory``,
+ ``pyramid.session.SignedCookieSessionFactory``, and
+ ``pyramid.session.UnencryptedCookieSessionFactoryConfig``.
+ See https://github.com/Pylons/pyramid/pull/3300
+
Documentation Changes
---------------------
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 60e4e5732..69ed023b0 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -319,4 +319,6 @@ Contributors
- Hunter Senft-Grupp, 2018/05/14
-- Junhak Lee, 2018/05/14 \ No newline at end of file
+- Junhak Lee, 2018/05/14
+
+- Alex Gaynor, 2018/05/24
diff --git a/pyramid/session.py b/pyramid/session.py
index 4a9c8c100..d05ac66eb 100644
--- a/pyramid/session.py
+++ b/pyramid/session.py
@@ -135,6 +135,7 @@ def BaseCookieSessionFactory(
domain=None,
secure=False,
httponly=False,
+ samesite='Lax',
timeout=1200,
reissue_time=0,
set_on_exception=True,
@@ -187,6 +188,10 @@ def BaseCookieSessionFactory(
Hide the cookie from Javascript by setting the 'HttpOnly' flag of the
session cookie. Default: ``False``.
+ ``samesite``
+ The 'samesite' option of the session cookie. Set the value to ``None``
+ to turn off the samesite option. Default: ``'Lax'``.
+
``timeout``
A number of seconds of inactivity before a session times out. If
``None`` then the cookie never expires. This lifetime only applies
@@ -216,6 +221,10 @@ def BaseCookieSessionFactory(
while rendering a view. Default: ``True``.
.. versionadded: 1.5a3
+
+ .. versionchanged: 1.10
+
+ Added the ``samesite`` option and made the default ``'Lax'``.
"""
@implementer(ISession)
@@ -229,6 +238,7 @@ def BaseCookieSessionFactory(
_cookie_domain = domain
_cookie_secure = secure
_cookie_httponly = httponly
+ _cookie_samesite = samesite
_cookie_on_exception = set_on_exception
_timeout = timeout if timeout is None else int(timeout)
_reissue_time = reissue_time if reissue_time is None else int(reissue_time)
@@ -367,6 +377,7 @@ def BaseCookieSessionFactory(
domain=self._cookie_domain,
secure=self._cookie_secure,
httponly=self._cookie_httponly,
+ samesite=self._cookie_samesite,
)
return True
@@ -382,6 +393,7 @@ def UnencryptedCookieSessionFactoryConfig(
cookie_domain=None,
cookie_secure=False,
cookie_httponly=False,
+ cookie_samesite='Lax',
cookie_on_exception=True,
signed_serialize=signed_serialize,
signed_deserialize=signed_deserialize,
@@ -434,6 +446,10 @@ def UnencryptedCookieSessionFactoryConfig(
``cookie_httponly``
The 'httpOnly' flag of the session cookie.
+ ``cookie_samesite``
+ The 'samesite' option of the session cookie. Set the value to ``None``
+ to turn off the samesite option. Default: ``'Lax'``.
+
``cookie_on_exception``
If ``True``, set a session cookie even if an exception occurs
while rendering a view.
@@ -447,6 +463,10 @@ def UnencryptedCookieSessionFactoryConfig(
A callable which takes a signed and serialized data structure in bytes
and a secret and returns the original data structure if the signature
is valid. Default: ``signed_deserialize`` (using pickle).
+
+ .. versionchanged: 1.10
+
+ Added the ``samesite`` option and made the default ``'Lax'``.
"""
class SerializerWrapper(object):
@@ -469,6 +489,7 @@ def UnencryptedCookieSessionFactoryConfig(
domain=cookie_domain,
secure=cookie_secure,
httponly=cookie_httponly,
+ samesite=cookie_samesite,
timeout=timeout,
reissue_time=0, # to keep session.accessed == session.renewed
set_on_exception=cookie_on_exception,
@@ -491,6 +512,7 @@ def SignedCookieSessionFactory(
domain=None,
secure=False,
httponly=False,
+ samesite='Lax',
set_on_exception=True,
timeout=1200,
reissue_time=0,
@@ -553,6 +575,10 @@ def SignedCookieSessionFactory(
Hide the cookie from Javascript by setting the 'HttpOnly' flag of the
session cookie. Default: ``False``.
+ ``samesite``
+ The 'samesite' option of the session cookie. Set the value to ``None``
+ to turn off the samesite option. Default: ``'Lax'``.
+
``timeout``
A number of seconds of inactivity before a session times out. If
``None`` then the cookie never expires. This lifetime only applies
@@ -589,6 +615,10 @@ def SignedCookieSessionFactory(
the :class:`pyramid.session.PickleSerializer` serializer will be used.
.. versionadded: 1.5a3
+
+ .. versionchanged: 1.10
+
+ Added the ``samesite`` option and made the default ``Lax``.
"""
if serializer is None:
serializer = PickleSerializer()
@@ -608,6 +638,7 @@ def SignedCookieSessionFactory(
domain=domain,
secure=secure,
httponly=httponly,
+ samesite=samesite,
timeout=timeout,
reissue_time=reissue_time,
set_on_exception=set_on_exception,
diff --git a/pyramid/tests/test_session.py b/pyramid/tests/test_session.py
index ade602799..e3d819944 100644
--- a/pyramid/tests/test_session.py
+++ b/pyramid/tests/test_session.py
@@ -145,13 +145,14 @@ class SharedCookieSessionTests(object):
response = Response()
self.assertEqual(session._set_cookie(response), True)
cookieval = response.headerlist[-1][1]
- val, domain, path, secure, httponly = [x.strip() for x in
- cookieval.split(';')]
+ val, domain, path, secure, httponly, samesite = [x.strip() for x in
+ cookieval.split(';')]
self.assertTrue(val.startswith('abc='))
self.assertEqual(domain, 'Domain=localhost')
self.assertEqual(path, 'Path=/foo')
self.assertEqual(secure, 'secure')
self.assertEqual(httponly, 'HttpOnly')
+ self.assertEqual(samesite, 'SameSite=Lax')
def test_flash_default(self):
request = testing.DummyRequest()
@@ -503,7 +504,7 @@ class TestUnencryptedCookieSession(SharedCookieSessionTests, unittest.TestCase):
expected_cookieval = dummy_signed_serialize(
(session.accessed, session.created, {'key': 'value'}), secret)
response = Response()
- response.set_cookie('session', expected_cookieval)
+ response.set_cookie('session', expected_cookieval, samesite='Lax')
expected_cookie = response.headerlist[-1][1]
self.assertEqual(cookie, expected_cookie)
diff --git a/setup.py b/setup.py
index 1873612c5..17a18f3b5 100644
--- a/setup.py
+++ b/setup.py
@@ -29,7 +29,7 @@ install_requires = [
'setuptools',
'translationstring >= 0.4', # py3 compat
'venusian >= 1.0', # ``ignore``
- 'webob >= 1.8.0', # acceptparse.create_accept_header
+ 'webob >= 1.8.2', # cookies.make_cookie allows non-bytes samesite
'zope.deprecation >= 3.5.0', # py3 compat
'zope.interface >= 3.8.0', # has zope.interface.registry
]