Published in


Secure JupyterLab using Keycloak

In this post, we will see how to secure JupyterLab & manage access for the JupyterLab notebook using Keycloak. I will be setting up the JupyterLab in the local system & require config changes for running it locally which will differ from the production setup. If you are not familiar with the Keycloak basics, you can go through this post Essentials. Let’s get started.


  • Python
  • Pip
  • JupterLab
  • Keycloak

Install JupyterLab & Notebook

pip install jupyterlabpip install notebook

Install oauthenticator

pip install oauthenticator

Proxy (Required for local development)

npm install -g configurable-http-proxy


Keycloak WildFly (deprecated)version

./ -Djboss.socket.binding.port-offset=100

Keycloak (Quarkus based)

./ start-dev --http-port 8180

Create a Realm: keycloak-demo

  • Create a Client ID: “jy” (“any preferred name)
  • Access Type: Confidential
  • Add Valid Redirect Uris: <Jupterhub-host>

Generate Config file

jupyterhub --generate-config

Open the in any editor

Copy ClientId & Client secret from Keycloak & add the following configuration

  • c.GenericOAuthenticator.client_id = ‘jy’
  • c.GenericOAuthenticator.client_secret = ‘<client secret>’

Keycloak Widlfy

Check the well-known end-point

http://keycloak-host: port>/realms/keycloak-demo/.well-known/openid-configuration

Keycloak Quarkus

Check the well-known end-point

http://keycloak-host: port>/realms/keycloak-demo/.well-known/openid-configuration

It will look like this:

from oauthenticator.generic import GenericOAuthenticatorc.JupyterHub.authenticator_class = GenericOAuthenticator
c.GenericOAuthenticator.client_id = 'jy'
c.GenericOAuthenticator.client_secret = '<client secret>'
c.GenericOAuthenticator.token_url = 'http://<keycloak-host: port>/auth/realms/keycloak-demo/protocol/openid-connect/token'
c.GenericOAuthenticator.userdata_url = 'http://<keycloak-host: port>/auth/realms/keycloak-demo/protocol/openid-connect/userinfo'
c.GenericOAuthenticator.userdata_params = {'state': 'state'}
c.GenericOAuthenticator.username_key = 'preferred_username'
c.GenericOAuthenticator.login_service = 'Keycloak'
c.GenericOAuthenticator.scope = ['openid', 'profile']

Update the Spawner

c.JupyterHub.spawner_class = 'jupyterhub.spawner.SimpleLocalProcessSpawner'

Note `Default: ‘jupyterhub.spawner.LocalProcessSpawner’

Requires local UNIX users matching the authenticated users to exist. Does not work on Windows.

Run the Jupterhub

Export Env variables

Keycloak WildFly

export OAUTH2_AUTHORIZE_URL=http://<keycloak-host:port>/auth/realms/keycloak-demo/protocol/openid-connect/authexport OAUTH2_TOKEN_URL=http://<keycloak-host:port/auth/realms/keycloak-demo/protocol/openid-connect/token

Keycloak Quarkus

export OAUTH2_AUTHORIZE_URL=http://<keycloak-host:port>/realms/keycloak-demo/protocol/openid-connect/authexport OAUTH2_TOKEN_URL=http://<keycloak-host:port/realms/keycloak-demo/protocol/openid-connect/token

Run the Jupterhub

jupyterhub -f

Open the JupterHub url in the browser. You will see the login screen

Click on the button: “Sign in with Keycloak” & You will it will redirect to the Keycloak login page.

You can now create a new notebook.


In this post, we have successfully secured Jupterhub using Keycloak. Setup & configuration is only for local setup. For production configuration will differ like using SSL.

If you like this post, give it a Cheer!!!

Follow the Collection: Keycloak for learning more…

Happy Secure Coding ❤



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store