From 1b99b1275c46c2daced0c24e68b433d3f9108685 Mon Sep 17 00:00:00 2001 From: Min RK Date: Tue, 19 Dec 2017 13:45:50 +0100 Subject: [PATCH] allow service redirect uri to come from config for external services - ensure Spawner.oauth_client_id is always defined, not just for running Spawners --- jupyterhub/app.py | 8 +++++--- jupyterhub/services/service.py | 24 +++++++++++++++++++++++- jupyterhub/user.py | 13 +++++++------ 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/jupyterhub/app.py b/jupyterhub/app.py index 9c9e3d23..3d6f3694 100644 --- a/jupyterhub/app.py +++ b/jupyterhub/app.py @@ -1197,13 +1197,15 @@ class JupyterHub(Application): ) self.db.add(server) + else: + service.orm.server = None + + if service.oauth_available: client_store.add_client( client_id=service.oauth_client_id, client_secret=service.api_token, - redirect_uri=host + url_path_join(service.prefix, 'oauth_callback'), + redirect_uri=service.oauth_redirect_uri, ) - else: - service.orm.server = None self._service_map[name] = service diff --git a/jupyterhub/services/service.py b/jupyterhub/services/service.py index f24645ad..ae14c672 100644 --- a/jupyterhub/services/service.py +++ b/jupyterhub/services/service.py @@ -223,7 +223,7 @@ class Service(LoggingConfigurable): oauth_client_id = Unicode( help="""OAuth client ID for this service. - + You shouldn't generally need to change this. Default: `service-` """ @@ -232,6 +232,28 @@ class Service(LoggingConfigurable): def _default_client_id(self): return 'service-%s' % self.name + oauth_redirect_uri = Unicode( + help="""OAuth redirect URI for this service. + + You shouldn't generally need to change this. + Default: `/services/:name/oauth_callback` + """ + ).tag(input=True) + @default('oauth_redirect_uri') + def _default_redirect_uri(self): + if self.server is None: + return '' + print(self.domain, self.host, self.server) + return self.host + url_path_join(self.prefix, 'oauth_callback') + + @property + def oauth_available(self): + """Is OAuth available for this client? + + Returns True if a server is defined or oauth_redirect_uri is specified manually + """ + return bool(self.server is not None or self.oauth_redirect_uri) + @property def server(self): if self.orm.server: diff --git a/jupyterhub/user.py b/jupyterhub/user.py index 4e908c5f..882ce1b1 100644 --- a/jupyterhub/user.py +++ b/jupyterhub/user.py @@ -203,6 +203,11 @@ class User: orm_spawner.state = self.state self.state = None + # use fully quoted name for client_id because it will be used in cookie-name + # self.escaped_name may contain @ which is legal in URLs but not cookie keys + client_id = 'user-%s' % quote(self.name) + if name: + client_id = '%s-%s' % (client_id, quote(name)) spawn_kwargs = dict( user=self, orm_spawner=orm_spawner, @@ -211,6 +216,7 @@ class User: config=self.settings.get('config'), proxy_spec=url_path_join(self.proxy_spec, name, '/'), db=self.db, + oauth_client_id=client_id, ) # update with kwargs. Mainly for testing. spawn_kwargs.update(kwargs) @@ -355,12 +361,7 @@ class User: # create API and OAuth tokens spawner.api_token = api_token spawner.admin_access = self.settings.get('admin_access', False) - # use fully quoted name for client_id because it will be used in cookie-name - # self.escaped_name may contain @ which is legal in URLs but not cookie keys - client_id = 'user-%s' % quote(self.name) - if server_name: - client_id = '%s-%s' % (client_id, quote(server_name)) - spawner.oauth_client_id = client_id + client_id = spawner.oauth_client_id oauth_provider = self.settings.get('oauth_provider') if oauth_provider: client_store = oauth_provider.client_authenticator.client_store