avoid cycle on current_user in _set_xsrf_cookie

pass authenticated explicitly
This commit is contained in:
Min RK
2024-03-25 13:18:54 +01:00
parent e0ea52af49
commit 87c2aebb5c
3 changed files with 24 additions and 5 deletions

View File

@@ -104,13 +104,20 @@ def _get_xsrf_token_cookie(handler):
return (None, None) return (None, None)
def _set_xsrf_cookie(handler, xsrf_id, cookie_path=""): def _set_xsrf_cookie(handler, xsrf_id, *, cookie_path="", authenticated=None):
"""Set xsrf token cookie""" """Set xsrf token cookie"""
xsrf_token = _create_signed_value_urlsafe(handler, "_xsrf", xsrf_id) xsrf_token = _create_signed_value_urlsafe(handler, "_xsrf", xsrf_id)
xsrf_cookie_kwargs = {} xsrf_cookie_kwargs = {}
xsrf_cookie_kwargs.update(handler.settings.get('xsrf_cookie_kwargs', {})) xsrf_cookie_kwargs.update(handler.settings.get('xsrf_cookie_kwargs', {}))
xsrf_cookie_kwargs.setdefault("path", cookie_path) xsrf_cookie_kwargs.setdefault("path", cookie_path)
if not handler.current_user: if authenticated is None:
try:
current_user = handler.current_user
except Exception:
authenticated = False
else:
authenticated = bool(current_user)
if not authenticated:
# limit anonymous xsrf cookies to one hour # limit anonymous xsrf cookies to one hour
xsrf_cookie_kwargs.pop("expires", None) xsrf_cookie_kwargs.pop("expires", None)
xsrf_cookie_kwargs.pop("expires_days", None) xsrf_cookie_kwargs.pop("expires_days", None)
@@ -166,7 +173,7 @@ def get_xsrf_token(handler, cookie_path=""):
) )
if _set_cookie: if _set_cookie:
_set_xsrf_cookie(handler, xsrf_id, cookie_path) _set_xsrf_cookie(handler, xsrf_id, cookie_path=cookie_path)
handler._xsrf_token = xsrf_token handler._xsrf_token = xsrf_token
return xsrf_token return xsrf_token

View File

@@ -738,7 +738,9 @@ class BaseHandler(RequestHandler):
# make sure xsrf cookie is updated # make sure xsrf cookie is updated
# this avoids needing a second request to set the right xsrf cookie # this avoids needing a second request to set the right xsrf cookie
self._jupyterhub_user = user self._jupyterhub_user = user
_set_xsrf_cookie(self, self._xsrf_token_id, cookie_path=self.hub.base_url) _set_xsrf_cookie(
self, self._xsrf_token_id, cookie_path=self.hub.base_url, authenticated=True
)
def authenticate(self, data): def authenticate(self, data):
return maybe_future(self.authenticator.get_authenticated_user(self, data)) return maybe_future(self.authenticator.get_authenticated_user(self, data))

View File

@@ -45,6 +45,7 @@ from tornado.httpclient import AsyncHTTPClient, HTTPRequest
from tornado.httputil import url_concat from tornado.httputil import url_concat
from tornado.log import app_log from tornado.log import app_log
from tornado.web import HTTPError, RequestHandler from tornado.web import HTTPError, RequestHandler
from tornado.websocket import WebSocketHandler
from traitlets import ( from traitlets import (
Any, Any,
Bool, Bool,
@@ -805,6 +806,10 @@ class HubAuth(SingletonConfigurable):
if not hasattr(self, 'set_cookie'): if not hasattr(self, 'set_cookie'):
# only HubOAuth can persist cookies # only HubOAuth can persist cookies
return return
fetch_mode = handler.request.headers.get("Sec-Fetch-Mode", "navigate")
if isinstance(handler, WebSocketHandler) or fetch_mode != "navigate":
# don't do this on websockets or non-navigate requests
return
self.log.info( self.log.info(
"Storing token from url in cookie for %s", "Storing token from url in cookie for %s",
handler.request.remote_ip, handler.request.remote_ip,
@@ -1197,7 +1202,12 @@ class HubOAuth(HubAuth):
# set updated xsrf token cookie, # set updated xsrf token cookie,
# which changes after login # which changes after login
handler._hub_auth_token_cookie = access_token handler._hub_auth_token_cookie = access_token
_set_xsrf_cookie(handler, handler._xsrf_token_id, cookie_path=self.base_url) _set_xsrf_cookie(
handler,
handler._xsrf_token_id,
cookie_path=self.base_url,
authenticated=True,
)
def clear_cookie(self, handler): def clear_cookie(self, handler):
"""Clear the OAuth cookie""" """Clear the OAuth cookie"""