Summary
The access-token verification in src/session.ts currently calls jwtVerify(accessToken, JWKS) without any issuer or audience options, so the JWT's iss and aud claims go unchecked. A validly-signed WorkOS JWT issued for a different clientId (aud) or by a different environment (iss) would still pass verifyAccessToken and authenticate the request.
This was flagged by Greptile on #67: #67 (comment) — the PR scope there was caching-only, and it was called out that none of the WorkOS SDKs currently validate these claims, so the fix should be coordinated across SDKs rather than shipped as a one-off here.
Scope
The same gap exists in (at least) authkit-nextjs, authkit-remix, authkit-astro, and the underlying @workos-inc/node UserManagement.getJWKS/authenticateWithAccessToken style helpers. Tackling it across SDKs together lets us:
- Pin down the exact
iss string WorkOS stamps on user-management access tokens (sandbox vs production, EU regions, self-hosted, etc.).
- Decide the policy for
audience — almost certainly audience: getConfig('clientId'), but confirm it matches what the API sets.
- Stage a rollout that won't break existing tokens in flight (e.g. a feature flag or opt-in config, depending on whether any existing deployments rely on cross-client token reuse).
Suggested fix (per SDK)
await jwtVerify(accessToken, JWKS, {
issuer: /* WorkOS iss string, confirmed via docs or decoded production token */,
audience: getConfig('clientId'),
});
plus tests for:
- Happy path (iss + aud match).
- Rejects a valid signature with a mismatched
aud (token minted for a different clientId).
- Rejects a valid signature with a mismatched
iss (token from a different WorkOS environment).
Related
Summary
The access-token verification in
src/session.tscurrently callsjwtVerify(accessToken, JWKS)without anyissueroraudienceoptions, so the JWT'sissandaudclaims go unchecked. A validly-signed WorkOS JWT issued for a differentclientId(aud) or by a different environment (iss) would still passverifyAccessTokenand authenticate the request.This was flagged by Greptile on #67: #67 (comment) — the PR scope there was caching-only, and it was called out that none of the WorkOS SDKs currently validate these claims, so the fix should be coordinated across SDKs rather than shipped as a one-off here.
Scope
The same gap exists in (at least)
authkit-nextjs,authkit-remix,authkit-astro, and the underlying@workos-inc/nodeUserManagement.getJWKS/authenticateWithAccessTokenstyle helpers. Tackling it across SDKs together lets us:issstring WorkOS stamps on user-management access tokens (sandbox vs production, EU regions, self-hosted, etc.).audience— almost certainlyaudience: getConfig('clientId'), but confirm it matches what the API sets.Suggested fix (per SDK)
plus tests for:
aud(token minted for a differentclientId).iss(token from a different WorkOS environment).Related