Add OAuth2 (PKCE + device code) login alongside personal access tokens#28
Open
AlexVanderbist wants to merge 2 commits into
Open
Add OAuth2 (PKCE + device code) login alongside personal access tokens#28AlexVanderbist wants to merge 2 commits into
AlexVanderbist wants to merge 2 commits into
Conversation
`flare login` now defaults to a browser-based PKCE flow against Passport, storing refreshable OAuth records per host. `--device` runs the device-code flow for headless terminals (auto-fallback when stdin is non-interactive). `--token` preserves the legacy paste-a-token UX. Stored OAuth tokens refresh transparently before each API call, with a `retryOn`-driven safety net for 401s using the openapi-cli 1.3.0 hook. `flare logout --all` wipes every host.
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.
Summary
flare loginnow defaults to a browser PKCE flow against Passport.--deviceruns the device-code flow for headless terminals (and is the auto-fallback when stdin is non-interactive).--tokenpreserves the legacy paste-a-PAT UX.CredentialStore::getAccessToken().spatie/laravel-openapi-cli@1.3.0's newretryOnhook acts as a 401 safety net viaCredentialStore::forceRefresh().flare loginagain — no migration needed.flare logout --allwipes every host in one go.What landed
app/Services/OAuth/:TokenRecord(value object),PkceCodes(RFC 7636 verifier/challenge/state),OAuthEndpoints,OAuthHttpClient,TokenRefresher,LocalCallbackServer(stream_socket_server on 127.0.0.1:0 with inline success/error HTML — PHAR-safe),PkceLoginFlow,DeviceLoginFlow,DeviceAuthorization+DevicePollResultDTOs,OAuthException.config/flare.php: client ID + scopes config. Default client UUID is the dev seed value — see launch blocker below.CredentialStore: extended withgetRecord()/setRecord()/getAccessToken()/forceRefresh()/flushAll(), withflock-guarded read-modify-write around refresh.AppServiceProvider: bound the new OAuth services and wired->auth()togetAccessToken()and->retryOn()toforceRefresh().LoginCommandrefactored: dispatches by mode flag, falls back to device flow on non-interactive stdin, warns when--tokenreplaces an existing OAuth session.config/flare.phpships the dev Flare CLI Passport client UUID (9d000000-0000-4000-8000-000000000001) as the default forFLARE_OAUTH_CLIENT_ID. The production client UUID must be substituted there before tagging a release. The CLI honors the env var at runtime so staging/local can keep overriding viaFLARE_OAUTH_CLIENT_ID=…— but the baked-in default is what end users will hit.Grep for
9d000000inconfig/flare.phpto spot it. Worth considering a CI grep that fails on a release branch if the placeholder is still present.Server-side dependencies
Flare CLIclient must be seeded with loopback redirect URIs (http://127.0.0.1/callback,http://[::1]/callback,flare://oauth/callback) — landed onpassport-oauthbranch.ApproveAuthorizationControllerandDenyAuthorizationControllermust convert Inertia redirects toInertia::location()(otherwise the XHR can't cross HTTPS → HTTP loopback). Landed onpassport-oauthbranch.Test plan
CredentialStoreTestPkceLoginFlowTestLocalCallbackServerTestDeviceLoginFlowTestOAuthHttpClientTestTokenRefresherTestCredentialStore::getAccessToken()refresh + write-back + no-op skip —CredentialStoreTestretryOn(401 → forceRefresh)wiring —OpenApiRegistrationTest--token, PKCE, non-TTY fallback to device, error paths —LoginCommandTest--all—LogoutCommandTestpassport-oauth.test--tokenwith both modern (Passport PAT) and legacy SHA-256 tokens