-
Notifications
You must be signed in to change notification settings - Fork 283
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(clerk-js,shared,nextjs): Support
__clerk_db_jwt
and `__dev_se…
…ssion` query params (#2428) * chore(clerk-js,shared,nextjs): Move `setDevBrowserJWTInURL` to shared * chore(shared): Support reading dev browser jwt from `__dev_session` and `__clerk_db_jwt` * chore(repo): Add changeset
- Loading branch information
Showing
13 changed files
with
104 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
'@clerk/clerk-js': minor | ||
'@clerk/nextjs': minor | ||
'@clerk/shared': minor | ||
--- | ||
|
||
Support reading from `__clerk_db_jwt` and `__dev_session` the dev browser jwt in development |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
import { DEV_BROWSER_JWT_MARKER } from '@clerk/shared'; | ||
import { createCookieHandler } from '@clerk/shared/cookie'; | ||
|
||
import { DEV_BROWSER_JWT_MARKER } from '../devBrowser'; | ||
|
||
export const devBrowserCookie = createCookieHandler(DEV_BROWSER_JWT_MARKER); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,19 @@ | ||
import { DEV_BROWSER_SSO_JWT_PARAMETER } from '../core/constants'; | ||
|
||
export const DEV_BROWSER_JWT_MARKER = '__clerk_db_jwt'; | ||
const DEV_BROWSER_JWT_MARKER_REGEXP = /__clerk_db_jwt\[(.*)\]/; | ||
|
||
// Sets the dev_browser JWT in the hash or the search | ||
export function setDevBrowserJWTInURL(url: URL, jwt: string, asQueryParam: boolean): URL { | ||
const resultURL = new URL(url); | ||
|
||
// extract & strip existing jwt from hash | ||
const jwtFromHash = extractDevBrowserJWTFromHash(resultURL.hash); | ||
resultURL.hash = resultURL.hash.replace(DEV_BROWSER_JWT_MARKER_REGEXP, ''); | ||
if (resultURL.href.endsWith('#')) { | ||
resultURL.hash = ''; | ||
} | ||
|
||
// extract & strip existing jwt from search | ||
const jwtFromSearch = resultURL.searchParams.get(DEV_BROWSER_SSO_JWT_PARAMETER); | ||
resultURL.searchParams.delete(DEV_BROWSER_SSO_JWT_PARAMETER); | ||
|
||
// Existing jwt takes precedence | ||
const jwtToSet = jwtFromHash || jwtFromSearch || jwt; | ||
|
||
if (jwtToSet) { | ||
if (asQueryParam) { | ||
resultURL.searchParams.append(DEV_BROWSER_SSO_JWT_PARAMETER, jwtToSet); | ||
} else { | ||
resultURL.hash = resultURL.hash + `${DEV_BROWSER_JWT_MARKER}[${jwtToSet}]`; | ||
} | ||
} | ||
|
||
return resultURL; | ||
} | ||
import { extractDevBrowserJWTFromURLHash, extractDevBrowserJWTFromURLSearchParams } from '@clerk/shared'; | ||
|
||
// Gets the dev_browser JWT from either the hash or the search | ||
// Side effect: | ||
// Removes dev_browser JWT from the URL as a side effect and updates the browser history | ||
export function getDevBrowserJWTFromURL(url: URL): string { | ||
const resultURL = new URL(url); | ||
|
||
// extract & strip existing jwt from hash | ||
const jwtFromHash = extractDevBrowserJWTFromHash(resultURL.hash); | ||
resultURL.hash = resultURL.hash.replace(DEV_BROWSER_JWT_MARKER_REGEXP, ''); | ||
if (resultURL.href.endsWith('#')) { | ||
resultURL.hash = ''; | ||
} | ||
|
||
// extract & strip existing jwt from search | ||
const jwtFromSearch = resultURL.searchParams.get(DEV_BROWSER_SSO_JWT_PARAMETER) || ''; | ||
resultURL.searchParams.delete(DEV_BROWSER_SSO_JWT_PARAMETER); | ||
const jwtFromHash = extractDevBrowserJWTFromURLHash(resultURL); | ||
const jwtFromSearch = extractDevBrowserJWTFromURLSearchParams(resultURL); | ||
|
||
const jwt = jwtFromHash || jwtFromSearch; | ||
|
||
if (jwt && typeof globalThis.history !== undefined) { | ||
if (jwt && typeof globalThis.history !== 'undefined') { | ||
globalThis.history.replaceState(null, '', resultURL.href); | ||
} | ||
|
||
return jwt; | ||
} | ||
|
||
function extractDevBrowserJWTFromHash(hash: string): string { | ||
const matches = hash.match(DEV_BROWSER_JWT_MARKER_REGEXP); | ||
return matches ? matches[1] : ''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ color | |
cookie | ||
date | ||
deprecated | ||
devBrowser | ||
error | ||
file | ||
globs | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,7 @@ | |
"cookie", | ||
"date", | ||
"deprecated", | ||
"devBrowser", | ||
"error", | ||
"file", | ||
"globs", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { setDevBrowserJWTInURL } from '../devBrowser'; | ||
|
||
const DUMMY_URL_BASE = 'http://clerk-dummy'; | ||
|
||
describe('setDevBrowserJWTInURL(url, jwt)', () => { | ||
const testCases: Array<[string, string, boolean, string]> = [ | ||
['', 'deadbeef', false, '#__clerk_db_jwt[deadbeef]'], | ||
['foo', 'deadbeef', false, 'foo#__clerk_db_jwt[deadbeef]'], | ||
['/foo', 'deadbeef', false, '/foo#__clerk_db_jwt[deadbeef]'], | ||
['#foo', 'deadbeef', false, '#foo__clerk_db_jwt[deadbeef]'], | ||
['/foo?bar=42#qux', 'deadbeef', false, '/foo?bar=42#qux__clerk_db_jwt[deadbeef]'], | ||
['/foo#__clerk_db_jwt[deadbeef]', 'deadbeef', false, '/foo#__clerk_db_jwt[deadbeef]'], | ||
['/foo?bar=42#qux__clerk_db_jwt[deadbeef]', 'deadbeef', false, '/foo?bar=42#qux__clerk_db_jwt[deadbeef]'], | ||
['/foo', 'deadbeef', true, '/foo?__dev_session=deadbeef'], | ||
['/foo?bar=42', 'deadbeef', true, '/foo?bar=42&__dev_session=deadbeef'], | ||
['/foo?bar=42&__clerk_db_jwt=deadbeef', 'deadbeef', true, '/foo?bar=42&__dev_session=deadbeef'], | ||
['/foo?bar=42&__dev_session=deadbeef', 'deadbeef', true, '/foo?bar=42&__dev_session=deadbeef'], | ||
]; | ||
|
||
test.each(testCases)( | ||
'sets the dev browser JWT at the end of the provided url. Params: url=(%s), jwt=(%s), expected url=(%s)', | ||
(input, paramName, asQueryParam, expected) => { | ||
expect(setDevBrowserJWTInURL(new URL(input, DUMMY_URL_BASE), paramName, asQueryParam).href).toEqual( | ||
new URL(expected, DUMMY_URL_BASE).href, | ||
); | ||
}, | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
export const DEV_BROWSER_SSO_JWT_PARAMETER = '__dev_session'; | ||
export const DEV_BROWSER_JWT_MARKER = '__clerk_db_jwt'; | ||
const DEV_BROWSER_JWT_MARKER_REGEXP = /__clerk_db_jwt\[(.*)\]/; | ||
|
||
// Sets the dev_browser JWT in the hash or the search | ||
export function setDevBrowserJWTInURL(url: URL, jwt: string, asQueryParam: boolean): URL { | ||
const resultURL = new URL(url); | ||
|
||
const jwtFromHash = extractDevBrowserJWTFromURLHash(resultURL); | ||
const jwtFromSearch = extractDevBrowserJWTFromURLSearchParams(resultURL); | ||
// Existing jwt takes precedence | ||
const jwtToSet = jwtFromHash || jwtFromSearch || jwt; | ||
|
||
if (jwtToSet) { | ||
if (asQueryParam) { | ||
resultURL.searchParams.append(DEV_BROWSER_SSO_JWT_PARAMETER, jwtToSet); | ||
} else { | ||
resultURL.hash = resultURL.hash + `${DEV_BROWSER_JWT_MARKER}[${jwtToSet}]`; | ||
} | ||
} | ||
|
||
return resultURL; | ||
} | ||
|
||
function extractDevBrowserJWTFromHash(hash: string): string { | ||
const matches = hash.match(DEV_BROWSER_JWT_MARKER_REGEXP); | ||
return matches ? matches[1] : ''; | ||
} | ||
|
||
/** | ||
* Extract & strip existing jwt from hash | ||
* Side effect: Removes dev browser from the url hash | ||
**/ | ||
export function extractDevBrowserJWTFromURLHash(url: URL) { | ||
const jwt = extractDevBrowserJWTFromHash(url.hash); | ||
url.hash = url.hash.replace(DEV_BROWSER_JWT_MARKER_REGEXP, ''); | ||
if (url.href.endsWith('#')) { | ||
url.hash = ''; | ||
} | ||
|
||
return jwt; | ||
} | ||
|
||
/** | ||
* Extract & strip existing jwt from search params | ||
* Side effect: Removes dev browser from the search params | ||
**/ | ||
export function extractDevBrowserJWTFromURLSearchParams(url: URL) { | ||
const jwtFromDevSession = url.searchParams.get(DEV_BROWSER_SSO_JWT_PARAMETER); | ||
url.searchParams.delete(DEV_BROWSER_SSO_JWT_PARAMETER); | ||
|
||
const jwtFromClerkDbJwt = url.searchParams.get(DEV_BROWSER_JWT_MARKER); | ||
url.searchParams.delete(DEV_BROWSER_JWT_MARKER); | ||
|
||
return jwtFromDevSession || jwtFromClerkDbJwt || ''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ export const subpathNames = [ | |
'cookie', | ||
'date', | ||
'deprecated', | ||
'devBrowser', | ||
'error', | ||
'file', | ||
'globs', | ||
|