get OAuth working with subdomains

needs a lot of host passing around
This commit is contained in:
Min RK
2017-04-05 13:58:28 +02:00
parent b1efe3a5c1
commit ef51eb21e0
4 changed files with 26 additions and 17 deletions

View File

@@ -1059,6 +1059,7 @@ class JupyterHub(Application):
db=self.db, orm=orm_service, db=self.db, orm=orm_service,
domain=domain, host=host, domain=domain, host=host,
hub_api_url=self.hub.api_url, hub_api_url=self.hub.api_url,
hub=self.hub,
) )
traits = service.traits(input=True) traits = service.traits(input=True)
@@ -1093,6 +1094,7 @@ class JupyterHub(Application):
base_url=service.prefix, base_url=service.prefix,
) )
self.db.add(server) self.db.add(server)
client_store.add_client( client_store.add_client(
client_id=service.oauth_client_id, client_id=service.oauth_client_id,
client_secret=service.api_token, client_secret=service.api_token,

View File

@@ -20,7 +20,6 @@ import requests
from tornado.gen import coroutine from tornado.gen import coroutine
from tornado.log import app_log from tornado.log import app_log
from tornado.httputil import url_concat from tornado.httputil import url_concat
from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.web import HTTPError, RequestHandler from tornado.web import HTTPError, RequestHandler
from traitlets.config import Configurable from traitlets.config import Configurable
@@ -112,13 +111,9 @@ class HubAuth(Configurable):
Only used if JupyterHub is spreading servers across subdomains. Only used if JupyterHub is spreading servers across subdomains.
""" """
).tag(config=True) ).tag(config=True)
@default('hub_host')
host = Unicode('', def _default_hub_host(self):
help="""The public host of this service/server return os.getenv('JUPYTERHUB_HOST', '')
Only used if JupyterHub is spreading servers across subdomains.
"""
).tag(config=True)
base_url = Unicode(os.getenv('JUPYTERHUB_SERVICE_PREFIX') or '/', base_url = Unicode(os.getenv('JUPYTERHUB_SERVICE_PREFIX') or '/',
help="""The base URL prefix of this application help="""The base URL prefix of this application
@@ -378,7 +373,7 @@ class HubAuth(Configurable):
class HubOAuth(HubAuth): class HubOAuth(HubAuth):
"""HubAuth using OAuth for login instead of cookies set by the Hub. """HubAuth using OAuth for login instead of cookies set by the Hub.
.. versionadded: 0.8 .. versionadded: 0.8
""" """
@@ -432,7 +427,7 @@ class HubOAuth(HubAuth):
).tag(config=True) ).tag(config=True)
@default('oauth_redirect_uri') @default('oauth_redirect_uri')
def _default_redirect(self): def _default_redirect(self):
return self.host + url_path_join(self.base_url, 'oauth_callback') return os.getenv('JUPYTERHUB_OAUTH_CALLBACK_URL') or url_path_join(self.base_url, 'oauth_callback')
oauth_authorization_url = Unicode('/hub/api/oauth2/authorize', oauth_authorization_url = Unicode('/hub/api/oauth2/authorize',
help="The URL to redirect to when starting the OAuth process", help="The URL to redirect to when starting the OAuth process",
@@ -625,7 +620,14 @@ class HubOAuthenticated(HubAuthenticated):
class HubOAuthCallbackHandler(HubOAuthenticated, RequestHandler): class HubOAuthCallbackHandler(HubOAuthenticated, RequestHandler):
"""OAuth Callback handler""" """OAuth Callback handler
Finishes the OAuth flow, setting a cookie to record the user's info.
Should be registered at SERVICE_PREFIX/oauth_callback
.. versionadded: 0.8
"""
@coroutine @coroutine
def get(self): def get(self):

View File

@@ -43,27 +43,25 @@ from getpass import getuser
import pipes import pipes
import shutil import shutil
from subprocess import Popen from subprocess import Popen
from urllib.parse import urlparse
from tornado import gen
from traitlets import ( from traitlets import (
HasTraits, HasTraits,
Any, Bool, Dict, Unicode, Instance, Any, Bool, Dict, Unicode, Instance,
default, observe, default,
) )
from traitlets.config import LoggingConfigurable from traitlets.config import LoggingConfigurable
from .. import orm from .. import orm
from ..traitlets import Command from ..traitlets import Command
from ..spawner import LocalProcessSpawner, set_user_setuid from ..spawner import LocalProcessSpawner, set_user_setuid
from ..utils import url_path_join, new_token from ..utils import url_path_join
class _MockUser(HasTraits): class _MockUser(HasTraits):
name = Unicode() name = Unicode()
server = Instance(orm.Server, allow_none=True) server = Instance(orm.Server, allow_none=True)
state = Dict() state = Dict()
service = Instance(__module__ + '.Service') service = Instance(__module__ + '.Service')
host = Unicode()
# We probably shouldn't use a Spawner here, # We probably shouldn't use a Spawner here,
# but there are too many concepts to share. # but there are too many concepts to share.
@@ -190,6 +188,7 @@ class Service(LoggingConfigurable):
domain = Unicode() domain = Unicode()
host = Unicode() host = Unicode()
hub = Any()
proc = Any() proc = Any()
# handles on globals: # handles on globals:
@@ -257,10 +256,12 @@ class Service(LoggingConfigurable):
api_token=self.api_token, api_token=self.api_token,
oauth_client_id=self.oauth_client_id, oauth_client_id=self.oauth_client_id,
cwd=self.cwd, cwd=self.cwd,
hub=self.hub,
user=_MockUser( user=_MockUser(
name=self.user, name=self.user,
service=self, service=self,
server=self.orm.server, server=self.orm.server,
host=self.host,
), ),
) )
self.spawner.start() self.spawner.start()

View File

@@ -27,7 +27,7 @@ from traitlets import (
) )
from .traitlets import Command, ByteSpecification from .traitlets import Command, ByteSpecification
from .utils import random_port from .utils import random_port, url_path_join
class Spawner(LoggingConfigurable): class Spawner(LoggingConfigurable):
@@ -431,6 +431,10 @@ class Spawner(LoggingConfigurable):
env['JUPYTERHUB_ADMIN_ACCESS'] = '1' env['JUPYTERHUB_ADMIN_ACCESS'] = '1'
# OAuth settings # OAuth settings
env['JUPYTERHUB_CLIENT_ID'] = self.oauth_client_id env['JUPYTERHUB_CLIENT_ID'] = self.oauth_client_id
env['JUPYTERHUB_HOST'] = self.hub.host
if self.user.server:
env['JUPYTERHUB_OAUTH_CALLBACK_URL'] = self.user.host + \
url_path_join(self.user.server.base_url, 'oauth_callback')
# Put in limit and guarantee info if they exist. # Put in limit and guarantee info if they exist.
# Note that this is for use by the humans / notebook extensions in the # Note that this is for use by the humans / notebook extensions in the