mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-18 07:23:00 +00:00
allow subclasses to override xsrf check
need to inject our override into the base class, rather than at the instance level, to avoid clobbering any overrides in extensions like jupyter-server-proxy
This commit is contained in:
@@ -936,13 +936,39 @@ class HubOAuth(HubAuth):
|
|||||||
|
|
||||||
def _patch_xsrf(self, handler):
|
def _patch_xsrf(self, handler):
|
||||||
"""Patch handler to inject JuptyerHub xsrf token behavior"""
|
"""Patch handler to inject JuptyerHub xsrf token behavior"""
|
||||||
handler._xsrf_token_id = self._get_xsrf_token_id(handler)
|
if isinstance(handler, HubAuthenticated):
|
||||||
# override xsrf_token property on class,
|
# doesn't need patch
|
||||||
# so it's still a getter, not invoked immediately
|
return
|
||||||
handler.__class__.xsrf_token = property(
|
|
||||||
partial(get_xsrf_token, cookie_path=self.base_url)
|
# patch in our xsrf token handling
|
||||||
)
|
# overrides tornado and jupyter_server defaults,
|
||||||
handler.check_xsrf_cookie = partial(self.check_xsrf_cookie, handler)
|
# but not others.
|
||||||
|
# subclasses will still inherit our overridden behavior,
|
||||||
|
# but their overrides (if any) will take precedence over ours
|
||||||
|
# such as jupyter-server-proxy
|
||||||
|
for cls in handler.__class__.__mro__:
|
||||||
|
# search for the nearest parent class defined
|
||||||
|
# in one of the 'base' Handler-defining packages.
|
||||||
|
# In current implementations, this will
|
||||||
|
# generally be jupyter_server.base.handlers.JupyterHandler
|
||||||
|
# or tornado.web.RequestHandler,
|
||||||
|
# but doing it this way ensures consistent results
|
||||||
|
if (cls.__module__ or '').partition('.')[0] not in {
|
||||||
|
"jupyter_server",
|
||||||
|
"notebook",
|
||||||
|
"tornado",
|
||||||
|
}:
|
||||||
|
continue
|
||||||
|
# override check_xsrf_cookie where it's defined
|
||||||
|
if "check_xsrf_cookie" in cls.__dict__:
|
||||||
|
if "_get_xsrf_token_id" in cls.__dict__:
|
||||||
|
# already patched
|
||||||
|
return
|
||||||
|
cls._xsrf_token_id = property(self._get_xsrf_token_id)
|
||||||
|
cls.xsrf_token = property(
|
||||||
|
partial(get_xsrf_token, cookie_path=self.base_url)
|
||||||
|
)
|
||||||
|
cls.check_xsrf_cookie = lambda handler: self.check_xsrf_cookie(handler)
|
||||||
|
|
||||||
def check_xsrf_cookie(self, handler):
|
def check_xsrf_cookie(self, handler):
|
||||||
"""check_xsrf_cookie patch
|
"""check_xsrf_cookie patch
|
||||||
@@ -987,8 +1013,10 @@ class HubOAuth(HubAuth):
|
|||||||
token = self._get_token_cookie(handler)
|
token = self._get_token_cookie(handler)
|
||||||
session_id = self.get_session_id(handler)
|
session_id = self.get_session_id(handler)
|
||||||
if token and self._needs_check_xsrf(handler):
|
if token and self._needs_check_xsrf(handler):
|
||||||
|
# call handler.check_xsrf_cookie instead of self.check_xsrf_cookie
|
||||||
|
# to allow subclass overrides
|
||||||
try:
|
try:
|
||||||
self.check_xsrf_cookie(handler)
|
handler.check_xsrf_cookie()
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
self.log.error(
|
self.log.error(
|
||||||
f"Not accepting cookie auth on {handler.request.method} {handler.request.path}: {e}"
|
f"Not accepting cookie auth on {handler.request.method} {handler.request.path}: {e}"
|
||||||
|
Reference in New Issue
Block a user