Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/smart-jars-repeat.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions packages/clerk-js/src/core/__tests__/clerk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ describe('Clerk singleton', () => {
const redirectUrl = new URL((sut.navigate as ReturnType<typeof vi.fn>).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 () => {
Expand Down
9 changes: 1 addition & 8 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
});
}
Expand Down
Loading