Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions keg_auth/core.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import socket

import arrow
import flask
import flask_login
Expand Down Expand Up @@ -437,18 +439,44 @@ def clear_session(app, user):
flask.session.clear()


def fix_session_cookies(app, **extra):
cookie_values = flask.request.cookies.getlist(
def is_ip(value: str) -> bool:
"""Determine if the given string is an IP address.

:param value: value to check
:type value: str

:return: True if string is an IP address
:rtype: bool

NOTE: This function was removed from Flask in 2.4
"""
for family in (socket.AF_INET, socket.AF_INET6):
try:
socket.inet_pton(family, value)
except OSError:
pass
else:
return True

return False


def get_cookie_values(app):
return flask.request.cookies.getlist(
app.config.get('SESSION_COOKIE_NAME')
)


def fix_session_cookies(app, **extra):
cookie_values = get_cookie_values(app)
server_name = app.config.get('SERVER_NAME')
if len(cookie_values) > 1 and server_name:
# werkzeug update has breaking session, since it matches both
# and doesn't remove the old value...

# chop off the port which is usually not supported by browsers
cookie_domain = server_name.rsplit(':', 1)[0].lstrip('.')
if flask.helpers.is_ip(cookie_domain):
if is_ip(cookie_domain):
return

cookie_domain = '.' + cookie_domain
Expand Down
13 changes: 12 additions & 1 deletion keg_auth/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import flask_login
import freezegun
import arrow
from keg_auth.core import update_last_login
from keg_auth.core import fix_session_cookies, update_last_login
from keg_auth_ta.model import entities as ents


Expand Down Expand Up @@ -34,3 +34,14 @@ def test_session_not_cleared_after_signing_out(self):
assert 'foo' in list(flask.session)
flask_login.logout_user()
assert len(list(flask.session)) == 1


def test_fix_session_cookies():
with flask.current_app.test_request_context():
with mock.patch(
'keg_auth.core.get_cookie_values', autospec=True, spec_set=True
) as m_cookies:
with mock.patch('flask.abort', autospec=True, spec_set=True) as m_abort:
m_cookies.return_value = ['FoObAr', 'BarFOo']
fix_session_cookies(flask.current_app)
m_abort.assert_called_once()