Skip to content

feat: SDKCore: implement startLogin() - authorization code grant start (ENG-4786)#203

Draft
mrudatsprint wants to merge 6 commits into
miker/eng-4784/central-coordinatorfrom
miker/eng-4786/code-grant-start
Draft

feat: SDKCore: implement startLogin() - authorization code grant start (ENG-4786)#203
mrudatsprint wants to merge 6 commits into
miker/eng-4784/central-coordinatorfrom
miker/eng-4786/code-grant-start

Conversation

@mrudatsprint

Copy link
Copy Markdown
Collaborator

What is this PR and why do we need it?

Describe the problem or feature in addition to a reference to the Jira issue.

Pre-Merge Checklist (if applicable)

  • Unit and Feature tests have been added/updated for logic changes, or there is a justifiable reason for not doing so.

…t (ENG-4786)

- Add Pkce module (generateCodeVerifier, generateCodeChallenge) with RFC 7636
  Appendix B test vector coverage; runs under @vitest-environment node
- Extend RedirectHelper to persist code_verifier as a second colon-delimited
  segment alongside state; add public getCodeVerifier() getter; add test file
- SDKCore: construct DPoPManager when config.useDpop is true; startLogin() is
  now async — DPoP branch calls getOrCreateKeyPair()/getThumbprint() and
  generates PKCE params then redirects to /oauth2/authorize directly; isLoggedIn
  delegates to DPoPManager.isLoggedIn in DPoP mode (not app.at_exp cookie)
- SDKCore.test.ts: add DPoP-mode describe block with mocked DPoPManager and Pkce
  (jsdom lacks crypto.subtle); all existing cookie-mode tests unaffected
- e2e/dpop-smoke.test.ts: replace local generatePkce() helper with shared Pkce
  module; add Tier 0 tests exercising SDKCore.startLogin() in DPoP mode
  end-to-end (no live FusionAuth required for Tier 0)
- Export Pkce from packages/core/src/index.ts

Note: yarn test:core cannot run in this sandbox environment due to a missing
@rollup/rollup-linux-arm64-gnu native binary (arch mismatch); TypeScript
compilation (tsc --noEmit) and ESLint/Prettier are clean.
…edirect assertion

Without the explicit jsdom annotation, vitest inherits the 'node' environment
from DPoPManager.test.ts when the full suite runs, causing 'document is not
defined' and 'window is not defined' failures in all SDKCore tests.

Also corrects the handlePreRedirect spy assertion: cookie-mode startLogin()
passes one argument (state), not two — the codeVerifier arg is only added in
DPoP mode.
SDKCore's constructor calls scheduleTokenExpiration() which calls
getAccessTokenExpirationMoment(). In a Node/Playwright process document
doesn't exist, so CookieHelpers catches the ReferenceError and logs
'Error accessing cookies...' to console.error. The tests still pass, but the
stderr noise is confusing.

Fix: extract a shared DPOP_CONFIG constant in the Tier 0 describe block that
includes a no-op cookieAdapter ({ at_exp: () => undefined }). This causes
getAccessTokenExpirationMoment() to take the adapter path and skip
document.cookie entirely, eliminating the noise.

Also fixes T0-1 where the await core.startLogin() call was accidentally
dropped during the previous config refactor.
@mrudatsprint
mrudatsprint changed the base branch from main to miker/eng-4784/central-coordinator July 18, 2026 21:18
@mrudatsprint mrudatsprint changed the title Miker/eng 4786/code grant start feat: SDKCore: implement startLogin() - authorization code grant start (ENG-4786) Jul 18, 2026
…ormat

RedirectHelper now stores nonce:codeVerifier:state (three colon-delimited
segments) instead of the previous nonce:state (two segments). The Angular
sdkcore/ directory is generated by 'yarn get-sdk-core' which copies
packages/core/src/ verbatim — so in CI the Angular RedirectHelper picks up
the updated parser automatically.

The test was writing the old two-segment format 'abc123:/welcome-page',
which the new parser splits as [nonce='abc123', codeVerifier='/welcome-page',
state=''] — returning undefined for state instead of '/welcome-page'.

Fix: write 'abc123::/welcome-page' (empty codeVerifier segment, matching
cookie mode where no verifier is stored).
…value format

RedirectHelper now stores nonce:codeVerifier:state (three colon-delimited
segments) instead of nonce:state (two segments). Both sdk-vue and sdk-react
import SDKCore directly from @fusionauth-sdk/core (via the @fusionauth-sdk/*
tsconfig path alias), so their tests exercise the live, current
RedirectHelper — same root cause as the earlier Angular fix.

- packages/sdk-vue/src/createFusionAuth/createFusionAuth.test.ts: was seeding
  the old 2-segment format ('rAnd0mStR1ng:<state>'), causing the new state
  getter to return undefined instead of the expected state value. Fixed to
  'rAnd0mStR1ng::<state>' (empty codeVerifier segment).

- packages/sdk-react/src/components/providers/FusionAuthProvider.test.tsx:
  had the same stale 2-segment seed, but wasn't caught by CI because the
  assertion only checked toHaveBeenCalled() (no argument check). Fixed the
  seed format and strengthened the assertion to toHaveBeenCalledWith(stateValue)
  to restore real coverage of the callback argument.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant