diff --git a/.changeset/smart-jars-repeat.md b/.changeset/smart-jars-repeat.md new file mode 100644 index 00000000000..dda587ded37 --- /dev/null +++ b/.changeset/smart-jars-repeat.md @@ -0,0 +1,9 @@ +--- +'@clerk/clerk-js': patch +--- + +Complete the Safari ITP cookie refresh when `setActive({ redirectUrl })` navigates. + +Safari's ITP caps the client cookie at 7 days when it is re-issued from a fetch, so `setActive()` routes its redirect through `/v1/client/touch` to restore the full lifetime. That navigation was immediately followed by a second one to the undecorated redirect URL, which superseded it and aborted the touch request before it completed, leaving the cookie capped. + +This applies to flows that pass `redirectUrl` without a `navigate` callback — email link sign-in, the password reset success screen, the OAuth popup flow, and direct `setActive({ session, redirectUrl })` calls — in apps where Clerk performs a full page navigation rather than handing off to a router. Users still landed on the correct page, so the only symptom was Safari sessions ending after 7 days and returning devices being challenged as if they were new. diff --git a/packages/clerk-js/src/core/__tests__/clerk.test.ts b/packages/clerk-js/src/core/__tests__/clerk.test.ts index 66412e0a5e4..0cf09181ffc 100644 --- a/packages/clerk-js/src/core/__tests__/clerk.test.ts +++ b/packages/clerk-js/src/core/__tests__/clerk.test.ts @@ -349,6 +349,8 @@ describe('Clerk singleton', () => { const redirectUrl = new URL((sut.navigate as ReturnType).mock.calls[0][0]); expect(redirectUrl.pathname).toEqual('/v1/client/touch'); expect(redirectUrl.searchParams.get('redirect_url')).toEqual(`${mockWindowLocation.href}/redirect-url-path`); + // A second navigate would supersede the touch hop and abort it before it completes. + expect(sut.navigate).toHaveBeenCalledTimes(1); }); it('does not redirect the user to the /v1/client/touch endpoint if the cookie_expires_at is more than 8 days away', async () => { diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 9eaa2d6732c..2ce3f87c2e6 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -1864,14 +1864,7 @@ export class Clerk implements ClerkInterface { ); } } else if (redirectUrl) { - if (this.client.isEligibleForTouch()) { - const absoluteRedirectUrl = new URL(redirectUrl, window.location.href); - const redirectUrlWithAuth = this.buildUrlWithAuth( - this.client.buildTouchUrl({ redirectUrl: absoluteRedirectUrl }), - ); - await this.navigate(redirectUrlWithAuth); - } - await this.navigate(redirectUrl); + await this.navigate(this.#decorateUrlWithTouch(redirectUrl)); } }); }