@@ -877,6 +877,53 @@ describe('tokens.authenticateRequest(options)', () => {
877877 expect ( requestState . toAuth ( ) ) . toBeNull ( ) ;
878878 } ) ;
879879
880+ test ( 'cookieToken: returns signedIn when no clientUat but in redirect loop with valid session (Safari ITP workaround)' , async ( ) => {
881+ server . use (
882+ http . get ( 'https://api.clerk.test/v1/jwks' , ( ) => {
883+ return HttpResponse . json ( mockJwks ) ;
884+ } ) ,
885+ ) ;
886+
887+ // Simulate Safari ITP scenario: valid session token, no client_uat, redirect loop detected
888+ const requestState = await authenticateRequest (
889+ mockRequestWithCookies (
890+ { } ,
891+ {
892+ __clerk_db_jwt : 'deadbeef' ,
893+ __session : mockJwt ,
894+ __clerk_redirect_count : '1' , // Redirect loop counter > 0
895+ } ,
896+ ) ,
897+ mockOptions ( {
898+ secretKey : 'test_deadbeef' ,
899+ } ) ,
900+ ) ;
901+
902+ expect ( requestState ) . toBeSignedIn ( ) ;
903+ expect ( requestState . toAuth ( ) ) . toBeSignedInToAuth ( ) ;
904+ } ) ;
905+
906+ test ( 'cookieToken: returns handshake when no clientUat and redirect loop but invalid session token' , async ( ) => {
907+ // Simulate scenario where we're in a redirect loop but the session token is invalid
908+ const requestState = await authenticateRequest (
909+ mockRequestWithCookies (
910+ { } ,
911+ {
912+ __clerk_db_jwt : 'deadbeef' ,
913+ __session : mockMalformedJwt ,
914+ __clerk_redirect_count : '1' ,
915+ } ,
916+ ) ,
917+ mockOptions ( {
918+ secretKey : 'test_deadbeef' ,
919+ } ) ,
920+ ) ;
921+
922+ // Should still return handshake since token verification failed
923+ expect ( requestState ) . toMatchHandshake ( { reason : AuthErrorReason . SessionTokenWithoutClientUAT } ) ;
924+ expect ( requestState . toAuth ( ) ) . toBeNull ( ) ;
925+ } ) ;
926+
880927 test ( 'cookieToken: returns handshake when no cookies in development [5y]' , async ( ) => {
881928 const requestState = await authenticateRequest (
882929 mockRequestWithCookies ( { } ) ,
0 commit comments