mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-18 07:23:00 +00:00
allow auth to expire
adds Authenticator.auth_refresh_age and Authenticator.refresh_pre_spawn config - auth_refresh_age allows auth to expire (default: 5 minutes) before calling Authenticator.refresh_user. - refresh_pre_spawn forces refresh prior to spawn (in case of auth tokens, etc.)
This commit is contained in:
@@ -19,7 +19,7 @@ except Exception as e:
|
||||
from tornado.concurrent import run_on_executor
|
||||
|
||||
from traitlets.config import LoggingConfigurable
|
||||
from traitlets import Bool, Set, Unicode, Dict, Any, default, observe
|
||||
from traitlets import Bool, Integer, Set, Unicode, Dict, Any, default, observe
|
||||
|
||||
from .handlers.login import LoginHandler
|
||||
from .utils import maybe_future, url_path_join
|
||||
@@ -50,6 +50,35 @@ class Authenticator(LoggingConfigurable):
|
||||
""",
|
||||
)
|
||||
|
||||
auth_refresh_age = Integer(
|
||||
300,
|
||||
config=True,
|
||||
help="""The max age (in seconds) of authentication info
|
||||
before forcing a refresh of user auth info.
|
||||
|
||||
Refreshing auth info allows, e.g. requesting/re-validating auth tokens.
|
||||
|
||||
See :meth:`.refresh_user` for what happens when user auth info is refreshed
|
||||
(nothing by default).
|
||||
"""
|
||||
)
|
||||
|
||||
refresh_pre_spawn = Bool(
|
||||
False,
|
||||
config=True,
|
||||
help="""Force refresh of auth prior to spawn.
|
||||
|
||||
This forces :meth:`.refresh_user` to be called prior to launching
|
||||
a server, to ensure that auth state is up-to-date.
|
||||
|
||||
This can be important when e.g. auth tokens that may have expired
|
||||
are passed to the spawner via environment variables from auth_state.
|
||||
|
||||
If refresh_user cannot refresh the user auth data,
|
||||
launch will fail until the user logs in again.
|
||||
"""
|
||||
)
|
||||
|
||||
admin_users = Set(
|
||||
help="""
|
||||
Set of users that will have admin rights on this JupyterHub.
|
||||
|
@@ -250,8 +250,14 @@ class BaseHandler(RequestHandler):
|
||||
user (User): the user having been refreshed,
|
||||
or None if the user must login again to refresh auth info.
|
||||
"""
|
||||
if not force: # TODO: and it's sufficiently recent
|
||||
refresh_age = self.settings.get('auth_refresh_age', 0)
|
||||
if not refresh_age:
|
||||
return user
|
||||
now = time.monotonic()
|
||||
if not force and user._auth_refreshed and (now - user._auth_refreshed < refresh_age):
|
||||
# auth up-to-date
|
||||
return user
|
||||
user._auth_refreshed = now
|
||||
|
||||
# refresh a user at most once per request
|
||||
if not hasattr(self, '_refreshed_users'):
|
||||
@@ -639,6 +645,11 @@ class BaseHandler(RequestHandler):
|
||||
|
||||
async def spawn_single_user(self, user, server_name='', options=None):
|
||||
# in case of error, include 'try again from /hub/home' message
|
||||
if self.authenticator.refresh_pre_spawn:
|
||||
auth_user = await self.refresh_user(user, force=True)
|
||||
if auth_user is None:
|
||||
raise web.HTTPError(403, "auth has expired for %s, login again", auth_user.name)
|
||||
|
||||
spawn_start_time = time.perf_counter()
|
||||
self.extra_error_html = self.spawn_home_error
|
||||
|
||||
|
@@ -136,6 +136,7 @@ class User:
|
||||
orm_user = None
|
||||
log = app_log
|
||||
settings = None
|
||||
auth_refreshed = None
|
||||
|
||||
def __init__(self, orm_user, settings=None, db=None):
|
||||
self.db = db or inspect(orm_user).session
|
||||
@@ -395,6 +396,11 @@ class User:
|
||||
"""
|
||||
db = self.db
|
||||
|
||||
authenticator = self.authenticator
|
||||
if authenticator and handler and authenticator.pre_spawn_start:
|
||||
auth_user = await handler.refresh_pre_spawn(self, force=True)
|
||||
|
||||
|
||||
base_url = url_path_join(self.base_url, server_name) + '/'
|
||||
|
||||
orm_server = orm.Server(
|
||||
@@ -435,7 +441,6 @@ class User:
|
||||
db.commit()
|
||||
|
||||
# trigger pre-spawn hook on authenticator
|
||||
authenticator = self.authenticator
|
||||
if (authenticator):
|
||||
await maybe_future(authenticator.pre_spawn_start(self, spawner))
|
||||
|
||||
|
Reference in New Issue
Block a user