Skip to content

Commit

Permalink
persist userid cookie when auth is disabled (jupyter-server#1076)
Browse files Browse the repository at this point in the history
* allow override of headers in jp_fetch

allows unsetting auth

* persist userid cookie for disabled auth

ensures stable userid for a given browser when auth is completely disabled
  • Loading branch information
minrk authored Nov 18, 2022
1 parent 908e843 commit e66306d
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 2 deletions.
3 changes: 3 additions & 0 deletions jupyter_server/auth/identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ async def _get_user(self, handler: JupyterHandler) -> User | None:
# Completely insecure! No authentication at all.
# No need to warn here, though; validate_security will have already done that.
user = self.generate_anonymous_user(handler)
# persist user on first request
# so the user data is stable for a given browser session
self.set_login_cookie(handler, user)

return user

Expand Down
5 changes: 3 additions & 2 deletions jupyter_server/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,9 @@ def client_fetch(*parts, headers=None, params=None, **kwargs):
base_path_url = url_path_join(jp_base_url, path_url)
params_url = urllib.parse.urlencode(params)
url = base_path_url + "?" + params_url
# Add auth keys to header
headers.update(jp_auth_header)
# Add auth keys to header, if not overridden
for key, value in jp_auth_header.items():
headers.setdefault(key, value)
# Make request.
return http_server_client.fetch(url, headers=headers, request_timeout=20, **kwargs)

Expand Down
32 changes: 32 additions & 0 deletions tests/auth/test_identity.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import json
import logging
from contextlib import nullcontext
from unittest import mock

import pytest

Expand Down Expand Up @@ -177,3 +179,33 @@ def test_password_required(identity_provider_class, password_set, password_requi

with ctx:
idp.validate_security(app, ssl_options=None)


async def test_auth_disabled(request, jp_serverapp, jp_fetch):
idp = PasswordIdentityProvider(
parent=jp_serverapp,
hashed_password="",
token="",
)
assert not idp.auth_enabled

with mock.patch.dict(jp_serverapp.web_app.settings, {"identity_provider": idp}):

resp = await jp_fetch("/api/me", headers={"Authorization": "", "Cookie": ""})

user_info = json.loads(resp.body.decode("utf8"))
# anonymous login sets a cookie
assert "Set-Cookie" in resp.headers
cookie = resp.headers["Set-Cookie"]

# second request, with cookie keeps the same anonymous user
resp = await jp_fetch("/api/me", headers={"Authorization": "", "Cookie": cookie})

user_info_repeat = json.loads(resp.body.decode("utf8"))
assert user_info_repeat["identity"] == user_info["identity"]

# another request, no cookie, new anonymous user
resp = await jp_fetch("/api/me", headers={"Authorization": "", "Cookie": ""})

user_info_2 = json.loads(resp.body.decode("utf8"))
assert user_info_2["identity"]["username"] != user_info["identity"]["username"]

0 comments on commit e66306d

Please sign in to comment.