Repository navigation
feat(lightning_cloud): read the credential per request and add a PKCE login behind a switch - #234
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.
fnwoke-lightning
force-pushed
the
fnwoke/auth-m4-9-10-vendor
branch
from
November 4, 2026 19:03
385e971 to
5867dfa
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>
…n is switched on 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>
…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>
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>
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>
Danidapena
approved these changes
Nov 5, 2026
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
The SDK picks its credential once, when the client is built, so a rotated token file or a refreshed login never reaches a running process, and it still sends Basic auth and legacy API keys. This PR moves the vendored
lightning_cloudto one credential source read on every request, and adds a PKCE login with keychain storage beside the current browser login, behindLIGHTNING_CLI_OIDC_LOGIN. The current login stays the default, so a release frommainlogs in as today.lightning_cloudis vendored into the SDK, and these files are edited here directly.Based on SDK
mainat572b60da(#233).What
cli_login.py,credentials.py, and updatedenv.py,login.py,rest_client.pyinpython/lightning_sdk/lightning_cloud/.keyringadded to the dependencies.LIGHTNING_AUTH_TOKEN_FILE(re-read each request),LIGHTNING_AUTH_TOKEN, the new login, then the saved interimsess_. Bearer only.LIGHTNING_API_KEYis gone from the credential path: neither an environment key nor anapi_keysaved incredentials.jsonis ever sent.Authloses itsapi_keyfield, the"api_key"header override andKeys.API_KEY.Auth.savestill accepts and ignorestoken=andapi_key=, becausemain's interim monkeypatch passes them; feat(cli): ship the PKCE login and auth commands #235 removes both with the patch.LIGHTNING_CLI_OIDC_LOGINunset (the default): the interimsess_browser login stays the login, with a state check and a 5-minute timeout. Set: the PKCE login through thelightning-cliclient, storing the login in the OS keychain, or with--no-keychainin a file only the user can read, refresh-token rotation under a cross-process lock, and the exact reuse message. No org or project hints on the authorize URL; those come in a follow-up.lightning-sdk/<version>.LIGHTNING_AUTH_TOKEN_FILEthat exists but can't be read (a directory, no read permission) raises aLoginErrornaming the variable and the path, instead of a bareOSError. A missing file still falls through to the next credential./sign-incheck passverify=env.SSL_CA_CERT, the CA bundle the generated client uses, so login and logout work where onlySSL_CERT_FILEis set.AuthServerandloggerstay importable, somain's interim monkeypatch incli/utils/auth.pykeeps working until feat(cli): ship the PKCE login and auth commands #235 removes it. FourmainCLI checks that readAuth.api_keynow readauth_tokenonly.lightning loginis a no-op with a dummyLIGHTNING_AUTH_TOKENinstead ofLIGHTNING_API_KEY, which is now ignored. The interim login's no-browser error points atLIGHTNING_AUTH_TOKENtoo.python/tests/lightning_cloud/(fake platform, keyrings, multi-process worker), with cases for both switch states, the per-request source, refresh, logout and replaced logins. Other test changes only move mock targets.Notes
vendoring.mainatcef7af9(fix(sdk): preserve modification times when downloading files #238).pytest python/tests3110 passed atf63788b, with no saved login and no credential in the environment. After the flag rename,pytest tests/lightning_cloud121 passed at019c503. The 2 failures also fail onmainlocally (terminal width:test_job_list_table_shows_tags,test_job_list_table_shows_creator).