diff --git a/.changeset/fix-multiple-token-types-array.md b/.changeset/fix-multiple-token-types-array.md new file mode 100644 index 00000000000..db48bdbb5db --- /dev/null +++ b/.changeset/fix-multiple-token-types-array.md @@ -0,0 +1,5 @@ +--- +"@clerk/backend": patch +--- + +Fix token-type-mismatch error when using multiple `acceptsToken` values in `authenticateRequest`. When `acceptsToken` is an array containing both session and machine token types (e.g., `['session_token', 'api_key']`), the function now correctly routes to the appropriate authentication handler based on the actual token type, instead of always treating them as machine tokens. \ No newline at end of file diff --git a/.changeset/fix-signup-signin-redirect-conflict.md b/.changeset/fix-signup-signin-redirect-conflict.md new file mode 100644 index 00000000000..b0aaac7c803 --- /dev/null +++ b/.changeset/fix-signup-signin-redirect-conflict.md @@ -0,0 +1,5 @@ +--- +"@clerk/ui": patch +--- + +Fix redirect conflicts when SignIn and SignUp components are used together on the same page. Added missing dependency arrays to useEffect hooks in redirect functions to prevent unwanted redirects during other component flows. \ No newline at end of file diff --git a/packages/backend/src/tokens/__tests__/request.test.ts b/packages/backend/src/tokens/__tests__/request.test.ts index 0d140f8b093..54b2e775e01 100644 --- a/packages/backend/src/tokens/__tests__/request.test.ts +++ b/packages/backend/src/tokens/__tests__/request.test.ts @@ -1426,6 +1426,38 @@ describe('tokens.authenticateRequest(options)', () => { isAuthenticated: false, }); }); + + test('accepts session_token when it is in acceptsToken array with machine tokens', async () => { + server.use( + http.get('https://api.clerk.test/v1/jwks', () => { + return HttpResponse.json(mockJwks); + }), + ); + + const request = mockRequest({ authorization: `Bearer ${mockJwt}` }); + const requestState = await authenticateRequest( + request, + mockOptions({ acceptsToken: ['session_token', 'api_key'] }), + ); + + expect(requestState).toBeSignedIn(); + }); + + test('accepts api_key when it is in acceptsToken array with session_token', async () => { + server.use( + http.post(mockMachineAuthResponses.api_key.endpoint, () => { + return HttpResponse.json(mockVerificationResults.api_key); + }), + ); + + const request = mockRequest({ authorization: `Bearer ${mockTokens.api_key}` }); + const requestState = await authenticateRequest( + request, + mockOptions({ acceptsToken: ['session_token', 'api_key'] }), + ); + + expect(requestState).toBeMachineAuthenticated(); + }); }); describe('Token Location Validation', () => { diff --git a/packages/backend/src/tokens/request.ts b/packages/backend/src/tokens/request.ts index 0061828b026..6624c292205 100644 --- a/packages/backend/src/tokens/request.ts +++ b/packages/backend/src/tokens/request.ts @@ -788,6 +788,13 @@ export const authenticateRequest: AuthenticateRequest = (async ( if (acceptsToken === TokenType.SessionToken) { return authenticateRequestWithTokenInHeader(); } + // When acceptsToken is an array, route based on the actual token type + if (Array.isArray(acceptsToken)) { + if (isMachineToken(authenticateContext.tokenInHeader)) { + return authenticateMachineRequestWithTokenInHeader(); + } + return authenticateRequestWithTokenInHeader(); + } return authenticateMachineRequestWithTokenInHeader(); } diff --git a/packages/ui/src/components/SignIn/index.tsx b/packages/ui/src/components/SignIn/index.tsx index 26e8caea30f..8e8a6df14bb 100644 --- a/packages/ui/src/components/SignIn/index.tsx +++ b/packages/ui/src/components/SignIn/index.tsx @@ -41,7 +41,7 @@ function RedirectToSignIn() { const clerk = useClerk(); React.useEffect(() => { void clerk.redirectToSignIn(); - }, []); + }, [clerk]); return null; } diff --git a/packages/ui/src/components/SignUp/index.tsx b/packages/ui/src/components/SignUp/index.tsx index 24487ff09ca..841159658ff 100644 --- a/packages/ui/src/components/SignUp/index.tsx +++ b/packages/ui/src/components/SignUp/index.tsx @@ -22,7 +22,7 @@ function RedirectToSignUp() { const clerk = useClerk(); React.useEffect(() => { void clerk.redirectToSignUp(); - }, []); + }, [clerk]); return null; }