use MiddlewareMixin on middleware (#36509)

Remove OPENED_SESSION_COOKIE_DOMAIN which has no use.
This commit is contained in:
Benjamin Dauvergne 2019-09-29 11:20:44 +02:00
parent 83abc78605
commit 7095b1368b
6 changed files with 72 additions and 25 deletions

View File

@ -31,7 +31,6 @@ class AppSettings(object):
'DEFAULT_ASSERTION_CONSUMER_BINDING': 'post', # or artifact
'VERIFY_SSL_CERTIFICATE': True,
'OPENED_SESSION_COOKIE_NAME': None,
'OPENED_SESSION_COOKIE_DOMAIN': None,
'ORGANIZATION': None,
'CONTACT_PERSONS': [],
'TRANSIENT_FEDERATION_ATTRIBUTE': None,

27
mellon/compat.py Normal file
View File

@ -0,0 +1,27 @@
# django-mellon - SAML2 authentication for Django
# Copyright (C) 2014-2019 Entr'ouvert
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import django
if django.VERSION < (1, 11, 0):
from django.core.urlresolvers import reverse
MiddlewareClass = object
is_authenticated = lambda user: user.is_authenticated()
else:
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
MiddlewareClass = MiddlewareMixin
is_authenticated = lambda user: user.is_authenticated

View File

@ -19,12 +19,12 @@ from django.utils.http import urlencode
from django.http import HttpResponseRedirect
from . import app_settings, utils
from .compat import reverse
from .compat import reverse, MiddlewareClass, is_authenticated
PASSIVE_TRIED_COOKIE = 'MELLON_PASSIVE_TRIED'
class PassiveAuthenticationMiddleware(object):
class PassiveAuthenticationMiddleware(MiddlewareClass):
def process_response(self, request, response):
# When unlogged remove the PASSIVE_TRIED cookie
if app_settings.OPENED_SESSION_COOKIE_NAME \
@ -47,26 +47,19 @@ class PassiveAuthenticationMiddleware(object):
return
if not app_settings.OPENED_SESSION_COOKIE_NAME:
return
if hasattr(request, 'user') and request.user.is_authenticated():
if hasattr(request, 'user') and is_authenticated(request.user):
return
if PASSIVE_TRIED_COOKIE in request.COOKIES:
return
if app_settings.OPENED_SESSION_COOKIE_NAME in request.COOKIES:
# get the common domain or guess
common_domain = app_settings.OPENED_SESSION_COOKIE_DOMAIN
if not common_domain:
host = request.get_host()
# accept automatic common domain selection if domain has at least three components
# and is not an IP address
if not host.count('.') > 1 or host.replace('.', '').isdigit():
return
common_domain = request.get_host().split('.', 1)[1]
params = {
'next': request.build_absolute_uri(),
'passive': '',
}
url = reverse('mellon_login') + '?%s' % urlencode(params)
response = HttpResponseRedirect(url)
# prevent loops
response.set_cookie(PASSIVE_TRIED_COOKIE, value='1', max_age=None)
return response
if app_settings.OPENED_SESSION_COOKIE_NAME not in request.COOKIES:
return
# all is good, try passive login
params = {
'next': request.build_absolute_uri(),
'passive': '',
}
url = reverse('mellon_login') + '?%s' % urlencode(params)
response = HttpResponseRedirect(url)
# prevent loops
response.set_cookie(PASSIVE_TRIED_COOKIE, value='1', max_age=None)
return response

View File

@ -373,3 +373,31 @@ def test_sso_slo_pass_login_hints_backoffice(db, app, idp, caplog, sp_settings):
login_hints = root.findall('.//{https://www.entrouvert.com/}login-hint')
assert len(login_hints) == 1, 'missing login hint'
assert login_hints[0].text == 'backoffice', 'login hint is not backoffice'
def test_middleware_mixin_first_time(db, app, idp, caplog, settings):
settings.MELLON_OPENED_SESSION_COOKIE_NAME = 'IDP_SESSION'
assert 'MELLON_PASSIVE_TRIED' not in app.cookies
# webtest-lint is against unicode
app.set_cookie(str('IDP_SESSION'), str('1'))
response = app.get('/', status=302)
assert urlparse.urlparse(response.location).path == '/login/'
assert (urlparse.parse_qs(urlparse.urlparse(response.location).query, keep_blank_values=True)
== {'next': ['http://testserver/'], 'passive': ['']})
# simulate closing of session at IdP
app.cookiejar.clear('testserver.local', '/', 'IDP_SESSION')
assert 'IDP_SESSION' not in app.cookies
# verify MELLON_PASSIVE_TRIED is removed
assert 'MELLON_PASSIVE_TRIED' in app.cookies
response = app.get('/', status=200)
assert 'MELLON_PASSIVE_TRIED' not in app.cookies
# check passive authentication is tried again
app.set_cookie(str('IDP_SESSION'), str('1'))
response = app.get('/', status=302)
assert urlparse.urlparse(response.location).path == '/login/'
assert (urlparse.parse_qs(urlparse.urlparse(response.location).query, keep_blank_values=True)
== {'next': ['http://testserver/'], 'passive': ['']})
assert 'MELLON_PASSIVE_TRIED' in app.cookies

View File

@ -13,8 +13,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import django
from django.conf.urls import url, include
from django.http import HttpResponse

View File

@ -21,12 +21,14 @@ if hasattr(global_settings, 'MIDDLEWARE_CLASSES'):
MIDDLEWARE_CLASSES += (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'mellon.middleware.PassiveAuthenticationMiddleware',
)
else:
MIDDLEWARE = global_settings.MIDDLEWARE
MIDDLEWARE += (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'mellon.middleware.PassiveAuthenticationMiddleware',
)
AUTHENTICATION_BACKENDS = (