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

Enable JS 2.0 (authenticated) extensions to work with classic notebook servers #1221

Closed
wants to merge 1 commit into from

Conversation

Zsailer
Copy link
Member

@Zsailer Zsailer commented Feb 22, 2023

Fixes #1038

If a server extension inherits from JupyterHandler in Jupyter Server 2.0, it won't currently work with the classic notebook server (from jupyter/notebook) because they use different+competing authentication logic.

Why? The extension looks for an identity provider that doesn't exist, so it creates a default one. Meanwhile, all other endpoints use the old/classic way of authenticating requests. The main reason this fails is that the classic auth flow and the identity provider over-write one another's login cookie because they are using the same cookie name by default. (Further, other issues arise if folks try to configure other settings on the login cookie...).

This PR allows both auth flows to coexist and ensures their settings+results are consistent. There are two key changes here

  1. The identity provider's cookie name is prefixed with model-. I can't think of any particular reason why this would be problematic...
  2. All other cookie settings are fetched from the classic server's webapp settings if they exist; otherwise, fall back to the defaults.

cc @fcollonval

@Zsailer Zsailer added the bug label Feb 22, 2023
@Zsailer Zsailer requested a review from minrk February 22, 2023 16:24
@codecov
Copy link

codecov bot commented Feb 22, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: +0.57 🎉

Comparison is base (ca4b062) 79.88% compared to head (9b71715) 80.46%.

❗ Current head 9b71715 differs from pull request most recent head 0a69ff1. Consider uploading reports for the commit 0a69ff1 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1221      +/-   ##
==========================================
+ Coverage   79.88%   80.46%   +0.57%     
==========================================
  Files          69       69              
  Lines        8299     8301       +2     
  Branches     1607     1607              
==========================================
+ Hits         6630     6679      +49     
+ Misses       1226     1198      -28     
+ Partials      443      424      -19     
Impacted Files Coverage Δ
jupyter_server/auth/identity.py 86.04% <100.00%> (ø)
jupyter_server/base/handlers.py 79.02% <100.00%> (+0.47%) ⬆️

... and 6 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.


# If there is no identity provider set, load the default. If using
# a classic notebook server, adding extensions that inherit
# from JupyterHandler will use a mix of new+old authentication log.
Copy link
Member Author

Choose a reason for hiding this comment

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

Suggested change
# from JupyterHandler will use a mix of new+old authentication log.
# from JupyterHandler will use a mix of new+old authentication logic.

@minrk minrk self-assigned this Mar 13, 2023
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.

Not sure how easy it is to add a test for this, but it looks sensible to me!

@@ -539,7 +540,8 @@ def process_login_form(self, handler: JupyterHandler) -> User | None:
return self.generate_anonymous_user(handler)

if self.token and self.token == typed_password:
return self.user_for_token(typed_password) # type:ignore[attr-defined]
# type:ignore[attr-defined]
Copy link
Contributor

Choose a reason for hiding this comment

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

moved type annotation? Does this work when it's not on the assignment line?

Copy link
Member Author

Choose a reason for hiding this comment

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

Weird. This was caused by my local linter for some reason. Let me update...

@echarles
Copy link
Member

How related is this to #1245?

@Zsailer Zsailer force-pushed the binder branch 2 times, most recently from a48f3c6 to 46e24b0 Compare April 12, 2023 21:05
config=self.settings.get("config", None),
# For backwards compatibility, pass the token
# from the webapp settings.
token=self.settings.get("token", "<generated>"),
Copy link
Contributor

@minrk minrk May 23, 2023

Choose a reason for hiding this comment

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

If the token's not set, this will actually set the token to the value "<generated>" and accept requests authenticated with that string.

@minrk
Copy link
Contributor

minrk commented May 23, 2023

How related is this to #1245?

I believe this will also fix #1245

I think this implementation does need to change a bit, because it will result in simultaneous credential cookies for the two components, which can become out of sync. For example, logging out of a notebook will not log out of the new handlers.

Instead, I think the LegacyIdentityProvider needs to work with both cookies, so it actually checks the original cookie (or calling the upstream LoginHandler.get_user) before looking in the new cookie for the model. That way, invalidation of the upstream cookie logs out of all endpoints.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Binder does not work with Jupyter Server v2
3 participants