Having some trouble implementing MultiAuthenticator with PAM and FirstUseAuthenticator. Eventually will add AzureAD and ORCID but for now I want to get initial admin account logged in before moving to Oauth. The reason for wanting to get the initial admin account logged in, it’s so that I can approve/promote new Oauth users to admin then deprecate firstuseauthenticator and PAM.
Created /opt/tljh/config/jupyterhub_config.d/Multiauthenticator.py and configured various authenticators e.g. FirstUseAuthenticator, PAM, generic-oauth (ORCID) and AzureAD.
On the PAM landing page I have sign-in with PAM button but no fields for credentials.
On the FirstUse page I enter credentials but for some reason username gets added but has : appended
e.g. “jupyter-:username”
Jun 11 17:06:18 python3[48231]: subprocess.CalledProcessError: Command '['useradd', '--create-home', 'jupyter-:username']' returned non-zero exit status 3.
Jun 11 17:06:18 python3[48231]:
Jun 11 17:06:18 1 python3[48231]: [E 2025-06-11 17:06:18.907 JupyterHub pages:312] Error starting server :username: Command '['useradd', '--create-home', 'jupyter-:username']' returned non-zero exit status 3.
Jun 11 17:06:18 svrlducklakemeta01 python3[48231]: Traceback (most recent call last):
Jun 11 17:06:18 svrlducklakemeta01 python3[48231]: NoneType: None
Jun 11 17:06:18 svrlducklakemeta01 python3[48231]:
Jun 11 17:06:18 svrlducklakemeta01 python3[48231]: [W 2025-06-11 17:06:18.907 JupyterHub web:1932] 500 GET /hub/spawn (172.18.27.55): Unhandled error starting server :username
Good Day - I omitted the multiauthenticator code example im using
from firstuseauthenticator import FirstUseAuthenticator
from jupyterhub.auth import PAMAuthenticator
from multiauthenticator import MultiAuthenticator
class MyPamAuthenticator(PAMAuthenticator):
login_service = "PAM"
auto_login = False
# Configure the available authenticators
c.MultiAuthenticator.authenticators = [
{
'authenticator_class': FirstUseAuthenticator,
'url_prefix': '/firstuse'
},
{
"authenticator_class": 'generic-oauth',
"url_prefix": '/orcid',
"config": {
'client_id': 'xxxx',
'client_secret': 'yyyy',
'oauth_callback_url': 'https://example.com/hub/oricid/oauth_callback'
}
},
{
"authenticator_class": 'azuread',
"url_prefix": '/azure',
"config": {
'client_id': 'xxxx',
'client_secret': 'yyyy',
'oauth_callback_url': 'https://example.com/hub/azure/oauth_callback',
'tenant_id': 'cccc',
'scope': ["openid", "email"]
}
},
{
"authenticator_class": MyPAMAuthenticator,
"url_prefix": "/pam",
},
]
# Set MultiAuthenticator as the main authenticator
c.JupyterHub.authenticator_class = 'Multiauthenticator'
Hello, i am having the same issue here… have you found a solution ?
Okay my bad, the solution was to specify the c.MultiAuthenticator.username_prefix.
I set it in ““ and it worked
2 Likes
That’s great, can you please share an example of your multiauthenticator config?
1 Like
celeste
December 12, 2025, 2:18pm
6
#/opt/tljh/config/jupyterhub_config.d/Multiauthenticator.py
from jupyterhub.auth import PAMAuthenticator
from multiauthenticator import MultiAuthenticator
from oauthenticator.generic import GenericOAuthenticator
from unidecode import unidecode
def word_normalizer (word) :
normalized = unidecode(word).strip(" ")
return “”.join( e for e in normalized if e.isalnum())
def username_modifier (userinfo) :
return word_normalizer(userinfo[“given_name”])+word_normalizer(userinfo[“family_name”])
c.MultiAuthenticator.authenticators = [
{
‘authenticator_class’: “pam”,
‘url_prefix’: ‘/pam’,
},
{
‘authenticator_class’: GenericOAuthenticator,
‘url_prefix’: ‘/oauth’,
‘config’: {
‘client_id’: [client],
‘login_service’ : [login],
‘oauth_callback_url’: [url here],
‘authorize_url’ : [url here],
‘token_urk’ : [url here],
‘userdata_url’ : [url here],
‘username_key’ :username_modifier,
},
},
]
c.JupyterHub.authenticator_class = MultiAuthenticator
c.MultiAuthenticator.username_prefix = “”
c.Authenticator.allow_existing_users = True
c.Application.log_level = ‘DEBUG’
Here you go
1 Like