misc: add SameSite cookie attribute (#52356)

This commit is contained in:
Frédéric Péters 2021-03-30 20:05:59 +02:00
parent c1909f5321
commit 86a24e5987
4 changed files with 53 additions and 3 deletions

View File

@ -1,3 +1,5 @@
import http.cookies
import pytest
from utilities import clean_temporary_pub, create_temporary_pub, get_app, login
@ -36,6 +38,23 @@ def teardown_module(module):
clean_temporary_pub()
def test_login_cookie(pub):
app = get_app(pub)
assert not app.cookies
resp = app.get('/login/')
resp.form['username'] = 'foo'
resp.form['password'] = 'foo'
resp = resp.form.submit()
assert app.cookies
cookie_name = pub.config.session_cookie_name
cookie_store = http.cookies.SimpleCookie()
cookie_store.load(resp.headers['Set-Cookie'])
assert list(cookie_store.keys()) == [cookie_name]
assert 'HttpOnly' in resp.headers['Set-Cookie']
assert 'SameSite=None' in resp.headers['Set-Cookie']
assert 'path=/' in resp.headers['Set-Cookie']
def test_login_logout(pub):
resp_initial = get_app(pub).get('/')
resp = login(get_app(pub), username='foo', password='foo').get('/')

View File

@ -1,4 +1,5 @@
import datetime
import http.cookies
import os
import shutil
import urllib.parse
@ -523,15 +524,19 @@ def test_opened_session_cookie(pub):
pub.site_options.write(fd)
resp = app.get('/?parameter=value')
assert 'secure' in resp.headers['Set-Cookie']
assert 'httponly' in resp.headers['Set-Cookie']
cookie_name = '%s-passive-auth-tried' % pub.config.session_cookie_name
cookie_store = http.cookies.SimpleCookie()
cookie_store.load(resp.headers['Set-Cookie'])
assert list(cookie_store.keys()) == [cookie_name]
assert 'Secure' in resp.headers['Set-Cookie']
assert 'HttpOnly' in resp.headers['Set-Cookie']
assert 'SameSite=Strict' in resp.headers['Set-Cookie']
assert 'path=/' in resp.headers['Set-Cookie']
assert resp.status_int == 302
assert (
resp.location
== 'http://example.net/login/?ReturnUrl=http%3A//example.net/%3Fparameter%3Dvalue&IsPassive=true'
)
cookie_name = '%s-passive-auth-tried' % pub.config.session_cookie_name
assert cookie_name in app.cookies

View File

@ -34,6 +34,31 @@ class HTTPResponse(quixote.http_response.HTTPResponse):
if not charset:
self.charset = get_publisher().site_charset
def _gen_cookie_headers(self):
cookie_headers = []
for name, attrs in self.cookies.items():
value = str(attrs['value'])
if '"' in value:
value = value.replace('"', '\\"')
chunks = ['%s="%s"' % (name, value)]
if 'samesite' not in attrs:
attrs['samesite'] = 'None'
for name, val in attrs.items():
name = name.lower()
if val is None:
continue
if name in ('expires', 'domain', 'path', 'max_age', 'comment'):
name = name.replace('_', '-')
chunks.append('%s=%s' % (name, val))
elif name == 'samesite':
chunks.append('SameSite=%s' % val)
elif name == 'secure' and val:
chunks.append('Secure')
elif name == 'httponly' and val:
chunks.append('HttpOnly')
cookie_headers.append(('Set-Cookie', '; '.join(chunks)))
return cookie_headers
def reset_includes(self):
self.javascript_scripts = None
self.javascript_code_parts = None

View File

@ -399,6 +399,7 @@ class RootDirectory(Directory):
httponly=1,
path=publisher.config.session_cookie_path,
domain=publisher.config.session_cookie_domain,
samesite='Strict',
)
url = request.get_url()
query = request.get_query()