Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend the User model with fields used by jupyter-server identity? #4780

Open
krassowski opened this issue Apr 10, 2024 · 1 comment
Open

Comments

@krassowski
Copy link
Contributor

krassowski commented Apr 10, 2024

Proposed change

jupyter-server 2.0 introduced a rich User identity model, which could:

  • improve the RTC experience as users could have a custom display name (different from user name), initials, colour, etc
  • enrich the JupyterHub dashboard by displaying more tailored information about user

JupyterHub currently only defines a name for the user:

class User(Base):
"""The User table
Each user can have one or more single user notebook servers.
Each single user notebook server will have a unique token for authorization.
Therefore, a user with multiple notebook servers will have multiple tokens.
API tokens grant access to the Hub's REST API.
These are used by single-user servers to authenticate requests,
and external services to manipulate the Hub.
Cookies are set with a single ID.
Resetting the Cookie ID invalidates all cookies, forcing user to login again.
A `state` column contains a JSON dict,
used for restoring state of a Spawner.
`servers` is a list that contains a reference for each of the user's single user notebook servers.
The method `server` returns the first entry in the user's `servers` list.
"""
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(Unicode(255), unique=True)

and passes it down as username to jupyter-server identity model:

class JupyterHubUser(User):
"""Subclass jupyter_server User to store JupyterHub user info"""
# not dataclass fields,
# so these aren't returned in the identity model via the REST API.
# The could be, though!
hub_user: dict
def __init__(self, hub_user):
self.hub_user = hub_user
super().__init__(username=self.hub_user["name"])

Would you consider a PR which brings (some) additional fields from the jupyter-server identity model and:

  • passes them down to jupyter-server
  • exposes them in /users/ API (if the fields are defined)
  • (optionally) add claims for (some of?) these fields in oauthenticator following OIDC standard

Alternative options

Do nothing?

Who would use this feature?

  • RTC users
  • jhub-apps
  • possibly JupyterHub itself in admin panel

Comparison of jupyter-server identity model with OIDC

In addition to already-supported username, jupyter-server's User identity model defines:

  • name: (string) For-humans name of the user. May be the same as username in systems where only usernames are available.
  • displayname: (string) Alternate rendering of name for display, such as a nickname. Often the same as name.
  • initials: (string or null) Short string of initials. Initials should not be derived automatically due to localization issues. May be null if unavailable.
  • avatar_url: (string or null) URL of an avatar image to be used for the user. May be null if unavailable.
  • color: (string or null) A CSS color string to use as a preferred color, such as for collaboration cursors. May be null if unavailable.

On the other hand, OIDC protocol supports standard claims:

  • name: End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences.
  • picture: URL of the End-User's profile picture. This URL MUST refer to an image file (for example, a PNG, JPEG, or GIF image file), rather than to a Web page containing an image. Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.
  • nickname: Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael.
  • preferred_username: Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace. The RP MUST NOT rely upon this value being unique, as discussed in Section 5.7
  • given_name, family_name and middle_name (self-explanatory)

So there is a good overlap here, surely we could find a sensible default mapping, while allowing for customization. The defaults for all claims could also be set to None, so that these would need to be opted-in when configuring the authenticator.

Other claims are allowed, so we could support color out of box, but likely no OIDC authenticator would return a color by default unless manually configured.

@minrk
Copy link
Member

minrk commented Apr 11, 2024

Adding these fields seems sensible to me. Following OIDC (ignoring preferred_username, which isn't meaningful here) makes the most sense in the JupyterHub User model, and the relevant subset can be mapped for Jupyter Server in the singleuser Extension.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants