[PATCH] middleware: use secure cookies over secure connections

Andrew Shadura andrew at shadura.me
Wed Mar 4 17:58:19 EST 2015


# HG changeset patch
# User Andrew Shadura <andrew at shadura.me>
# Date 1425509877 -3600
#      Wed Mar 04 23:57:57 2015 +0100
# Node ID 6e0cecf00cdad2d108caca97c4cd9dece0333d73
# Parent  599fba9967a4981e8c401c39521a52635dd93380
middleware: use secure cookies over secure connections

Use our own wrapper around Beaker's SessionMiddleware class to
give secure cookies over HTTPS connections.

diff --git a/kallithea/config/middleware.py b/kallithea/config/middleware.py
--- a/kallithea/config/middleware.py
+++ b/kallithea/config/middleware.py
@@ -15,7 +15,6 @@
     Pylons middleware initialization
 """
 
-from beaker.middleware import SessionMiddleware
 from routes.middleware import RoutesMiddleware
 from paste.cascade import Cascade
 from paste.registry import RegistryManager
@@ -29,6 +28,7 @@ from pylons.wsgiapp import PylonsApp
 from kallithea.lib.middleware.simplehg import SimpleHg
 from kallithea.lib.middleware.simplegit import SimpleGit
 from kallithea.lib.middleware.https_fixup import HttpsFixup
+from kallithea.lib.middleware.sessionmiddleware import SessionMiddleware
 from kallithea.config.environment import load_environment
 from kallithea.lib.middleware.wrapper import RequestWrapper
 
diff --git a/kallithea/lib/middleware/sessionmiddleware.py b/kallithea/lib/middleware/sessionmiddleware.py
new file mode 100644
--- /dev/null
+++ b/kallithea/lib/middleware/sessionmiddleware.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+kallithea.lib.middleware.sessionmiddleware
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+session management middleware
+
+This file overrides Beaker's built-in SessionMiddleware
+class to automagically use secure cookies over HTTPS.
+
+Original Beaker SessionMiddleware class written by Ben Bangert
+
+:created_on: March 04, 2015
+:author: andrewsh
+:copyright: (c) 2015 Andrew Shadura
+:license: GPLv3, see LICENSE.md for more details.
+"""
+
+from beaker.session import SessionObject
+from beaker.middleware import SessionMiddleware as BeakerSessionMiddleware
+
+class SessionMiddleware(BeakerSessionMiddleware):
+    def __init__(self, wrap_app, config=None, environ_key='beaker.session',
+                **kwargs):
+        """
+        Initialise the session middleware
+
+        Call Beaker's original constructor to set the options, then
+        unset secure option as we're handling that on our own and don't
+        want Beaker to interfere.
+        """
+        super(SessionMiddleware, self).__init__(wrap_app, config,
+            environ_key, **kwargs)
+        self.options["secure"] = False
+        # self.options["httponly"] = True
+
+    def __call__(self, environ, start_response):
+        """
+        This function's implementation is taken directly from Beaker,
+        with HTTPS detection added. When accessed over HTTPS, force
+        setting cookie's secure flag.
+        """
+        session = SessionObject(environ, **self.options)
+        if environ.get('paste.registry'):
+            if environ['paste.registry'].reglist:
+                environ['paste.registry'].register(self.session, session)
+        environ[self.environ_key] = session
+        environ['beaker.get_session'] = self._get_session
+
+        if 'paste.testing_variables' in environ and 'webtest_varname' in self.options:
+            environ['paste.testing_variables'][self.options['webtest_varname']] = session
+
+        is_ssl = environ['wsgi.url_scheme'] == 'https'
+
+        def session_start_response(status, headers, exc_info=None):
+            if session.accessed():
+                session.persist()
+                if session.__dict__['_headers']['set_cookie']:
+                    cookie = session.__dict__['_headers']['cookie_out']
+
+                    if is_ssl:
+                        cookie += "; secure"
+                    if cookie:
+                        headers.append(('Set-cookie', cookie))
+            return start_response(status, headers, exc_info)
+        return self.wrap_app(environ, session_start_response)


More information about the kallithea-general mailing list