Skip to content

Commit

Permalink
fix(elements): Preserve absolute URLs passed via redirect_url (#3947)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstaley authored Aug 14, 2024
1 parent 3f6150f commit 362ad5f
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/itchy-geckos-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/elements": patch
---

Preserve absolute URLs passed via `redirect_url`
10 changes: 10 additions & 0 deletions packages/elements/src/react/router/__tests__/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ describe('createClerkRouter', () => {
expect(mockRouter.replace).toHaveBeenCalledWith('/app/dashboard?after_sign_in_url=foobar');
});

it('pushes absolute URLs unmodified', () => {
const path = 'https://example.com';
const clerkRouter = createClerkRouter(mockRouter, '/app');

mockRouter.searchParams.mockImplementation(() => new URLSearchParams('after_sign_in_url=foobar&foo=bar'));
clerkRouter.push(path);

expect(mockRouter.push).toHaveBeenCalledWith('https://example.com');
});

it('returns the correct pathname', () => {
const clerkRouter = createClerkRouter(mockRouter, '/app');

Expand Down
6 changes: 6 additions & 0 deletions packages/elements/src/react/router/router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { withLeadingSlash, withoutTrailingSlash } from '@clerk/shared/url';

import type { ROUTING } from '~/internals/constants';
import { isAbsoluteUrl } from '~/utils/is-absolute-url';

export const PRESERVED_QUERYSTRING_PARAMS = ['after_sign_in_url', 'after_sign_up_url', 'redirect_url'];

Expand Down Expand Up @@ -87,6 +88,11 @@ export function createClerkRouter(router: ClerkHostRouter, basePath: string = '/
* Certain query parameters need to be preserved when navigating internally. These query parameters are ultimately used by Clerk to dictate behavior, so we keep them around.
*/
function makeDestinationUrlWithPreservedQueryParameters(path: string) {
// If the provided path is an absolute URL, return it unmodified.
if (isAbsoluteUrl(path)) {
return path;
}

const destinationUrl = new URL(path, window.location.origin);
const currentSearchParams = router.searchParams();

Expand Down
6 changes: 6 additions & 0 deletions packages/elements/src/utils/is-absolute-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/* Code below is taken from https://github.com/vercel/next.js/blob/fe7ff3f468d7651a92865350bfd0f16ceba27db5/packages/next/src/shared/lib/utils.ts. LICENSE: MIT */

// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
const ABSOLUTE_URL_REGEX = /^[a-zA-Z][a-zA-Z\d+\-.]*?:/;
export const isAbsoluteUrl = (url: string) => ABSOLUTE_URL_REGEX.test(url);

0 comments on commit 362ad5f

Please sign in to comment.