Generic Oauth Authenticate Method
78 lines
@gen.coroutine
##Version 0.8.0 of the oauthenticator.generic.GenericOAuthenticator.authenticate method
##https://github.com/jupyterhub/oauthenticator/blob/0.8.0/oauthenticator/generic.py
##Modifications noted
@gen.coroutine
def authenticate(self, handler, data=None):
def authenticate(self, handler, data=None):
print("Doing custom authenticate method") ##CHANGE
code = handler.get_argument("code")
code = handler.get_argument("code")
# TODO: Configure the curl_httpclient for tornado
# TODO: Configure the curl_httpclient for tornado
http_client = AsyncHTTPClient()
http_client = AsyncHTTPClient()
params = dict(
params = dict(
redirect_uri=self.get_callback_url(handler),
redirect_uri=self.get_callback_url(handler),
code=code,
code=code,
grant_type='authorization_code'
grant_type='authorization_code'
)
)
params.update(self.extra_params)
params.update(self.extra_params)
if self.token_url:
if self.token_url:
url = self.token_url
url = self.token_url
else:
else:
raise ValueError("Please set the OAUTH2_TOKEN_URL environment variable")
raise ValueError("Please set the OAUTH2_TOKEN_URL environment variable")
b64key = base64.b64encode(
b64key = base64.b64encode(
bytes(
bytes(
"{}:{}".format(self.client_id, self.client_secret),
"{}:{}".format(self.client_id, self.client_secret),
"utf8"
"utf8"
)
)
)
)
headers = {
headers = {
"Accept": "application/json",
"Accept": "application/json",
"User-Agent": "JupyterHub",
"User-Agent": "JupyterHub",
"Authorization": "Basic {}".format(b64key.decode("utf8"))
"Authorization": "Basic {}".format(b64key.decode("utf8"))
}
}
req = HTTPRequest(url,
req = HTTPRequest(url,
method="POST",
method="POST",
headers=headers,
headers=headers,
validate_cert=self.tls_verify,
validate_cert=self.tls_verify,
body=urllib.parse.urlencode(params) # Body is required for a POST...
body=urllib.parse.urlencode(params) # Body is required for a POST...
)
)
resp = yield http_client.fetch(req)
resp = yield http_client.fetch(req)
resp_json = json.loads(resp.body.decode('utf8', 'replace'))
resp_json = json.loads(resp.body.decode('utf8', 'replace'))
access_token = resp_json['access_token']
access_token = resp_json['access_token']
refresh_token = resp_json.get('refresh_token', None)
refresh_token = resp_json.get('refresh_token', None)
token_type = resp_json['token_type']
token_type = resp_json['token_type']
scope = (resp_json.get('scope', '')).split(' ')
scope = (resp_json.get('scope', '')).split(' ')
token_resp = resp_json ##CHANGED: Store original response. AWS sends additional data we need like the idToken
# Determine who the logged in user is
# Determine who the logged in user is
headers = {
headers = {
"Accept": "application/json",
"Accept": "application/json",
"User-Agent": "JupyterHub",
"User-Agent": "JupyterHub",
"Authorization": "{} {}".format(token_type, access_token)
"Authorization": "{} {}".format(token_type, access_token)
}
}
if self.userdata_url:
if self.userdata_url:
url = url_concat(self.userdata_url, self.userdata_params)
url = url_concat(self.userdata_url, self.userdata_params)
else:
else:
raise ValueError("Please set the OAUTH2_USERDATA_URL environment variable")
raise ValueError("Please set the OAUTH2_USERDATA_URL environment variable")
req = HTTPRequest(url,
req = HTTPRequest(url,
method=self.userdata_method,
method=self.userdata_method,
headers=headers,
headers=headers,
validate_cert=self.tls_verify,
validate_cert=self.tls_verify,
)
)
resp = yield http_client.fetch(req)
resp = yield http_client.fetch(req)
resp_json = json.loads(resp.body.decode('utf8', 'replace'))
resp_json = json.loads(resp.body.decode('utf8', 'replace'))
if not resp_json.get(self.username_key):
if not resp_json.get(self.username_key):
self.log.error("OAuth user contains no key %s: %s", self.username_key, resp_json)
self.log.error("OAuth user contains no key %s: %s", self.username_key, resp_json)
return
return
return {
##CHANGED: Store return value for easier debugging
retval = {
'name': resp_json.get(self.username_key),
'name': resp_json.get(self.username_key),
'auth_state': {
'auth_state': {
'access_token': access_token,
'access_token': access_token,
'refresh_token': refresh_token,
'refresh_token': refresh_token,
'oauth_user': resp_json,
'oauth_user': resp_json,
'scope': scope,
'scope': scope,
}
'token_resp': token_resp, ##CHANGED: Return the extra information
},
}
}
return retval