Merge pull request #2342 from minrk/expire-auth

allow auth to expire
This commit is contained in:
Min RK
2019-02-05 13:05:00 +01:00
committed by GitHub
12 changed files with 508 additions and 147 deletions

View File

@@ -28,6 +28,7 @@ from .. import __version__
from .. import orm
from ..objects import Server
from ..spawner import LocalProcessSpawner
from ..user import User
from ..utils import maybe_future, url_path_join
from ..metrics import (
SERVER_SPAWN_DURATION_SECONDS, ServerSpawnStatus,
@@ -240,7 +241,7 @@ class BaseHandler(RequestHandler):
self.db.commit()
return self._user_from_orm(orm_token.user)
async def refresh_user_auth(self, user, force=False):
async def refresh_auth(self, user, force=False):
"""Refresh user authentication info
Calls `authenticator.refresh_user(user)`
@@ -254,7 +255,12 @@ 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.authenticator.auth_refresh_age
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
# refresh a user at most once per request
@@ -275,6 +281,8 @@ class BaseHandler(RequestHandler):
)
return
user._auth_refreshed = now
if auth_info == True:
# refresh_user confirmed that it's up-to-date,
# nothing to refresh
@@ -355,8 +363,8 @@ class BaseHandler(RequestHandler):
user = self.get_current_user_token()
if user is None:
user = self.get_current_user_cookie()
if user:
user = await self.refresh_user_auth(user)
if user and isinstance(user, User):
user = await self.refresh_auth(user)
self._jupyterhub_user = user
except Exception:
# don't let errors here raise more than once
@@ -610,6 +618,7 @@ class BaseHandler(RequestHandler):
self.statsd.incr('login.success')
self.statsd.timing('login.authenticate.success', auth_timer.ms)
self.log.info("User logged in: %s", user.name)
user._auth_refreshed = time.monotonic()
return user
else:
self.statsd.incr('login.failure')
@@ -643,6 +652,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_auth(user, force=True)
if auth_user is None:
raise web.HTTPError(403, "auth has expired for %s, login again", user.name)
spawn_start_time = time.perf_counter()
self.extra_error_html = self.spawn_home_error