It looks like the credentials are passed into the builder here:
But then you need to trace that up the chain- I expect it’d require some refactoring to get the user credentials in there.
I’m not sure how much work is involved in passing the user credentials into BinderHub though, if you’ve got an authenticated BinderHub the auth is handled by JupyterHub, so you need to figure out how to pass that auth to Binder.
I suspect your original idea of checking for access in the Spawner may be the easiest even if it’s not the most elegant solution, since as you point out the Spawner has access to auth_state.
It is possible to control the user access before launching a Binder, using the c.Launcher.pre_launch_hook configurable. For example:
from urllib.parse import urlparse, quote
from tornado.httpclient import AsyncHTTPClient, HTTPError
GITLAB_HOSTNAME = "gitlab.example.com"
async def pre_launch_hook(launcher, image, username, server_name, repo_url):
user = await launcher.get_user_data(username)
auth_state = user.get('auth_state', None)
if not auth_state:
launcher.log.warning("No auth state for %s", username)
return
access_token = auth_state['access_token']
namespace = urlparse(repo_url).path.strip('/').strip('.git')
namespace = quote(namespace, safe='')
# check the user has access to the repo
client = AsyncHTTPClient()
api_url = f"https://{GITLAB_HOSTNAME}/api/v4/projects/{namespace}?access_token={access_token}"
try:
resp = await client.fetch(api_url)
except HTTPError as err:
raise Exception(f"User {username} does not have access to {repo_url}") from err
c.Launcher.pre_launch_hook = pre_launch_hook
c.GitLabRepoProvider.hostname = GITLAB_HOSTNAME
The user will then be faced with the following messages in the BinderHub UI:
However there doesn’t seem to be a way at the moment to control access at build time. Which could be used to check whether users are allowed to build a repo they don’t have access to. For now they can still build a repo by guessing the name. The repo builds because the c.GitLabProvider.private_token has access to the repo to resolve the refs: