Closed JuanCab closed 3 years ago
Definitely possible, just need to add a switch. It seems like this should have been the default, but it's hard to change defaults without causing pain for existing users. Check out username_key in generic.py for a configurable source of username from the OAuth response.
I should note I am dealing with this in the context of TLJH and not a full JupyterHub installation.
I am not an OAuth expert, just a professor trying to piece together a solution for a class server. As far as I can interpret, username_key is a traitlet (which I partly understand the concept of) which can contain a string, the default being 'username'. Is this supposed to allow me to change what part of the response JSON the generic oauthenticator
interprets as the username?
I believe (if I understand the documentation well enough) the Auth0 OAuth authenticator responds with preferred_username
as the username, so do I just have to set the username_key
traitlet value in the Jupyter config and then I will get the proper username instead of email address as the username?
OK, I attempted to set up the generic Oauth authenticator, using the following settings (these are from TLJH config):
auth:
type: oauthenticator.generic.GenericOAuthenticator
GenericOAuthenticator:
client_id: [REMOVED]
client_secret: [REMOVED]
oauth_callback_url: https://jupyter.mnstate.edu/hub/oauth_callback
token_url: https://msumjupyter.auth0.com/oauth/token
and this just seems to generate a ERR_TOO_MANY_REDIRECTS
in Chrome. :(
I also, as a brute force approach, tried to edit my auth0.py file and replaced 'name': resp_json["email”]
with 'name': resp_json["username”]
but that triggered a 500 Server error, the TLJH logs indicating that this is because
File "/opt/tljh/hub/lib/python3.6/site-packages/oauthenticator/auth0.py", line 99, in authenticate
'name': resp_json["username"],
KeyError: 'username'
I would really appreciate if someone can find some way to use Auth0 usernames as the account names for JupyterHub.
We're having the same problem as well.
Writing this out after working through this myself...
You'll need to check that your scope actually includes the username, and that auth0 is returning a username (which will depend on what you're using to authenticate with auth0 itself). A scope defines what information will be returned about the user.
There are three 'scopes' available with auth0: openid, email and profile. It's likely you're using the first two and need to add 'profile' by specifying this in your jupyterhub_config.py:
c.Auth0OAuthenticator.scope = ['openid', 'email', 'profile']
This will expose these fields in the auth0 userinfo response: name, family_name, given_name, middle_name, nickname, picture, and updated_at
From my brief testing with auth0's built-in user database (as opposed to connecting to a third-party auth platform), the 'username' field appears to be exposed as 'nickname' in the /userinfo response:
{"sub": "auth0|12345", "nickname": "myusernamehere", "name": "myemail@email.com", "picture": "", "updated_at": "2019-11-07T13:33:58.827Z", "email": "myemail@email.com", "email_verified": false}
...and so, after including the 'profile' scope in jupyterhub_config.py, I could reference this username in auth0.py by replacing email with 'nickname':
return {
'name': resp_json["nickname"],
'auth_state': {
'access_token': access_token,
'auth0_user': resp_json,
}
}
If you're using a different source for authentication (e.g. Active Directory, Google, Facebook), it's possible you'll need to do some playing to see if the username is exposed in the 'profile' scope, or if you need to expose it manually using auth0 rules (which is a whole other game).
To help see the actual response JupyterHub is getting from auth0, I found it easy to just dump this to a file by adding this code...
with open('/home/jamie/auth0data.json', 'w') as f:
json.dump(resp_json, f)
...after:
# Determine who the logged in user is
headers={"Accept": "application/json",
"User-Agent": "JupyterHub",
"Authorization": "Bearer {}".format(access_token)
}
req = HTTPRequest("https://%s.auth0.com/userinfo" % AUTH0_SUBDOMAIN,
method="GET",
headers=headers
)
resp = await http_client.fetch(req)
resp_json = json.loads(resp.body.decode('utf8', 'replace'))
...which just dumps the json response into a file in my home directory.
More reading: https://auth0.com/docs/scopes/current/oidc-scopes
Best of luck!
I noticed that
https://github.com/jupyterhub/oauthenticator/blob/master/oauthenticator/auth0.py
appears to hardcode use of email address as the username when using Auth0. Is there a way to allow Auth0 USERNAME as the JupyterHub username? It would make my life a lot easier to not have usernames locked to email addresses.