From f09875e53d45c126adcedd9d3661571e26ba803e Mon Sep 17 00:00:00 2001 From: Kieran Spear Date: Mon, 25 Feb 2013 15:19:09 +1100 Subject: [PATCH] Support custom redirect url from the 'switch' view The 'login' view currently accepts a parameter specifying the URL to redirect to after a successful login (via ?next=). This adds the same support for the 'switch' view by reusing a couple of lines of code from the Django login view. --- openstack_auth/tests/tests.py | 16 ++++++++++++++-- openstack_auth/views.py | 12 ++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/openstack_auth/tests/tests.py b/openstack_auth/tests/tests.py index 1f555a3..b02609d 100644 --- a/openstack_auth/tests/tests.py +++ b/openstack_auth/tests/tests.py @@ -1,5 +1,6 @@ from django import test from django.conf import settings +from django.contrib.auth import REDIRECT_FIELD_NAME from django.core.urlresolvers import reverse from keystoneclient import exceptions as keystone_exceptions @@ -156,7 +157,7 @@ class OpenStackAuthTests(test.TestCase): ("An error occurred authenticating. Please try " "again later.")) - def test_switch(self): + def test_switch(self, next=None): tenant = self.data.tenant_two tenants = [self.data.tenant_one, self.data.tenant_two] user = self.data.user @@ -211,8 +212,19 @@ class OpenStackAuthTests(test.TestCase): sc.catalog['token']['id'] = self.data.tenant_two.id form_data['tenant_id'] = tenant.id + + if next: + form_data.update({REDIRECT_FIELD_NAME: next}) + response = self.client.get(url, form_data) - self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) + if next: + expected_url = 'http://testserver%s' % next + self.assertEqual(response['location'], expected_url) + else: + self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) self.assertEqual(self.client.session['token']['token']['tenant']['id'], scoped.tenant['id']) + + def test_switch_with_next(self): + self.test_switch(next='/next_url') diff --git a/openstack_auth/views.py b/openstack_auth/views.py index af08be0..4c01ffa 100644 --- a/openstack_auth/views.py +++ b/openstack_auth/views.py @@ -10,6 +10,7 @@ from django.contrib.auth.views import (login as django_login, from django.contrib.auth.decorators import login_required from django.views.decorators.debug import sensitive_post_parameters from django.utils.functional import curry +from django.utils.http import is_safe_url from django.views.decorators.cache import never_cache from django.views.decorators.csrf import csrf_protect @@ -87,7 +88,7 @@ def delete_all_tokens(token_list): @login_required -def switch(request, tenant_id): +def switch(request, tenant_id, redirect_field_name=REDIRECT_FIELD_NAME): """ Switches an authenticated user from one tenant to another. """ LOG.debug('Switching to tenant %s for user "%s".' % (tenant_id, request.user.username)) @@ -99,7 +100,14 @@ def switch(request, tenant_id): except keystone_exceptions.ClientException: token = None LOG.exception('An error occurred while switching sessions.') + + # Ensure the user-originating redirection url is safe. + # Taken from django.contrib.auth.views.login() + redirect_to = request.REQUEST.get(redirect_field_name, '') + if not is_safe_url(url=redirect_to, host=request.get_host()): + redirect_to = settings.LOGIN_REDIRECT_URL + if token: user = create_user_from_token(request, token, endpoint) set_session_from_user(request, user) - return shortcuts.redirect(settings.LOGIN_REDIRECT_URL) + return shortcuts.redirect(redirect_to)