diff --git a/README.md b/README.md index cc6868c..687db62 100644 --- a/README.md +++ b/README.md @@ -29,26 +29,23 @@ This property shall contain a list of tuple with the following content: As an example: ```python -from oauthenticator.github import GitHubOAuthenticator -from oauthenticator.google import GoogleOAuthenticator -from oauthenticator.gitlab import GitLabOAuthenticator from jupyterhub.auth import PAMAuthenticator class MyPamAutenticator(PAMAuthenticator): login_service = "PAM" c.MultiAuthenticator.authenticators = [ - (GitHubOAuthenticator, '/github', { + ('github', '/github', { 'client_id': 'XXXX', 'client_secret': 'YYYY', 'oauth_callback_url': 'https://jupyterhub.example.com/hub/github/oauth_callback' }), - (GoogleOAuthenticator, '/google', { + ('google', '/google', { 'client_id': 'xxxx', 'client_secret': 'yyyy', 'oauth_callback_url': 'https://jupyterhub.example.com/hub/google/oauth_callback' }), - (GitLabOAuthenticator, '/gitlab', { + ('gitlab', '/gitlab', { "client_id": "ZZZZ", "client_secret": "AAAAA", "oauth_callback_url": "https://jupyterhub.example.com/hub/gitlab/oauth_callback", @@ -57,5 +54,5 @@ c.MultiAuthenticator.authenticators = [ (MyPamAutenticator, "/pam", {}), ] -c.JupyterHub.authenticator_class = 'multiauthenticator.multiauthenticator.MultiAuthenticator' +c.JupyterHub.authenticator_class = 'multiauthenticator' ``` diff --git a/multiauthenticator/multiauthenticator.py b/multiauthenticator/multiauthenticator.py index b8853cd..09862a2 100644 --- a/multiauthenticator/multiauthenticator.py +++ b/multiauthenticator/multiauthenticator.py @@ -6,36 +6,54 @@ Example of configuration: - from oauthenticator.github import GitHubOAuthenticator - from oauthenticator.google import GoogleOAuthenticator - c.MultiAuthenticator.authenticators = [ - (GitHubOAuthenticator, '/github', { + ("github", '/github', { 'client_id': 'xxxx', 'client_secret': 'xxxx', 'oauth_callback_url': 'http://example.com/hub/github/oauth_callback' }), - (GoogleOAuthenticator, '/google', { + ("google", '/google', { 'client_id': 'xxxx', 'client_secret': 'xxxx', 'oauth_callback_url': 'http://example.com/hub/google/oauth_callback' }), - (PAMAuthenticator, "/pam", {"service_name": "PAM"}), + ("pam", "/pam", {"service_name": "PAM"}), ] - c.JupyterHub.authenticator_class = 'oauthenticator.MultiAuthenticator.MultiAuthenticator' + c.JupyterHub.authenticator_class = 'multiauthenticator' The same Authenticator class can be used several to support different providers. """ +try: + # Python < 3.10 + from importlib_metadata import entry_points +except ImportError: + from importlib.metadata import entry_points + from jupyterhub.auth import Authenticator from jupyterhub.utils import url_path_join from traitlets import List from traitlets import Unicode +from traitlets import import_item PREFIX_SEPARATOR = ":" +def _load_authenticator(authenticator_name): + """Load an authenticator from a string + + Looks up authenticators entrypoint registration (e.g. 'github') + or full import name ('jupyterhub.auth.PAMAuthenticator'). + + Returns the Authenticator subclass. + """ + for entry_point in entry_points(group="jupyterhub.authenticators"): + if authenticator_name.lower() == entry_point.name.lower(): + return entry_point.load() + return import_item(authenticator_name) + + class URLScopeMixin: """Mixin class that adds the""" @@ -82,6 +100,8 @@ def __init__(self, *arg, **kwargs): url_scope_authenticator, authenticator_configuration, ) in self.authenticators: + if isinstance(authenticator_klass, str): + authenticator_klass = _load_authenticator(authenticator_klass) class WrapperAuthenticator(URLScopeMixin, authenticator_klass): url_scope = url_scope_authenticator diff --git a/multiauthenticator/tests/test_multiauthenticator.py b/multiauthenticator/tests/test_multiauthenticator.py index 4e920fc..2de6bbc 100644 --- a/multiauthenticator/tests/test_multiauthenticator.py +++ b/multiauthenticator/tests/test_multiauthenticator.py @@ -31,7 +31,7 @@ class CustomPAMAuthenticator(PAMAuthenticator): def test_different_authenticators(): MultiAuthenticator.authenticators = [ ( - GitLabOAuthenticator, + "gitlab", "/gitlab", { "client_id": "xxxx", @@ -40,7 +40,7 @@ def test_different_authenticators(): }, ), ( - GitHubOAuthenticator, + "oauthenticator.github.GitHubOAuthenticator", "/github", { "client_id": "xxxx", diff --git a/pyproject.toml b/pyproject.toml index ec5f290..5ef6d99 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,13 +24,17 @@ classifiers = [ ] dependencies = [ "jupyterhub", - "oauthenticator" + "oauthenticator", + "importlib_metadata>=4.6; python_version < '3.10'", ] [project.optional-dependencies] test = ["pytest", "pytest-cov", "pytest-asyncio"] dev = ["pre-commit", "jupyterhub-multiauthenticator[test]"] +[project.entry-points."jupyterhub.authenticators"] +multiauthenticator = "multiauthenticator:MultiAuthenticator" + [tool.setuptools] packages = ["multiauthenticator"]