Skip to content

Commit

Permalink
Merge pull request 2i2c-org#428 from GeorgianaElena/logout-handler
Browse files Browse the repository at this point in the history
Custom logout handler
  • Loading branch information
yuvipanda authored May 22, 2021
2 parents edb7771 + 1769fca commit e4be7fc
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 8 deletions.
36 changes: 28 additions & 8 deletions deployer/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,24 @@ def get_connections(self):

def create_client(self, name, domains):
callbacks = self._get_callback_url_list(domains)
logout_urls = self._get_allowed_logout_url_list(domains)

client = {
'name': name,
'app_type': 'regular_web',
'callbacks': callbacks
'callbacks': callbacks,
'allowed_logout_urls': logout_urls
}
created_client = self.auth0.clients.create(client)
return created_client

def _get_callback_url_list(self, domains):
if isinstance(domains, list):
callbacks = []
for domain in domains:
callbacks.append(f'https://{domain}/hub/oauth_callback')
return callbacks
return [f'https://{domain}/hub/oauth_callback' for domain in domains] if isinstance(domains, list) else [f'https://{domains}/hub/oauth_callback']

def _get_allowed_logout_url_list(self, domains):
# Mark the hub address as a valid URL address to return to after logout
return [f'https://{domain}' for domain in domains] if isinstance(domains, list) else [f'https://{domains}']

return [f'https://{domains}/hub/oauth_callback']

def _ensure_client_callback(self, client, domains):
callback_urls = self._get_callback_url_list(domains)
Expand All @@ -80,6 +81,23 @@ def _ensure_client_callback(self, client, domains):
}
)

def _ensure_client_logout_urls(self, client, domains):
logout_urls = self._get_allowed_logout_url_list(domains)
missing_logout_urls = []

for logout_url in logout_urls:
if 'allowed_logout_urls' not in client or logout_url not in client['allowed_logout_urls']:
missing_logout_urls.append(logout_url)

if missing_logout_urls:
self.auth0.clients.update(
client['client_id'],
{
# Don't remove other logout URLs
'allowed_logout_urls': client.get('allowed_logout_urls', []) + missing_logout_urls
}
)


def ensure_client(self, name, domains, connection_name):
current_clients = self.get_clients()
Expand All @@ -89,6 +107,7 @@ def ensure_client(self, name, domains, connection_name):
else:
client = current_clients[name]
self._ensure_client_callback(client, domains)
self._ensure_client_logout_urls(client, domains)

current_connections = self.get_connections()

Expand Down Expand Up @@ -147,7 +166,8 @@ def get_client_creds(self, client, connection_name):
'username_key': USERNAME_KEYS[connection_name],
'client_id': client['client_id'],
'client_secret': client['client_secret'],
'scope': ['openid', 'name', 'profile', 'email']
'scope': ['openid', 'name', 'profile', 'email'],
'logout_redirect_url': f'https://{self.domain}/v2/logout?client_id={client["client_id"]}'
}

return auth
30 changes: 30 additions & 0 deletions hub-templates/basehub/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,39 @@ jupyterhub:
06-custom-authenticator: |
from oauthenticator.generic import GenericOAuthenticator
from jupyterhub.handlers import LogoutHandler
from tornado.httputil import url_concat
from traitlets import Unicode
from z2jh import get_config
class CustomLogoutHandler(LogoutHandler):
"""
Handle custom logout URLs. If a custom logout url
is specified, the 'logout' button will log the user out of that identity
provider in addition to clearing the session with Jupyterhub, otherwise
only the Jupyterhub session is cleared.
"""
async def render_logout_page(self):
if self.authenticator.logout_redirect_url:
# Return to the hub main page after logout
params = {
'returnTo': f'https://{self.request.host}'
}
self.redirect(
url_concat(self.authenticator.logout_redirect_url, params),
permanent=False
)
return
super().render_logout_page()
class CustomOAuthenticator(GenericOAuthenticator):
logout_redirect_url = Unicode(help="""URL for logging out.""", default_value='').tag(config=True)
def get_handlers(self, app):
return super().get_handlers(app) + [(r'/logout', CustomLogoutHandler)]
async def authenticate(self, *args, **kwargs):
resp = await super().authenticate(*args, **kwargs)
if self.username_key == 'sub':
Expand Down

0 comments on commit e4be7fc

Please sign in to comment.