From 008ff972ef2c7f6acf5e6a8f9b6b25e8b5bdb2ce Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 28 May 2026 15:30:31 -0500 Subject: [PATCH] fix(backend): warn once for azp-less cookie token instead of per request --- .changeset/azp-cookie-warning-warn-once.md | 5 +++++ .../src/tokens/__tests__/request_azp.test.ts | 22 ++++++++++++------- packages/backend/src/tokens/request.ts | 6 ++++- 3 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 .changeset/azp-cookie-warning-warn-once.md diff --git a/.changeset/azp-cookie-warning-warn-once.md b/.changeset/azp-cookie-warning-warn-once.md new file mode 100644 index 00000000000..6e0c9991131 --- /dev/null +++ b/.changeset/azp-cookie-warning-warn-once.md @@ -0,0 +1,5 @@ +--- +'@clerk/backend': patch +--- + +Emit the "session token from cookie is missing the `azp` claim" warning once per process instead of on every authenticated request. An `azp`-less cookie token is reused across requests, so the previous unguarded `console.warn` could flood production logs. diff --git a/packages/backend/src/tokens/__tests__/request_azp.test.ts b/packages/backend/src/tokens/__tests__/request_azp.test.ts index f1dd61be7d5..d4aadb142a0 100644 --- a/packages/backend/src/tokens/__tests__/request_azp.test.ts +++ b/packages/backend/src/tokens/__tests__/request_azp.test.ts @@ -14,7 +14,7 @@ vi.mock('../../jwt/verifyJwt', () => ({ })); describe('authenticateRequest with cookie token', () => { - test('logs a warning when azp claim is missing but still returns signed-in', async () => { + test('warns once across repeated requests when azp claim is missing but still returns signed-in', async () => { const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const payload = { @@ -35,20 +35,26 @@ describe('authenticateRequest with cookie token', () => { errors: undefined, }); - const request = new Request('http://localhost:3000', { - headers: { - cookie: '__session=mock_token; __client_uat=1234567890', - }, - }); + const buildRequest = () => + new Request('http://localhost:3000', { + headers: { + cookie: '__session=mock_token; __client_uat=1234567890', + }, + }); const options = { publishableKey: 'pk_live_Y2xlcmsuaW5zcGlyZWQucHVtYS03NC5sY2wuZGV2JA', secretKey: 'sk_live_deadbeef', }; - const result = await authenticateRequest(request, options); + // A single azp-less cookie token is reused across every authenticated + // request, so the warning must not fire per request (issue #8231). + const first = await authenticateRequest(buildRequest(), options); + const second = await authenticateRequest(buildRequest(), options); - expect(result.isSignedIn).toBe(true); + expect(first.isSignedIn).toBe(true); + expect(second.isSignedIn).toBe(true); + expect(warnSpy).toHaveBeenCalledTimes(1); expect(warnSpy).toHaveBeenCalledWith( 'Clerk: Session token from cookie is missing the azp claim. In a future version of Clerk, this token will be considered invalid. Please contact Clerk support if you see this warning.', ); diff --git a/packages/backend/src/tokens/request.ts b/packages/backend/src/tokens/request.ts index 415f1e4e0b6..5b9781783f0 100644 --- a/packages/backend/src/tokens/request.ts +++ b/packages/backend/src/tokens/request.ts @@ -1,3 +1,4 @@ +import { logger } from '@clerk/shared/logger'; import type { JwtPayload } from '@clerk/shared/types'; import { constants } from '../constants'; @@ -635,7 +636,10 @@ export const authenticateRequest: AuthenticateRequest = (async ( } if (!data.azp) { - console.warn( + // Warn once per process rather than per request: a single azp-less cookie + // token is reused across every authenticated request until it refreshes, + // so an unguarded console.warn floods production logs (see issue #8231). + logger.warnOnce( 'Clerk: Session token from cookie is missing the azp claim. In a future version of Clerk, this token will be considered invalid. Please contact Clerk support if you see this warning.', ); }