From 2bb911a28f18230b815d9da717693bd49aba9a5c Mon Sep 17 00:00:00 2001 From: Dominic Couture Date: Mon, 19 Oct 2026 14:38:21 +0100 Subject: [PATCH] fix(backend): stop accepting the legacy ignore JWT category as a session token Clerk no longer issues cl_I7d4PD111III, so treat it like any other non-session category. Co-Authored-By: Claude Opus 5.5 --- .changeset/drop-jwt-category-ignore.md | 5 +++++ .../backend/src/tokens/__tests__/handshakeToken.test.ts | 8 +------- packages/backend/src/tokens/jwtCategories.ts | 5 +---- 3 files changed, 7 insertions(+), 11 deletions(-) create mode 100644 .changeset/drop-jwt-category-ignore.md diff --git a/.changeset/drop-jwt-category-ignore.md b/.changeset/drop-jwt-category-ignore.md new file mode 100644 index 00000000000..08a193ad032 --- /dev/null +++ b/.changeset/drop-jwt-category-ignore.md @@ -0,0 +1,5 @@ +--- +'@clerk/backend': patch +--- + +Stop accepting the legacy `cl_I7d4PD111III` JWT category as a session or handshake token. Clerk no longer issues it, so `authenticateRequest()` now returns a signed-out state with reason `token-type-mismatch` for a token carrying it, the same as for other non-session categories. diff --git a/packages/backend/src/tokens/__tests__/handshakeToken.test.ts b/packages/backend/src/tokens/__tests__/handshakeToken.test.ts index 94c88df2b33..c7bb61c5569 100644 --- a/packages/backend/src/tokens/__tests__/handshakeToken.test.ts +++ b/packages/backend/src/tokens/__tests__/handshakeToken.test.ts @@ -5,12 +5,7 @@ import { mockJwks, mockRsaJwkKid, signingJwks } from '../../fixtures'; import { signJwt } from '../../jwt/signJwt'; import { server, validateHeaders } from '../../mock-server'; import { verifyHandshakeToken } from '../handshake'; -import { - JWT_CATEGORY_IGNORE, - JWT_CATEGORY_JWT_TEMPLATE, - JWT_CATEGORY_M2M_TOKEN, - JWT_CATEGORY_SESSION_TOKEN, -} from '../jwtCategories'; +import { JWT_CATEGORY_JWT_TEMPLATE, JWT_CATEGORY_M2M_TOKEN, JWT_CATEGORY_SESSION_TOKEN } from '../jwtCategories'; const directives = ['__session=foo; Path=/']; @@ -42,7 +37,6 @@ describe('tokens.verifyHandshakeToken(token, options)', () => { it.each([ ['the session-token category, which is what the handshake minter stamps', JWT_CATEGORY_SESSION_TOKEN], - ['the ignore category, used by instances that opt out of category tagging', JWT_CATEGORY_IGNORE], ['no category, for tokens minted before the category rollout', undefined], ])('verifies a handshake token with %s', async (_label, cat) => { await expect(verify(await createHandshakeJwt(cat))).resolves.toMatchObject({ handshake: directives }); diff --git a/packages/backend/src/tokens/jwtCategories.ts b/packages/backend/src/tokens/jwtCategories.ts index f76eaf0baa8..859c0a36386 100644 --- a/packages/backend/src/tokens/jwtCategories.ts +++ b/packages/backend/src/tokens/jwtCategories.ts @@ -5,9 +5,6 @@ import { decodeJwt } from '../jwt/verifyJwt'; export const JWT_CATEGORY_SESSION_TOKEN = 'cl_B7d4PD111AAA'; export const JWT_CATEGORY_JWT_TEMPLATE = 'cl_B7d4PD222AAA'; export const JWT_CATEGORY_M2M_TOKEN = 'cl_B7d4PD333AAA'; -// Instances with `use_ignore_jwt_cat` stamp this on every class, so it carries no class info -// and must not be discriminated on. -export const JWT_CATEGORY_IGNORE = 'cl_I7d4PD111III'; /** * Whether `cat` marks a JWT as something other than a session token. Handshake tokens are @@ -15,7 +12,7 @@ export const JWT_CATEGORY_IGNORE = 'cl_I7d4PD111III'; * before the category rollout. */ export function isNonSessionJwtCategory(cat?: string): boolean { - return cat !== undefined && cat !== JWT_CATEGORY_SESSION_TOKEN && cat !== JWT_CATEGORY_IGNORE; + return cat !== undefined && cat !== JWT_CATEGORY_SESSION_TOKEN; } /** Malformed tokens return `false`; signature verification is left to reject them. */