From 3a2d2122e686987c08f4e0930743908672be267f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 02:27:02 -0500 Subject: [PATCH 01/10] Return forbidden in callback if user is not allowed expecting a custom exception. --- .gitignore | 1 + oauthadmin/errors.py | 8 ++++++++ oauthadmin/views.py | 13 +++++++++---- 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 oauthadmin/errors.py diff --git a/.gitignore b/.gitignore index e3f3570..24a8fff 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dist/ *.egg-info .tox/ .cache/ +*.swp diff --git a/oauthadmin/errors.py b/oauthadmin/errors.py new file mode 100644 index 0000000..364e940 --- /dev/null +++ b/oauthadmin/errors.py @@ -0,0 +1,8 @@ + + +class OAuthAdminException(Exception) + pass + + +class UserNotAllowed(OAuthAdminException): + pass diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 8a22bd5..4632924 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -11,12 +11,14 @@ from urllib.parse import quote_plus from django.shortcuts import redirect -from django.http import HttpResponseRedirect +from django.http import HttpResponseRedirect, HttpResponseForbidden -from oauthadmin.utils import import_by_path -from oauthadmin.settings import app_setting import oauthadmin.views +from oauthadmin.errors import UserNotAllowed +from oauthadmin.settings import app_setting +from oauthadmin.utils import import_by_path + try: from django.urls import reverse, NoReverseMatch except ImportError: @@ -82,7 +84,10 @@ def callback(request): except (MismatchingStateError, InvalidGrantError): return HttpResponseRedirect(request.build_absolute_uri(reverse(oauthadmin.views.login))) - user = import_by_path(app_setting('GET_USER'))(token) + try: + user = import_by_path(app_setting('GET_USER'))(token) + except UserNotAllowed: + return HttpResponseForbidden() request.session['last_verified_at'] = int(time()) request.session['oauth_token'] = token From 7c74f282f582699c13c498c717d7b7263745d9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 02:29:23 -0500 Subject: [PATCH 02/10] Minor edits. --- oauthadmin/errors.py | 2 -- oauthadmin/views.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/oauthadmin/errors.py b/oauthadmin/errors.py index 364e940..5d947d7 100644 --- a/oauthadmin/errors.py +++ b/oauthadmin/errors.py @@ -1,5 +1,3 @@ - - class OAuthAdminException(Exception) pass diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 4632924..f485b30 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -84,8 +84,9 @@ def callback(request): except (MismatchingStateError, InvalidGrantError): return HttpResponseRedirect(request.build_absolute_uri(reverse(oauthadmin.views.login))) + user_getter = import_by_path(app_setting('GET_USER')) try: - user = import_by_path(app_setting('GET_USER'))(token) + user = user_getter(token) except UserNotAllowed: return HttpResponseForbidden() From 6f165569541197dfd949af995bf432361b59dc22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 17:58:56 -0500 Subject: [PATCH 03/10] Typo fix. --- oauthadmin/errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oauthadmin/errors.py b/oauthadmin/errors.py index 5d947d7..aae1198 100644 --- a/oauthadmin/errors.py +++ b/oauthadmin/errors.py @@ -1,4 +1,4 @@ -class OAuthAdminException(Exception) +class OAuthAdminException(Exception): pass From 1086684f0d73d0c718be699b58a90315c3c89e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 18:26:50 -0500 Subject: [PATCH 04/10] Introduce FORBIDDEN_HANDLER setting. --- README.md | 2 ++ oauthadmin/views.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index c4a7549..359de25 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ Step 6: Set up all the correct options (see below for available options) * OAUTHADMIN_GET_USER: This is function that is given the oauth token and returns a django.auth.models.User model corresponding to the currently logged-in user. You can set permissions on this user object and stuff. + * OAUTHADMIN_FORBIDDEN_HANDLER: Callable that receives request object and OAuth token and should return + proper response for not allowed users. * OAUTHADMIN_CLIENT_ID: Your oAuth client ID * OAUTHADMIN_CLIENT_SECRET: oAuth client secret * OAUTHADMIN_BASE_URL: The landing point for all oAuth related queries. diff --git a/oauthadmin/views.py b/oauthadmin/views.py index f485b30..0ad1239 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -88,6 +88,9 @@ def callback(request): try: user = user_getter(token) except UserNotAllowed: + forbidden_handler = app_setting('FORBIDDEN_HANDLER') + if forbidden_handler: + return forbidden_handler(request, token) return HttpResponseForbidden() request.session['last_verified_at'] = int(time()) From 78d759d20aa774f37765d972c560b843f46cb139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 18:35:15 -0500 Subject: [PATCH 05/10] Rename handler to unauthorized. --- README.md | 4 ++-- oauthadmin/errors.py | 2 +- oauthadmin/views.py | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 359de25..a16a011 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ Step 6: Set up all the correct options (see below for available options) * OAUTHADMIN_GET_USER: This is function that is given the oauth token and returns a django.auth.models.User model corresponding to the currently logged-in user. You can set permissions on this user object and stuff. - * OAUTHADMIN_FORBIDDEN_HANDLER: Callable that receives request object and OAuth token and should return - proper response for not allowed users. + * OAUTHADMIN_UNAUTHORIZED_USER_HANDLER: Callable that receives request object and OAuth token + and should return proper response object for unauthorized users. * OAUTHADMIN_CLIENT_ID: Your oAuth client ID * OAUTHADMIN_CLIENT_SECRET: oAuth client secret * OAUTHADMIN_BASE_URL: The landing point for all oAuth related queries. diff --git a/oauthadmin/errors.py b/oauthadmin/errors.py index aae1198..edfca9c 100644 --- a/oauthadmin/errors.py +++ b/oauthadmin/errors.py @@ -2,5 +2,5 @@ class OAuthAdminException(Exception): pass -class UserNotAllowed(OAuthAdminException): +class UnauthorizedUser(OAuthAdminException): pass diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 0ad1239..76c9458 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -11,7 +11,7 @@ from urllib.parse import quote_plus from django.shortcuts import redirect -from django.http import HttpResponseRedirect, HttpResponseForbidden +from django.http import HttpResponse, HttpResponseRedirect import oauthadmin.views @@ -87,11 +87,11 @@ def callback(request): user_getter = import_by_path(app_setting('GET_USER')) try: user = user_getter(token) - except UserNotAllowed: - forbidden_handler = app_setting('FORBIDDEN_HANDLER') - if forbidden_handler: - return forbidden_handler(request, token) - return HttpResponseForbidden() + except UnauthorizedUser: + unauthorized_user_handler = app_setting('UNAUTHORIZED_USER_HANDLER') + if unauthorized_user_handler: + return unauthorized_user_handler(request, token) + return HttpResponse(status=401) request.session['last_verified_at'] = int(time()) request.session['oauth_token'] = token From 489d263ce3ba98858d80e415444c8f2829bba937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 18:38:13 -0500 Subject: [PATCH 06/10] Typo fix. --- oauthadmin/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 76c9458..3470327 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -15,7 +15,7 @@ import oauthadmin.views -from oauthadmin.errors import UserNotAllowed +from oauthadmin.errors import UnauthorizedUser from oauthadmin.settings import app_setting from oauthadmin.utils import import_by_path From 200702ea63e401f3d85a5e41b7170b931e9d787e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 18:47:07 -0500 Subject: [PATCH 07/10] Add exception as argument to handler callable. --- README.md | 4 ++-- oauthadmin/views.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a16a011..d3d2a6d 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ Step 6: Set up all the correct options (see below for available options) * OAUTHADMIN_GET_USER: This is function that is given the oauth token and returns a django.auth.models.User model corresponding to the currently logged-in user. You can set permissions on this user object and stuff. - * OAUTHADMIN_UNAUTHORIZED_USER_HANDLER: Callable that receives request object and OAuth token - and should return proper response object for unauthorized users. + * OAUTHADMIN_UNAUTHORIZED_USER_HANDLER: Callable that receives request object, OAuth token + and exception. This callable should return proper response object for unauthorized users. * OAUTHADMIN_CLIENT_ID: Your oAuth client ID * OAUTHADMIN_CLIENT_SECRET: oAuth client secret * OAUTHADMIN_BASE_URL: The landing point for all oAuth related queries. diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 3470327..5e6eda8 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -87,10 +87,10 @@ def callback(request): user_getter = import_by_path(app_setting('GET_USER')) try: user = user_getter(token) - except UnauthorizedUser: + except UnauthorizedUser as e: unauthorized_user_handler = app_setting('UNAUTHORIZED_USER_HANDLER') if unauthorized_user_handler: - return unauthorized_user_handler(request, token) + return unauthorized_user_handler(request, token, e) return HttpResponse(status=401) request.session['last_verified_at'] = int(time()) From 0f3509488768f2a4f378f93231ab363f8099bed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 18:54:57 -0500 Subject: [PATCH 08/10] Make get_user exception as generic for any validation logic. --- README.md | 5 +++-- oauthadmin/errors.py | 2 +- oauthadmin/views.py | 12 ++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d3d2a6d..46d8577 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,9 @@ Step 6: Set up all the correct options (see below for available options) * OAUTHADMIN_GET_USER: This is function that is given the oauth token and returns a django.auth.models.User model corresponding to the currently logged-in user. You can set permissions on this user object and stuff. - * OAUTHADMIN_UNAUTHORIZED_USER_HANDLER: Callable that receives request object, OAuth token - and exception. This callable should return proper response object for unauthorized users. + * OAUTHADMIN_GET_USER_EXCEPTION_HANDLER: Callable that receives request object, OAuth token + and exception to handle business logics such as unauthorized users. This callable should + return proper response object. * OAUTHADMIN_CLIENT_ID: Your oAuth client ID * OAUTHADMIN_CLIENT_SECRET: oAuth client secret * OAUTHADMIN_BASE_URL: The landing point for all oAuth related queries. diff --git a/oauthadmin/errors.py b/oauthadmin/errors.py index edfca9c..3509aef 100644 --- a/oauthadmin/errors.py +++ b/oauthadmin/errors.py @@ -2,5 +2,5 @@ class OAuthAdminException(Exception): pass -class UnauthorizedUser(OAuthAdminException): +class GetUserException(OAuthAdminException): pass diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 5e6eda8..3473662 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -15,7 +15,7 @@ import oauthadmin.views -from oauthadmin.errors import UnauthorizedUser +from oauthadmin.errors import GetUserException from oauthadmin.settings import app_setting from oauthadmin.utils import import_by_path @@ -87,11 +87,11 @@ def callback(request): user_getter = import_by_path(app_setting('GET_USER')) try: user = user_getter(token) - except UnauthorizedUser as e: - unauthorized_user_handler = app_setting('UNAUTHORIZED_USER_HANDLER') - if unauthorized_user_handler: - return unauthorized_user_handler(request, token, e) - return HttpResponse(status=401) + except GetUserException as e: + get_user_exception_handler = app_setting('GET_USER_EXCEPTION_HANDLER') + if get_user_exception_handler: + return get_user_exception_handler(request, token, e) + raise request.session['last_verified_at'] = int(time()) request.session['oauth_token'] = token From 73865cc68d71fe85e8f0e9aaf079fb636661eb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 19:01:39 -0500 Subject: [PATCH 09/10] Minor edit. --- oauthadmin/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 3473662..7d8b625 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -88,7 +88,7 @@ def callback(request): try: user = user_getter(token) except GetUserException as e: - get_user_exception_handler = app_setting('GET_USER_EXCEPTION_HANDLER') + get_user_exception_handler = import_by_path(app_setting('GET_USER_EXCEPTION_HANDLER')) if get_user_exception_handler: return get_user_exception_handler(request, token, e) raise From ed1551e70887a0183cc1a36ed05a27787dbc3e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Puente-Sarr=C3=ADn?= Date: Sat, 27 Oct 2018 19:05:30 -0500 Subject: [PATCH 10/10] Minor fixes --- oauthadmin/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/oauthadmin/views.py b/oauthadmin/views.py index 7d8b625..2887c26 100644 --- a/oauthadmin/views.py +++ b/oauthadmin/views.py @@ -88,8 +88,9 @@ def callback(request): try: user = user_getter(token) except GetUserException as e: - get_user_exception_handler = import_by_path(app_setting('GET_USER_EXCEPTION_HANDLER')) - if get_user_exception_handler: + get_user_exception_handler_module = app_setting('GET_USER_EXCEPTION_HANDLER') + if get_user_exception_handler_module: + get_user_exception_handler = import_by_path(get_user_exception_handler_module) return get_user_exception_handler(request, token, e) raise