Skip to content

Commit

Permalink
prefix internal session keys with underscore (#470)
Browse files Browse the repository at this point in the history
  • Loading branch information
alanhamlett committed Feb 6, 2020
1 parent 5fce013 commit 1d1a3a8
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 31 deletions.
3 changes: 2 additions & 1 deletion CHANGES
Expand Up @@ -5,7 +5,8 @@ Here you can see the full list of changes between each Flask-Login release.

Unreleased
----------
nothing yet
- Prefix authenticated user_id, remember, and remember_seconds in Flask Session
with underscores to prevent accidental usage in application code. #465

Version 1.0.0
-------------
Expand Down
9 changes: 8 additions & 1 deletion flask_login/config.py
Expand Up @@ -42,7 +42,14 @@

#: A set of session keys that are populated by Flask-Login. Use this set to
#: purge keys safely and accurately.
SESSION_KEYS = set(['user_id', 'remember', '_id', '_fresh', 'next'])
SESSION_KEYS = set([
'_user_id',
'_remember',
'_remember_seconds',
'_id',
'_fresh',
'next',
])

#: A set of HTTP methods which are exempt from `login_required` and
#: `fresh_login_required`. By default, this is just ``OPTIONS``.
Expand Down
24 changes: 12 additions & 12 deletions flask_login/login_manager.py
Expand Up @@ -313,7 +313,7 @@ def _load_user(self):
user = None

# Load user from Flask Session
user_id = session.get('user_id')
user_id = session.get('_user_id')
if user_id is not None and self._user_callback is not None:
user = self._user_callback(user_id)

Expand All @@ -323,7 +323,7 @@ def _load_user(self):
cookie_name = config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME)
header_name = config.get('AUTH_HEADER_NAME', AUTH_HEADER_NAME)
has_cookie = (cookie_name in request.cookies and
session.get('remember') != 'clear')
session.get('_remember') != 'clear')
if has_cookie:
cookie = request.cookies[cookie_name]
user = self._load_user_from_remember_cookie(cookie)
Expand Down Expand Up @@ -356,7 +356,7 @@ def _session_protection_failed(self):
for k in SESSION_KEYS:
sess.pop(k, None)

sess['remember'] = 'clear'
sess['_remember'] = 'clear'
session_protected.send(app)
return True

Expand All @@ -365,7 +365,7 @@ def _session_protection_failed(self):
def _load_user_from_remember_cookie(self, cookie):
user_id = decode_cookie(cookie)
if user_id is not None:
session['user_id'] = user_id
session['_user_id'] = user_id
session['_fresh'] = False
user = None
if self._user_callback:
Expand Down Expand Up @@ -396,14 +396,14 @@ def _load_user_from_request(self, request):

def _update_remember_cookie(self, response):
# Don't modify the session unless there's something to do.
if 'remember' not in session and \
if '_remember' not in session and \
current_app.config.get('REMEMBER_COOKIE_REFRESH_EACH_REQUEST'):
session['remember'] = 'set'
session['_remember'] = 'set'

if 'remember' in session:
operation = session.pop('remember', None)
if '_remember' in session:
operation = session.pop('_remember', None)

if operation == 'set' and 'user_id' in session:
if operation == 'set' and '_user_id' in session:
self._set_cookie(response)
elif operation == 'clear':
self._clear_cookie(response)
Expand All @@ -420,13 +420,13 @@ def _set_cookie(self, response):
secure = config.get('REMEMBER_COOKIE_SECURE', COOKIE_SECURE)
httponly = config.get('REMEMBER_COOKIE_HTTPONLY', COOKIE_HTTPONLY)

if 'remember_seconds' in session:
duration = timedelta(seconds=session['remember_seconds'])
if '_remember_seconds' in session:
duration = timedelta(seconds=session['_remember_seconds'])
else:
duration = config.get('REMEMBER_COOKIE_DURATION', COOKIE_DURATION)

# prepare data
data = encode_cookie(text_type(session['user_id']))
data = encode_cookie(text_type(session['_user_id']))

