allow service redirect uri to come from config

for external services

- ensure Spawner.oauth_client_id is always defined, not just for running Spawners
This commit is contained in:
Min RK
2017-12-19 13:45:50 +01:00
parent d16461052b
commit 1b99b1275c
3 changed files with 35 additions and 10 deletions

View File

@@ -1197,13 +1197,15 @@ class JupyterHub(Application):
) )
self.db.add(server) self.db.add(server)
else:
service.orm.server = None
if service.oauth_available:
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,
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 self._service_map[name] = service

View File

@@ -223,7 +223,7 @@ class Service(LoggingConfigurable):
oauth_client_id = Unicode( oauth_client_id = Unicode(
help="""OAuth client ID for this service. help="""OAuth client ID for this service.
You shouldn't generally need to change this. You shouldn't generally need to change this.
Default: `service-<name>` Default: `service-<name>`
""" """
@@ -232,6 +232,28 @@ class Service(LoggingConfigurable):
def _default_client_id(self): def _default_client_id(self):
return 'service-%s' % self.name 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 @property
def server(self): def server(self):
if self.orm.server: if self.orm.server:

View File

@@ -203,6 +203,11 @@ class User:
orm_spawner.state = self.state orm_spawner.state = self.state
self.state = None 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( spawn_kwargs = dict(
user=self, user=self,
orm_spawner=orm_spawner, orm_spawner=orm_spawner,
@@ -211,6 +216,7 @@ class User:
config=self.settings.get('config'), config=self.settings.get('config'),
proxy_spec=url_path_join(self.proxy_spec, name, '/'), proxy_spec=url_path_join(self.proxy_spec, name, '/'),
db=self.db, db=self.db,
oauth_client_id=client_id,
) )
# update with kwargs. Mainly for testing. # update with kwargs. Mainly for testing.
spawn_kwargs.update(kwargs) spawn_kwargs.update(kwargs)
@@ -355,12 +361,7 @@ class User:
# create API and OAuth tokens # create API and OAuth tokens
spawner.api_token = api_token spawner.api_token = api_token
spawner.admin_access = self.settings.get('admin_access', False) spawner.admin_access = self.settings.get('admin_access', False)
# use fully quoted name for client_id because it will be used in cookie-name client_id = spawner.oauth_client_id
# 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
oauth_provider = self.settings.get('oauth_provider') oauth_provider = self.settings.get('oauth_provider')
if oauth_provider: if oauth_provider:
client_store = oauth_provider.client_authenticator.client_store client_store = oauth_provider.client_authenticator.client_store