Skip to content

Commit

Permalink
Merge pull request #51 from johngian/next-url
Browse files Browse the repository at this point in the history
Redirect to `next` on login success.
  • Loading branch information
johngian committed Nov 15, 2016
2 parents f7be3e8 + 38ebd6c commit 72ed275
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
5 changes: 4 additions & 1 deletion mozilla_django_oidc/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def failure_url(self):

@property
def success_url(self):
return import_from_settings('LOGIN_REDIRECT_URL', '/')
next_url = self.request.session.get('oidc_login_next', None)
return next_url or import_from_settings('LOGIN_REDIRECT_URL', '/')

def login_failure(self):
return HttpResponseRedirect(self.failure_url)
Expand Down Expand Up @@ -70,6 +71,7 @@ def __init__(self, *args, **kwargs):
def get(self, request):
"""OIDC client authentication initialization HTTP endpoint"""
state = get_random_string(import_from_settings('OIDC_STATE_SIZE', 32))
redirect_field_name = import_from_settings('OIDC_REDIRECT_FIELD_NAME', 'next')

params = {
'response_type': 'code',
Expand All @@ -80,6 +82,7 @@ def get(self, request):
}

request.session['oidc_state'] = state
request.session['oidc_login_next'] = request.GET.get(redirect_field_name)

query = urlencode(params)
redirect_url = '{url}?{query}'.format(url=self.OIDC_OP_AUTH_ENDPOINT, query=query)
Expand Down
56 changes: 54 additions & 2 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ def setUp(self):
def test_get_auth_success(self):
"""Test successful callback request to RP."""
user = User.objects.create_user('example_username')
user.is_active = True
user.save()

get_data = {
'code': 'example_code',
Expand All @@ -49,6 +47,34 @@ def test_get_auth_success(self):
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, '/success')

@override_settings(LOGIN_REDIRECT_URL='/success')
def test_get_auth_success_next_url(self):
"""Test successful callback request to RP with custom `next` url."""
user = User.objects.create_user('example_username')

get_data = {
'code': 'example_code',
'state': 'example_state'
}
url = reverse('oidc_authentication_callback')
request = self.factory.get(url, get_data)
request.session = {
'oidc_state': 'example_state',
'oidc_login_next': '/foobar'
}
callback_view = views.OIDCAuthenticationCallbackView.as_view()

with patch('mozilla_django_oidc.views.auth.authenticate') as mock_auth:
with patch('mozilla_django_oidc.views.auth.login') as mock_login:
mock_auth.return_value = user
response = callback_view(request)

mock_auth.assert_called_once_with(code='example_code', state='example_state')
mock_login.assert_called_once_with(request, user)

self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, '/foobar')

@override_settings(LOGIN_REDIRECT_URL_FAILURE='/failure')
def test_get_auth_failure_nonexisting_user(self):
"""Test unsuccessful authentication and redirect url."""
Expand Down Expand Up @@ -193,3 +219,29 @@ def test_get(self, mock_random_string):
self.assertDictEqual(parse_qs(o.query), expected_query)
self.assertEqual(o.hostname, 'server.example.com')
self.assertEqual(o.path, '/auth')

@override_settings(OIDC_OP_AUTHORIZATION_ENDPOINT='https://server.example.com/auth')
@override_settings(OIDC_RP_CLIENT_ID='example_id')
def test_next_url(self):
"""Test that `next` url gets stored to user session."""
url = reverse('oidc_authentication_init')
request = self.factory.get('{url}?{params}'.format(url=url, params='next=/foo'))
request.session = dict()
login_view = views.OIDCAuthenticationRequestView.as_view()
login_view(request)
self.assertTrue('oidc_login_next' in request.session)
self.assertEqual(request.session['oidc_login_next'], '/foo')

@override_settings(OIDC_OP_AUTHORIZATION_ENDPOINT='https://server.example.com/auth')
@override_settings(OIDC_RP_CLIENT_ID='example_id')
def test_missing_next_url(self):
"""Test that `next` url gets invalidated in user session."""
url = reverse('oidc_authentication_init')
request = self.factory.get(url)
request.session = {
'oidc_login_next': 'foobar'
}
login_view = views.OIDCAuthenticationRequestView.as_view()
login_view(request)
self.assertTrue('oidc_login_next' in request.session)
self.assertTrue(request.session['oidc_login_next'] is None)

0 comments on commit 72ed275

Please sign in to comment.