New Feature: Added Support for cookie's SameSite attribute.

This commit is contained in:
Fadhel_Chaabane 2018-01-23 13:57:50 +00:00
parent 22708b048d
commit a1d9ebe4ab
5 changed files with 61 additions and 4 deletions

View file

@ -208,6 +208,14 @@ The following configuration values are used internally by Flask:
Default: ``False``
.. py:data:: SESSION_COOKIE_SAMESITE
Browser will only send cookies to the domain that created them.
There are two possible values for the same-site attribute: "Strict" and "Lax"
If set to "None", the samesite flag is not set.
Default: ``None``
.. py:data:: PERMANENT_SESSION_LIFETIME
If ``session.permanent`` is true, the cookie's expiration will be set this
@ -635,4 +643,3 @@ Example usage for both::
# or via open_instance_resource:
with app.open_instance_resource('application.cfg') as f:
config = f.read()

View file

@ -195,16 +195,18 @@ They can be set on other cookies too.
- ``HttpOnly`` protects the contents of cookies from being read with
JavaScript.
- ``SameSite`` ensures that cookies can only be requested from the same
domain that created them. It is not supported by Flask yet.
domain that created them. There are two possible values for the same-site
attribute: "Strict" and "Lax"
::
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Strict'
)
response.set_cookie('username', 'flask', secure=True, httponly=True)
response.set_cookie('username', 'flask', secure=True, httponly=True, samesite='Strict')
Specifying ``Expires`` or ``Max-Age`` options, will remove the cookie after
the given time, or the current time plus the age, respectively. If neither

View file

@ -284,6 +284,7 @@ class Flask(_PackageBoundObject):
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'SESSION_COOKIE_SAMESITE': None,
'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),

View file

@ -249,6 +249,13 @@ class SessionInterface(object):
"""
return app.config['SESSION_COOKIE_SECURE']
def get_cookie_samesite(self, app):
"""Returns "Strict", "Lax" or None if the cookie should use
samesite attribute. This currently just returns the value of
the ``SESSION_COOKIE_SAMESITE`` setting.
"""
return app.config['SESSION_COOKIE_SAMESITE']
def get_expiration_time(self, app, session):
"""A helper method that returns an expiration date for the session
or ``None`` if the session is linked to the browser session. The
@ -362,6 +369,7 @@ class SecureCookieSessionInterface(SessionInterface):
httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
samesite = self.get_cookie_samesite(app)
expires = self.get_expiration_time(app, session)
val = self.get_signing_serializer(app).dumps(dict(session))
response.set_cookie(
@ -371,5 +379,6 @@ class SecureCookieSessionInterface(SessionInterface):
httponly=httponly,
domain=domain,
path=path,
secure=secure
secure=secure,
samesite=samesite
)

View file

@ -319,6 +319,7 @@ def test_session_using_session_settings(app, client):
SESSION_COOKIE_DOMAIN='.example.com',
SESSION_COOKIE_HTTPONLY=False,
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_SAMESITE='Strict',
SESSION_COOKIE_PATH='/'
)
@ -333,8 +334,45 @@ def test_session_using_session_settings(app, client):
assert 'path=/' in cookie
assert 'secure' in cookie
assert 'httponly' not in cookie
assert 'samesite' in cookie
def test_session_using_samesite_attribute(app, client):
app.config.update(
SERVER_NAME='www.example.com:8080',
APPLICATION_ROOT='/test',
SESSION_COOKIE_DOMAIN='.example.com',
SESSION_COOKIE_HTTPONLY=False,
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_SAMESITE='anyvalue',
SESSION_COOKIE_PATH='/'
)
@app.route('/')
def index():
flask.session['testing'] = 42
return 'Hello World'
# assert excption when samesite is not set to 'Strict', 'Lax' or None
with pytest.raises(ValueError):
rv = client.get('/', 'http://www.example.com:8080/test/')
# assert the samesite flag is not set in the cookie, when set to None
app.config.update(SESSION_COOKIE_SAMESITE=None)
rv = client.get('/', 'http://www.example.com:8080/test/')
cookie = rv.headers['set-cookie'].lower()
assert 'samesite' not in cookie
app.config.update(SESSION_COOKIE_SAMESITE='Strict')
rv = client.get('/', 'http://www.example.com:8080/test/')
cookie = rv.headers['set-cookie'].lower()
assert 'samesite=strict' in cookie
app.config.update(SESSION_COOKIE_SAMESITE='Lax')
rv = client.get('/', 'http://www.example.com:8080/test/')
cookie = rv.headers['set-cookie'].lower()
assert 'samesite=lax' in cookie
def test_session_localhost_warning(recwarn, app, client):
app.config.update(
SERVER_NAME='localhost:5000',