GenericAuthenticator Redirect Issue

Hey all,

I’m one of many who currently face issues with the GenericAuthenticator.

I am currently running TheLittlesJupyter with the following config:

hub:
 extraEnv:
   OAUTH2_AUTHORIZE_URL: <;URL;>
   OAUTH2_TOKEN_URL: <;URL;>
   OAUTH_CALLBACK_URL:<;URL;>
 extraConfig:
   myConfig.py: |
     c.JupyterHub.authenticator_class.login_handler._OAUTH_AUTHORIZE_URL = "<;URL;>"
users:
 admin:
 - <user;>
auth:
 FirstUseAuthenticator:
   create_users: true
 type: oauthenticator.generic.GenericOAuthenticator
GenericOAuthenticator:
  login_service: Test
  userdata_url: <;URL;>
  token_url: <;URL;>
  username_key: username
  client_id: <;ID;>
  client_secret: <;Secrect;>

However it seems like the oAuthenticator is not ready the environment variables.
Thats why I set them in the extra Config.

I already read all the issues regarding this topic, but it seems like the provided fixes dont work.

Any help is appreciated!

Thanks,

Marvin

I can’t fully infer your issue here, but you aren’t setting OAUTH2_USERDATA_URL in the env vars as a start.

From generic.py (generic OAuthenticator)

if self.userdata_url:
    url = url_concat(self.userdata_url, self.userdata_params)
else:
    raise ValueError("Please set the OAUTH2_USERDATA_URL environment variable")

Actually, I think I just ended up setting everything in hub.extraEnv because that’s where the generic authenticator actually gets its values instead of from the config. This was my working structure:

hub:
  extraEnv:
    #Endpoints
    OAUTH2_AUTHORIZE_URL: 'https://host/oauth2/token'
    OAUTH2_TOKEN_URL: 'https://host/oauth2/token'

    # Jupyterhub callback (default: https://<host>/hub/oauth_callback)
    OAUTH_CALLBACK_URL: 'https://hub.host/hub/oauth_callback'
    
    # User information is used to name server created by kubespawner. 
    OAUTH2_USERDATA_URL: 'https://host/jupyter_userdata'
    OAUTH2_USERNAME_KEY: 'username_key'
    OAUTH2_USERDATA_METHOD: 'GET'

    # General settings
    OAUTH2_BASIC_AUTH: 'false'
    OAUTH2_TLS_VERIFY : 'true'

Two things to make sure of:

  1. If you are using your own custom oauth, are you making sure that you implemented a listener/endpoint/handler at oauth_userdata_url?

I won’t paste too much code here but in generic.py (the generic OAuthenticator):

    if not resp_json.get(self.username_key):
        self.log.error("OAuth user contains no key %s: %s", self.username_key, resp_json)
        return

You need to be certain that whatever provider you are using for your auth is returning a json dict that includes a key value pair where at least one key == ‘username_key’.

  1. GenericOAuthenticator does’t include client_secret and client_id in the POST body when it sends the first POST to actually get a token. https://github.com/jupyterhub/oauthenticator/pull/274

The workaround is to add client_id and client_secret to your auth.className.config.extra_params

auth:
  type: custom
  custom:
  className: oauthenticator.generic.GenericOAuthenticator
    config:
      login_service: 'Your Auth'
      extra_params:
        client_id : 'TEST12345'
        client_secret: 'TEST12345'
      client_id: 'TEST12345'
      client_secret: 'TEST12345'

This is also what my config looks like, I added almost everything in the env vars and auth does work. If you gave me a little more detail perhaps I could help further.

1 Like

Hey kkapper!

Thanks so much for helping out.

Sadly that did not fix my issues. I double checked all the values set in my config and it seems (atleast I think thats whats happening) that the GenericAuthenticator does not pick up my Authorize URL.

As you proposed I now set all the variables inside the extra env, however looking at the logs it seems like my request gets send via:

Jun 24 08:24:51 python3[14735]: [I 2019-06-24 08:24:51.784 JupyterHub log:158] 302 GET /hub/oauth_login?next= -> ?response_type=code&redirect_uri=<URI>&client_id=<id>&state=[secret]

Shouldnt there be the proper authorize url after the next=? After that it redirects with the above parameters to itself again and again, being stuck in said loop.

I hope this helps to pinpoint my problem furhter.

Thanks for your help again!

Regards,
Marvin

I would probably remove this whole block and see if it works as a next step.

It seems unnecessary, and actually might be conflicting with, or overriding the env vars that are set earlier.

Let me know what you get if that is removed, and your config for the auth section looks like mine.

What provider are you using for oauth if you don’t mind me asking?

Hey!

Yeah this block is removed from my config now:

hub:
  extraEnv:
    OAUTH2_AUTHORIZE_URL: https://example.com/oauth/authorize
    OAUTH2_TOKEN_URL: https://example.com/oauth/token
    OAUTH_CALLBACK_URL: https://example.com/hub/oauth_callback
    OAUTH2_USERDATA_URL: https://example.com/oauth/me
    OAUTH2_USERNAME_KEY: user_login
    OAUTH2_USERDATA_METHOD: GET
    OAUTH2_TLS_VERIFY: 'true'
    OAUTH2_BASIC_AUTH: 'false'
  myConfig: |
    c.JupyterHub.base_url = '/hub/'
users:
  admin:
  - ubuntu
auth:
  FirstUseAuthenticator:
    create_users: true
  type: oauthenticator.generic.GenericOAuthenticator
  GenericOAuthenticator:
    login_service: Test
    extra_params:
      client_id: CLIENT_ID
      client_secret: CLIENT_SECRET
    client_id: CLIENT_ID
    client_secret: CLIENT_SECRET

I have to admit, for a demo yesterday we now just hardcoded the Authorize URL inside the python sitepackage of the oauthenticator. This is of course not a permanent solution.

But this shows me that the Authorize URL not being read is the only problem we have. The oauth is working find as soon as I hardcode it inside generic.py.

Regarding the OAuth Provider:

Im breaking out from Wordpress into JupyterHub via OAuth. Which means, I authenticate the signed in WP User in JupyterHub and use WP as the OAuth provider!

Thanks for you help!