Replace cookie implementation with flask builtin secure cookie.

However, by default, session cookies don't expire (only cleared out by
the end user's browser).

This is dumb. You'd think, given that there's
`config['PERMANENT_SESSION_LIFETIME']`, that you'd enable permanent
sessions in the config too - but no, you have to declare it for each
request. session.permanent is also, helpfully, a way of saying that the
session isn't permanent - in that, it will expire on its own, as
opposed to being controlled by the browser's session. Because session
is a proxy, it's only accessible from within a request context, so we
need to set this before every request 🙄

http://flask.pocoo.org/docs/0.12/api/#flask.session
https://stackoverflow.com/questions/34118093/flask-permanent-session-where-to-define-them
This commit is contained in:
Leo Hemsted
2018-01-05 16:27:51 +00:00
parent 08dca5b879
commit b9f7fa1f6f
2 changed files with 10 additions and 56 deletions

View File

@@ -38,7 +38,6 @@ from werkzeug.local import LocalProxy
from app import proxy_fix
from app.config import configs
from app.asset_fingerprinter import AssetFingerprinter
from app.its_dangerous_session import ItsdangerousSessionInterface
from app.notify_client.service_api_client import ServiceAPIClient
from app.notify_client.api_key_api_client import ApiKeyApiClient
from app.notify_client.invite_api_client import InviteApiClient
@@ -124,8 +123,6 @@ def create_app(application):
proxy_fix.init_app(application)
application.session_interface = ItsdangerousSessionInterface()
add_template_filters(application)
register_errorhandlers(application)
@@ -139,6 +136,16 @@ def init_app(application):
application.before_request(load_service_before_request)
application.before_request(request_helper.check_proxy_header_before_request)
@application.before_request
def make_session_permanent():
# this is dumb. You'd think, given that there's `config['PERMANENT_SESSION_LIFETIME']`, that you'd enable
# permanent sessions in the config too - but no, you have to declare it for each request.
# https://stackoverflow.com/questions/34118093/flask-permanent-session-where-to-define-them
# session.permanent is also, helpfully, a way of saying that the session isn't permanent - in that, it will
# expire on its own, as opposed to being controlled by the browser's session. Because session is a proxy, it's
# only accessible from within a request context, so we need to set this before every request :rolls_eyes:
session.permanent = True
@application.context_processor
def _attach_current_service():
return {'current_service': current_service}

View File

@@ -1,53 +0,0 @@
from datetime import timedelta, datetime
from werkzeug.datastructures import CallbackDict
from flask.sessions import SessionInterface, SessionMixin
from itsdangerous import URLSafeTimedSerializer, BadSignature
class ItsdangerousSession(CallbackDict, SessionMixin):
def __init__(self, initial=None):
def on_update(self):
self.modified = True
CallbackDict.__init__(self, initial, on_update)
self.modified = False
class ItsdangerousSessionInterface(SessionInterface):
session_class = ItsdangerousSession
def get_serializer(self, app):
salt = app.config.get('DANGEROUS_SALT')
if not app.secret_key:
return None
return URLSafeTimedSerializer(app.secret_key,
salt=salt)
def open_session(self, app, request):
s = self.get_serializer(app)
if s is None:
return None
val = request.cookies.get(app.session_cookie_name)
if not val:
return self.session_class()
max_age = app.permanent_session_lifetime.total_seconds()
try:
data = s.loads(val, max_age=max_age)
return self.session_class(data)
except BadSignature:
return self.session_class()
def save_session(self, app, session, response):
domain = self.get_cookie_domain(app)
if not session:
if session.modified:
response.delete_cookie(app.session_cookie_name,
domain=domain)
return
session.permanent = True
expires = datetime.utcnow() + timedelta(seconds=app.config.get('PERMANENT_SESSION_LIFETIME'))
val = self.get_serializer(app).dumps(dict(session))
response.set_cookie(app.session_cookie_name, val,
expires=expires, httponly=True,
domain=domain, secure=app.config.get('SESSION_COOKIE_SECURE'))