if isinstance(duration, int):
duration = timedelta(seconds=duration)
Expand Down
2 changes: 1 addition & 1 deletion flask_login/test_client.py
Expand Up @@ -15,5 +15,5 @@ def __init__(self, *args, **kwargs):

if user:
with self.session_transaction() as sess:
sess["user_id"] = user.get_id()
sess["_user_id"] = user.get_id()
sess["_fresh"] = fresh
22 changes: 11 additions & 11 deletions flask_login/utils.py
Expand Up @@ -167,19 +167,19 @@ def login_user(user, remember=False, duration=None, force=False, fresh=True):
return False

user_id = getattr(user, current_app.login_manager.id_attribute)()
session['user_id'] = user_id
session['_user_id'] = user_id
session['_fresh'] = fresh
session['_id'] = current_app.login_manager._session_identifier_generator()

if remember:
session['remember'] = 'set'
session['_remember'] = 'set'
if duration is not None:
try:
# equal to timedelta.total_seconds() but works with Python 2.6
session['remember_seconds'] = (duration.microseconds +
(duration.seconds +
duration.days * 24 * 3600) *
10**6) / 10.0**6
session['_remember_seconds'] = (duration.microseconds +
(duration.seconds +
duration.days * 24 * 3600) *
10**6) / 10.0**6
except AttributeError:
raise Exception('duration must be a datetime.timedelta, '
'instead got: {0}'.format(duration))
Expand All @@ -197,8 +197,8 @@ def logout_user():

user = _get_user()

if 'user_id' in session:
session.pop('user_id')
if '_user_id' in session:
session.pop('_user_id')

if '_fresh' in session:
session.pop('_fresh')
Expand All @@ -208,9 +208,9 @@ def logout_user():

cookie_name = current_app.config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME)
if cookie_name in request.cookies:
session['remember'] = 'clear'
if 'remember_seconds' in session:
session.pop('remember_seconds')
session['_remember'] = 'clear'
if '_remember_seconds' in session:
session.pop('_remember_seconds')

user_logged_out.send(current_app._get_current_object(), user=user)

Expand Down
10 changes: 5 additions & 5 deletions test_login.py
Expand Up @@ -202,7 +202,7 @@ def test_login_disabled_is_set(self):
def test_no_user_loader_raises(self):
login_manager = LoginManager(self.app, add_context_processor=True)
with self.app.test_request_context():
session['user_id'] = '2'
session['_user_id'] = '2'
with self.assertRaises(Exception) as cm:
login_manager._load_user()
expected_message = 'Missing user_loader or request_loader'
Expand Down Expand Up @@ -443,7 +443,7 @@ def test_logout_emits_signal(self):
def test_logout_without_current_user(self):
with self.app.test_request_context():
login_user(notch)
del session['user_id']
del session['_user_id']
with listen_to(user_logged_out) as listener:
logout_user()
listener.assert_heard_one(self.app, user=ANY)
Expand Down Expand Up @@ -783,7 +783,7 @@ def test_set_cookie_with_invalid_duration_raises_exception(self):

with self.assertRaises(Exception) as cm:
with self.app.test_request_context():
session['user_id'] = 2
session['_user_id'] = 2
self.login_manager._set_cookie(None)

expected_exception_message = 'REMEMBER_COOKIE_DURATION must be a ' \
Expand Down Expand Up @@ -1036,7 +1036,7 @@ def test_invalid_remember_cookie(self):
with self.app.test_client() as c:
c.get('/login-notch-remember')
with c.session_transaction() as sess:
sess['user_id'] = None
sess['_user_id'] = None
c.set_cookie(domain, self.remember_cookie_name, 'foo')
result = c.get('/username')
self.assertEqual(u'Anonymous', result.data.decode('utf-8'))
Expand Down Expand Up @@ -1322,7 +1322,7 @@ def logout():

@self.login_manager.request_loader
def load_user_from_request(request):
user_id = request.args.get('user_id') or session.get('user_id')
user_id = request.args.get('user_id') or session.get('_user_id')
try:
user_id = int(float(user_id))
except TypeError:
Expand Down

0 comments on commit 1d1a3a8

Please sign in to comment.