This example embeds an authenticated request to a service into the template for /hub/home
.
The user may not be logged in to the service when the page is requested,
so we must process the oauth login to the service in that event.
To avoid the user having to experience any of the login process, this requires:
- attempting to fetch the endpoint
- if it fails with a login redirect, send the viewport to the service to start login, with
?next=current page
- on completion of oauth with the service, the service redirects back to the originating page to try again
- on the next attempt, the page will be able to make requests to the service
Uses jupyterhub.services.HubOAuthenticated
to authenticate requests with the Hub.
There is an implementation each of api-token-based HubAuthenticated
and OAuth-based HubOAuthenticated
.
-
Launch JupyterHub and the
whoami
services withjupyterhub
After logging in with any username and password, you should see a JSON dump of your user info at the bottom of the hub home page:
{
"admin": false,
"groups": [],
"kind": "user",
"name": "queequeg",
"scopes": ["access:services!service=whoami-oauth"],
"session_id": "5a2164273a7346728873bcc2e3c26415"
}
The javascript added to /hub/home
:
<pre id="whoami-out"></pre>
<script type="text/javascript">
async function fetchService() {
const serviceUrl = "{{base_url}}../services/whoami/"
console.log("fetching", serviceUrl);
try {
resp = await fetch(serviceUrl, {redirect: "manual"});
} catch (e) {
console.log(e);
return;
}
if (resp.type === "opaqueredirect") {
// not logged in to service,
// construct local absolute path URI
const here = location.pathname + location.search + location.hash;
// login to service and trust it to redirect back here
window.location = serviceUrl + "?next=" + encodeURIComponent(here);
return;
}
// logged in, put the service response on the page
const text = await resp.text();
document.getElementById("whoami-out").appendChild(document.createTextNode(text));
}
fetchService();
</script>
The service definition:
c.JupyterHub.services = [
{
'name': 'whoami',
'url': 'http://127.0.0.1:10102',
'command': [sys.executable, './service.py'],
# oauth_no_confirm skips the confirmation page
# this is required for the login to the service to be fully transparent
# note: you are taking away your users' ability to consent to login to this service,
# so use with caution.
'oauth_no_confirm': True,
},
]
Grant users access to services:
c.JupyterHub.load_roles = [
{
"name": "user",
# grant all users access to all services
"scopes": ["access:services", "self"],
}
]
Register custom template:
from pathlib import Path
here = Path(__file__).parent
c.JupyterHub.template_paths = [str(here.joinpath("templates"))]