Binderhub oauth(keycloak) setup

I installed binderhub using the helm chart in my AKS Cluster.
I have created a setup, running so with a jupyterhub in the same cluster. But I do not get binderhub to authorize my users.
Here some questions I did not manage to get answered by the docs.
(The redirection from bunderhub to keycliak works (and seems to have correct parameters)

Should the oauth_callback_url be:
https://mydomain/jupyterhub/hub/oauth_callback
or
https://mydomain/hub/oauth_callback
or
https://mydomain/oauth_callback
all are giving me a 403, but with different outfit.
I have to specify oauth_callback_url in

jupyterhub:
  hub:
    services:
      binder:
        oauth_redirect_uri: 

and in the

jupyterhub:
  hub:
    config:
      GenericOAuthenticator:
        oauth_callback_uri: 

right? Are they the same?

The

jupyterhub:
  hub:
   services:
      binder:
        oauth_client_id: 

needs to start with “service-”? (And is not the same as my keycloak client_id?)

To give access to every authorized user, I put

jupyterhub:
  hub:
    loadRoles:
      user:
        scopes:
         - self
         - "access:services"

in my values. But seems to have no effect.
Do I habe to specify a (keycloak) oauth group and if so how.

In the log of the binder pod, I find: “Detected unused OAuth state cookies.” Could this point to my problem? How may I solve this?

It depends on how you’ve configured JupyterHub, e.g. are you running at the root of a domain, or under a URL prefix? Can you show us your full JupyterHub config? Is OAuth already working with JupyterHub?

Can you also show us your BinderHub config?

1 Like

I have a running jupyterhub with keycloak integration in this Cluster but I want to create a complete new binderhub (with its own jupyterhub) in an other namespace.
So my jupyterhub config is taken from the helm chart defaults.
I startet with the current helm chart including the default values und overwrite the values for my instance as followed:(changed some internals)

config:
  BinderHub:
    auth_enabled: true
    base_url: /
    hub_url: https://binder.my.domain
    use_registry: true
    KubernetesBuildExecutor: {}

imageBuilderType: pink

jupyterhub:
  cull:
    # don't cull authenticated users
    users: False
  hub:
    baseUrl: /jupyterhub
#    allowNamedServers: true
#    namedServerLimitPerUser: 1
    loadRoles:
      user:
        scopes:
          - self
          - "access:services"
    config:
      BinderSpawner:
        auth_enabled: true
      JupyterHub:
        authenticator_class: generic-oauth
      GenericOAuthenticator:
        client_id: binderhub
        client_secret: "some secret" 
        oauth_callback_url: https://binder.my.domain/jupyterhub/hub/oauth_callback
        authorize_url: https://id.my.domain/realms/myrealm/protocol/openid-connect/auth
        token_url: https://id.my.domain/realms/myrealm/protocol/openid-connect/token
        userdata_url: https://id.my.domain/realms/myrealm/protocol/openid-connect/userinfo
        login_service: keycloak
        username_key: preferred_username
        userdata_params:
          state: state

    services:
      binder:
        oauth_client_id: service-binderhub
        oauth_redirect_uri: "https://binder.my.domain/jupyterhub/hub/oauth_callback"
  singleuser:
    cmd: jupyterhub-singleuser
  proxy:
    service:
      type: ClusterIP

  ingress:
    enabled: true
    annotations:
      cert-manager.io/cluster-issuer: letsencrypt-prod
      kubernetes.io/ingress.class: nginx
    hosts: [binder.my.domain]
    pathType: Prefix
    pathSuffix: hub
    tls:
      - hosts:
          - binder.my.domain
        secretName: binder-my_domain


ingress:
  enabled: true
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    kubernetes.io/ingress.class: nginx
  hosts: [binder.my.domain]
  pathType: Prefix
  tls:
    - hosts:
        - binder.my.domain
      secretName: binder-my_domain

Most of the jupyterhub config is taken from my other instance wich is running right now.

You need to include the JupyterHub baseUrl (/jupyterhub) here.

Can you log into JupyterHub directly (without going via BinderHub)?
Can you show us your debug logs for JupyterHub?

OK, thanks for reply.
I don’t know, how to login into jupyterhub without using binderhub.
If I open my binder url, I will be redirected to /hupyterhub/hub.
Starting on this url behaves same.
Find my logs at the end. I got an 403 after authenticate successful with keycloak.
I dont get the lines
[I 2023-11-06 19:30:53.742 JupyterHub app:1984] Not using allowed_users. Any authenticated user will be allowed.
and
[W 2023-11-06 19:32:10.375 JupyterHub auth:533] User ‘uli’ not allowed.
[W 2023-11-06 19:32:10.375 JupyterHub base:843] Failed login for unknown user
together.

One remark. I want to create a “as simple as possible” and “as default as possible” deployment via helm chart in kuberneres. The only special is that it should authenticate with keycloak.
Do you know a good sample as starting point?

Here the log (fresh, one login)

Loading /usr/local/etc/jupyterhub/secret/values.yaml
No config at /usr/local/etc/jupyterhub/existing-secret/values.yaml
Loading extra config: 0-binderspawnermixin
Loading extra config: 00-binder
[I 2023-11-06 19:30:53.666 JupyterHub app:2859] Running JupyterHub version 4.0.2
[I 2023-11-06 19:30:53.666 JupyterHub app:2889] Using Authenticator: oauthenticator.generic.GenericOAuthenticator-16.1.0
[I 2023-11-06 19:30:53.667 JupyterHub app:2889] Using Spawner: builtins.BinderSpawner
[I 2023-11-06 19:30:53.667 JupyterHub app:2889] Using Proxy: jupyterhub.proxy.ConfigurableHTTPProxy-4.0.2
[W 2023-11-06 19:30:53.741 JupyterHub oauth2:1061] GenericOAuthenticator.username_key is deprecated in GenericOAuthenticator 16.0.0, use GenericOAuthenticator.username_claim instead
[I 2023-11-06 19:30:53.742 JupyterHub app:1984] Not using allowed_users. Any authenticated user will be allowed.
[I 2023-11-06 19:30:53.787 JupyterHub provider:661] Updating oauth client service-binderhub
[I 2023-11-06 19:30:53.834 JupyterHub app:2313] Adding API token for service: binder
[I 2023-11-06 19:30:53.886 JupyterHub app:2928] Initialized 0 spawners in 0.002 seconds
[I 2023-11-06 19:30:53.891 JupyterHub metrics:278] Found 0 active users in the last ActiveUserPeriods.twenty_four_hours
[I 2023-11-06 19:30:53.891 JupyterHub metrics:278] Found 0 active users in the last ActiveUserPeriods.seven_days
[I 2023-11-06 19:30:53.892 JupyterHub metrics:278] Found 0 active users in the last ActiveUserPeriods.thirty_days
[I 2023-11-06 19:30:53.892 JupyterHub app:3142] Not starting proxy
[I 2023-11-06 19:30:53.900 JupyterHub app:3178] Hub API listening on http://:8081/jupyterhub/hub/
[I 2023-11-06 19:30:53.900 JupyterHub app:3180] Private Hub API connect url http://hub:8081/jupyterhub/hub/
[I 2023-11-06 19:30:53.900 JupyterHub app:3189] Starting managed service jupyterhub-idle-culler
[I 2023-11-06 19:30:53.900 JupyterHub service:385] Starting service 'jupyterhub-idle-culler': ['python3', '-m', 'jupyterhub_idle_culler', '--url=http://localhost:8081/jupyterhub/hub/api', '--timeout=3600', '--cull-every=600', '--concurrency=10']
[I 2023-11-06 19:30:53.901 JupyterHub service:133] Spawning python3 -m jupyterhub_idle_culler --url=http://localhost:8081/jupyterhub/hub/api --timeout=3600 --cull-every=600 --concurrency=10
[I 2023-11-06 19:30:53.902 JupyterHub app:3198] Adding external service binder
[I 2023-11-06 19:30:53.905 JupyterHub proxy:477] Adding route for Hub: /jupyterhub/ => http://hub:8081
[I 2023-11-06 19:30:53.907 JupyterHub app:3247] JupyterHub is now running, internal Hub API at http://hub:8081/jupyterhub/hub/
[I 2023-11-06 19:30:54.456 JupyterHub log:191] 200 GET /jupyterhub/hub/api/ (jupyterhub-idle-culler@::1) 20.04ms
[I 2023-11-06 19:30:54.464 JupyterHub log:191] 200 GET /jupyterhub/hub/api/users?state=[secret] (jupyterhub-idle-culler@::1) 5.91ms
[I 2023-11-06 19:32:07.888 JupyterHub log:191] 301 GET /jupyterhub/hub -> /jupyterhub/hub/ (@10.244.6.1) 0.46ms
[I 2023-11-06 19:32:07.908 JupyterHub log:191] 302 GET /jupyterhub/hub/ -> /jupyterhub/hub/login?next=%2Fjupyterhub%2Fhub%2F (@10.244.6.1) 0.45ms
[I 2023-11-06 19:32:07.953 JupyterHub log:191] 200 GET /jupyterhub/hub/login?next=%2Fjupyterhub%2Fhub%2F (@10.244.6.1) 24.12ms
[I 2023-11-06 19:32:10.260 JupyterHub oauth2:97] OAuth redirect: https://ddd.yyy.zz/jupyterhub/hub/oauth_callback
[I 2023-11-06 19:32:10.260 JupyterHub log:191] 302 GET /jupyterhub/hub/oauth_login?next=%2Fjupyterhub%2Fhub%2F -> https://xxx.yyy.zz/realms/aaa/protocol/openid-connect/auth?response_type=code&redirect_uri=https%3A%2F%2Fbinder.andromeda.robsky.eu%2Fjupyterhub%2Fhub%2Foauth_callback&client_id=binderhub&state=[secret] (@10.244.6.1) 1.01ms
[W 2023-11-06 19:32:10.375 JupyterHub auth:533] User 'uli' not allowed.
[W 2023-11-06 19:32:10.375 JupyterHub base:843] Failed login for unknown user
[W 2023-11-06 19:32:10.375 JupyterHub web:1869] 403 GET /jupyterhub/hub/oauth_callback?state=scscs&session_state=dcdcdc (10.244.6.1): Sorry, you are not currently authorized to use this hub. Please contact the hub administrator.
[W 2023-11-06 19:32:10.393 JupyterHub log:191] 403 GET /jupyterhub/hub/oauth_callback?state=[secret]&session_state=[secret]&code=[secret] (@10.244.6.1) 73.91ms

If you’re using a recent version of Z2JH/BinderHub you’ll need to either add all the allowed users, or set OAuthenticator.allow_all. This was done to improve the security of the default configuration of OAuthenticator.

This is, what I found in the Doku.


And as I use Helm Charts, its hard to find, where to set.
And - I do not unterstand the concept of existing users. I do not have existing users in the jupyterhub database, all of my users should be from keycloak.
I´ll try to figure out, what to do.
Many thanks.