0002-views-improve-handling-of-next_url-for-sp-initiated-.patch
mellon/views.py | ||
---|---|---|
612 | 612 | |
613 | 613 | |
614 | 614 |
class LogoutView(ProfileMixin, LogMixin, View): |
615 |
def get(self, request, *args, **kwargs): |
|
615 |
def get(self, request, *args, next_url=None, **kwargs):
|
|
616 | 616 |
if 'SAMLRequest' in request.GET: |
617 | 617 |
return self.idp_logout(request, request.META['QUERY_STRING'], 'redirect') |
618 | 618 |
elif 'SAMLResponse' in request.GET: |
619 | 619 |
return self.sp_logout_response(request) |
620 | 620 |
else: |
621 |
return self.sp_logout_request(request) |
|
621 |
return self.sp_logout_request(request, next_url=next_url)
|
|
622 | 622 | |
623 | 623 |
def post(self, request, *args, **kwargs): |
624 | 624 |
return self.idp_logout(request, force_str(request.body), 'soap') |
... | ... | |
721 | 721 |
else: |
722 | 722 |
return HttpResponseRedirect(logout.msgUrl) |
723 | 723 | |
724 |
def sp_logout_request(self, request): |
|
724 |
def sp_logout_request(self, request, next_url=None):
|
|
725 | 725 |
'''Launch a logout request to the identity provider''' |
726 |
next_url = request.GET.get(REDIRECT_FIELD_NAME) |
|
727 | 726 |
referer = request.headers.get('Referer') |
727 |
if not next_url: |
|
728 |
field_next_url = request.GET.get(REDIRECT_FIELD_NAME) |
|
729 |
if field_next_url and utils.same_origin(request.build_absolute_uri(), field_next_url): |
|
730 |
next_url = field_next_url |
|
731 |
next_url = next_url or '/' |
|
728 | 732 |
if not referer or utils.same_origin(request.build_absolute_uri(), referer): |
729 | 733 |
if hasattr(request, 'user') and request.user.is_authenticated: |
730 | 734 |
logout = None |
... | ... | |
754 | 758 |
self.log.info('user logged out, SLO request sent to IdP') |
755 | 759 |
else: |
756 | 760 |
# anonymous user: if next_url is None redirect to referer |
757 |
return HttpResponseRedirect(next_url or referer)
|
|
761 |
return HttpResponseRedirect(next_url) |
|
758 | 762 |
else: |
759 | 763 |
self.log.warning('logout refused referer %r is not of the same origin', referer) |
760 | 764 |
return HttpResponseRedirect(next_url) |
tests/test_sso_slo.py | ||
---|---|---|
254 | 254 | |
255 | 255 |
# again, user is already logged out |
256 | 256 |
response = app.get(reverse('mellon_logout'), extra_environ={'HTTP_REFERER': '/some/path'}) |
257 |
assert urlparse.urlparse(response['Location']).path == '/some/path'
|
|
257 |
assert urlparse.urlparse(response['Location']).path == '/' |
|
258 | 258 | |
259 | 259 | |
260 | 260 |
def test_sso_slo_next(db, app, idp, caplog, sp_settings): |
261 | 261 |
response = app.get(reverse('mellon_login')) |
262 | 262 |
url, body, relay_state = idp.process_authn_request_redirect(response['Location']) |
263 | 263 |
response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state}) |
264 |
response = app.get(reverse('mellon_logout') + '?next=/some/path/') |
|
264 |
response = app.get( |
|
265 |
reverse('mellon_logout') + '?next=/some/path/', extra_environ={'HTTP_REFERER': '/other/path'} |
|
266 |
) |
|
265 | 267 |
assert urlparse.urlparse(response['Location']).path == '/singleLogout' |
266 | 268 |
url = idp.process_logout_request_redirect(response.location) |
267 | 269 |
response = app.get(url) |
268 | 270 |
assert response.location == '/some/path/' |
269 | 271 | |
270 | 272 | |
273 |
def test_sso_slo_forced_next(db, app, idp, caplog, sp_settings, rf): |
|
274 |
from mellon.views import logout |
|
275 | ||
276 |
response = app.get(reverse('mellon_login')) |
|
277 |
url, body, relay_state = idp.process_authn_request_redirect(response['Location']) |
|
278 |
response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state}) |
|
279 | ||
280 |
request = rf.get('/logout/?next=/some/path/') |
|
281 |
request.session = app.session |
|
282 |
request.user = mock.Mock() |
|
283 |
request.user.is_authenticated = True |
|
284 |
response = logout(request, next_url='/other/path/') |
|
285 |
assert list(request.session.values()) == ['/other/path/'] |
|
286 | ||
287 | ||
271 | 288 |
def test_sso_idp_slo(db, app, idp, caplog, sp_settings): |
272 | 289 |
assert Session.objects.count() == 0 |
273 | 290 |
assert User.objects.count() == 0 |
274 |
- |