Repository navigation
feat(cli): ship the PKCE login and auth commands - #235
Merged
Merged
Conversation
Copy the per-request credential source and PKCE login from grid's lightning-cloud package into the SDK's vendored copy, and switch the CLI to the vendored login.
Add lightning login options, auth status, auth token and logout, and move the remaining SDK credential paths to the per-request source.
fnwoke-lightning
force-pushed
the
fnwoke/auth-m4-11-login-commands
branch
from
November 4, 2026 19:03
640b707 to
678347c
Compare
A release from main must keep logging in on production, which serves only the interim login until relaunch. A new login is the interim one unless LIGHTNING_CLI_OIDC_LOGIN is set, read when the login starts. - Restore AuthServer with get_auth_url(port) and login_with_browser(auth). It sends state on the /sign-in redirectTo, adds caller sign-in params, refuses a callback whose state doesn't match, saves the sess_ as auth_token with Auth.save, and redirects with no credential in the URL. - Auth.save accepts and ignores token again, writes a 0600 file. - credentials: CredentialKind, Credential, resolve(), refresh(token) for the token a request sent, start_login() dispatching on the switch with LoginUnavailable for options the interim login can't honour, and logout() that revokes each saved kind and reports which revokes failed. - A login that saves revokes the login it replaced, after the save: /oidc/revoke for a new login, /v1/auth/logout for a sess_. - Both browser logins stop after five minutes with no callback. - Reuse is detected only from the exact error_description. - The source's own login goes through Auth.authenticate, so main's browser_authentication(False) still keeps resource commands from opening a browser. - Restore llm_api.py, cli/entrypoint.py, cli/legacy/entrypoint.py and cli/utils/auth.py to main. Their changes belong to sdk#235. Co-authored-by: Cursor <cursoragent@cursor.com>
Port grid's fake platform, fake browser, keyrings and login worker under tests.lightning_cloud, and extend the fake platform with the interim /sign-in to /login-complete flow and POST /v1/auth/logout. The conftest overrides the SDK's autouse threading.Thread mock, clears the SDK's dummy LIGHTNING_API_KEY and LIGHTNING_AUTH_TOKEN, and puts back the vendored interim login that main's CLI replaces when imported. New cases cover the interim login, the switch at every entry point, the options only the new login has, replacing either kind of login with either kind, logout of both kinds, the five minute stop, and the exact reuse text. Co-authored-by: Cursor <cursoragent@cursor.com>
sdk#235 rewrites the CLI and credential readers against the lightning_cloud API from sdk#234, including the interim sess_ login as the default.
A 401 retries once after the source refreshes, and a folder download hands its workers that handler instead of a header captured once. Co-authored-by: Cursor <cursoragent@cursor.com>
The interim sess_ login stays the default. The new login runs only when LIGHTNING_CLI_OIDC_LOGIN is set, and the SDK no longer patches Auth. Co-authored-by: Cursor <cursoragent@cursor.com>
…n is switched on Co-authored-by: Cursor <cursoragent@cursor.com>
…n-commands Co-authored-by: Cursor <cursoragent@cursor.com>
…switch Co-authored-by: Cursor <cursoragent@cursor.com>
… key With the switch unset, a saved sess_ is sent ahead of LIGHTNING_API_KEY. When it went stale, requests said to run lightning login and login refused because the key was set. Login now returns early only when the key is what requests send. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
… failed revokes on login Co-authored-by: Cursor <cursoragent@cursor.com>
…n-commands Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # python/lightning_sdk/cli/entrypoint.py # python/lightning_sdk/cli/resource_completion.py # python/lightning_sdk/cli/utils/lockdown_status.py # python/lightning_sdk/cli/utils/logging.py # python/tests/cli/test_entrypoint.py # python/tests/cli/utils/test_auth.py
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…g OSError Co-authored-by: Cursor <cursoragent@cursor.com>
…sign-in calls Also applies ruff-format to test_replaced_login.py, which failed pre-commit. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…necting forever Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
fnwoke-lightning
marked this pull request as ready for review
November 5, 2026 15:13
fnwoke-lightning
requested review from
ethanwharris,
justusschock,
k223kim,
rusenask and
tejapulagam
as code owners
November 5, 2026 15:13
…he API key is ignored The interim login's headless error now points at LIGHTNING_AUTH_TOKEN too. Co-authored-by: Cursor <cursoragent@cursor.com>
…n-commands Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # python/lightning_sdk/cli/utils/auth.py
…oken is set The API key in the test env is ignored now, so it goes too. Co-authored-by: Cursor <cursoragent@cursor.com>
…n-commands Co-authored-by: Cursor <cursoragent@cursor.com>
Danidapena
reviewed
Nov 5, 2026
The flag keeps the login in a file only the user can read instead of the OS keychain; the new name says that without alarming users. Co-authored-by: Cursor <cursoragent@cursor.com>
…hain Co-authored-by: Cursor <cursoragent@cursor.com>
Danidapena
reviewed
Nov 5, 2026
A Studio sets LIGHTNING_AUTH_TOKEN_FILE, so lightning login there reported the token-file refusal instead of the Studio-specific error. Check in_studio() first; the env guards still apply outside a Studio.
Auth().auth_header raises LoginError, a ConnectionError and therefore an OSError, which the reconnect handler caught. With reconnect on and no idle timeout, following logs retried forever on an unreadable token file or refused login. Read the header before the try so the error reaches the caller, and pin it with an unreadable-token-file test.
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # .github/workflows/test-cli.yaml # python/lightning_sdk/cli/entrypoint.py # python/lightning_sdk/cli/resource_completion.py # python/lightning_sdk/cli/utils/auth.py # python/lightning_sdk/cli/utils/lockdown_status.py # python/lightning_sdk/cli/utils/logging.py # python/lightning_sdk/lightning_cloud/login.py # python/tests/api/test_billing_api.py # python/tests/api/test_filesystem_api.py # python/tests/api/test_studio_api.py # python/tests/api/test_teamspace_api.py # python/tests/cli/test_entrypoint.py # python/tests/cli/utils/test_auth.py # python/tests/lightning_cloud/test_credentials.py # python/tests/lightning_cloud/utils/fake_platform.py
Danidapena
reviewed
Nov 6, 2026
Danidapena
approved these changes
Nov 6, 2026
Danidapena
left a comment
Contributor
There was a problem hiding this comment.
small Claude issue :D
…ss-host redirect requests follows redirects with a copy of the request, response hooks included, and drops Authorization when the host changes. The 401 hook then ran on the redirect target's response, refreshed, and resent the fresh token to that host, then told the user to log in. Retry only a 401 to a request that carried the credential. Co-authored-by: Cursor <cursoragent@cursor.com>
justusschock
approved these changes
Nov 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
#234 added a per-request credential source and a PKCE login behind
LIGHTNING_CLI_OIDC_LOGIN, but the CLI still had no commands to log in with it, inspect it or end it, and several SDK paths still read credentials their own way. This PR adds the login and auth commands, and moves every remaining SDK credential path to the per-request source.What
lightning login [--no-browser] [--no-keychain]on both entrypoints.--no-keychainkeeps the login in a file only the user can read instead of the OS keychain. WithLIGHTNING_CLI_OIDC_LOGINunset it runs the interimsess_login, and both flags fail with a usage error naming the switch. With it set it runs the PKCE login.--organd--projectcome in a follow-up.LIGHTNING_AUTH_TOKEN_FILEorLIGHTNING_AUTH_TOKENis set. A setLIGHTNING_API_KEYgets a stderr warning that it is ignored, then login continues.lightning auth status: source, user, orgs, teamspaces (a whole-org grant shows asall in <org>), permissions, expiry. It never prints a token.lightning auth token: prints what requests send.auth statusandauth tokenturn an unreadable token file or login into a CLI error instead of a traceback.lightning logout: revokes both the new login and a savedsess_, forgets both, names any server revoke that failed, and says whenLIGHTNING_AUTH_TOKEN_FILEorLIGHTNING_AUTH_TOKENstill authenticates requests.Auth.save/AuthServermonkeypatch is deleted, and with it the ignoredtoken=andapi_key=arguments ofAuth.save.requestscalls (filesystem, studio, teamspace, billing,_BlobUploader, folder downloads) attach credentials per request through oneAuthBase, which refreshes and resends once on a 401 and sends thelightning-sdk/<version>User-Agent. A 401 no refresh fixes (a revokedsess_, a stale token file) raisesConnectionErrorwith the generated client's "Authentication failed. Please runlightning login." message. A 401 from another host after a redirect, such as a storage URL, is returned as it is: the credential is never refreshed for it or sent to that host.lightning login, or names an unreadable token file. License validation no longer writes its token over the saved login.lightning loginnow refuses when a token is set, and the test step no longer sets the ignoredLIGHTNING_API_KEY.Notes
Auth.save's ignored arguments, whichmain's monkeypatch needed until this PR. Labeledvendoringfor that.credentials.Authhere, since the auth-header helper they patched is gone.pytest python/tests3140 passed at82ff06f, merged withmain, with no saved login and no credential in the environment. The 2 failures (test_job_list_table_shows_tags,test_job_list_table_shows_creator) also fail onmainlocally (terminal width).