feat!: support oauth authorization code flow (#906)#905
Conversation
based on poc patches in DataBiosphere/data-browser#4793. url hardcoded as in the original; subsequent commit makes it configurable. Co-authored-by: hannes-ucsc <hannes-ucsc@users.noreply.github.com> Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
introduce optional `authorize` field on oauthprovider; service.login uses initcodeclient + requestcode when set and falls back to the existing inittokenclient + requestaccesstoken implicit flow when unset. add unit tests covering both branches. refs DataBiosphere/data-browser#4793 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds an opt-in Google OAuth authorization code flow to the existing Google sign-in service, allowing consumers of @databiosphere/findable-ui to exchange an auth code for tokens via a configurable backend endpoint while preserving the current implicit token flow as the default.
Changes:
- Introduces
OAuthProvider.authorize?: stringto toggle between code flow (code exchange via POST) and implicit token flow. - Updates Google login service to use
initCodeClient + requestCode()whenauthorizeis set, and factors token handling into a shared path. - Adds unit tests to validate branching between code flow and implicit flow.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/config/entities.ts |
Adds optional authorize endpoint to the OAuth provider config to enable code flow. |
src/google/types.ts |
Introduces a CodeResponse interface for the Google auth code callback payload shape. |
src/google/service.ts |
Implements the new code-flow branch with backend token exchange and shared access-token handling. |
tests/googleService.test.ts |
Adds tests asserting correct client initialization based on presence/absence of provider.authorize. |
per copilot review on #905: - catch network errors, non-ok responses, and missing access_token in the authorize exchange; reset auth/token state on failure so login no longer hangs - extract resetSession helper now that the reset is reused by both the fetchprofile error path and the new authorize catch - add tests covering successful exchange (POST + updateToken dispatch), non-ok response, and missing access_token Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds opt-in support for OAuth 2.0 authorization code flow to the Google sign-in service in @databiosphere/findable-ui, enabling clients (e.g., Data Browser) to exchange Google auth codes server-side for access tokens while preserving the existing implicit token flow as the default.
Changes:
- Added
authorize?: stringtoOAuthProviderto configure a backend code-exchange endpoint. - Updated Google
service.loginto useinitCodeClient+requestCode()and POST theCodeResponsetoauthorizewhen configured; otherwise keepinitTokenClient+requestAccessToken(). - Added Jest coverage for both flows and success/failure cases of the code-exchange request.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| tests/googleService.test.ts | Adds test coverage for code flow vs implicit flow selection and for code-exchange success/failure behaviors. |
| src/google/types.ts | Introduces CodeResponse type used by the auth code callback path. |
| src/google/service.ts | Implements the opt-in auth code flow and factors shared token/profile handling into helpers. |
| src/config/entities.ts | Extends OAuthProvider with optional authorize URL for backend token exchange. |
google's oauth code-flow callback returns either a success payload (code, scope, state) or an error payload (error, error_description, error_uri, state) — required strings on every field misrepresent the contract. trim the test fixture down to the only field we actually populate. Closes #907 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ode flow (#906) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
select the oauth flow via an explicit `flow` field on the provider config instead of inferring it from `authorize` truthiness. oauthprovider is now a discriminated union of implicitflowprovider | authorizationcodeflowprovider, so misconfiguration (auth code flow without an authorize url) is a type error rather than a silent fallback to implicit. drops the `as string` cast on authorize. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
per copilot review on #905: deleting globalThis.fetch in afterEach permanently removes node 18+'s built-in fetch for any later tests in the same worker, risking order-dependent failures. snapshot the original in beforeEach and restore (or delete only if it wasn't there) in afterEach. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| fetchProfile(userinfo, getAuthenticationRequestOptions(token), { | ||
| onError: resetSession, | ||
| onSuccess: (r: GoogleProfile) => | ||
| dispatch.authenticationDispatch?.( | ||
| updateAuthentication({ |
| callback: (response: TokenSetParameters) => | ||
| onAccessToken(response.access_token), |
Summary
service.loginauthorize?: stringfield onOAuthProvider— when set,initCodeClient+requestCode()is used and the resulting code is POSTed to that URL to exchange for an access token; when unset, the existinginitTokenClient+requestAccessToken()flow is preservedCloses #906. Refs DataBiosphere/data-browser#4793. Companion PR in data-browser wires this up for the anvil-cmg/dev site.
Test plan
npm run check-formatcleannpm run lintcleannpm run test-compilecleannpm test— 47 suites, 389 tests pass (includes newgoogleService.test.tscovering both branches)/user/authorizereturns tokens, profile loads), logout, inactivity timeout, Terra checks