Reputation: 143
I'm trying to set up jupyterhub on vagrant, but after I connected (I think) the authentication to keycloak, I got the ERR_TOO_MANY_REDIRECTS error in my browser, after clicking the oauth2 button. Is it problem with my jupyterhub_config.py or wrong oauth_callback_url?
My keycloak init:
cd $KEYCLOAK_PATH/bin && sudo bash add-user-keycloak.sh -u admin -p admin
cd $KEYCLOAK_PATH/bin && sudo nohup ./standalone.sh -Djboss.bind.address.management=0.0.0.0 -Djboss.socket.binding.port-offset=100 -Djboss.bind.address=0.0.0.0 > $KEYCLOAK_LOGS/keycloak.log 2>&1 &
My jupyterhub_config.py:
c.Authenticator.admin_users = {'vagrant'}
from oauthenticator.generic import GenericOAuthenticator
c.JupyterHub.authenticator_class = GenericOAuthenticator
c.GenericOAuthenticator.oauth_callback_url = 'http://0.0.0.0:8180/auth/realms/testrealm/protocol/openid-connect/auth'
c.GenericOAuthenticator.client_id = 'oauth-secret'
c.GenericOAuthenticator.client_secret = ''
c.GenericOAuthenticator.token_url = 'http://0.0.0.0:8180/auth/realms/testrealm/protocol/openid-connect/token'
c.GenericOAuthenticator.userdata_url = 'http://0.0.0.0:8180/auth/realms/testrealm/protocol/openid-connect/userinfo'
Forwarded ports from Vagrantfile:
config.vm.network "forwarded_port", guest: 8000, host: 8000
config.vm.network "forwarded_port", guest: 8001, host: 8001
config.vm.network "forwarded_port", guest: 8081, host: 8081
Some of the redirects:
[I 2020-10-23 08:25:51.287 JupyterHub oauth2:103] OAuth redirect: 'http://0.0.0.0:8180/auth/realms/testrealm/protocol/openid-connect/auth'
[I 2020-10-23 08:25:51.290 JupyterHub log:174] 302 GET /hub/oauth_login?response_type=code&redirect_uri=http%3A%2F%2F0.0.0.0%3A8180%2Fauth%2Frealms%2Ftestrealm%2Fprotocol%2Fopenid-connect%2Fauth&client_id=oauth-secret&state=[secret] -> ?response_type=code&redirect_uri=http%3A%2F%2F0.0.0.0%3A8180%2Fauth%2Frealms%2Ftestrealm%2Fprotocol%2Fopenid-connect%2Fauth&client_id=oauth-secret&state=[secret] (@10.0.2.2) 3.66ms
[I 2020-10-23 08:25:51.307 JupyterHub oauth2:103] OAuth redirect: 'http://0.0.0.0:8180/auth/realms/testrealm/protocol/openid-connect/auth'
[I 2020-10-23 08:25:51.311 JupyterHub log:174] 302 GET /hub/oauth_login?response_type=code&redirect_uri=http%3A%2F%2F0.0.0.0%3A8180%2Fauth%2Frealms%2Ftestrealm%2Fprotocol%2Fopenid-connect%2Fauth&client_id=oauth-secret&state=[secret] -> ?response_type=code&redirect_uri=http%3A%2F%2F0.0.0.0%3A8180%2Fauth%2Frealms%2Ftestrealm%2Fprotocol%2Fopenid-connect%2Fauth&client_id=oauth-secret&state=[secret] (@10.0.2.2) 4.66ms
[I 2020-10-23 08:25:51.326 JupyterHub oauth2:103] OAuth redirect: 'http://0.0.0.0:8180/auth/realms/testrealm/protocol/openid-connect/auth'
[I 2020-10-23 08:25:51.329 JupyterHub log:174] 302 GET /hub/oauth_login?response_type=code&redirect_uri=http%3A%2F%2F0.0.0.0%3A8180%2Fauth%2Frealms%2Ftestrealm%2Fprotocol%2Fopenid-connect%2Fauth&client_id=oauth-secret&state=[secret] -> ?response_type=code&redirect_uri=http%3A%2F%2F0.0.0.0%3A8180%2Fauth%2Frealms%2Ftestrealm%2Fprotocol%2Fopenid-connect%2Fauth&client_id=oauth-secret&state=[secret] (@10.0.2.2) 4.80ms
Upvotes: 1
Views: 1261
Reputation: 161
TL;DR: Set the OAUTH2_AUTHORIZE_URL
and OAUTH2_TOKEN_URL
environment variables to the appropriate URLs which you can find in your identity provider (i.e. KeyCloak).
I've been scratching my head with this one for a bit... As you see on your own logs, JupyterHub somehow believes it is the one responsible for authenticating a user but it also says that, after authentication, the user should be redirected back to itself (that's what the oauth_callback_url
is saying). This leads to the JupyterHub server calling itself in a recursive way until the browser gives up.
I assume you are running both keyCloak and JupyterHub on the same VM, which you provisioned with vagrant. If that's the case, consider changing the 0.0.0.0
bits with 127.0.0.1
. Otherwise, try to change 0.0.0.0
to the IPv4 address where KeyCloak can be reached for c.GenericOAuthenticator.userdata_url
and c.GenericOAuthenticator.token_url
. When things aren't working as they should it's usually a good idea to avoid wildcards and the like to narrow down where the problem lies...
The address where the JupyterHub instance lives should be included for c.GenericOAuthenticator.oauth_callback_url
and, on top of that, you should point it back to the JupyterHub instance. In my case, that would be <jupyterhub-ip>:<jupyterhub-port>/hub/oauth_callback
. Remember that this member is telling KeyCloak where it should contact JupyterHub during the authentication flow.
In any case, the only thing for us to do is point JupyterHub to the KeyCloak instance. If you take a look at this snippet from JupyterHub's OAuthenticator, you'll find that the default value for the authorize_url
is extracted from an environment variable named OAUTH2_AUTHORIZE_URL
. I'm not really confident on what the @default
decorator does, but I do now that manually setting the value of authorize_url
in the configuration file didn't work for me...
You just need to export the aforementioned environment value and that should be the end of it. You can do so with:
export OAUTH2_AUTHORIZE_URL="https://<keycloak-ip>:<keycloak-port>auth/realms/testrealm/protocol/openid-connect/auth"
I have also exported the token url through the OAUTH2_TOKEN_URL
variable in pretty much the same way, with a value equivalent to what you have in your configuration (once you change the 0.0.0.0
IP address). The GitHub issue that helped me
Make sure these variable are visible to the JupyterHub process. I was running The Littlest JupyterHub and I had to include them in the appropriate unit file (/etc/systemd/system/jupyterhub.service
) like below:
Environment=OAUTH2_AUTHORIZE_URL=https://<keycloak-ip>:<keycloak-port>/auth/realms/<realm-name>/protocol/openid-connect/auth
Environment=OAUTH2_TOKEN_URL=https://<keycloak-ip>:<keycloak-port>/auth/realms/<realm-name>/protocol/openid-connect/token
Remember to run systemctl daemon-reload
and systemctl restart jupyterlab
if that's your scenario...
Coming now to an end, the key idea is to set the appropriate environment variables so that things behave as they should...
P.D: I might be missing something with the @default
decorator, but I would rather set an environment variable than get down to brass tacks with python for this kind of issue...
If you have any further questions feel free to fire away!
Upvotes: 2