Hello,
I would like to implement oauth authentication with edu-id. edu-id supports openIDConnect OpenID Connect - For services - Documentation - SWITCH edu-ID - SWITCH Help
I was wondering where I can find more information and an example of such a custom oauth implementation. The only thing I could find was a slide from one of the jupyterhub presentations by mnirk (screenshot attached). I asked chatgpt to complete this example and it provided the below code. Would you have any comments? I appreciate it if you can provide me an example or more information on this.
from tornado.auth import OAuth2Mixin
from jupyterhub.handlers import BaseHandler
from jupyterhub.auth import Authenticator
from tornado import gen
import json
class MyServiceMixin(OAuth2Mixin):
_OAUTH_AUTHORIZE_URL = "https://myservice.horse/login/oauth/authorize"
_OAUTH_ACCESS_TOKEN_URL = "https://myservice.horse/login/oauth/access_token"
class MyServiceLoginHandler(BaseHandler, MyServiceMixin):
@gen.coroutine
def get(self):
if self.get_argument("code", False):
user = yield self.get_authenticated_user(
redirect_uri=self.settings["oauth_redirect_uri"],
code=self.get_argument("code"))
# You might want to store the user data in a more robust way
self.set_login_cookie(user)
self.redirect(self.get_next_url())
else:
yield self.authorize_redirect(
redirect_uri=self.settings["oauth_redirect_uri"],
client_id=self.settings["my_service_client_id"],
scope=["openid", "profile"],
response_type="code",
extra_params={"approval_prompt": "auto"})
class MyServiceOAuthenticator(Authenticator):
login_service = "My Service"
login_handler = MyServiceLoginHandler
@gen.coroutine
def authenticate(self, handler, data=None):
code = handler.get_argument("code", False)
info = yield self.ask_my_service_about(code)
return info['username']
@gen.coroutine
def ask_my_service_about(self, code):
# Here you should implement the logic to exchange code for user info
# and return the user info as a dictionary
# You might use Tornado's HTTP client to make requests
# to the my service's endpoints
# For example:
token_response = yield self.fetch(
self._OAUTH_ACCESS_TOKEN_URL,
method="POST",
body="grant_type=authorization_code&"
f"code={code}&"
f"client_id={self.settings['my_service_client_id']}&"
f"client_secret={self.settings['my_service_client_secret']}&"
f"redirect_uri={self.settings['oauth_redirect_uri']}"
)
access_token = json.loads(token_response.body)["access_token"]
user_info_response = yield self.fetch(
"https://myservice.horse/api/userinfo",
headers={"Authorization": f"Bearer {access_token}"}
)
user_info = json.loads(user_info_response.body)
return user_info
Here is the answer from Erik Sundell oauth with edu-id · Issue #672 · jupyterhub/oauthenticator · GitHub but I would still need help (if possible a similar example with custom oauth authentication).
best
B