add external oauth example

This commit is contained in:
Min RK
2018-02-22 17:00:59 +01:00
parent 22c3064ec4
commit 6970df4dda
5 changed files with 157 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
# Using JupyterHub as an OAuth provider
JupyterHub 0.9 introduces
Uses `jupyterhub.services.HubAuthenticated` to authenticate requests with the Hub.
There is an implementation each of cookie-based `HubAuthenticated` and OAuth-based `HubOAuthenticated`.
## Run
1. generate an API token:
export JUPYTERHUB_API_TOKEN=`openssl rand -hex 32`
2. launch the whoami service:
bash launch-service.sh &
3. Launch JupyterHub:
4. Visit http://127.0.0.1:5555/
After logging in with your local-system credentials, you should see a JSON dump of your user info:
```json
{
"admin": false,
"last_activity": "2016-05-27T14:05:18.016372",
"name": "queequeg",
"pending": null,
"server": "/user/queequeg"
}
```
The essential pieces for using JupyterHub as an OAuth provider are:
1. registering your service with jupyterhub:
```python
c.JupyterHub.services = [
{
# the name of your service
# should be simple and unique.
# mostly used to identify your service in logging
"name": "my-service",
# the oauth client id of your service
# must be unique but isn't private
# can be randomly generated or hand-written
"oauth_client_id": "abc123",
# the API token and client secret of the service
# should be generated securely,
# e.g. via `openssl rand -hex 32`
"api_token": "abc123...",
# the redirect target for jupyterhub to send users
# after successful authentication
"oauth_redirect_uri": "https://service-host/oauth_callback"
}
]
```
2. Telling your service how to authenticate with JupyterHub.
The relevant OAuth URLs for working with JupyterHub are:
1. the client_id, used in oauth requests
2. the api token registered with jupyterhub is the client_secret for oauth requests
3. oauth url of the Hub, which is "/hub/api/oauth2/authorize", e.g. `https://myhub.horse/hub/api/oauth2/authorize`
4. a redirect handler to receive the authenticated response
(at `oauth_redirect_uri` registered in jupyterhub config)
5. the token URL for completing the oauth process is "/hub/api/oauth2/token",
e.g. `https://myhub.horse/hub/api/oauth2/token`.
The reply is JSON and the token is in the field `access_token`.
6. Users can be identified by oauth token by making a request to `/hub/api/user`
with the new token in the `Authorization` header.

View File

@@ -0,0 +1,17 @@
import os
# get the oauth client's API token.
# this could come from anywhere
api_token = os.getenv("JUPYTERHUB_API_TOKEN")
if not api_token:
raise ValueError("Make sure to `export JUPYTERHUB_API_TOKEN=$(openssl rand -hex 32)`")
# tell JupyterHub to register the service as an external oauth client
c.JupyterHub.services = [
{
'name': 'external-oauth',
'oauth_client_id': "whoami-oauth-client-test",
'api_token': api_token,
'oauth_redirect_uri': 'http://127.0.0.1:5555/oauth_callback',
},
]

View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
# the service needs to know:
# 1. API token
if [[ -z "${JUPYTERHUB_API_TOKEN}" ]]; then
echo 'set API token with export JUPYTERHUB_API_TOKEN=$(openssl rand -hex 32)'
fi
# 2. oauth client ID
export JUPYTERHUB_CLIENT_ID="whoami-oauth-client-test"
# 3. what URL to run on
export JUPYTERHUB_SERVICE_PREFIX='/'
export JUPYTERHUB_SERVICE_URL='http://127.0.0.1:5555'
export JUPYTERHUB_OAUTH_CALLBACK_URL="$JUPYTERHUB_SERVICE_URL/oauth_callback"
# 4. where the Hub is
export JUPYTERHUB_HOST='http://127.0.0.1:8000'
# launch the service
exec python3 whoami-oauth.py

View File

@@ -0,0 +1,46 @@
"""An example service authenticating with the Hub.
This example service serves `/services/whoami/`,
authenticated with the Hub,
showing the user their own info.
"""
from getpass import getuser
import json
import os
from urllib.parse import urlparse
from tornado.ioloop import IOLoop
from tornado import log
from tornado.httpserver import HTTPServer
from tornado.web import RequestHandler, Application, authenticated
from jupyterhub.services.auth import HubOAuthenticated, HubOAuthCallbackHandler
from jupyterhub.utils import url_path_join
class WhoAmIHandler(HubOAuthenticated, RequestHandler):
hub_users = {getuser()} # the users allowed to access this service
@authenticated
def get(self):
user_model = self.get_current_user()
self.set_header('content-type', 'application/json')
self.write(json.dumps(user_model, indent=1, sort_keys=True))
def main():
log.enable_pretty_logging()
app = Application([
(os.environ['JUPYTERHUB_SERVICE_PREFIX'], WhoAmIHandler),
(url_path_join(os.environ['JUPYTERHUB_SERVICE_PREFIX'], 'oauth_callback'), HubOAuthCallbackHandler),
(r'.*', WhoAmIHandler),
], cookie_secret=os.urandom(32))
http_server = HTTPServer(app)
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
log.app_log.info("Running whoami service on %s", os.environ['JUPYTERHUB_SERVICE_URL'])
http_server.listen(url.port, url.hostname)
IOLoop.current().start()
if __name__ == '__main__':
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB