Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to have authentication enabled for all endpoints by default #1392

Merged
merged 20 commits into from
Mar 4, 2024

Conversation

krassowski
Copy link
Collaborator

@krassowski krassowski commented Feb 10, 2024

Opening a draft for early feedback on naming and implementation.

References

Closes #389

Builds upon @yuvipanda's idea of using prepare method as described in #1012 (comment).

Code changes

  • adds ServerApp.allow_unauthenticated_access traitlet (True by default for backwards compatibility)
  • adds @allow_unauthenticated decorator, an opposite of Torando's @web.authenticated
  • if allow_unauthenticated_access is False rejects requests to endpoints which do not have @allow_unauthenticated decorator for any non-authenticated user

Punchlist

  • add a test for ServerApp.allow_unauthenticated_access and @allow_unauthenticated
  • add a test ensuring that all methods on all JupyterHandler descendants in jupyter-server have either @web.authenticated or @allow_unauthenticated
    • maybe make it a runtime warning?
    • maybe also add a runtime warning if any handlers which inherit directly from web.RequestHandler rather than AuthenticatedHandler/JupyterHandler get registered with the router?
    • maybe raise or warn if both @allow_unauthenticated and @web.authenticated are set?
  • check if any other endpoint beside login and logout requires @allow_unauthenticated
  • support websockets in the same way
  • consider moving the logic to AuthenticatedHandler, but this also requires setting current_user in AuthenticatedHandler; I do not understand why it is only set in JupyterHandler I opened Should current_user and prepare guards be set in AuthenticatedHandler rather than JupyterHandler? #1398 to track this as a future improvement

@yuvipanda
Copy link
Contributor

Haven't looked too deep into this, but I absolutely love this.

fix passing the setting down from the traitlet to web server
`WebsocketMixing` may be used with or without `JupyterHandler`;
- if used with it, we want to have custom auth implementation
  because redirecting to login page does not make sense for
  a websocket's GET request
- if these are used without `JupyterHandler `we want the auth
  rules to still apply, even though the `current_user`
  logic may differ slightly
@@ -1214,6 +1215,21 @@ def _deprecated_password_config(self, change: t.Any) -> None:
""",
)

allow_unauthenticated_access = Bool(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For ease of use in JupyterHub deployments, I would also suggest making this available as an env variable. I know you can setup a _config.json file reasonably easily, but given the possible high impact here, I think it's worth making an env var for this too. JUPYTER_SERVER_ALLOW_UNAUTHENTICATED_ACCESS or similar?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in cd84175

Also adds `@ws_authenticated` to make the check simpler
@krassowski krassowski marked this pull request as ready for review February 13, 2024 13:04
@krassowski
Copy link
Collaborator Author

This is ready for review. The failing tests (Downstream Tests / jupytext and Downstream Tests / downstream_check) are also failing on the main branch and I believe these are unrelated.

@Wh1isper
Copy link
Contributor

Wh1isper commented Feb 15, 2024

Maybe allow_ws_unauthenticated is better compared to ws_authenticated?

Otherwise, user seems to have to add @ws_authenticated to every websocket's get method...?

@krassowski
Copy link
Collaborator Author

krassowski commented Feb 15, 2024

If you do not turn the flag on you do not have to add it. But all websockets should be authenticated.

Also, you can decorate websocket's get with @allow_unauthenticated if you wish.

@@ -85,3 +85,58 @@ async def inner(self, *args, **kwargs):
return cast(FuncT, wrapper(method))

return cast(FuncT, wrapper)


def allow_unauthenticated(method: FuncT) -> FuncT:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps something even more aggressive, e.g. @UNAUTHENTICATED.

@bollwyvl
Copy link
Contributor

This seems like a really good step forward.

Not sure where it should go, but it seems like this should already start tossing out warnings, which can be hidden with e.g. JUPYTER_SERVER_ANNOUNCE_AUTH=0.

Perhaps related, having an @authorized(RESOURCE_NAME) might avoid a bunch of boilerplate.

@krassowski
Copy link
Collaborator Author

Not sure where it should go, but it seems like this should already start tossing out warnings, which can be hidden with e.g. JUPYTER_SERVER_ANNOUNCE_AUTH=0.

Since the motion of "warnings are bad for users, we want developers to see it, not users" was brought up on the meeting before I started working on it, I kept the warnings only to core endpoints (errors when ServerApp.allow_unauthenticated_access=True; mostly to catch these early in PRs against jupyter-server) and to warnings for extensions endpoints when ServerApp.allow_unauthenticated_access=True.

I think that adding a warning for extension endpoints even if allow_unauthenticated_access=False (for now the default) is a good idea but for purpose of getting this PR merged sooner than later I wanted to avoid the potentially contentious issue of when and how to introduce the warning for extension when allow_unauthenticated_access=False.

jupyter_server/base/handlers.py Outdated Show resolved Hide resolved
@no_type_check
def prepare(self, *args, **kwargs):
"""Handle a get request."""
self._maybe_auth()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

._maybe_auth accesses .current_user, but .prepare() below is where it is set. The order needs to be reversed, but I assume there's a reason this is first. I think the override may need to be done a different way.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I assume there's a reason this is first

Yes, this is because JupyterHandler.prepare() would raise HTTPError with redirect which does not make sense for websocket.

The order needs to be reversed

So this works in test because .current_user is nominally a getter implemented in tornado.web.RequestHandler. Unfortunately JupyterHandler.prepare() overrides it in a way which will cause a problem for this logic for a non-trivial identity provider (if I see it right, the default user will be used instead of the one provided by IdentityProvider).

It feels like we should move the implementation of setting the current_user from JupyterHandler.prepare to JupyterHandler.get_current_user. Thoughts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, why is IdentityProvider setting the current user in JupyterHandler and not in AuthenticatedHandler in the first place? I do not see rationale for it in #671

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see the user from identity provider may require awaiting. I guess I can just pass an argument to JupyterHandler.prepare() instructing it to not redirect to login page.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JupyterHandler is responsible for .current_user being set, since it may be async, it cannot be done in a property. It would be appropriate to override the .current_user getter, which should make it very clear it can never be accessed before .prepare() is called:

@property
def current_user(self):
    if not hasattr(self, "_jupyter_current_user"):
        raise RuntimeError(".current_user accessed before being populated in JupyterHandler.prepare()")
    return self. _jupyter_current_user

@current_user.setter
def current_user(self, user):
    self._jupyter_current_user = user

Any time that error is hit is necessarily code that is bypassing Jupyter Server authentication.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5e7615d (added test) and 4265f4e (fixed it).

Would you like me to add the RuntimeError on accessing current_user too early (from the last comment) in this PR, or would it be better to ensure that this PR does not introduce potentially breaking changes and can be adopted in existing deployments easily?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code, I guess we already have this RuntimeError in get_current_user. So maybe it's just the message that wants clarifying?

Because it's already there, I don't think moving the RuntimeError to the .current_user getter can break anything. But at the same time, since folks may call get_current_user() or access the (correct) .current_user, then I guess .get_current_user covers both cases. So maybe it only makes sense to put it in .current_user if it helps to have two distinct, clear error messages.

# new in 3.11
return code.co_qualname.startswith("authenticated") # type:ignore[no-any-return]
elif hasattr(code, "co_filename"):
return code.co_filename.replace("\\", "/").endswith("tornado/web.py")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only checks if it's anything from web.py, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will have false positives in Python < 3.11. In the ideal world we can get a PR into tornado which would set a flag on the wrapped method, but it would still only work in a future version of tornado.

Copy link
Collaborator Author

@krassowski krassowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @minrk for the review!

jupyter_server/base/handlers.py Outdated Show resolved Hide resolved
@no_type_check
def prepare(self, *args, **kwargs):
"""Handle a get request."""
self._maybe_auth()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I assume there's a reason this is first

Yes, this is because JupyterHandler.prepare() would raise HTTPError with redirect which does not make sense for websocket.

The order needs to be reversed

So this works in test because .current_user is nominally a getter implemented in tornado.web.RequestHandler. Unfortunately JupyterHandler.prepare() overrides it in a way which will cause a problem for this logic for a non-trivial identity provider (if I see it right, the default user will be used instead of the one provided by IdentityProvider).

It feels like we should move the implementation of setting the current_user from JupyterHandler.prepare to JupyterHandler.get_current_user. Thoughts?

# new in 3.11
return code.co_qualname.startswith("authenticated") # type:ignore[no-any-return]
elif hasattr(code, "co_filename"):
return code.co_filename.replace("\\", "/").endswith("tornado/web.py")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will have false positives in Python < 3.11. In the ideal world we can get a PR into tornado which would set a flag on the wrapped method, but it would still only work in a future version of tornado.

The websocket test is failing as of this commit
because as pointed out in review the `_maybe_auth`
is using the default user rather the one from `IdentityProvider`
even in websockets (but only if those inherit from JupyterHandler,
and if they do not fallback to previous implementation and warn).
@krassowski
Copy link
Collaborator Author

krassowski commented Feb 20, 2024

Trying to nail down why after switching WebSocketMixin.prepare to re-use JupyterHandler.prepare the identity provider (PasswordIdentityProvider) returns a valid user for requests without proper auth for websocket connection in Jupyter Server Tests / Test Minimum Versions despite passing locally.

enabled `jp_ws_fetch` header override in:
gttps://github.com/jupyter-server/pytest-jupyter/pull/51
@krassowski
Copy link
Collaborator Author

Found it, it was due to minimum versions check using minimum pytest-jupyter version which did not yet have the ability to override headers (jupyter-server/pytest-jupyter#51). Something to consider in maintainer-tools action is whether it should only use minimum versions of the runtime rather than test deps.

Copy link
Contributor

@minrk minrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

I've written some other auth decorators that are like @web.authenticated (e.g. to raise 403 instead of login redirect, or only accept token auth on this handler, not cookies). How would this interact with those? i.e. how would I explicitly mark that "this handler really is authenticated, even if you can't find @web.authenticated on it. I see there's a check for __allow_unauthenticated, so maybe there should also be __is_authenticated?

@@ -726,7 +745,7 @@ def write_error(self, status_code: int, **kwargs: Any) -> None:
class APIHandler(JupyterHandler):
"""Base class for API handlers"""

async def prepare(self) -> None:
async def prepare(self) -> None: # type:ignore[override]
"""Prepare an API response."""
await super().prepare()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something for later - API handlers should probably 403, not redirect. Now that we have logic for this.

@@ -589,7 +589,7 @@ def check_host(self) -> bool:
)
return allow

async def prepare(self) -> Awaitable[None] | None: # type:ignore[override]
async def prepare(self, *, _redirect_to_login=True) -> Awaitable[None] | None: # type:ignore[override]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private keyword arg makes this hard for subclasses, e.g. extensions with websockets, but I suppose they will inherit from our own websocket classes, too?

I wonder if this should be a Handler class attribute, rather than a private argument.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a check for inheritance from JupyterHandler in the weboscket mixin class:

if not isinstance(self, JupyterHandler):
should_authenticate = not self.settings.get("allow_unauthenticated_access", False)
if "identity_provider" in self.settings and should_authenticate:
warnings.warn(
"WebSocketMixin sub-class does not inherit from JupyterHandler"
" preventing proper authentication using custom identity provider.",
JupyterServerAuthWarning,
stacklevel=2,
)
self._maybe_auth()
return super().prepare(*args, **kwargs)
return super().prepare(*args, **kwargs, _redirect_to_login=False)

A Handler class attribute is certainly a reasonable alternative that I briefly considered. My thinking was along: if you pass _redirect_to_login argument but are inheriting from wrong class you will get an error. If you set a class attribute but are inheriting from a wrong class you would not get anything. The downside of passing argument is that mypy typing might complain downstream.

@krassowski
Copy link
Collaborator Author

I see there's a check for __allow_unauthenticated, so maybe there should also be __is_authenticated?

Currently you could use __allow_unauthenticated = False.

@minrk
Copy link
Contributor

minrk commented Feb 22, 2024

Currently you could use __allow_unauthenticated = False.

I see, I suppose that would have the desired behavior, even if the name is the opposite of the effect.

Perhaps one issue: it is not the case that @web.authenticated is the only way to authenticate a request. It is a convenient way to encode a specific behavior when authentication fails (specifically: redirect to login on failure). Where redirect on failure is not desired, it is quite appropriate to use other decorators to authenticate request methods (e.g. we should probably use a 403 instead of redirect on ~all of our APIHandlers, using decorators like these in JupyterHub).

So a public API from jupyter_server (e.g. a decorator) that serves only to 'mark' a method as authenticated might be appropriate. Right now, I guess that's @allow_unauthenticated, which is a bit confusing?

@krassowski
Copy link
Collaborator Author

krassowski commented Mar 2, 2024

So a public API from jupyter_server (e.g. a decorator) that serves only to 'mark' a method as authenticated might be appropriate. Right now, I guess that's @allow_unauthenticated, which is a bit confusing?

@do_not_check_authentication_and_do_not_warn_about_it? At this point I would be happy to see a version of this PR land; it feels to me that the developer experience improvements could be made separately (naming things is difficult, but I would trust you or whoever may wish to push to my branch or open a follow up PR to make a right choice).

Edit: regarding naming not sure if everyone here is familiar with this classic from React codebase: __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.

@yuvipanda
Copy link
Contributor

+1 for getting this merged in some form and getting a release out, and tackling the devex separately :)

@minrk
Copy link
Contributor

minrk commented Mar 4, 2024

I'm happy with this as-is. I'm not sure i understand the current state of the downstream tests enough to merge or if things need fixing.

I'll add one note from the JupyterHub perspective: I think even the allow_unauthenticated decorator is not necessary in JupyterHub, as there are no handlers in a single-user server that require unauthenticated access. So the much simpler "just always authenticate" without any checking of individual handlers would work there, I believe (unlike a regular jupyter server, which at least needs to serve static files for the login page itself).

@blink1073 blink1073 merged commit da50f2a into jupyter-server:main Mar 4, 2024
34 of 37 checks passed
sigmarkarl added a commit to spotinst/jupyter_server that referenced this pull request Oct 8, 2024
* ContentsHandler return 404 rather than raise exc (jupyter-server#1357)

* Add more typings (jupyter-server#1356)

* Publish 2.10.1

SHA256 hashes:

jupyter_server-2.10.1-py3-none-any.whl: 20519e355d951fc5e1b6ac5952854fe7620d0cfb56588fa4efe362a758977ed3

jupyter_server-2.10.1.tar.gz: e6da2657a954a7879eed28cc08e0817b01ffd81d7eab8634660397b55f926472

* Bump to 2.11.0.dev0

* typo: ServerApp (jupyter-server#1361)

* Support get file(notebook) md5 (jupyter-server#1363)

* Update ruff and typings (jupyter-server#1365)

* Update api docs with md5 param (jupyter-server#1364)

* Publish 2.11.0

SHA256 hashes:

jupyter_server-2.11.0-py3-none-any.whl: c9bd6e6d71dc5a2a25df167dc323422997f14682b008bfecb5d7920a55020ea7

jupyter_server-2.11.0.tar.gz: 78c97ec8049f9062f0151725bc8a1364dfed716646a66819095e0e8a24793eba

* Bump to 2.12.0.dev0

* Change md5 to hash and hash_algorithm, fix incompatibility (jupyter-server#1367)

Co-authored-by: Frédéric Collonval <fcollonval@gmail.com>

* avoid unhandled error on some invalid paths (jupyter-server#1369)

* Publish 2.11.1

SHA256 hashes:

jupyter_server-2.11.1-py3-none-any.whl: 4b3a16e3ed16fd202588890f10b8ca589bd3e29405d128beb95935f059441373

jupyter_server-2.11.1.tar.gz: fe80bab96493acf5f7d6cd9a1575af8fbd253dc2591aa4d015131a1e03b5799a

* Bump to 2.12.0.dev0

* Merge pull request from GHSA-h56g-gq9v-vc8r

Co-authored-by: Steven Silvester <steven.silvester@ieee.org>

* Publish 2.11.2

SHA256 hashes:

jupyter_server-2.11.2-py3-none-any.whl: 0c548151b54bcb516ca466ec628f7f021545be137d01b5467877e87f6fff4374

jupyter_server-2.11.2.tar.gz: 0c99f9367b0f24141e527544522430176613f9249849be80504c6d2b955004bb

* Bump to 2.12.0.dev0

* chore: update pre-commit hooks (jupyter-server#1370)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Steven Silvester <steven.silvester@ieee.org>

* Update for tornado 6.4 (jupyter-server#1372)

* Support async Authorizers (jupyter-server#1373)

* Publish 2.12.0

SHA256 hashes:

jupyter_server-2.12.0-py3-none-any.whl: 3482912efa4387bb1edc23ba60531796aff3b6d6a6e93a5810f5719e2bdb48b7

jupyter_server-2.12.0.tar.gz: 9fa74ed3bb931cf33f42b3d9046e2788328ec9e6dcc59d48aa3e0910a491e3e4

* Bump to 2.13.0.dev0

* log extension import time at debug level unless it's actually slow (jupyter-server#1375)

* Add support for async Authorizers (part 2) (jupyter-server#1374)

* Publish 2.12.1

SHA256 hashes:

jupyter_server-2.12.1-py3-none-any.whl: fd030dd7be1ca572e4598203f718df6630c12bd28a599d7f1791c4d7938e1010

jupyter_server-2.12.1.tar.gz: dc77b7dcc5fc0547acba2b2844f01798008667201eea27c6319ff9257d700a6d

* Bump to 2.13.0.dev0

* Use ruff docstring-code-format (jupyter-server#1377)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Enable htmlzip and epub on readthedocs (jupyter-server#1379)

* Update pre-commit deps (jupyter-server#1380)

* Fix a typo in error message (jupyter-server#1381)

* Force legacy ws subprotocol when using gateway (jupyter-server#1311)

Co-authored-by: Emmanuel Pignot <emmanuel.pignot@netapp.com>
Co-authored-by: Zachary Sailer <zachsailer@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Zachary Sailer <zsailer@apple.com>

* Publish 2.12.2

SHA256 hashes:

jupyter_server-2.12.2-py3-none-any.whl: abcfa33f98a959f908c8733aa2d9fa0101d26941cbd49b148f4cef4d3046fc61

jupyter_server-2.12.2.tar.gz: 5eae86be15224b5375cdec0c3542ce72ff20f7a25297a2a8166a250bb455a519

* Bump to 2.13.0.dev0

* Fix test param for pytest-xdist (jupyter-server#1382)

* Simplify the jupytext downstream test (jupyter-server#1383)

* Import User unconditionally (jupyter-server#1384)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Publish 2.12.3

SHA256 hashes:

jupyter_server-2.12.3-py3-none-any.whl: 6f85310ea5e6068568a521f079fba99d8d17e4884dd1d602ab0f43b3115204a8

jupyter_server-2.12.3.tar.gz: a1d2d51e497b1a6256c48b6940b0dd49b2553981baf1690077c37792f1fa23a1

* Bump to 2.13.0.dev0

* Fix log arguments for gateway client error (jupyter-server#1385)

* Publish 2.12.4

SHA256 hashes:

jupyter_server-2.12.4-py3-none-any.whl: a125ae18a60de568f78f55c84dd58759901a18ef279abf0418ac220653ca1320

jupyter_server-2.12.4.tar.gz: 41f4a1e6b912cc24a7c6c694851b37d3d8412b180f43d72315fe422cb2b85cc2

* Bump to 2.13.0.dev0

* Improve warning handling (jupyter-server#1386)

* Publish 2.12.5

SHA256 hashes:

jupyter_server-2.12.5-py3-none-any.whl: 184a0f82809a8522777cfb6b760ab6f4b1bb398664c5860a27cec696cb884923

jupyter_server-2.12.5.tar.gz: 0edb626c94baa22809be1323f9770cf1c00a952b17097592e40d03e6a3951689

* Bump to 2.13.0.dev0

* fix "Shutdown" -> "Shut down" (jupyter-server#1389)

* chore: update pre-commit hooks (jupyter-server#1390)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* websockets: add configurations for ping interval and timeout (jupyter-server#1391)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Add deprecation note for `ServerApp.preferred_dir` (jupyter-server#1396)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Fix color in windows log console with colorama (jupyter-server#1397)

* Replace _jupyter_server_extension_paths in apidocs (jupyter-server#1393)

* Add an option to have authentication enabled for all endpoints by default (jupyter-server#1392)

* Update release workflows (jupyter-server#1399)

* Publish 2.13.0

SHA256 hashes:

jupyter_server-2.13.0-py3-none-any.whl: 77b2b49c3831fbbfbdb5048cef4350d12946191f833a24e5f83e5f8f4803e97b

jupyter_server-2.13.0.tar.gz: c80bfb049ea20053c3d9641c2add4848b38073bf79f1729cea1faed32fc1c78e

* Bump to 2.14.0.dev0

* Pin to Pytest 7 (jupyter-server#1401)

* Update pytest requirement from <8,>=7.0 to >=7.0,<9 (jupyter-server#1402)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Don't crash on invalid JSON in page_config (jupyter-server#1403) (jupyter-server#1404)

* Ignore zero-length page_config.json, restore previous behavior of crashing for invalid JSON (jupyter-server#1405)

* don't include token in dashboard link, when available (jupyter-server#1406)

* chore: update pre-commit hooks (jupyter-server#1409)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Update simple extension README to cd into correct subdirectory (jupyter-server#1410)

Co-authored-by: Mark Pizzutillo <pizmark@amazon.com>

* Set all min deps (jupyter-server#1411)

* Fix jupytext and lint CI failures (jupyter-server#1413)

* docs: list server extensions (jupyter-server#1412)

* Link to GitHub repo from the docs (jupyter-server#1415)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Publish 2.14.0

SHA256 hashes:

jupyter_server-2.14.0-py3-none-any.whl: fb6be52c713e80e004fac34b35a0990d6d36ba06fd0a2b2ed82b899143a64210

jupyter_server-2.14.0.tar.gz: 659154cea512083434fd7c93b7fe0897af7a2fd0b9dd4749282b42eaac4ae677

* Bump to 2.15.0.dev0

* chore: update pre-commit hooks (jupyter-server#1421)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Steven Silvester <steven.silvester@ieee.org>

* Removing excessive logging from reading local files (jupyter-server#1420)

Co-authored-by: Kevin Bates <kbates4@gmail.com>

* Use hatch fmt command (jupyter-server#1424)

* Merge pull request from GHSA-hrw6-wg82-cm62

* filefind: avoid handling absolute paths

we don't need or want absolute path support,
which we inherited from generic ipython_genutils

only supporting relative paths lets us avoid attempting to accessing files we know we won't accept

* Apply suggestions from code review

Co-authored-by: M Bussonnier <bussonniermatthias@gmail.com>

* filefind: only accept Sequence[str]

we only call it one place, might as well be simple about it

* version_info gate for is_relative_to

* clarify docstring

Co-authored-by: Carol Willing <carolcode@willingconsulting.com>

---------

Co-authored-by: M Bussonnier <bussonniermatthias@gmail.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>

* Publish 2.14.1

SHA256 hashes:

jupyter_server-2.14.1-py3-none-any.whl: 16f7177c3a4ea8fe37784e2d31271981a812f0b2874af17339031dc3510cc2a5

jupyter_server-2.14.1.tar.gz: 12558d158ec7a0653bf96cc272bc7ad79e0127d503b982ed144399346694f726

* Bump to 2.15.0.dev0

* Update simple extension examples: _jupyter_server_extension_points (jupyter-server#1426)

* chore: update pre-commit hooks (jupyter-server#1427)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Steven Silvester <steven.silvester@ieee.org>

* Add Changelog for 2.14.1 (jupyter-server#1430)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* chore: update pre-commit hooks (jupyter-server#1441)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Steven Silvester <steve.silvester@mongodb.com>

* Update documentation for `cookie_secret` (jupyter-server#1433)

* Do not log environment variables passed to kernels (jupyter-server#1437)

* Pass session_id during Websocket connect (jupyter-server#1440)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* Publish 2.14.2

SHA256 hashes:

jupyter_server-2.14.2-py3-none-any.whl: 47ff506127c2f7851a17bf4713434208fc490955d0e8632e95014a9a9afbeefd

jupyter_server-2.14.2.tar.gz: 66095021aa9638ced276c248b1d81862e4c50f292d575920bbe960de1c56b12b

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Sam Bloomquist <bloomquist.sam@gmail.com>
Co-authored-by: Steven Silvester <steven.silvester@ieee.org>
Co-authored-by: blink1073 <blink1073@users.noreply.github.com>
Co-authored-by: IITII <ccmejx@gmail.com>
Co-authored-by: Zhongsheng Ji <9573586@qq.com>
Co-authored-by: Frédéric Collonval <fcollonval@gmail.com>
Co-authored-by: Min RK <benjaminrk@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Zachary Sailer <zsailer@apple.com>
Co-authored-by: Zsailer <Zsailer@users.noreply.github.com>
Co-authored-by: Nicholas Bollweg <nick.bollweg@gmail.com>
Co-authored-by: Michał Krassowski <5832902+krassowski@users.noreply.github.com>
Co-authored-by: Manu <21658174+epignot@users.noreply.github.com>
Co-authored-by: Emmanuel Pignot <emmanuel.pignot@netapp.com>
Co-authored-by: Zachary Sailer <zachsailer@gmail.com>
Co-authored-by: Gonzalo Tornaría <tornaria@gmail.com>
Co-authored-by: Marc Wouts <marc.wouts@gmail.com>
Co-authored-by: Yuvi Panda <yuvipanda@gmail.com>
Co-authored-by: Alex Meiburg <timeroot.alex@gmail.com>
Co-authored-by: Oliver Sanders <oliver.sanders@metoffice.gov.uk>
Co-authored-by: hansepac <131813389+hansepac@users.noreply.github.com>
Co-authored-by: Simon Li <orpheus+devel@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Burt Holzman <burt@fnal.gov>
Co-authored-by: Mark <markypizz@gmail.com>
Co-authored-by: Mark Pizzutillo <pizmark@amazon.com>
Co-authored-by: Luciano Resende <lresende@apple.com>
Co-authored-by: Kevin Bates <kbates4@gmail.com>
Co-authored-by: M Bussonnier <bussonniermatthias@gmail.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
Co-authored-by: Steven Silvester <steve.silvester@mongodb.com>
Co-authored-by: Gonzalo Gasca Meza <gogasca@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Have handlers be @web.authenticated by default ?
6 participants