I am trying to configure a generic oauth2 endpoint (Azure AD) to work with Jupyter Hub.
The implementation is provided here
https://github.com/jupyterhub/oauthenticator/blob/master/oauthenticator/oauth2.py
As I don't see a "generic" type to be supported in the config, I tried "custom" as follows:
auth:
type: custom
custom:
class-name: oauthenticator.OAuthenticator
clientId: "xxx"
clientSecret: "xxx"
callbackUrl: "http://host/hub/oauth_callback"
token_url: "https://login.microsoftonline.com/tenantId/oauth2/token"
which leads to the following error upon the creation of the container
File "/usr/local/lib/python3.5/dist-packages/traitlets/config/application.py", line 562, in _load_config_files
config = loader.load_config()
File "/usr/local/lib/python3.5/dist-packages/traitlets/config/loader.py", line 457, in load_config
self._read_file_as_dict()
File "/usr/local/lib/python3.5/dist-packages/traitlets/config/loader.py", line 489, in _read_file_as_dict
py3compat.execfile(conf_filename, namespace)
File "/usr/local/lib/python3.5/dist-packages/ipython_genutils/py3compat.py", line 198, in execfile
exec(compiler(f.read(), fname, 'exec'), glob, loc)
File "/srv/jupyterhub_config.py", line 194, in <module>
auth_class_name = full_class_name.rsplit('.', 1)[-1]
AttributeError: 'NoneType' object has no attribute 'rsplit'
Should we perhaps add an explicit oauth2 as a new type?
https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/master/images/hub/jupyterhub_config.py#L186
What is the issue with the custom type otherwise?
Figured out syntactically correct structure:
type: custom
custom:
className: 'oauthenticator.generic.GenericOAuthenticator'
config:
client_id: "xxx"
client_secret: "xxxx"
oauth_callback_url: "https://mydomain.com/hub/oauth_callback"
token_url: "https://login.microsoftonline.com/xzy/oauth2/token"
I am now presented the "Sign in with GenericOauth2" button, after clicking getting "too many redirects", where the page is not getting redirected to the token_url
Implemented Azure AD authenticator in this fork https://github.com/oxygenanywhere/oauthenticator/blob/02b2a3b98e361474d67fe79cd27e06224b88e2e1/oauthenticator/azuread.py
Do you intend to continue using the helm chart as an interface? i.e. something along the lines of the following (note also the de-indent on the custom field):
auth:
type: custom
custom:
className: 'oauthenticator.azuread.AzureAdOAuthenticator'
config:
client_id: "xxx"
client_secret: "xxxx"
oauth_callback_url: "https://mydomain.com/hub/oauth_callback"
token_url: "https://login.microsoftonline.com/xzy/oauth2/token"
Sure, I still have some things to clean up and then submit a pull request, to have Azure Auth supported
When following the zero-to-juperhub-k8s approach, I'm trying to understand the point at which you need to install the latest custom/patched oauthenticator python module (to access this newer Azure AD authenticator). If you install oauthenticator within a custom docker image and then upgrade with helm (via this approach https://zero-to-jupyterhub.readthedocs.io/en/latest/user-environment.html) is this enough?
For example, we could upgrade with this mock custom image below, which has the oauthenticator/jwt dependencies installed.
FROM jupyter/minimal-notebook:c7fb6660d096
USER root
# python jwt is needed for oxygenanywhere/oauthenticator
# libssl-dev is needed for python jwt
RUN set -x && \
apt-get update && \
sudo apt-get -y install apt-utils && \
sudo apt-get -y install apt-file && \
sudo apt-get -y install build-essential libssl-dev libffi-dev && \
apt-get install -y software-properties-common && \
apt-get clean && \
RUN conda install --yes 'pip' && \
# install custom OAuth2 handler
git clone https://github.com/oxygenanywhere/oauthenticator.git && \
pip install -e oauthenticator && \
pip install jwt && \
USER $NB_USER
Or, do you need to somehow install the oxygenanywhere/oauthenticator oauthenticator version as part of the initial kubernetes jupyterhub image? (i.e. as part of the process of the initial jupyterhub install https://zero-to-jupyterhub.readthedocs.io/en/latest/setup-jupyterhub.html).
Apologies, I'm new to helm/kubernetes. My understanding is that I need to extend the default 'hub' image and pass its URL and tag to helm upgrade (as part of this step https://zero-to-jupyterhub.readthedocs.io/en/latest/extending-jupyterhub.html).
For example we could add the hub image/tag to config.yaml or pass as an argument:
helm upgrade <YOUR_RELEASE_NAME> jupyterhub/jupyterhub --version=v0.5 -f config.yaml \
--set hub.image.name=<IMAGE_URL>\
--set hub.image.tag=<IMAGE_TAG>
The base docker image for the 'hub' is here: https://hub.docker.com/r/jupyterhub/k8s-hub/
@masonlr, You are right, it is possible to extend a default k8s-hub image with custom authenticator or other dependencies. For instance I made an image that has Azure AD support available here
https://hub.docker.com/r/gigabit/jupyterhub/
My config looks like this
hub:
#using custom Ox image
image:
name: gigabit/jupyterhub
tag: v0.5.34
extraEnv:
OAUTH2_TOKEN_URL: "https://login.microsoftonline.com/xxxx/oauth2/token"
OAUTH2_AUTHORIZE_URL: "https://login.microsoftonline.com/xxx/oauth2/authorize"
....
auth:
type: custom
custom:
className: 'oauthenticator.azuread.AzureAdOAuthenticator'
config:
client_id: "zzzz"
client_secret: "yyy"
oauth_callback_url: "https://mydomain/hub/oauth_callback"
token_url: "https://login.microsoftonline.com/xxxx/oauth2/token"
authorize_url: "https://login.microsoftonline.com/xxxx/oauth2/authorize"
I still need to find the way to avoid passing the environment variables, and getting all the values straight from the config section
Okay, thanks. I'm getting a 500 : Internal Server Error with https://hub.docker.com/r/gigabit/jupyterhub/. This may be to do with the hardcoded self.client_id in the earlier versions of this fork.
please use tag v0.5.34
Thanks.
There also looks to be a typo in https://github.com/oxygenanywhere/oauthenticator/blob/2cf61aba85c5f921138d39f4832c9dd621ee85df/oauthenticator/azuread.py
azuread.py has a line:
os.environ.get('OAUTH_AUTHORIZE_URL', '')
but the environment variable from the config would be set to OAUTH2_AUTHORIZE_URL.
you mean this one
https://github.com/oxygenanywhere/oauthenticator/blob/master/oauthenticator/azuread.py#L53
it is not being used in the code, I was trying to follow the GitHub authorizer, still need to clean up the code, but it is functional in this version
Yes.
@avaranovich I can't get https://hub.docker.com/r/gigabit/jupyterhub/ to work with my mock Azure AD, so I suspect that I am missing something on the Azure AD side. I can reproduce the same error if I run jupyterhub on my own localhost.
To test, what I'm doing is creating a jupyterhub_config.py with the contents:
from oauthenticator.azuread import AzureAdOAuthenticator
c.JupyterHub.authenticator_class = AzureAdOAuthenticator
c.AzureAdOAuthenticator.oauth_callback_url = 'http://localhost:8000/hub/oauth_callback'
c.AzureAdOAuthenticator.client_id = 'xxx'
c.AzureAdOAuthenticator.client_secret = 'yyy'
c.AzureAdOAuthenticator.token_url = 'https://login.microsoftonline.com/zzz/oauth2/token'
c.AzureAdOAuthenticator.authorize_url = 'https://login.microsoftonline.com/zzz/oauth2/authorize'
In the Azure AD portal I set a reply URL to http://localhost:8000/hub/oauth_callback,
I then run
OAUTH2_TOKEN_URL="https://login.microsoftonline.com/zzz/oauth2/token"
OAUTH2_AUTHORIZE_URL="https://login.microsoftonline.com/zzz/oauth2/authorize"
jupyterhub -f jupyterhub_config.py
only to get a 401 Unauthorized error the following tornado log:
HTTPServerRequest(protocol='http', host='localhost:8000', method='GET', uri='/hub/oauth_callback?code=AQABAAIAAABHh4kmS_aKT5XrjzxRAtHzrrCNbWozRnxmAfEEasfKpt_ecCuBlTMopYhq5ihQtQtaL5QylDSu0pWI6RU8lmel_J81GAvssjlEw1HHWYib8TxXNGpVGwvKCUjBlhbyHNyxVg7Bgkxlw9AdygSdwkTzEabD9_x-8VEIjFv1AVkrOJQSyEVYFh3SHzgMrrQXMClzitybBwYQCAzZ-zql_SV9fXx4Hru4w7fIfJxTklIRtlYziUceQtuI_7YegwHcvKgIMZdm9FtQUObfd7oFkVyizd7Qb6amUGHegR62PYTyxR8vZV3SOvgdEtierSxYqCmqdob5kppM-ANNb1V7yoY9eomft7WfnaDdGvyyP9tTDHTUV1HhDMHcF07FHBnFWb_4nrZvj6RLoe_cbPflJOfWE4PUMQN_NpJf_vSbheT_tsR7ShxW0I0npQc9M4FouTerm18MaGM_JPRshfmOvHOFJZJO0miC8TdplrGiuHfrHXpYIckh2I68gRwklIlyPPhWXUFVW3FzlEPUfgF8jaRKY1aaX3FK5SSdS-RvVqrweDxGmcipTQ2BYY45BK30ZOs-i8t56hBFmRvLjG0c1zEk22vOrDIQz2TLoKwFLYEcerIcxUaccTTyU2H9GwBkBcGuReVCgjwFZ2OObbFx9_MvMOpQVRLLmZwlAFXjJkncTJUyzq5ytbeEzTYOxIx0rJ8oeRpZ7sRRT34GDkfYSlDiKUITvKMiEqTGBEHEop55rphWRxnOp4t-YKlS7TwQrX4H0HQAhJWwNpLwisqfniGn5iJOTwPDWjVZmGMRJV4rKAi4oddqXM749P1Zd9uGlPWOcFXTTeKKQO1bhP9_Vima2p5HRx2LtPLErHg3DDMXX25vrBHV7WJFTDHQCX-t7ZSoJ1acDRtlEfYGNPVx8Y8IwPB-kDWB7rqwnQm0eXEPxB6jZqu7udxWSMqawQgYxvBR7Iq5k0tTvv1DUnws3bSlUYTBHArFzJLJji5YANc_KSE4mA68qLz4mDvadcKOSgR9YW7asuTK4r9zZHnqVbCf8CNo3RfDA3LRkacM92ylym2JfiGb_-gdCoql3OjK5JjziW32gjecIRPo5wjTXVtPIAA&state=eyJzdGF0ZV9pZCI6ICIwZDlhOTFmYzgxMWM0NjZhYjAxMGFhMGViN2U1Yzk5NCIsICJuZXh0X3VybCI6ICIifQ%3d%3d&session_state=552ff6dd-1926-4656-9e2b-e5d6acdfd14b', version='HTTP/1.1', remote_ip='::1', headers={'X-Forwarded-Host': 'localhost:8000', 'X-Forwarded-Proto': 'http', 'X-Forwarded-Port': '8000', 'X-Forwarded-For': '::1', 'Cookie': 'oauthenticator-state="2|1:0|10:1515762614|20:oauthenticator-state|120:ZXlKemRHRjBaVjlwWkNJNklDSXdaRGxoT1RGbVl6Z3hNV00wTmpaaFlqQXhNR0ZoTUdWaU4yVTFZems1TkNJc0lDSnVaWGgwWDNWeWJDSTZJQ0lpZlE9PQ==|5f0dee0b2c596c0b010799fd9a07b99d810412d00dd8417830b516a64fb55680"', 'Accept-Language': 'en-AU,en;q=0.9,en-US;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', 'Upgrade-Insecure-Requests': '1', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache', 'Connection': 'close', 'Host': 'localhost:8000'})
Traceback (most recent call last):
File "/Users/lrmason/miniconda3/lib/python3.6/site-packages/tornado/web.py", line 1511, in _execute
result = yield result
File "/private/tmp/oauthenticator/oauthenticator/oauth2.py", line 182, in get
user = yield self.login_user()
File "/Users/lrmason/miniconda3/lib/python3.6/site-packages/jupyterhub/handlers/base.py", line 328, in login_user
authenticated = yield self.authenticate(data)
File "/Users/lrmason/miniconda3/lib/python3.6/site-packages/jupyterhub/auth.py", line 227, in get_authenticated_user
authenticated = yield self.authenticate(handler, data)
File "/private/tmp/oauthenticator/oauthenticator/azuread.py", line 94, in authenticate
resp = yield http_client.fetch(req)
tornado.httpclient.HTTPError: HTTP 401: Unauthorized
Do you know if this is an issue with azuread.py or whether I need to alter the properties in Azure AD? Thanks, again.
Apologies, this may be an error with the way I'm generating the client secret. About to try this tutorial and will let you know if it works: https://www.netiq.com/communities/cool-solutions/creating-application-client-id-client-secret-microsoft-azure-new-portal/
I'm reasonably certain that I have the correct client id, client secret, etc, but I still get a tornado error:
302 GET /hub/oauth_login?next= → https://login.microsoftonline.com/8895da17-b135-41ad-bab5-0505bd7c950c/oauth2/authorize?redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fhub%2Foauth_callback&client_id=02352c56-7089-4e3f-8afd-a089ce012b44&response_type=code&state=eyJzdGF0ZV9pZCI6ICIxNjc0NDY3OWM1NzE0YTJkYjNhODBiZmNhMGFmNjZiMCIsICJuZXh0X3VybCI6ICIifQ%3D%3D (@::1) 1.00ms
[E 2018-01-12 14:32:06.135 JupyterHub web:1590] Uncaught exception GET /hub/oauth_callback?code=AQABAAIAAABHh4kmS_aKT5XrjzxRAtHz3ZLS-fGNC1hh1z1olpQHxdfeavXRIYt7ahDb4K3RXLPP_o-boNPrHAUQlKRCGBlAZs1D_T7TWuZNF8z6a4Cbot8KhkrQs-nUVZYGVURRiXM8b2DLlr7r1PCA59w3KdSdTqGw-0u1EXqL6mHYbzMlGr9aatPBjezNzbKyuC-h2ocZuQFWyFJY4k-c24sD25sBczjc9QXgdpwR85wQbxIokXfO_u0X75CufRLeMs1Hmlkb7CL4lZnBArQ2tPqPRA5prYCGn5hjVR4bCvqpdlA_4e_nS1m6K3ddUzvC8F2UBaLCVpn4lXcI-yS3ugzvd11erzmXgspOQoouGXRAMYOmnBVOdP7M4NTSnIuKyaMSZXrmrN3it2kCFQdaMxQ-iFkPj1111cMMY0vZTDO2khLjnKM2ZLefh6aueQNv4iCBPwQvlvEPEzS7UfhvZoOmFzjPVNWaqLQAj8Ec1ZjIyuWq_LHZPxNa1-9pBOAWjA_MeUQlpGrv76nnl2_0JcZb4ZCqQp23d6bPnIYyvNZmA8UQnxscj5mTTg58uBC9L_pioNWEiUQHy9LNtD6pam7gZFWARoBPxZsNaQVALCU7nWEXkJGr7kXkxZex1m_iwPE_LTsr0_UoUV8olzjQpIriQBQYPeQbveVb9nHjduANMRWEo-zfqWDr-1-FOcLLbBn6xiNtLstVMCewoxfAi0f_GmD4OKIE2TGQ_erSoEcRZYwjdnom6y-5pRvIOx4teAvFh2upEHQTq2Mly4J-kfftusxlXdRs9QX_1_A24A3_351vGY1jOEJJ_XmHoYRk_K1B78IegXqrMkcq1a3sq3OVDWb93cU9C_qlU18DRcyi3ZeoQm7pAY-wDDkFzZpIK4hxw5cw6ZURY4xg3ApO22G7bD3SwZ8odyZRYAHODEW8B8rXC3zxqHSWdz-Z2I0sgkz8gJPspoFayz-P_aIG4hcqz4buuBrm4SGj8EATgrheKllcuiTMccbSbgGFsf6F7Rra8pbTQa47DkrDus_GHUcnKaXmP7SAM8X6IdLVLrTchT2JX_-d3Si7v2egCwNhtHvNE4jYuPpVcdhet1c35xE3bmHJIAA&state=eyJzdGF0ZV9pZCI6ICIxNjc0NDY3OWM1NzE0YTJkYjNhODBiZmNhMGFmNjZiMCIsICJuZXh0X3VybCI6ICIifQ%3d%3d&session_state=6489af4d-19e1-4fe4-b57a-55f782af90cd (::1)
HTTPServerRequest(protocol='http', host='localhost:8000', method='GET', uri='/hub/oauth_callback?code=AQABAAIAAABHh4kmS_aKT5XrjzxRAtHz3ZLS-fGNC1hh1z1olpQHxdfeavXRIYt7ahDb4K3RXLPP_o-boNPrHAUQlKRCGBlAZs1D_T7TWuZNF8z6a4Cbot8KhkrQs-nUVZYGVURRiXM8b2DLlr7r1PCA59w3KdSdTqGw-0u1EXqL6mHYbzMlGr9aatPBjezNzbKyuC-h2ocZuQFWyFJY4k-c24sD25sBczjc9QXgdpwR85wQbxIokXfO_u0X75CufRLeMs1Hmlkb7CL4lZnBArQ2tPqPRA5prYCGn5hjVR4bCvqpdlA_4e_nS1m6K3ddUzvC8F2UBaLCVpn4lXcI-yS3ugzvd11erzmXgspOQoouGXRAMYOmnBVOdP7M4NTSnIuKyaMSZXrmrN3it2kCFQdaMxQ-iFkPj1111cMMY0vZTDO2khLjnKM2ZLefh6aueQNv4iCBPwQvlvEPEzS7UfhvZoOmFzjPVNWaqLQAj8Ec1ZjIyuWq_LHZPxNa1-9pBOAWjA_MeUQlpGrv76nnl2_0JcZb4ZCqQp23d6bPnIYyvNZmA8UQnxscj5mTTg58uBC9L_pioNWEiUQHy9LNtD6pam7gZFWARoBPxZsNaQVALCU7nWEXkJGr7kXkxZex1m_iwPE_LTsr0_UoUV8olzjQpIriQBQYPeQbveVb9nHjduANMRWEo-zfqWDr-1-FOcLLbBn6xiNtLstVMCewoxfAi0f_GmD4OKIE2TGQ_erSoEcRZYwjdnom6y-5pRvIOx4teAvFh2upEHQTq2Mly4J-kfftusxlXdRs9QX_1_A24A3_351vGY1jOEJJ_XmHoYRk_K1B78IegXqrMkcq1a3sq3OVDWb93cU9C_qlU18DRcyi3ZeoQm7pAY-wDDkFzZpIK4hxw5cw6ZURY4xg3ApO22G7bD3SwZ8odyZRYAHODEW8B8rXC3zxqHSWdz-Z2I0sgkz8gJPspoFayz-P_aIG4hcqz4buuBrm4SGj8EATgrheKllcuiTMccbSbgGFsf6F7Rra8pbTQa47DkrDus_GHUcnKaXmP7SAM8X6IdLVLrTchT2JX_-d3Si7v2egCwNhtHvNE4jYuPpVcdhet1c35xE3bmHJIAA&state=eyJzdGF0ZV9pZCI6ICIxNjc0NDY3OWM1NzE0YTJkYjNhODBiZmNhMGFmNjZiMCIsICJuZXh0X3VybCI6ICIifQ%3d%3d&session_state=6489af4d-19e1-4fe4-b57a-55f782af90cd', version='HTTP/1.1', remote_ip='::1', headers={'X-Forwarded-Host': 'localhost:8000', 'X-Forwarded-Proto': 'http', 'X-Forwarded-Port': '8000', 'X-Forwarded-For': '::1', 'Upgrade-Insecure-Requests': '1', 'Connection': 'close', 'Cookie': 'oauthenticator-state="2|1:0|10:1515767518|20:oauthenticator-state|120:ZXlKemRHRjBaVjlwWkNJNklDSXhOamMwTkRZM09XTTFOekUwWVRKa1lqTmhPREJpWm1OaE1HRm1OalppTUNJc0lDSnVaWGgwWDNWeWJDSTZJQ0lpZlE9PQ==|9e61583bda18d270174fd36ebb551a89a49e2675330d2097a5c3d8a3ceba3fa9"', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-GB,en;q=0.5', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:57.0) Gecko/20100101 Firefox/57.0', 'Host': 'localhost:8000'})
Traceback (most recent call last):
File "/Users/lrmason/miniconda3/lib/python3.6/site-packages/tornado/web.py", line 1511, in _execute
result = yield result
File "/private/tmp/oauthenticator/oauthenticator/oauth2.py", line 182, in get
user = yield self.login_user()
File "/Users/lrmason/miniconda3/lib/python3.6/site-packages/jupyterhub/handlers/base.py", line 328, in login_user
authenticated = yield self.authenticate(data)
File "/Users/lrmason/miniconda3/lib/python3.6/site-packages/jupyterhub/auth.py", line 227, in get_authenticated_user
authenticated = yield self.authenticate(handler, data)
File "/private/tmp/oauthenticator/oauthenticator/azuread.py", line 94, in authenticate
resp = yield http_client.fetch(req)
tornado.httpclient.HTTPError: HTTP 400: Bad Request
[E 2018-01-12 14:32:06.147 JupyterHub log:114] {
"X-Forwarded-Host": "localhost:8000",
"X-Forwarded-Proto": "http",
"X-Forwarded-Port": "8000",
"X-Forwarded-For": "::1",
"Upgrade-Insecure-Requests": "1",
"Connection": "close",
"Cookie": "oauthenticator-state=\"2|1:0|10:1515767518|20:oauthenticator-state|120:ZXlKemRHRjBaVjlwWkNJNklDSXhOamMwTkRZM09XTTFOekUwWVRKa1lqTmhPREJpWm1OaE1HRm1OalppTUNJc0lDSnVaWGgwWDNWeWJDSTZJQ0lpZlE9PQ==|9e61583bda18d270174fd36ebb551a89a49e2675330d2097a5c3d8a3ceba3fa9\"",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-GB,en;q=0.5",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:57.0) Gecko/20100101 Firefox/57.0",
"Host": "localhost:8000"
}
[E 2018-01-12 14:32:06.147 JupyterHub log:122] 500 GET /hub/oauth_callback?code=AQABAAIAAABHh4kmS_aKT5XrjzxRAtHz3ZLS-fGNC1hh1z1olpQHxdfeavXRIYt7ahDb4K3RXLPP_o-boNPrHAUQlKRCGBlAZs1D_T7TWuZNF8z6a4Cbot8KhkrQs-nUVZYGVURRiXM8b2DLlr7r1PCA59w3KdSdTqGw-0u1EXqL6mHYbzMlGr9aatPBjezNzbKyuC-h2ocZuQFWyFJY4k-c24sD25sBczjc9QXgdpwR85wQbxIokXfO_u0X75CufRLeMs1Hmlkb7CL4lZnBArQ2tPqPRA5prYCGn5hjVR4bCvqpdlA_4e_nS1m6K3ddUzvC8F2UBaLCVpn4lXcI-yS3ugzvd11erzmXgspOQoouGXRAMYOmnBVOdP7M4NTSnIuKyaMSZXrmrN3it2kCFQdaMxQ-iFkPj1111cMMY0vZTDO2khLjnKM2ZLefh6aueQNv4iCBPwQvlvEPEzS7UfhvZoOmFzjPVNWaqLQAj8Ec1ZjIyuWq_LHZPxNa1-9pBOAWjA_MeUQlpGrv76nnl2_0JcZb4ZCqQp23d6bPnIYyvNZmA8UQnxscj5mTTg58uBC9L_pioNWEiUQHy9LNtD6pam7gZFWARoBPxZsNaQVALCU7nWEXkJGr7kXkxZex1m_iwPE_LTsr0_UoUV8olzjQpIriQBQYPeQbveVb9nHjduANMRWEo-zfqWDr-1-FOcLLbBn6xiNtLstVMCewoxfAi0f_GmD4OKIE2TGQ_erSoEcRZYwjdnom6y-5pRvIOx4teAvFh2upEHQTq2Mly4J-kfftusxlXdRs9QX_1_A24A3_351vGY1jOEJJ_XmHoYRk_K1B78IegXqrMkcq1a3sq3OVDWb93cU9C_qlU18DRcyi3ZeoQm7pAY-wDDkFzZpIK4hxw5cw6ZURY4xg3ApO22G7bD3SwZ8odyZRYAHODEW8B8rXC3zxqHSWdz-Z2I0sgkz8gJPspoFayz-P_aIG4hcqz4buuBrm4SGj8EATgrheKllcuiTMccbSbgGFsf6F7Rra8pbTQa47DkrDus_GHUcnKaXmP7SAM8X6IdLVLrTchT2JX_-d3Si7v2egCwNhtHvNE4jYuPpVcdhet1c35xE3bmHJIAA&state=eyJzdGF0ZV9pZCI6ICIxNjc0NDY3OWM1NzE0YTJkYjNhODBiZmNhMGFmNjZiMCIsICJuZXh0X3VybCI6ICIifQ%3d%3d&session_state=6489af4d-19e1-4fe4-b57a-55f782af90cd (@::1) 594.06ms
Okay, I now have https://github.com/oxygenanywhere/oauthenticator/tree/e60d9c6bef6e1e95fc5e13fa8224a9ba43f66caf working with an Azure active directory. I needed to remove the jwt installation which is mentioned by me above in the Dockerfile fragment. So
pip uninstall JWT
pip uninstall PyJWT
pip install PyJWT
@avaranovich if jwt needs to be added to the base hub docker image, can you please ensure that pyjwt is installed instead of jwt?
For reference, I also couldn't get https://github.com/oxygenanywhere/oauthenticator/blob/e60d9c6bef6e1e95fc5e13fa8224a9ba43f66caf/oauthenticator/azuread.py to work with the v2 Active Directory API, i.e. when app authentication is set up via https://apps.dev.microsoft.com/
The error is:
Additional technical information:
--
Correlation ID: 4a042d00-934b-4b46-92c6-f4a3da0b0dc6
Timestamp: 2018-01-12 18:06:47Z
AADSTS90014: The request body must contain the following parameter: 'scope'.
@masonlr would you mind filing the issues directly in the fork
https://github.com/oxygenanywhere/oauthenticator/issues
I am aware about incompatibility with v2 endpoints.
Sure.
@avaranovich
This conversation was really helpful for me to set jupyterhub up, could you point me to the Dockerfile linked to gigabit/jupyterhub?
It's not possible to retrieve the Dockerfile from Docker hub.
Thank you by advance
@avaranovich
This conversation was really helpful for me to set jupyterhub up, could you point me to the Dockerfile linked to gigabit/jupyterhub?
It's not possible to retrieve the Dockerfile from Docker hub.
Thank you by advance
Late answer but maybe helpful for others:
https://github.com/dkipping/zero-to-jupyterhub-k8s/tree/master/images/hub
This folder should contain all files necessary for the hub image at least.
Still, when building my own image, I got the following errors:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/jupyterhub/app.py", line 1955, in launch_instance_async
await self.initialize(argv)
File "/usr/local/lib/python3.6/dist-packages/jupyterhub/app.py", line 1639, in initialize
self.load_config_file(self.config_file)
File "<decorator-gen-5>", line 2, in load_config_file
File "/usr/local/lib/python3.6/dist-packages/traitlets/config/application.py", line 87, in catch_config_error
return method(app, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/traitlets/config/application.py", line 598, in load_config_file
raise_config_file_errors=self.raise_config_file_errors,
File "/usr/local/lib/python3.6/dist-packages/traitlets/config/application.py", line 562, in _load_config_files
config = loader.load_config()
File "/usr/local/lib/python3.6/dist-packages/traitlets/config/loader.py", line 457, in load_config
self._read_file_as_dict()
File "/usr/local/lib/python3.6/dist-packages/traitlets/config/loader.py", line 489, in _read_file_as_dict
py3compat.execfile(conf_filename, namespace)
File "/usr/local/lib/python3.6/dist-packages/ipython_genutils/py3compat.py", line 198, in execfile
exec(compiler(f.read(), fname, 'exec'), glob, loc)
File "/srv/jupyterhub_config.py", line 328, in <module>
raise ValueError("Unhandled auth type: %r" % auth_type)
ValueError: Unhandled auth type: None
No config at /etc/jupyterhub/config/values.yaml
No config at /etc/jupyterhub/secret/values.yaml
so something else seems to be missing
I able to integrate azure ad to my jupyterhub.
Please modify config.yaml ->
add auth like this
auth:
type: custom
custom:
className: oauthenticator.azuread.AzureAdOAuthenticator
config:
client_id:
client_secret:
oauth_callback_url: https://yourdomainame/hub/oauth_callback
You also have to modify jupyterhub/values.yaml or hub configuration.
extraEnv: {AAD_TENANT_ID: "Your add_tenant_id"}

Most helpful comment
I'm reasonably certain that I have the correct client id, client secret, etc, but I still get a
tornadoerror: