Skip to content

feat: support maxAge authorization param (@workos-inc/node >= 10.6)#49

Merged
nicknisi merged 4 commits into
mainfrom
feat/maxage-passthrough
Jun 25, 2026
Merged

feat: support maxAge authorization param (@workos-inc/node >= 10.6)#49
nicknisi merged 4 commits into
mainfrom
feat/maxage-passthrough

Conversation

@nicknisi

Copy link
Copy Markdown
Member

What

Adds support for the maxAge authorization-URL parameter (OIDC max_age) on the sign-in/sign-up/authorization flow, and removes a dead types file.

Why

maxAge was added to UserManagementAuthorizationURLOptions in @workos-inc/node v10.6.0. We want to expose it without raising the peer-dependency floor — the package still supports the full ^8 || ^9 || ^10 range, so consumers aren't forced into a breaking SDK major upgrade for one optional param.

How

GetAuthorizationUrlOptions gains maxAge via a version-gated conditional type in core/session/types.ts:

type VersionedAuthParams = 'maxAge' extends keyof UserManagementAuthorizationURLOptions
  ? { maxAge?: number }
  : { maxAge?: never };
  • On >= 10.6 peers it resolves to { maxAge?: number } — settable, and forwarded to getAuthorizationUrl.
  • On ^8 / ^9 / <10.6 peers the SDK type lacks the key, so it resolves to { maxAge?: never } — the option is rejected at compile time rather than advertised and silently dropped at runtime (the SDK whitelists params and discards unknown keys).

keyof is read from the consumer's installed @workos-inc/node at their compile time, so the surface tracks the peer. The value is forwarded only when provided: ...(options.maxAge !== undefined && { maxAge: options.maxAge }).

The devDependency is bumped to ^10.6.0 so authkit's own build sees the field; the peerDependency range is unchanged.

Commits

  • refactor: remove unused core/client/types.ts — dead code (no importers, not exposed via exports), and a drifted copy of SDK types.
  • feat: maxAge support.

Testing

  • tsc --noEmit ✅ · tsc -p tsconfig.build.json ✅ · vitest --run 273 passed (+2) ✅ · oxlint 0 warnings / 0 errors ✅
  • Added tests: maxAge forwarded when set, omitted when unset.
  • Type-level proof: maxAge accepted on a >=10.6 peer and rejected on an older peer for both fresh object literals and pre-built option objects (the never branch is what makes the non-literal case honest — an empty object type would only block fresh literals).

nicknisi added 2 commits June 25, 2026 16:32
Dead code: nothing imported ./core/client/types.js and it was not exposed via package.json exports. Its AuthorizationURLOptions had also drifted from the SDK (wrong clientId optionality, unbound PKCE fields). Public types come straight from @workos-inc/node.
Surface the OIDC max_age authorization-URL param (added to UserManagementAuthorizationURLOptions in @workos-inc/node v10.6.0) while keeping the wide ^8 || ^9 || ^10 peer range.

GetAuthorizationUrlOptions gains maxAge via a version-gated conditional type: it resolves to { maxAge?: number } when the installed SDK supports the field and { maxAge?: never } otherwise, so the option is visible exactly when it works -- no false promise on older peers. The value is forwarded to getAuthorizationUrl only when provided.

- bump devDependency @workos-inc/node to ^10.6.0 (peer range unchanged)
- add tests: forwarded when set, omitted when unset
@nicknisi nicknisi requested a review from imkesin June 25, 2026 21:33

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment thread src/core/session/types.ts Outdated
Comment on lines +243 to +245
type VersionedAuthParams =
'maxAge' extends keyof UserManagementAuthorizationURLOptions
? { maxAge?: number }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Conditional type depends on UserManagementAuthorizationURLOptions existing in all supported peer versions

The VersionedAuthParams conditional type (src/core/session/types.ts:243-245) imports UserManagementAuthorizationURLOptions from @workos-inc/node. The library's peerDependencies accept ^8.0.0 || ^9.0.0 || ^10.0.0. When this library is published, the emitted .d.ts will contain this import. If a consumer uses a peer version (e.g. v8.x or v9.x) where UserManagementAuthorizationURLOptions is not an exported type, their TypeScript build will fail on the import — before the conditional type can even evaluate. The PR's design comment says the conditional type is read "from the consumer's installed version at their compile time," which works correctly if the type exists in all supported peers (just with varying keys). Worth verifying that v8 and v9 of the SDK actually export this type name.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good flag — this is the right invariant to check. Verified it holds: UserManagementAuthorizationURLOptions is exported across the entire ^8 || ^9 || ^10 peer range, so the emitted .d.ts import resolves on every supported peer (the conditional then varies only by available keys, as intended).

Checked against the published artifacts a consumer actually installsimport type { UserManagementAuthorizationURLOptions } plus a tsc --noEmit resolution test:

published peer import resolves 'maxAge' in keyof → branch
8.0.0 no → { maxAge?: never }
8.13.0 no → { maxAge?: never }
9.0.0 no → { maxAge?: never }
10.7.0 yes → { maxAge?: number }

The test imports the type directly (export type _ = UserManagementAuthorizationURLOptions), so a missing export would surface as "Module has no exported member" — it didn't on any version. (v8.0.0 initially showed unrelated errors from a transitive jose .d.ts under the default tsc target; isolating with --skipLibCheck confirmed our import resolves.)

Export chain is stable across the range:
index.ts → export * from './user-management/interfaces' → export * from './authorization-url-options.interface' (which declares export type UserManagementAuthorizationURLOptions).

Bonus: on v8/v9 'maxAge' is genuinely absent from the type's keys, so the conditional resolves to { maxAge?: never } — the option is correctly hidden (and rejected) on older peers, which is exactly the intended behavior.

@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR exposes the WorkOS maxAge authorization parameter while keeping older peer versions supported. The main changes are:

  • Adds a conditional maxAge option to authorization URL types.
  • Forwards maxAge to the WorkOS SDK only when callers provide it.
  • Updates local WorkOS development types for the new parameter.
  • Removes an unused client types file.
  • Adds tests for forwarding and omission behavior.

Confidence Score: 5/5

The maxAge authorization URL path is implemented and covered by focused runtime and type checks.

No code issues were identified. The changed behavior is narrow: the new option is conditionally exposed in types, forwarded only when defined, and omitted otherwise. Targeted checks cover the main runtime behavior and TypeScript contract.

None.

T-Rex T-Rex Logs

What T-Rex did

  • The base PKCE spec tests were run and the file src/core/pkce/pkce.spec.ts passed 10 tests.
  • The head PKCE spec tests were run and the file src/core/pkce/pkce.spec.ts passed 12 tests, including forwards maxAge to getAuthorizationUrl when provided and omits maxAge from the SDK call when not provided.
  • A TypeScript type check was run with tsc --noEmit and exited 0, confirming the type-level contract remains compatible with installed dependencies.
  • An environment note states that a Node 22 package was required to run the tests because the default Node 20.9 could not start the pnpm/vitest toolchain.

View all artifacts

T-Rex Ran code and verified through T-Rex

Reviews (2): Last reviewed commit: "refactor: keep GetAuthorizationUrlOption..." | Re-trigger Greptile

Comment thread src/core/session/types.ts Outdated
Comment thread src/core/session/types.ts Outdated
… gate from SDK method

Addresses PR review feedback:

- Keep GetAuthorizationUrlOptions an interface (it had become a type alias), so consumers can still extend it via module-augmentation declaration merging.

- Derive the SDK options type from the getAuthorizationUrl method via Parameters<> instead of importing UserManagementAuthorizationURLOptions by name, so the version gate never depends on that type being exported by a given peer -- only on the method existing, which it does across ^8 || ^9 || ^10.

maxAge stays version-gated: number on @workos-inc/node >= 10.6, never on older peers. Verified against published 8.0.0 / 8.13.0 / 9.0.0.
@nicknisi nicknisi merged commit 34ca118 into main Jun 25, 2026
7 checks passed
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.

2 participants