From b024d2e2b6ecc7167fd33a021425321d1694eab3 Mon Sep 17 00:00:00 2001 From: Stefanos Anagnostou Date: Wed, 5 Feb 2025 14:16:56 +0200 Subject: [PATCH 1/2] fix(clerk-js): Prevent infinite loop when client is blocked --- .changeset/tasty-socks-hide.md | 5 +++++ packages/clerk-js/src/core/resources/Base.ts | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .changeset/tasty-socks-hide.md diff --git a/.changeset/tasty-socks-hide.md b/.changeset/tasty-socks-hide.md new file mode 100644 index 00000000000..2fdd7411363 --- /dev/null +++ b/.changeset/tasty-socks-hide.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': patch +--- + +Prevent infinite loop when the client is blocked diff --git a/packages/clerk-js/src/core/resources/Base.ts b/packages/clerk-js/src/core/resources/Base.ts index 105e255a37c..c9cadf19a54 100644 --- a/packages/clerk-js/src/core/resources/Base.ts +++ b/packages/clerk-js/src/core/resources/Base.ts @@ -118,10 +118,13 @@ export abstract class BaseResource { const message = errors?.[0]?.long_message; const code = errors?.[0]?.code; + const isCaptchaRequired = code === 'requires_captcha'; + const isClientEndpointBlocked = requestInit.path === '/client' && code === 'resource_forbidden'; + // if the status is 401, we need to handle unauthenticated as we did before // otherwise, we are going to ignore the requires_captcha error // as we're going to handle it by triggering the captcha challenge - if (status === 401 && code !== 'requires_captcha') { + if (status === 401 && !isCaptchaRequired && !isClientEndpointBlocked) { await BaseResource.clerk.handleUnauthenticated(); } From 4582aec2545631bd26dea51a995cdc434286da01 Mon Sep 17 00:00:00 2001 From: Stefanos Anagnostou Date: Wed, 5 Feb 2025 20:36:53 +0200 Subject: [PATCH 2/2] handle the 403 error --- packages/clerk-js/src/core/clerk.ts | 25 +++++++++++++------- packages/clerk-js/src/core/resources/Base.ts | 5 +--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 4eaddfe4fb4..5eb64d4940f 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -1493,15 +1493,24 @@ export class Clerk implements ClerkInterface { if (!this.client || !this.session) { return; } - const newClient = await Client.getOrCreateInstance().fetch(); - this.updateClient(newClient); - if (this.session) { - return; - } - if (opts.broadcast) { - this.#broadcastSignOutEvent(); + try { + const newClient = await Client.getOrCreateInstance().fetch(); + this.updateClient(newClient); + if (this.session) { + return; + } + if (opts.broadcast) { + this.#broadcastSignOutEvent(); + } + return this.setActive({ session: null }); + } catch (err) { + // Handle the 403 Forbidden + if (err.status === 403) { + return this.setActive({ session: null }); + } else { + throw err; + } } - return this.setActive({ session: null }); }; public authenticateWithGoogleOneTap = async ( diff --git a/packages/clerk-js/src/core/resources/Base.ts b/packages/clerk-js/src/core/resources/Base.ts index c9cadf19a54..105e255a37c 100644 --- a/packages/clerk-js/src/core/resources/Base.ts +++ b/packages/clerk-js/src/core/resources/Base.ts @@ -118,13 +118,10 @@ export abstract class BaseResource { const message = errors?.[0]?.long_message; const code = errors?.[0]?.code; - const isCaptchaRequired = code === 'requires_captcha'; - const isClientEndpointBlocked = requestInit.path === '/client' && code === 'resource_forbidden'; - // if the status is 401, we need to handle unauthenticated as we did before // otherwise, we are going to ignore the requires_captcha error // as we're going to handle it by triggering the captcha challenge - if (status === 401 && !isCaptchaRequired && !isClientEndpointBlocked) { + if (status === 401 && code !== 'requires_captcha') { await BaseResource.clerk.handleUnauthenticated(); }