Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/azp-cookie-warning-warn-once.md
Original file line number Diff line number Diff line change
@@ -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.
22 changes: 14 additions & 8 deletions packages/backend/src/tokens/__tests__/request_azp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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.',
);
Expand Down
6 changes: 5 additions & 1 deletion packages/backend/src/tokens/request.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { logger } from '@clerk/shared/logger';
import type { JwtPayload } from '@clerk/shared/types';

import { constants } from '../constants';
Expand Down Expand Up @@ -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.',
);
}
Expand Down
Loading