From 7f8eef5e196cf3c1562bf59233e336f3c3e47927 Mon Sep 17 00:00:00 2001 From: YuviPanda Date: Thu, 25 Jan 2024 14:05:21 -0800 Subject: [PATCH 1/2] Note that you can throw a 403 from check_allowed From https://github.com/jupyterhub/oauthenticator/pull/719#pullrequestreview-1838530737 --- jupyterhub/auth.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jupyterhub/auth.py b/jupyterhub/auth.py index aa5430d3..bd29e94a 100644 --- a/jupyterhub/auth.py +++ b/jupyterhub/auth.py @@ -453,7 +453,10 @@ class Authenticator(LoggingConfigurable): def check_allowed(self, username, authentication=None): """Check if a username is allowed to authenticate based on configuration - Return True if username is allowed, False otherwise. + Return True if username is allowed, False otherwise. Subclasses can also + raise a `web.HTTPError(403, message)` to immediately *deny* access and show + the end user the given message. + No allowed_users set means any username is allowed. Names are normalized *before* being checked against the allowed set. From be1848fba02dfaec11ae070efddc2ddb924bfdf3 Mon Sep 17 00:00:00 2001 From: Min RK Date: Mon, 4 Mar 2024 10:42:41 +0100 Subject: [PATCH 2/2] clarify that web.HTTPError may be raised anywhere in the auth process --- jupyterhub/auth.py | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/jupyterhub/auth.py b/jupyterhub/auth.py index bd29e94a..705ba5d4 100644 --- a/jupyterhub/auth.py +++ b/jupyterhub/auth.py @@ -453,9 +453,7 @@ class Authenticator(LoggingConfigurable): def check_allowed(self, username, authentication=None): """Check if a username is allowed to authenticate based on configuration - Return True if username is allowed, False otherwise. Subclasses can also - raise a `web.HTTPError(403, message)` to immediately *deny* access and show - the end user the given message. + Return True if username is allowed, False otherwise. No allowed_users set means any username is allowed. @@ -466,6 +464,18 @@ class Authenticator(LoggingConfigurable): .. versionchanged:: 1.2 Renamed check_whitelist to check_allowed + + Args: + username (str): + The normalized username + authentication (dict): + The authentication model, as returned by `.authenticate()`. + Returns: + allowed (bool): + Whether the user is allowed + Raises: + web.HTTPError(403): + Raising HTTPErrors directly allows customizing the message shown to the user. """ if not self.allowed_users: # No allowed set means any name is allowed @@ -487,6 +497,18 @@ class Authenticator(LoggingConfigurable): .. versionchanged:: 1.2 Renamed check_blacklist to check_blocked_users + + Args: + username (str): + The normalized username + authentication (dict): + The authentication model, as returned by `.authenticate()`. + Returns: + allowed (bool): + Whether the user is allowed + Raises: + web.HTTPError(403, message): + Raising HTTPErrors directly allows customizing the message shown to the user. """ if not self.blocked_users: # No block list means any name is allowed @@ -612,6 +634,12 @@ class Authenticator(LoggingConfigurable): It must return the username on successful authentication, and return None on failed authentication. + Subclasses can also raise a `web.HTTPError(403, message)` + in order to halt the authentication process + and customize the error message that will be shown to the user. + This error may be raised anywhere in the authentication process + (`authenticate`, `check_allowed`, `check_blocked_users`). + Checking allowed_users/blocked_users is handled separately by the caller. .. versionchanged:: 0.8 @@ -634,6 +662,9 @@ class Authenticator(LoggingConfigurable): - `groups`, the list of group names the user should be a member of, if Authenticator.manage_groups is True. `groups` MUST always be present if manage_groups is enabled. + Raises: + web.HTTPError(403): + Raising errors directly allows customizing the message shown to the user. """ def pre_spawn_start(self, user, spawner):