Skip to content

Commit

Permalink
allow sub-authenticators to be specified as dicts
Browse files Browse the repository at this point in the history
will be clearer especially in declarative config like helm chart yaml
  • Loading branch information
minrk committed Oct 19, 2024
1 parent a999a2d commit 3606d07
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 114 deletions.
49 changes: 32 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,38 @@ class MyPamAutenticator(PAMAuthenticator):
login_service = "PAM"

c.MultiAuthenticator.authenticators = [
('github', '/github', {
'client_id': 'XXXX',
'client_secret': 'YYYY',
'oauth_callback_url': 'https://jupyterhub.example.com/hub/github/oauth_callback'
}),
('google', '/google', {
'client_id': 'xxxx',
'client_secret': 'yyyy',
'oauth_callback_url': 'https://jupyterhub.example.com/hub/google/oauth_callback'
}),
('gitlab', '/gitlab', {
"client_id": "ZZZZ",
"client_secret": "AAAAA",
"oauth_callback_url": "https://jupyterhub.example.com/hub/gitlab/oauth_callback",
"gitlab_url": "https://gitlab.example.com"
}),
(MyPamAutenticator, "/pam", {}),
{
"authenticator_class": 'github',
"url_prefix": '/github',
"config": {
'client_id': 'XXXX',
'client_secret': 'YYYY',
'oauth_callback_url': 'https://jupyterhub.example.com/hub/github/oauth_callback'
}
},
{
"authenticator_class": 'google',
"url_prefix": '/google',
"config": {
'client_id': 'xxxx',
'client_secret': 'yyyy',
'oauth_callback_url': 'https://jupyterhub.example.com/hub/google/oauth_callback'
}
},
{
"authenticator_class": 'gitlab',
"url_prefix": '/gitlab',
"config": {
'client_id': 'ZZZZ',
'client_secret': 'AAAA',
'oauth_callback_url': 'https://jupyterhub.example.com/hub/gitlab/oauth_callback'
"gitlab_url": "https://gitlab.example.com"
}
},
{
"authenticator_class": MyPamAuthenticator,
"url_prefix": "/pam",
},
]

c.JupyterHub.authenticator_class = 'multiauthenticator'
Expand Down
57 changes: 41 additions & 16 deletions multiauthenticator/multiauthenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,28 @@
Example of configuration:
c.MultiAuthenticator.authenticators = [
("github", '/github', {
'client_id': 'xxxx',
'client_secret': 'xxxx',
'oauth_callback_url': 'http://example.com/hub/github/oauth_callback'
}),
("google", '/google', {
'client_id': 'xxxx',
'client_secret': 'xxxx',
'oauth_callback_url': 'http://example.com/hub/google/oauth_callback'
}),
("pam", "/pam", {"service_name": "PAM"}),
{
"authenticator_class": 'github',
"url_prefix": '/github',
"config": {
'client_id': 'XXXX',
'client_secret': 'YYYY',
'oauth_callback_url': 'https://jupyterhub.example.com/hub/github/oauth_callback'
}
},
{
"authenticator_class": 'google',
"url_prefix": '/google',
"config": {
'client_id': 'xxxx',
'client_secret': 'yyyy',
'oauth_callback_url': 'https://jupyterhub.example.com/hub/google/oauth_callback'
}
},
{
"authenticator_class": "pam",
"url_prefix": "/pam",
},
]
c.JupyterHub.authenticator_class = 'multiauthenticator'
Expand All @@ -30,6 +41,7 @@
from importlib_metadata import entry_points
except ImportError:
from importlib.metadata import entry_points
import warnings

