views: allow overriding the default return url after logout (#69740)
This commit is contained in:
parent
86d3cad3b8
commit
e98308d45c
|
@ -612,13 +612,13 @@ login = transaction.non_atomic_requests(csrf_exempt(LoginView.as_view()))
|
|||
|
||||
|
||||
class LogoutView(ProfileMixin, LogMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
def get(self, request, *args, logout_next_url='/', **kwargs):
|
||||
if 'SAMLRequest' in request.GET:
|
||||
return self.idp_logout(request, request.META['QUERY_STRING'], 'redirect')
|
||||
elif 'SAMLResponse' in request.GET:
|
||||
return self.sp_logout_response(request)
|
||||
return self.sp_logout_response(request, logout_next_url=logout_next_url)
|
||||
else:
|
||||
return self.sp_logout_request(request)
|
||||
return self.sp_logout_request(request, logout_next_url=logout_next_url)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
return self.idp_logout(request, force_str(request.body), 'soap')
|
||||
|
@ -721,14 +721,14 @@ class LogoutView(ProfileMixin, LogMixin, View):
|
|||
else:
|
||||
return HttpResponseRedirect(logout.msgUrl)
|
||||
|
||||
def sp_logout_request(self, request):
|
||||
def sp_logout_request(self, request, logout_next_url=None):
|
||||
'''Launch a logout request to the identity provider'''
|
||||
referer = request.headers.get('Referer')
|
||||
field_next_url = request.GET.get(REDIRECT_FIELD_NAME)
|
||||
next_url = None
|
||||
if field_next_url and utils.same_origin(request.build_absolute_uri(), field_next_url):
|
||||
next_url = field_next_url
|
||||
next_url = next_url or '/'
|
||||
next_url = next_url or logout_next_url
|
||||
if not referer or utils.same_origin(request.build_absolute_uri(), referer):
|
||||
if hasattr(request, 'user') and request.user.is_authenticated:
|
||||
logout = None
|
||||
|
@ -763,7 +763,7 @@ class LogoutView(ProfileMixin, LogMixin, View):
|
|||
self.log.warning('logout refused referer %r is not of the same origin', referer)
|
||||
return HttpResponseRedirect(next_url)
|
||||
|
||||
def sp_logout_response(self, request):
|
||||
def sp_logout_response(self, request, logout_next_url='/'):
|
||||
'''Launch a logout request to the identity provider'''
|
||||
self.profile = logout = utils.create_logout(request)
|
||||
logout.msgRelayState = request.GET.get('RelayState')
|
||||
|
@ -778,7 +778,7 @@ class LogoutView(ProfileMixin, LogMixin, View):
|
|||
self.log.warning('partial logout')
|
||||
except lasso.Error as e:
|
||||
self.log.warning('unable to process a logout response: %s', e)
|
||||
return HttpResponseRedirect(self.get_next_url() or '/')
|
||||
return HttpResponseRedirect(self.get_next_url() or logout_next_url)
|
||||
|
||||
|
||||
logout = csrf_exempt(LogoutView.as_view())
|
||||
|
|
|
@ -270,6 +270,32 @@ def test_sso_slo_next(db, app, idp, caplog, sp_settings):
|
|||
assert response.location == '/some/path/'
|
||||
|
||||
|
||||
def test_sso_slo_default_next_url(db, app, idp, caplog, sp_settings, rf):
|
||||
from mellon.views import logout
|
||||
|
||||
response = app.get(reverse('mellon_login'))
|
||||
url, body, relay_state = idp.process_authn_request_redirect(response['Location'])
|
||||
response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state})
|
||||
|
||||
request = rf.get('/logout/')
|
||||
request.session = app.session
|
||||
request.user = mock.Mock()
|
||||
request.user.is_authenticated = True
|
||||
response = logout(request, logout_next_url='/other/path/')
|
||||
assert list(request.session.values()) == ['/other/path/']
|
||||
|
||||
response = app.get(reverse('mellon_login'))
|
||||
url, body, relay_state = idp.process_authn_request_redirect(response['Location'])
|
||||
response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state})
|
||||
|
||||
request = rf.get('/logout/?next=/some/path/')
|
||||
request.session = app.session
|
||||
request.user = mock.Mock()
|
||||
request.user.is_authenticated = True
|
||||
response = logout(request, logout_next_url='/other/path/')
|
||||
assert list(request.session.values()) == ['/some/path/']
|
||||
|
||||
|
||||
def test_sso_idp_slo(db, app, idp, caplog, sp_settings):
|
||||
assert Session.objects.count() == 0
|
||||
assert User.objects.count() == 0
|
||||
|
|
Loading…
Reference in New Issue