Projet

Général

Profil

0001-views-use-MELLON_OPENED_SESSION-to-anchor-local-sess.patch

Benjamin Dauvergne, 29 juin 2022 07:30

Télécharger (5,39 ko)

Voir les différences:

Subject: [PATCH] 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.
 mellon/middleware.py  | 14 +++++++++++---
 mellon/views.py       |  7 +++++++
 tests/test_sso_slo.py | 23 ++++++++++++++++++++++-
 3 files changed, 40 insertions(+), 4 deletions(-)
mellon/middleware.py
14 14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 15

  
16 16

  
17
from django.contrib import auth
17 18
from django.http import HttpResponseRedirect
18 19
from django.urls import reverse
19 20
from django.utils.deprecation import MiddlewareMixin
......
58 59
        if not app_settings.OPENED_SESSION_COOKIE_NAME:
59 60
            return
60 61
        if hasattr(request, 'user') and request.user.is_authenticated:
61
            return
62
        if PASSIVE_TRIED_COOKIE in request.COOKIES:
62
            # close current session if the opened session cookie changed...
63
            old_opened_session_cookie = request.session.get('mellon_opened_session_cookie')
64
            if old_opened_session_cookie and old_opened_session_cookie != request.COOKIES.get(
65
                app_settings.OPENED_SESSION_COOKIE_NAME
66
            ):
67
                auth.logout(request)
63 68
            return
64 69
        if app_settings.OPENED_SESSION_COOKIE_NAME not in request.COOKIES:
65 70
            return
71
        opened_session_cookie = request.COOKIES[app_settings.OPENED_SESSION_COOKIE_NAME]
72
        if request.COOKIES.get(PASSIVE_TRIED_COOKIE) == opened_session_cookie:
73
            return
66 74
        # all is good, try passive login
67 75
        params = {
68 76
            'next': request.build_absolute_uri(),
......
71 79
        url = reverse('mellon_login') + '?%s' % urlencode(params)
72 80
        response = HttpResponseRedirect(url)
73 81
        # prevent loops
74
        response.set_cookie(PASSIVE_TRIED_COOKIE, value='1', max_age=None)
82
        response.set_cookie(PASSIVE_TRIED_COOKIE, value=opened_session_cookie, max_age=None)
75 83
        return response
mellon/views.py
335 335
            return
336 336

  
337 337
        utils.login(self.request, user)
338
        if (
339
            app_settings.OPENED_SESSION_COOKIE_NAME
340
            and app_settings.OPENED_SESSION_COOKIE_NAME in self.request.COOKIES
341
        ):
342
            self.request.session['mellon_opened_session_cookie'] = self.request.COOKIES[
343
                app_settings.OPENED_SESSION_COOKIE_NAME
344
            ]
338 345
        session_index = attributes['session_index']
339 346
        if session_index:
340 347
            if not self.request.session.session_key:
tests/test_sso_slo.py
676 676
    settings.MELLON_OPENED_SESSION_COOKIE_NAME = 'IDP_SESSION'
677 677
    assert 'MELLON_PASSIVE_TRIED' not in app.cookies
678 678
    # webtest-lint is against unicode
679
    app.set_cookie('IDP_SESSION', '1')
679
    app.set_cookie('IDP_SESSION', '1234')
680 680
    response = app.get('/', headers={'Accept': 'text/html'}, status=302)
681 681
    assert urlparse.urlparse(response.location).path == '/login/'
682 682
    assert urlparse.parse_qs(urlparse.urlparse(response.location).query, keep_blank_values=True) == {
683 683
        'next': ['http://testserver/'],
684 684
        'passive': [''],
685 685
    }
686
    assert app.cookies['MELLON_PASSIVE_TRIED'] == '1234'
686 687

  
687 688
    # simulate closing of session at IdP
688 689
    app.cookiejar.clear('testserver.local', '/', 'IDP_SESSION')
......
703 704
    }
704 705
    assert 'MELLON_PASSIVE_TRIED' in app.cookies
705 706

  
707
    # but not two times
708
    response = app.get('/', headers={'Accept': 'text/html'}, status=200)
709
    # if session change at IdP
710
    app.set_cookie('IDP_SESSION', 'abcd')
711
    # then we try again...
712
    response = app.get('/', headers={'Accept': 'text/html'}, status=302)
713

  
714
    # ok, let's change again and login
715
    app.set_cookie('IDP_SESSION', '5678')
716
    response = app.get(reverse('mellon_login') + '?next=/whatever/')
717
    url, body, relay_state = idp.process_authn_request_redirect(response['Location'])
718
    response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state})
719
    assert app.session['mellon_opened_session_cookie'] == '5678'
720
    assert '_auth_user_id' in app.session
721
    # ok change the idp session id
722
    app.set_cookie('IDP_SESSION', '1234')
723
    response = app.get('/', headers={'Accept': 'text/html'}, status=200)
724
    # we are automatically unlogged
725
    assert '_auth_user_id' not in app.session
726

  
706 727

  
707 728
def test_passive_auth_middleware_no_passive_auth_parameter(db, app, idp, caplog, settings):
708 729
    settings.MELLON_OPENED_SESSION_COOKIE_NAME = 'IDP_SESSION'
709
-