from jupyterhub.auth import Authenticator
from jupyterhub.utils import url_path_join
Expand Down Expand Up @@ -95,11 +107,24 @@ class MultiAuthenticator(Authenticator):
def __init__(self, *arg, **kwargs):
super().__init__(*arg, **kwargs)
self._authenticators = []
for (
authenticator_klass,
url_scope_authenticator,
authenticator_configuration,
) in self.authenticators:
for entry in self.authenticators:
if isinstance(entry, (list, tuple)):
tuple_entry = entry
entry = {
"authenticator_class": tuple_entry[0],
"url_prefix": tuple_entry[1],
"config": tuple_entry[2],
}
warnings.warn(
"Configuring subauthenticators with tuples is deprecated."
f" Use a dict like: {entry!r}",
DeprecationWarning,
)

authenticator_klass = entry["authenticator_class"]
url_scope_authenticator = entry["url_prefix"]
authenticator_configuration = entry.get("config", {})

if isinstance(authenticator_klass, str):
authenticator_klass = _load_authenticator(authenticator_klass)

Expand Down
65 changes: 40 additions & 25 deletions multiauthenticator/tests/test_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,26 @@ def test_service_name():
gitlab_service_name = "gitlab-service"
google_service_name = "google-service"
authenticators = [
(
GitLabOAuthenticator,
"/gitlab",
{
{
"authenticator_class": GitLabOAuthenticator,
"url_prefix": "/gitlab",
"config": {
"service_name": gitlab_service_name,
"client_id": "xxxx",
"client_secret": "xxxx",
"oauth_callback_url": "http://example.com/hub/gitlab/oauth_callback",
},
),
(
GoogleOAuthenticator,
"/google",
{
},
{
"authenticator_class": GoogleOAuthenticator,
"url_prefix": "/google",
"config": {
"service_name": google_service_name,
"client_id": "xxxx",
"client_secret": "xxxx",
"oauth_callback_url": "http://example.com/hub/othergoogle/oauth_callback",
},
),
},
]
MultiAuthenticator.authenticators = authenticators

Expand All @@ -49,26 +49,26 @@ def test_service_name():

def test_same_authenticators():
MultiAuthenticator.authenticators = [
(
GoogleOAuthenticator,
"/mygoogle",
{
{
"authenticator_class": GoogleOAuthenticator,
"url_prefix": "/mygoogle",
"config": {
"service_name": "My Google",
"client_id": "yyyyy",
"client_secret": "yyyyy",
"oauth_callback_url": "http://example.com/hub/mygoogle/oauth_callback",
},
),
(
GoogleOAuthenticator,
"/othergoogle",
{
},
{
"authenticator_class": GoogleOAuthenticator,
"url_prefix": "/othergoogle",
"config": {
"service_name": "Other Google",
"client_id": "xxxx",
"client_secret": "xxxx",
"oauth_callback_url": "http://example.com/hub/othergoogle/oauth_callback",
},
),
},
]

multi_authenticator = MultiAuthenticator()
Expand All @@ -89,11 +89,11 @@ def test_same_authenticators():

def test_username_prefix_validation_with_service_name(invalid_name, caplog):
MultiAuthenticator.authenticators = [
(
PAMAuthenticator,
"/pam",
{"service_name": invalid_name, "allowed_users": {"test"}},
),
{
"authenticator_class": PAMAuthenticator,
"url_prefix": "/pam",
"config": {"service_name": invalid_name, "allowed_users": {"test"}},
},
]

with pytest.raises(ValueError) as excinfo:
Expand All @@ -105,3 +105,18 @@ def test_username_prefix_validation_with_service_name(invalid_name, caplog):
caplog.records[0].message
== "service_name is deprecated, please create a subclass and set the login_service class variable"
)


def test_tuple_config():
MultiAuthenticator.authenticators = [
(
PAMAuthenticator,
"/pam",
{"service_name": "pam", "allowed_users": {"test"}},
),
]
with pytest.deprecated_call():
authenticator = MultiAuthenticator()
sub_authenticator = authenticator._authenticators[0]
assert sub_authenticator.service_name == "pam"
assert sub_authenticator.allowed_users == {"test"}
Loading

0 comments on commit 3606d07

Please sign in to comment.