views: use MELLON_OPENED_SESSION to anchor local session to the global session (#66747)
If the MELLON_OPENED_SESSION cookie change or disappear during an opened session, the user is automatically logged out. If it changes after a previous passive login try, passive login is allowed again.
This commit is contained in:
parent
025cda4293
commit
1fa1541c02
|
@ -14,6 +14,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
from django.contrib import auth
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import reverse
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
@ -58,11 +59,21 @@ class PassiveAuthenticationMiddleware(MiddlewareMixin):
|
|||
if not app_settings.OPENED_SESSION_COOKIE_NAME:
|
||||
return
|
||||
if hasattr(request, 'user') and request.user.is_authenticated:
|
||||
return
|
||||
if PASSIVE_TRIED_COOKIE in request.COOKIES:
|
||||
return
|
||||
old_opened_session_cookie = request.session.get('mellon_opened_session_cookie')
|
||||
if old_opened_session_cookie and old_opened_session_cookie != request.COOKIES.get(
|
||||
app_settings.OPENED_SESSION_COOKIE_NAME
|
||||
):
|
||||
# close current session if the opened session cookie changed...
|
||||
auth.logout(request)
|
||||
# and continue with unlogged behaviour
|
||||
else:
|
||||
# otherwise, if current session is still active, do nothing
|
||||
return
|
||||
if app_settings.OPENED_SESSION_COOKIE_NAME not in request.COOKIES:
|
||||
return
|
||||
opened_session_cookie = request.COOKIES[app_settings.OPENED_SESSION_COOKIE_NAME]
|
||||
if request.COOKIES.get(PASSIVE_TRIED_COOKIE) == opened_session_cookie:
|
||||
return
|
||||
# all is good, try passive login
|
||||
params = {
|
||||
'next': request.build_absolute_uri(),
|
||||
|
@ -71,5 +82,5 @@ class PassiveAuthenticationMiddleware(MiddlewareMixin):
|
|||
url = reverse('mellon_login') + '?%s' % urlencode(params)
|
||||
response = HttpResponseRedirect(url)
|
||||
# prevent loops
|
||||
response.set_cookie(PASSIVE_TRIED_COOKIE, value='1', max_age=None)
|
||||
response.set_cookie(PASSIVE_TRIED_COOKIE, value=opened_session_cookie, max_age=None)
|
||||
return response
|
||||
|
|
|
@ -335,6 +335,13 @@ class LoginView(ProfileMixin, LogMixin, View):
|
|||
return
|
||||
|
||||
utils.login(self.request, user)
|
||||
if (
|
||||
app_settings.OPENED_SESSION_COOKIE_NAME
|
||||
and app_settings.OPENED_SESSION_COOKIE_NAME in self.request.COOKIES
|
||||
):
|
||||
self.request.session['mellon_opened_session_cookie'] = self.request.COOKIES[
|
||||
app_settings.OPENED_SESSION_COOKIE_NAME
|
||||
]
|
||||
session_index = attributes['session_index']
|
||||
if session_index:
|
||||
if not self.request.session.session_key:
|
||||
|
|
|
@ -676,13 +676,14 @@ def test_passive_auth_middleware_ok(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('IDP_SESSION', '1')
|
||||
app.set_cookie('IDP_SESSION', '1234')
|
||||
response = app.get('/', headers={'Accept': 'text/html'}, 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 app.cookies['MELLON_PASSIVE_TRIED'] == '1234'
|
||||
|
||||
# simulate closing of session at IdP
|
||||
app.cookiejar.clear('testserver.local', '/', 'IDP_SESSION')
|
||||
|
@ -703,6 +704,26 @@ def test_passive_auth_middleware_ok(db, app, idp, caplog, settings):
|
|||
}
|
||||
assert 'MELLON_PASSIVE_TRIED' in app.cookies
|
||||
|
||||
# but not two times
|
||||
response = app.get('/', headers={'Accept': 'text/html'}, status=200)
|
||||
# if session change at IdP
|
||||
app.set_cookie('IDP_SESSION', 'abcd')
|
||||
# then we try again...
|
||||
response = app.get('/', headers={'Accept': 'text/html'}, status=302)
|
||||
|
||||
# ok, let's change again and login
|
||||
app.set_cookie('IDP_SESSION', '5678')
|
||||
response = app.get(reverse('mellon_login') + '?next=/whatever/')
|
||||
url, body, relay_state = idp.process_authn_request_redirect(response['Location'])
|
||||
response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state})
|
||||
assert app.session['mellon_opened_session_cookie'] == '5678'
|
||||
assert '_auth_user_id' in app.session
|
||||
# ok change the idp session id
|
||||
app.set_cookie('IDP_SESSION', '1234')
|
||||
# if we try a request, we are logged out and redirected to try a new passive login
|
||||
response = app.get('/', headers={'Accept': 'text/html'}, status=302)
|
||||
assert '_auth_user_id' not in app.session
|
||||
|
||||
|
||||
def test_passive_auth_middleware_no_passive_auth_parameter(db, app, idp, caplog, settings):
|
||||
settings.MELLON_OPENED_SESSION_COOKIE_NAME = 'IDP_SESSION'
|
||||
|
|
Loading…
Reference in New Issue