I’m trying to launch a binder server using the BinderHub API by following this example: https://github.com/jupyterhub/binderhub/blob/31ab3c7069141f14ad6c45c0c7a58ffbfbc5c4c4/examples/binder-api.py .
In the example there is no authentication used but my BinderHub has authentication enabled, it uses Keycloak (OpenId). I am able to build my OAuth2Session but when I do my GET request it does not launch a binder, instead it redirects to the JupyterHub login page with the button “Sign in with keycloak” while I am already authenticated. Can someone point me out what I am doing wrong?
This is what I have so far:
import json
import webbrowser
import sys
from bs4 import BeautifulSoup as bs
from oauthlib.oauth2 import LegacyApplicationClient
from requests_oauthlib import OAuth2Session
def build_binder(repo, ref='master', filepath=None, *, binder_url='https://binderhub.xxx.io', oauth_session):
"""Launch a binder
Yields Binder's event-stream events (dicts)
"""
print("Building binder for {repo}@{ref}".format(repo=repo, ref=ref))
url = binder_url + '/build/gh/{repo}/{ref}'.format(repo=repo, ref=ref)
r = oauth_session.get(url, stream=True)
r.raise_for_status()
# Printing HTML for debugging purposes
soup = bs(r.content, features="html.parser") # make BeautifulSoup
prettyHTML = soup.prettify() # prettify the html
print(prettyHTML)
for line in r.iter_lines():
line = line.decode('utf8', 'replace')
if line.startswith('data:'):
yield json.loads(line.split(':', 1)[1])
if __name__ == '__main__':
repo = 'jakevdp/PythonDataScienceHandbook'
client_id = "xxx-xxx-xxx"
client_secret = "xxx-xxx-xxx-xxx-xxx"
# Start OAuth2 session
oauth = OAuth2Session(client=LegacyApplicationClient(client_id=client_id))
oauth.redirect_uri = "https://jhub.xxx.io/hub/oauth_callback"
token = oauth.fetch_token(token_url='https://auth.xxx.io/auth/realms/xxx/protocol/openid-connect/token',
username="patrick", password="spongebob", client_id=client_id,
client_secret=client_secret)
for evt in build_binder(repo, oauth_session=oauth):
if 'message' in evt:
print("[{phase}] {message}".format(
phase=evt.get('phase', ''),
message=evt['message'].rstrip(),
))
if evt.get('phase') == 'ready':
url = "{url}?token={token}".format(**evt)
print("Opening %s" % url)
webbrowser.open(url)
break
else:
sys.exit("binder never became ready")