diff --git a/jupyterhub/app.py b/jupyterhub/app.py index 23ee42e6..b6b89293 100644 --- a/jupyterhub/app.py +++ b/jupyterhub/app.py @@ -1173,10 +1173,12 @@ class JupyterHub(Application): db.commit() def init_oauth(self): + base_url = self.hub.server.base_url self.oauth_provider = make_provider( self.session_factory, - url_prefix=url_path_join(self.hub.server.base_url, 'api/oauth2'), - login_url=self.authenticator.login_url(self.hub.server.base_url), + url_prefix=url_path_join(base_url, 'api/oauth2'), + login_url=url_path_join(base_url, 'login') +, ) def init_proxy(self): @@ -1307,7 +1309,7 @@ class JupyterHub(Application): **jinja_options ) - login_url = self.authenticator.login_url(base_url) + login_url = url_path_join(base_url, 'login') logout_url = self.authenticator.logout_url(base_url) # if running from git, disable caching of require.js diff --git a/jupyterhub/auth.py b/jupyterhub/auth.py index 6b00d8c1..d6474f1e 100644 --- a/jupyterhub/auth.py +++ b/jupyterhub/auth.py @@ -31,7 +31,7 @@ class Authenticator(LoggingConfigurable): help=""" Set of users that will have admin rights on this JupyterHub. - Admin users have extra privilages: + Admin users have extra privileges: - Use the admin panel to see list of users logged in - Add / remove users in some authenticators - Restart / halt the hub @@ -250,10 +250,23 @@ class Authenticator(LoggingConfigurable): """ self.whitelist.discard(user.name) + auto_login = Bool(False, config=True, + help="""Automatically begin the login process + + rather than starting with a "Login with..." link at `/hub/login` + + To work, `.login_url()` must give a URL other than the default `/hub/login`, + such as an oauth handler or another automatic login handler, + registered with `.get_handlers()`. + + .. versionadded:: 0.8 + """ + ) + def login_url(self, base_url): """Override this when registering a custom login handler - Generally used by authenticators that do not use simple form based authentication. + Generally used by authenticators that do not use simple form-based authentication. The subclass overriding this is responsible for making sure there is a handler available to handle the URL returned from this method, using the `get_handlers` diff --git a/jupyterhub/handlers/login.py b/jupyterhub/handlers/login.py index dd250ac8..fa28e6f6 100644 --- a/jupyterhub/handlers/login.py +++ b/jupyterhub/handlers/login.py @@ -7,8 +7,8 @@ from urllib.parse import urlparse from tornado.escape import url_escape from tornado import gen +from tornado.httputil import url_concat -from ..utils import url_path_join from .base import BaseHandler @@ -23,8 +23,10 @@ class LogoutHandler(BaseHandler): self.clear_login_cookie(name) user.other_user_cookies = set([]) self.statsd.incr('logout') - - self.redirect(url_path_join(self.hub.server.base_url, 'login'), permanent=False) + if self.authenticator.auto_login: + self.render('logout.html') + else: + self.redirect(self.settings['login_url'], permanent=False) class LoginHandler(BaseHandler): @@ -37,6 +39,7 @@ class LoginHandler(BaseHandler): login_error=login_error, custom_html=self.authenticator.custom_html, login_url=self.settings['login_url'], + authenticator_login_url=self.authenticator.login_url(self.hub.server.base_url), ) def get(self): @@ -60,6 +63,16 @@ class LoginHandler(BaseHandler): self.set_login_cookie(self.get_current_user()) self.redirect(next_url, permanent=False) else: + if self.authenticator.auto_login: + auto_login_url = self.authenticator.login_url(self.hub.server.base_url) + if auto_login_url == self.settings['login_url']: + self.authenticator.auto_login = False + self.log.warning("Authenticator.auto_login cannot be used without a custom login_url") + else: + if next_url: + auto_login_url = url_concat(auto_login_url, {'next': next_url}) + self.redirect(auto_login_url) + return username = self.get_argument('username', default='') self.finish(self._render(username=username)) diff --git a/jupyterhub/handlers/pages.py b/jupyterhub/handlers/pages.py index ccfcea99..3e857943 100644 --- a/jupyterhub/handlers/pages.py +++ b/jupyterhub/handlers/pages.py @@ -53,7 +53,7 @@ class RootHandler(BaseHandler): url = url_path_join(self.hub.server.base_url, 'home') self.log.debug("User is not running: %s", url) else: - url = url_path_join(self.hub.server.base_url, 'login') + url = self.settings['login_url'] self.redirect(url) diff --git a/share/jupyter/hub/templates/login.html b/share/jupyter/hub/templates/login.html index dfdec9a5..7aae34c9 100644 --- a/share/jupyter/hub/templates/login.html +++ b/share/jupyter/hub/templates/login.html @@ -11,7 +11,7 @@ {{ custom_html }} {% elif login_service %}
- + Sign in with {{login_service}}
diff --git a/share/jupyter/hub/templates/logout.html b/share/jupyter/hub/templates/logout.html new file mode 100644 index 00000000..53514d2c --- /dev/null +++ b/share/jupyter/hub/templates/logout.html @@ -0,0 +1,9 @@ +{% extends "page.html" %} +{% block main %} +
+

+ Successfully logged out. +

+
+{% endblock %} +