Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions jupyter_server/auth/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import binascii
import datetime
import hmac
import json
import os
import re
Expand All @@ -28,6 +29,9 @@
from .security import passwd_check, set_password
from .utils import get_anonymous_username

if t.TYPE_CHECKING:
import hmac

_non_alphanum = re.compile(r"[^A-Za-z0-9]")


Expand Down Expand Up @@ -610,6 +614,18 @@ def logout_available(self):
"""Whether a LogoutHandler is needed."""
return True

def cookie_secret_hook(self, h: hmac.HMAC) -> hmac.HMAC:
"""Update cookie secret input

Subclasses may call `h.update()` with any credentials that,
when changed, should invalidate existing cookies, such as a
password.

The updated hashlib object should be returned.

"""
return h


class PasswordIdentityProvider(IdentityProvider):
"""A password identity provider."""
Expand Down Expand Up @@ -740,6 +756,14 @@ def validate_security(
self.log.critical(_i18n("\t$ python -m jupyter_server.auth password"))
sys.exit(1)

def cookie_secret_hook(self, h: hmac.HMAC) -> hmac.HMAC:
"""Include password in cookie secret.

This makes it so changing the password invalidates cookies.
"""
h.update(self.hashed_password.encode())
return h


class LegacyIdentityProvider(PasswordIdentityProvider):
"""Legacy IdentityProvider for use with custom LoginHandlers
Expand Down
1 change: 1 addition & 0 deletions jupyter_server/serverapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,7 @@ def _default_cookie_secret(self) -> bytes:
self._write_cookie_secret_file(key)
h = hmac.new(key, digestmod=hashlib.sha256)
h.update(self.password.encode())
h = self.identity_provider.cookie_secret_hook(h)
return h.digest()

def _write_cookie_secret_file(self, secret: bytes) -> None:
Expand Down
Loading