Keycloak¶
Keycloak is the identity provider. JupyterHub delegates login to it using OpenID Connect (OIDC), and it decides which groups a user is in. In KID, group membership is how project membership works.
Realm tre¶
Imported at start-up from gitops/keycloak/realm-tre.json:
- Client
jupyterhub: confidential OIDC client with agroupsprotocol mapper (oidc-group-membership-mapper,full.path: false), so tokens and the userinfo endpoint carry"groups": ["alpha", "beta"]. - Groups:
alpha,beta(one per project) andtre-admins. - Users:
researcher1–researcher4,tre-admin. See First steps.
Consoles¶
- Admin console:
/keycloak(redirects to/auth/admin/master/console/), loginadmin/admin. Switch to the tre realm with the realm selector at the top left. - Account console for a user:
/auth/realms/tre/account/.
Adding a user to a project¶
- Admin console → realm tre → Users → pick the user → Groups → Join Group → pick the project group.
- The user must log out of JupyterHub and back in (groups are synced at login).
Use File → Log Out in JupyterLab, or visit
/jupyter/hub/logout.
Dev mode caveats¶
Keycloak runs with start-dev: an embedded H2 database inside the container and no TLS.
Changes made in the admin console don't survive a Keycloak restart
When the Keycloak pod restarts, the database is recreated and the realm is re-imported from
Git. That is handy for training (you can always get back to a clean state with
kubectl -n keycloak rollout restart deploy/keycloak), but a real TRE uses an external
PostgreSQL database and manages realms declaratively or through an operator.
How JupyterHub uses it¶
# gitops/jupyterhub/values.yaml (abridged)
GenericOAuthenticator:
username_claim: preferred_username
manage_groups: true
auth_state_groups_key: oauth_user.groups
admin_groups: [tre-admins]
The browser is sent to the public URL ($PUBLIC_URL/auth/...). The hub exchanges the code for
a token and fetches userinfo over the cluster-internal Service
(keycloak.keycloak.svc.cluster.local), which the hub's network policy allows on port 8080.