From 7496b2f0360ce6db42eb408888b6fbc96ab2b4f0 Mon Sep 17 00:00:00 2001 From: Wojciech Bartosiak Date: Fri, 27 Jan 2017 09:05:25 +0100 Subject: [PATCH] OIDC_POST_END_SESSION_HOOK + tests --- oidc_provider/lib/utils/common.py | 27 +++++++++++++++++++ oidc_provider/settings.py | 8 ++++++ .../tests/test_end_session_endpoint.py | 8 ++++++ oidc_provider/views.py | 11 ++++++++ 4 files changed, 54 insertions(+) diff --git a/oidc_provider/lib/utils/common.py b/oidc_provider/lib/utils/common.py index b7a6676..52bb962 100644 --- a/oidc_provider/lib/utils/common.py +++ b/oidc_provider/lib/utils/common.py @@ -84,6 +84,33 @@ def default_after_userlogin_hook(request, user, client): """ 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): """ Hook to perform some additional actions ti `id_token` dictionary just before serialization. diff --git a/oidc_provider/settings.py b/oidc_provider/settings.py index 610534c..20f2f78 100644 --- a/oidc_provider/settings.py +++ b/oidc_provider/settings.py @@ -30,6 +30,14 @@ class DefaultSettings(object): """ 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 def OIDC_CODE_EXPIRE(self): """ diff --git a/oidc_provider/tests/test_end_session_endpoint.py b/oidc_provider/tests/test_end_session_endpoint.py index 46d9cc0..6982704 100644 --- a/oidc_provider/tests/test_end_session_endpoint.py +++ b/oidc_provider/tests/test_end_session_endpoint.py @@ -11,6 +11,7 @@ from oidc_provider.tests.app.utils import ( create_fake_client, create_fake_user, ) +import mock class EndSessionTestCase(TestCase): @@ -44,3 +45,10 @@ class EndSessionTestCase(TestCase): response = self.client.get(self.url, query_params) 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)) + diff --git a/oidc_provider/views.py b/oidc_provider/views.py index 6bf142f..ffc60c4 100644 --- a/oidc_provider/views.py +++ b/oidc_provider/views.py @@ -264,8 +264,10 @@ class EndSessionView(View): id_token_hint = request.GET.get('id_token_hint', '') post_logout_redirect_uri = request.GET.get('post_logout_redirect_uri', '') state = request.GET.get('state', '') + client = None next_page = settings.get('LOGIN_URL') + post_end_session_hook = settings.get('OIDC_POST_END_SESSION_HOOK', import_str=True) if id_token_hint: client_id = client_id_from_id_token(id_token_hint) @@ -283,6 +285,15 @@ class EndSessionView(View): except Client.DoesNotExist: 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)