Skip to content

feat: support keyless PKCE public clients - #495

Open
nicknisi wants to merge 5 commits into
mainfrom
riker/97-let-workos-inc-authkit-nextjs-run-as-a-k
Open

nicknisi wants to merge 5 commits into
mainfrom
riker/97-let-workos-inc-authkit-nextjs-run-as-a-k

Conversation

@nicknisi

@nicknisi nicknisi commented Oct 7, 2026

Copy link
Copy Markdown
Member

Let @workos-inc/authkit-nextjs run as a keyless PKCE public client, bringing the experience shipped in workos/authkit-react-router#96 (workos/authkit-react-router#96, "feat: support keyless PKCE public clients", merged Oct 6) to Next.js. A Next.js app that only signs users in should work with WORKOS_CLIENT_ID, NEXT_PUBLIC_WORKOS_REDIRECT_URI (or the package's redirect setting) and WORKOS_COOKIE_PASSWORD and no WORKOS_API_KEY.

Read #96's diff first (gh pr diff 96 --repo workos/authkit-react-router) and mirror its design and rigor, adapted to authkit-nextjs's env-variable-driven config:

  • Construct the client keyless. src/workos.ts builds new WorkOS(WORKOS_API_KEY, options) with an empty-string fallback. Construct it as new WorkOS({ apiKey, clientId, ...options }), omitting apiKey when unset, so workos-node 8.x's keyless mode applies (authenticateWithCode with a codeVerifier and authenticateWithRefreshToken omit client_secret when there's no key). Check the @workos-inc/node peer range supports it and raise the minimum if needed.

  • Model the config as a union where the package exposes config types (authkitMiddleware/handleAuth options, any configure-style API), so TypeScript makes clear which features need a key. Discriminate the way Sign-in callback returns SyntaxError: Unexpected token 'e" is not valid JSON #96 did if it fits. Where config is purely env-driven at runtime, do the closest sound version and explain the trade-off in the hand-back.

  • Clear errors for key-only features. Anything that needs a key must fail with a clear, actionable error naming WORKOS_API_KEY, not an opaque 401. At least:

    • organizations.getOrganization in src/actions.ts
    • apiKeys.createValidation in src/validate-api-key.ts
    • featureFlags.createRuntimeClient in src/feature-flags.ts
    • the claim-token / fetchClaimNonce path in src/get-authorization-url.ts if it needs a key

    Audit every getWorkOS() use and list which need a key.

  • README: a public-client (keyless) section saying when to use it and what's unavailable without a key.

  • Unit tests:

    • client construction with and without a key
    • code exchange (authkit-callback-route.ts) and both refresh paths (session.ts) sending no client_secret in public mode (assert the request bodies)
    • the clear errors for key-only features
    • any type-level union tests

Then prove it end to end in the repo's example (examples/next): copy it to a scratch directory outside the repo and point it at this branch's packed build (pnpm pack, then a file: or overrides dependency in the copy only). Run it with no WORKOS_API_KEY, and show that the sign-in route redirects to the AuthKit authorization URL with code_challenge and code_challenge_method=S256. Leave the dev server running and give Nick the URL and exact steps to sign in and see the session load and a refresh succeed. If a refresh can be shown without his login (e.g. a debug log line in the demo copy only), add it to the demo copy, not the library.

Riker's check pnpm install --frozen-lockfile >/dev/null && pnpm typecheck && pnpm lint && pnpm format:check && pnpm test && pnpm build passed.

Opened as a draft by Riker (job 97).

…KEY is unset

Build the client with new WorkOS({ apiKey, clientId, ...options }) and treat
an empty WORKOS_API_KEY as absent, so the SDK runs as a PKCE public client
instead of carrying an empty-string key. Key-only features (getOrganizationAction,
validateApiKey, getFeatureFlagsRuntimeClient) now fail before any network call
with an error naming WORKOS_API_KEY.
@nicknisi
nicknisi marked this pull request as ready for review October 7, 2026 17:25
@nicknisi
nicknisi requested a review from a team as a code owner October 7, 2026 17:25
@greptile-apps

greptile-apps Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Critical risk] Adds keyless PKCE mode that disables API key requirement for sign-in.

The PR appears safe to merge; the previous organization-name finding is fixed.

What we checked:

  • Old lookups erase current names: Effect cleanup marks the old lookup stale. Both callbacks check that flag before changing the organization.

Summary

Adds keyless PKCE sign-in through the shared WorkOS client, clear errors for key-only helpers, and public-client documentation.

  • Adds request-body tests for code exchange and both session refresh paths.
  • The latest change prevents old organization lookups from overwriting the current name.
  • No new actionable issues were found.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  E[Environment settings] --> W[Shared WorkOS client]
  W --> A[PKCE sign-in and session refresh]
  W --> K{API key present?}
  K -->|Yes| M[Key-only helpers]
  K -->|No| F[Clear configuration error]
Loading

Reviews (2) · Last reviewed commit: "fix: ignore stale organization lookups i..." · Reviewed by Greptile

Comment thread src/components/impersonation.tsx Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant