Merge pull request #11 from juanifioren/develop

Develop
This commit is contained in:
Wojciech Bartosiak 2017-03-28 09:50:14 +01:00 committed by GitHub
commit af57fd0056
6 changed files with 94 additions and 1 deletions

View file

@ -207,7 +207,7 @@ class AuthorizeEndpoint(object):
query_fragment['session_state'] = session_state query_fragment['session_state'] = session_state
except Exception as error: except Exception as error:
logger.debug('[Authorize] Error when trying to create response uri: %s', error) logger.exception('[Authorize] Error when trying to create response uri: %s', error)
raise AuthorizeError(self.params['redirect_uri'], 'server_error', self.grant_type) raise AuthorizeError(self.params['redirect_uri'], 'server_error', self.grant_type)
uri = uri._replace(query=urlencode(query_params, doseq=True), fragment=uri.fragment + urlencode(query_fragment, doseq=True)) uri = uri._replace(query=urlencode(query_params, doseq=True), fragment=uri.fragment + urlencode(query_fragment, doseq=True))

View file

@ -84,6 +84,33 @@ def default_after_userlogin_hook(request, user, client):
""" """
return None return None
def default_post_end_session_hook(request, id_token=None, post_logout_redirect_uri=None, state=None, client=None, next_page=None):
"""
Default function for setting OIDC_POST_END_SESSION_HOOK.
:param request: Django request object
:type request: django.http.HttpRequest
:param id_token: token passed by `id_token_hint` url query param - do NOT trust this param or validate token
:type id_token: str
:param post_logout_redirect_uri: redirect url from url query param - do NOT trust this param
:type post_logout_redirect_uri: str
:param state: state param from url query params
:type state: str
:param client: If id_token has `aud` param and associated Client exists, this is an instance of it - do NOT trust this param
:type client: oidc_provider.models.Client
:param next_page: calculated next_page redirection target
:type next_page: str
:return:
"""
return None
def default_idtoken_processing_hook(id_token, user): def default_idtoken_processing_hook(id_token, user):
""" """
Hook to perform some additional actions ti `id_token` dictionary just before serialization. Hook to perform some additional actions ti `id_token` dictionary just before serialization.

View file

@ -30,6 +30,14 @@ class DefaultSettings(object):
""" """
return 'oidc_provider.lib.utils.common.default_after_userlogin_hook' return 'oidc_provider.lib.utils.common.default_after_userlogin_hook'
@property
def OIDC_POST_END_SESSION_HOOK(self):
"""
OPTIONAL. Provide a way to plug into the end session process just before calling
Django's logout function, typically to perform some business logic.
"""
return 'oidc_provider.lib.utils.common.default_post_end_session_hook'
@property @property
def OIDC_CODE_EXPIRE(self): def OIDC_CODE_EXPIRE(self):
""" """

View file

@ -7,6 +7,7 @@ try:
except ImportError: except ImportError:
from urlparse import parse_qs, urlsplit from urlparse import parse_qs, urlsplit
import uuid import uuid
from mock import patch
from django.contrib.auth.models import AnonymousUser from django.contrib.auth.models import AnonymousUser
from django.core.management import call_command from django.core.management import call_command
@ -26,6 +27,7 @@ from oidc_provider.tests.app.utils import (
is_code_valid, is_code_valid,
) )
from oidc_provider.views import AuthorizeView from oidc_provider.views import AuthorizeView
from oidc_provider.lib.endpoints.authorize import AuthorizeEndpoint
class AuthorizeEndpointMixin(object): class AuthorizeEndpointMixin(object):
@ -498,3 +500,40 @@ class AuthorizationHybridFlowTestCase(TestCase, AuthorizeEndpointMixin):
response = self._auth_request('post', self.data, is_user_authenticated=True) response = self._auth_request('post', self.data, is_user_authenticated=True)
self.assertIn('expires_in=36000', response['Location']) self.assertIn('expires_in=36000', response['Location'])
class TestCreateResponseURI(TestCase):
def setUp(self):
url = reverse('oidc_provider:authorize')
user = create_fake_user()
client = create_fake_client(response_type='code', is_public=True)
# Base data to create a uri response
data = {
'client_id': client.client_id,
'redirect_uri': client.default_redirect_uri,
'response_type': client.response_type,
}
factory = RequestFactory()
self.request = factory.post(url, data=data)
self.request.user = user
@patch('oidc_provider.lib.endpoints.authorize.create_code')
@patch('oidc_provider.lib.endpoints.authorize.logger.exception')
def test_create_response_uri_logs_to_error(self, log_exception, create_code):
"""
A lot can go wrong when creating a response uri and this is caught with a general Exception error. The
information contained within this error should show up in the error log so production servers have something
to work with when things don't work as expected.
"""
exception = Exception("Something went wrong!")
create_code.side_effect = exception
authorization_endpoint = AuthorizeEndpoint(self.request)
authorization_endpoint.validate_params()
with self.assertRaises(Exception):
authorization_endpoint.create_response_uri()
log_exception.assert_called_once_with('[Authorize] Error when trying to create response uri: %s', exception)

View file

@ -11,6 +11,7 @@ from oidc_provider.tests.app.utils import (
create_fake_client, create_fake_client,
create_fake_user, create_fake_user,
) )
import mock
class EndSessionTestCase(TestCase): class EndSessionTestCase(TestCase):
@ -44,3 +45,10 @@ class EndSessionTestCase(TestCase):
response = self.client.get(self.url, query_params) response = self.client.get(self.url, query_params)
self.assertRedirects(response, self.LOGOUT_URL, fetch_redirect_response=False) self.assertRedirects(response, self.LOGOUT_URL, fetch_redirect_response=False)
@mock.patch(settings.get('OIDC_POST_END_SESSION_HOOK'))
def test_call_post_end_session_hook(self, hook_function):
self.client.get(self.url)
self.assertTrue(hook_function.called, 'OIDC_POST_END_SESSION_HOOK should be called')
self.assertTrue(hook_function.call_count == 1, 'OIDC_POST_END_SESSION_HOOK should be called once but was {}'.format(hook_function.call_count))

View file

@ -264,8 +264,10 @@ class EndSessionView(View):
id_token_hint = request.GET.get('id_token_hint', '') id_token_hint = request.GET.get('id_token_hint', '')
post_logout_redirect_uri = request.GET.get('post_logout_redirect_uri', '') post_logout_redirect_uri = request.GET.get('post_logout_redirect_uri', '')
state = request.GET.get('state', '') state = request.GET.get('state', '')
client = None
next_page = settings.get('LOGIN_URL') next_page = settings.get('LOGIN_URL')
post_end_session_hook = settings.get('OIDC_POST_END_SESSION_HOOK', import_str=True)
if id_token_hint: if id_token_hint:
client_id = client_id_from_id_token(id_token_hint) client_id = client_id_from_id_token(id_token_hint)
@ -283,6 +285,15 @@ class EndSessionView(View):
except Client.DoesNotExist: except Client.DoesNotExist:
pass pass
post_end_session_hook(
request=request,
id_token=id_token_hint,
post_logout_redirect_uri=post_logout_redirect_uri,
state=state,
client=client,
next_page=next_page
)
return logout(request, next_page=next_page) return logout(request, next_page=next_page)