Skip to content

Commit 682c57c

Browse files
committed
feat(backend): For production apps, let all errors end up in handshake
If a handshake loop occurs, it's going to be stopped by the infinite loop prevention mechanism and the request will terminate with a signed out state
1 parent 6b79914 commit 682c57c

File tree

1 file changed

+14
-32
lines changed

1 file changed

+14
-32
lines changed

packages/backend/src/tokens/request.ts

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -229,30 +229,6 @@ ${error.getFullMessage()}`,
229229
throw new Error(`Clerk: Handshake token verification failed: ${error.getFullMessage()}.`);
230230
}
231231

232-
function handleHandshakeTokenVerificationErrorInProduction(error: TokenVerificationError) {
233-
// In production, the handshake token is being transferred as a cookie, so there is a possibility of collision
234-
// with a handshake token of another app running on the same etld+1 domain.
235-
// For example, if one app is running on sub1.clerk.com and another on sub2.clerk.com, the handshake token
236-
// cookie for both apps will be set on etld+1 (clerk.com) so there's a possibility that one app will accidentally
237-
// use the handshake token of a different app during the handshake flow.
238-
// In this scenario, verification will fail with TokenInvalidSignature. In contrast to the development case,
239-
// we need to allow the flow to continue so the app eventually retries another handshake with the correct token.
240-
// We need to make sure, however, that we don't allow the flow to continue indefinitely, so we throw an error after X
241-
// retries to avoid an infinite loop. An infinite loop can happen if the customer switched Clerk keys for their prod app.
242-
if (
243-
error.reason === TokenVerificationErrorReason.TokenInvalidSignature ||
244-
error.reason === TokenVerificationErrorReason.InvalidSecretKey ||
245-
error.reason === TokenVerificationErrorReason.JWKKidMismatch ||
246-
error.reason === TokenVerificationErrorReason.JWKFailedToResolve
247-
) {
248-
// Let the request go through and eventually retry another handshake,
249-
// only if needed - a handshake will be thrown if another rule matches
250-
return;
251-
}
252-
const msg = `Clerk: Handshake token verification failed with "${error.getFullMessage()}"`;
253-
return signedOut(authenticateContext, AuthErrorReason.UnexpectedError, msg);
254-
}
255-
256232
async function authenticateRequestWithTokenInCookie() {
257233
const hasActiveClient = authenticateContext.clientUat;
258234
const hasSessionToken = !!authenticateContext.sessionTokenInCookie;
@@ -270,19 +246,23 @@ ${error.getFullMessage()}`,
270246
try {
271247
return await resolveHandshake();
272248
} catch (error) {
249+
// In production, the handshake token is being transferred as a cookie, so there is a possibility of collision
250+
// with a handshake token of another app running on the same etld+1 domain.
251+
// For example, if one app is running on sub1.clerk.com and another on sub2.clerk.com, the handshake token
252+
// cookie for both apps will be set on etld+1 (clerk.com) so there's a possibility that one app will accidentally
253+
// use the handshake token of a different app during the handshake flow.
254+
// In this scenario, verification will fail with TokenInvalidSignature. In contrast to the development case,
255+
// we need to allow the flow to continue so the app eventually retries another handshake with the correct token.
256+
// We need to make sure, however, that we don't allow the flow to continue indefinitely, so we throw an error after X
257+
// retries to avoid an infinite loop. An infinite loop can happen if the customer switched Clerk keys for their prod app.
258+
259+
// Check the handleHandshakeTokenVerificationErrorInDevelopment function for the development case.
273260
if (error instanceof TokenVerificationError && authenticateContext.instanceType === 'development') {
274261
handleHandshakeTokenVerificationErrorInDevelopment(error);
275262
}
276-
277-
if (error instanceof TokenVerificationError && authenticateContext.instanceType === 'production') {
278-
const terminateEarly = handleHandshakeTokenVerificationErrorInProduction(error);
279-
if (terminateEarly) {
280-
return terminateEarly;
281-
}
282-
}
283263
}
284264
}
285-
265+
console.log('4');
286266
/**
287267
* Otherwise, check for "known unknown" auth states that we can resolve with a handshake.
288268
*/
@@ -360,6 +340,8 @@ ${error.getFullMessage()}`,
360340
return handleError(decodedErrors[0], 'cookie');
361341
}
362342

343+
console.log('5');
344+
// prin eskage edo
363345
if (decodeResult.payload.iat < authenticateContext.clientUat) {
364346
return handleMaybeHandshakeStatus(authenticateContext, AuthErrorReason.SessionTokenOutdated, '');
365347
}

0 commit comments

Comments
 (0)