I’m using this guide to write oAuthenticator for jupyterhub. This is the code for that file:
import json
from jupyterhub.auth import LocalAuthenticator
from oauthenticator.oauth2 import OAuthLoginHandler, OAuthenticator
from tornado.auth import OAuth2Mixin
from tornado.httputil import url_concat
from tornado.httpclient import HTTPRequest, AsyncHTTPClient, HTTPError
class MyServiceMixin(OAuth2Mixin):
_OAUTH_AUTHORIZE_URL = "https://<my_company>.com/adfs/oauth2/authorize/"
_OAUTH_ACCESS_TOKEN_URL = "https://<my_company>.com/adfs/oauth2/token/"
class MyServiceLoginHandler(OAuthLoginHandler, MyServiceMixin):
pass
class CustomOAuthenticator(OAuthenticator):
login_service = "custom"
login_handler = MyServiceLoginHandler
async def authenticate(self, handler, data=None):
code = handler.get_argument("code")
http_client = AsyncHTTPClient()
params = dict(
client_id="<client_id>",
resource="resource_uri",
code=code ,
redirect_uri="https://notebook.net/hub/oauth_callback"
)
url = url_concat("https://<mycompany>.com/adfs/oauth2/token/", params)
req = HTTPRequest(url, method="POST", headers={"Accept": "application/json"}, body='')
resp = await http_client.fetch(req)
resp_json = json.loads(resp.body.decode('utf8', 'replace'))
if 'access_token' in resp_json:
access_token = resp_json['access_token']
elif 'error_description' in resp_json:
raise HTTPError(
403,
"An access token was not returned: {}".format(
resp_json['error_description']
),
)
else:
raise HTTPError(500, "Bad response: %s".format(resp))
req = HTTPRequest(
"https://<my_company>.com/adfs/userinfo",
method="GET",
headers={"Authorization": f"Bearer {access_token}"},
)
resp = await http_client.fetch(req)
resp_json = json.loads(resp.body.decode('utf8', 'replace'))
username = resp_json[""]
if not username:
return None
user_info = {"name": username}
user_info["auth_state"] = auth_state = {}
auth_state['access_token'] = access_token
auth_state['auth_reply'] = resp_json
return user_info
class LocalCustomOAuthenticator(LocalAuthenticator, CustomOAuthenticator):
pass
And this is the code in the configmap file:
auth:
custom:
className: CustomOAuth.CustomOAuthenticator
config:
login_service: "Custom"
client_id: "<client_id"
token_url: https://<my_company>.com/adfs/oauth2/token/
userdata_url: https://<my_company>.com/adfs/userinfo
admin:
access: true
users: null
type: custom
whitelist:
users: null
custom: {}
debug:
enabled: true
hub:
extraEnv:
OAUTH2_AUTHORIZE_URL: https://<my_company>.com/adfs/oauth2/authorize/
OAUTH2_TOKEN_URL: https://<my_company>/adfs/oauth2/token/
OAUTH_CALLBACK_URL: https://notebook.net/hub/oauth_callback
When I click on the sign in button, it redirects me to the callback url, and some cookies are also set. BUT I get 500 Internal error.
This is the error log:
Traceback (most recent call last):
File "/usr/local/lib64/python3.6/site-packages/tornado/web.py", line 1703, in _execute
result = await result
File "/usr/local/lib/python3.6/site-packages/oauthenticator/oauth2.py", line 182, in get
user = yield self.login_user()
File "/usr/local/lib/python3.6/site-packages/jupyterhub/handlers/base.py", line 483, in login_user
authenticated = await self.authenticate(data)
File "/usr/local/lib/python3.6/site-packages/jupyterhub/auth.py", line 257, in get_authenticated_user
authenticated = await maybe_future(self.authenticate(handler, data))
File "/usr/local/bin/IDAnywhereOAuth.py", line 84, in authenticate
resp_json = json.loads(dataform)
File "/usr/lib64/python3.6/json/__init__.py", line 354, in loads
return _default_decoder.decode(s)
File "/usr/lib64/python3.6/json/decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib64/python3.6/json/decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
As the resp which I am getting is not a JSON but a html string.
Is there any problem in my code or setup?