Skip to content

Commit

Permalink
feat(backend): Use __clerk_suffixed_cookies cookie to ask suffixed co…
Browse files Browse the repository at this point in the history
…okies in handshake
  • Loading branch information
dimkl committed May 23, 2024
1 parent 731aae4 commit ffdf6ea
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 29 deletions.
1 change: 1 addition & 0 deletions packages/backend/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const Cookies = {
ClientUat: '__client_uat',
Handshake: '__clerk_handshake',
DevBrowser: '__clerk_db_jwt',
SuffixedCookies: '__clerk_suffixed_cookies',
} as const;

const QueryParameters = {
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/tokens/authenticateContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface AuthenticateContextInterface extends AuthenticateRequestOptions {
// cookie-based values
sessionTokenInCookie: string | undefined;
clientUat: number;
suffixedCookies: boolean;
// handshake-related values
devBrowserToken: string | undefined;
handshakeToken: string | undefined;
Expand Down Expand Up @@ -95,6 +96,7 @@ class AuthenticateContext {
private initCookieValues() {
this.sessionTokenInCookie = this.getMultipleAppsCookie(constants.Cookies.Session);
this.clientUat = Number.parseInt(this.getMultipleAppsCookie(constants.Cookies.ClientUat) || '') || 0;
this.suffixedCookies = this.getMultipleAppsCookie(constants.Cookies.SuffixedCookies) === 'true';
}

private stripAuthorizationHeader(authValue: string | undefined | null): string | undefined {
Expand Down
22 changes: 3 additions & 19 deletions packages/backend/src/tokens/cookie.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,7 @@
const getCookieName = (cookieDirective: string): string => {
export const getCookieName = (cookieDirective: string): string => {
return cookieDirective.split(';')[0]?.split('=')[0];
};

const getSuffixedName = (name: string, suffix: string): string => {
if (name.endsWith(suffix)) {
return name;
}
return `${name}_${suffix}`;
};

export const suffixCookie = (suffix: string, cookieDirective: string): string => {
const name = getCookieName(cookieDirective);
const suffixedName = getSuffixedName(name, suffix);

return cookieDirective.replace(name + '=', suffixedName + '=');
};

export const unSuffixCookie = (suffix: string, cookieDirective: string): string => {
const name = getCookieName(cookieDirective).replace('_' + suffix, '');
const suffixedName = getSuffixedName(suffix, cookieDirective);
return cookieDirective.replace(suffixedName + '=', name + '=');
export const getCookieValue = (cookieDirective: string): string => {
return cookieDirective.split(';')[0]?.split('=')[1];
};
16 changes: 6 additions & 10 deletions packages/backend/src/tokens/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import type { TokenCarrier } from '../errors';
import { TokenVerificationError, TokenVerificationErrorReason } from '../errors';
import { decodeJwt } from '../jwt/verifyJwt';
import { assertValidSecretKey } from '../util/optionsAssertions';
import { getCookieSuffix, isDevelopmentFromSecretKey } from '../util/shared';
import { isDevelopmentFromSecretKey } from '../util/shared';
import type { AuthenticateContext } from './authenticateContext';
import { createAuthenticateContext } from './authenticateContext';
import type { RequestState } from './authStatus';
import { AuthErrorReason, handshake, signedIn, signedOut } from './authStatus';
import { createClerkRequest } from './clerkRequest';
import { suffixCookie, unSuffixCookie } from './cookie';
import { getCookieName, getCookieValue } from './cookie';
import { verifyHandshakeToken } from './handshake';
import type { AuthenticateRequestOptions } from './types';
import { verifyToken } from './verify';
Expand Down Expand Up @@ -89,7 +89,7 @@ export async function authenticateRequest(

const url = new URL(`https://${frontendApiNoProtocol}/v1/client/handshake`);
url.searchParams.append('redirect_url', redirectUrl?.href || '');
url.searchParams.append('suffixed_cookies', 'true');
url.searchParams.append('suffixed_cookies', authenticateContext.suffixedCookies.toString());

if (authenticateContext.instanceType === 'development' && authenticateContext.devBrowserToken) {
url.searchParams.append(constants.QueryParameters.DevBrowser, authenticateContext.devBrowserToken);
Expand All @@ -106,16 +106,12 @@ export async function authenticateRequest(

const handshakePayload = await verifyHandshakeToken(authenticateContext.handshakeToken!, authenticateContext);
const cookiesToSet = handshakePayload.handshake;
const cookieSuffix = getCookieSuffix(authenticateContext.publishableKey);

let sessionToken = '';
cookiesToSet.forEach((x: string) => {
const suffixedCookie = suffixCookie(cookieSuffix, x);
headers.append('Set-Cookie', suffixedCookie);
const unSuffixedCookie = unSuffixCookie(cookieSuffix, x);
headers.append('Set-Cookie', unSuffixedCookie);
if (unSuffixedCookie.startsWith(`${constants.Cookies.Session}=`)) {
sessionToken = unSuffixedCookie.split(';')[0].substring(10);
headers.append('Set-Cookie', x);
if (getCookieName(x).startsWith(constants.Cookies.Session)) {
sessionToken = getCookieValue(x);
}
});

Expand Down

0 comments on commit ffdf6ea

Please sign in to comment.