diff --git a/lib/build/recipe/dashboard/api/analytics.js b/lib/build/recipe/dashboard/api/analytics.js index 1a4dba3db..db0811840 100644 --- a/lib/build/recipe/dashboard/api/analytics.js +++ b/lib/build/recipe/dashboard/api/analytics.js @@ -65,6 +65,7 @@ async function analyticsPost(_, ___, options, __) { websiteDomain: websiteDomain({ request: undefined, userContext: {}, + tenantId: undefined, }).getAsStringDangerous(), apiDomain: apiDomain.getAsStringDangerous(), appName, diff --git a/lib/build/recipe/emailpassword/utils.js b/lib/build/recipe/emailpassword/utils.js index f2518e26e..0c4e09be8 100644 --- a/lib/build/recipe/emailpassword/utils.js +++ b/lib/build/recipe/emailpassword/utils.js @@ -217,6 +217,7 @@ function getPasswordResetLink(input) { .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/build/recipe/emailverification/utils.js b/lib/build/recipe/emailverification/utils.js index 603f823ea..6f2aafead 100644 --- a/lib/build/recipe/emailverification/utils.js +++ b/lib/build/recipe/emailverification/utils.js @@ -69,6 +69,7 @@ function getEmailVerifyLink(input) { .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/build/recipe/passwordless/api/implementation.js b/lib/build/recipe/passwordless/api/implementation.js index 9ac97df00..9f1411298 100644 --- a/lib/build/recipe/passwordless/api/implementation.js +++ b/lib/build/recipe/passwordless/api/implementation.js @@ -228,6 +228,7 @@ function getAPIImplementation() { .getOrigin({ request: input.options.req, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.options.appInfo.websiteBasePath.getAsStringDangerous() + @@ -363,6 +364,7 @@ function getAPIImplementation() { .getOrigin({ request: input.options.req, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.options.appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/build/recipe/passwordless/recipe.js b/lib/build/recipe/passwordless/recipe.js index 9412e8b8b..8ddd664e8 100644 --- a/lib/build/recipe/passwordless/recipe.js +++ b/lib/build/recipe/passwordless/recipe.js @@ -133,6 +133,7 @@ class Recipe extends recipeModule_1.default { .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/build/recipe/session/cookieAndHeaders.d.ts b/lib/build/recipe/session/cookieAndHeaders.d.ts index 40b15126f..646f059eb 100644 --- a/lib/build/recipe/session/cookieAndHeaders.d.ts +++ b/lib/build/recipe/session/cookieAndHeaders.d.ts @@ -5,14 +5,16 @@ export declare function clearSessionFromAllTokenTransferMethods( config: TypeNormalisedInput, res: BaseResponse, request: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ): void; export declare function clearSession( config: TypeNormalisedInput, res: BaseResponse, transferMethod: TokenTransferMethod, request: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ): void; export declare function getAntiCsrfTokenFromHeaders(req: BaseRequest): string | undefined; export declare function setAntiCsrfTokenInHeaders(res: BaseResponse, antiCsrfToken: string): void; @@ -32,7 +34,8 @@ export declare function setToken( expires: number, transferMethod: TokenTransferMethod, req: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ): void; export declare function setHeader(res: BaseResponse, name: string, value: string): void; /** @@ -54,6 +57,7 @@ export declare function setCookie( expires: number, pathType: "refreshTokenPath" | "accessTokenPath", req: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ): void; export declare function getAuthModeFromHeader(req: BaseRequest): string | undefined; diff --git a/lib/build/recipe/session/cookieAndHeaders.js b/lib/build/recipe/session/cookieAndHeaders.js index d0987ad6b..5db99197a 100644 --- a/lib/build/recipe/session/cookieAndHeaders.js +++ b/lib/build/recipe/session/cookieAndHeaders.js @@ -26,7 +26,7 @@ const refreshTokenHeaderKey = "st-refresh-token"; const antiCsrfHeaderKey = "anti-csrf"; const frontTokenHeaderKey = "front-token"; const authModeHeaderKey = "st-auth-mode"; -function clearSessionFromAllTokenTransferMethods(config, res, request, userContext) { +function clearSessionFromAllTokenTransferMethods(config, res, request, userContext, tenantId) { // We are clearing the session in all transfermethods to be sure to override cookies in case they have been already added to the response. // This is done to handle the following use-case: // If the app overrides signInPOST to check the ban status of the user after the original implementation and throwing an UNAUTHORISED error @@ -34,15 +34,15 @@ function clearSessionFromAllTokenTransferMethods(config, res, request, userConte // We can't know which to clear since we can't reliably query or remove the set-cookie header added to the response (causes issues in some frameworks, i.e.: hapi) // The safe solution in this case is to overwrite all the response cookies/headers with an empty value, which is what we are doing here for (const transferMethod of constants_2.availableTokenTransferMethods) { - clearSession(config, res, transferMethod, request, userContext); + clearSession(config, res, transferMethod, request, userContext, tenantId); } } exports.clearSessionFromAllTokenTransferMethods = clearSessionFromAllTokenTransferMethods; -function clearSession(config, res, transferMethod, request, userContext) { +function clearSession(config, res, transferMethod, request, userContext, tenantId) { // If we can be specific about which transferMethod we want to clear, there is no reason to clear the other ones const tokenTypes = ["access", "refresh"]; for (const token of tokenTypes) { - setToken(config, res, token, "", 0, transferMethod, request, userContext); + setToken(config, res, token, "", 0, transferMethod, request, userContext, tenantId); } res.removeHeader(antiCsrfHeaderKey); // This can be added multiple times in some cases, but that should be OK @@ -111,7 +111,7 @@ function getToken(req, tokenType, transferMethod) { } } exports.getToken = getToken; -function setToken(config, res, tokenType, value, expires, transferMethod, req, userContext) { +function setToken(config, res, tokenType, value, expires, transferMethod, req, userContext, tenantId) { logger_1.logDebugMessage(`setToken: Setting ${tokenType} token as ${transferMethod}`); if (transferMethod === "cookie") { setCookie( @@ -122,7 +122,8 @@ function setToken(config, res, tokenType, value, expires, transferMethod, req, u expires, tokenType === "refresh" ? "refreshTokenPath" : "accessTokenPath", req, - userContext + userContext, + tenantId ); } else if (transferMethod === "header") { setHeader(res, getResponseHeaderNameForTokenType(tokenType), value); @@ -145,12 +146,13 @@ exports.setHeader = setHeader; * @param expires * @param path */ -function setCookie(config, res, name, value, expires, pathType, req, userContext) { +function setCookie(config, res, name, value, expires, pathType, req, userContext, tenantId) { let domain = config.cookieDomain; let secure = config.cookieSecure; let sameSite = config.getCookieSameSite({ request: req, userContext, + tenantId, }); let path = ""; if (pathType === "refreshTokenPath") { diff --git a/lib/build/recipe/session/recipe.js b/lib/build/recipe/session/recipe.js index ab82761bb..92b85b26f 100644 --- a/lib/build/recipe/session/recipe.js +++ b/lib/build/recipe/session/recipe.js @@ -107,7 +107,8 @@ class SessionRecipe extends recipeModule_1.default { this.config, response, request, - userContext + userContext, + undefined ); } return await this.config.errorHandlers.onUnauthorised(err.message, request, response); @@ -121,7 +122,8 @@ class SessionRecipe extends recipeModule_1.default { this.config, response, request, - userContext + userContext, + undefined ); return await this.config.errorHandlers.onTokenTheftDetected( err.payload.sessionHandle, diff --git a/lib/build/recipe/session/sessionClass.js b/lib/build/recipe/session/sessionClass.js index 8d6180ffb..8dc185a69 100644 --- a/lib/build/recipe/session/sessionClass.js +++ b/lib/build/recipe/session/sessionClass.js @@ -74,7 +74,8 @@ class Session { this.reqResInfo.res, this.reqResInfo.transferMethod, this.reqResInfo.req, - userContext === undefined ? utils_2.makeDefaultUserContextFromAPI(this.reqResInfo.req) : userContext + userContext === undefined ? utils_2.makeDefaultUserContextFromAPI(this.reqResInfo.req) : userContext, + this.getTenantId() ); } } @@ -178,7 +179,10 @@ class Session { this.helpers.config, this.reqResInfo.transferMethod, this.reqResInfo.req, - userContext === undefined ? utils_2.makeDefaultUserContextFromAPI(this.reqResInfo.req) : userContext + userContext === undefined + ? utils_2.makeDefaultUserContextFromAPI(this.reqResInfo.req) + : userContext, + this.getTenantId() ); } } else { @@ -277,7 +281,8 @@ class Session { this.helpers.config, transferMethod, info.req, - userContext !== undefined ? userContext : utils_2.makeDefaultUserContextFromAPI(info.req) + userContext !== undefined ? userContext : utils_2.makeDefaultUserContextFromAPI(info.req), + this.getTenantId() ); if (this.refreshToken !== undefined) { cookieAndHeaders_1.setToken( @@ -288,7 +293,8 @@ class Session { this.refreshToken.expiry, transferMethod, info.req, - userContext !== undefined ? userContext : utils_2.makeDefaultUserContextFromAPI(info.req) + userContext !== undefined ? userContext : utils_2.makeDefaultUserContextFromAPI(info.req), + this.getTenantId() ); } if (this.antiCsrfToken !== undefined) { diff --git a/lib/build/recipe/session/sessionRequestFunctions.js b/lib/build/recipe/session/sessionRequestFunctions.js index fee9b14bc..ade885eb3 100644 --- a/lib/build/recipe/session/sessionRequestFunctions.js +++ b/lib/build/recipe/session/sessionRequestFunctions.js @@ -101,6 +101,7 @@ async function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, op antiCsrf = antiCsrf({ request: req, userContext, + tenantId: undefined, }); } if (doAntiCsrfCheck && antiCsrf === "VIA_CUSTOM_HEADER") { @@ -214,7 +215,8 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn 0, "accessTokenPath", req, - userContext + userContext, + undefined ); } logger_1.logDebugMessage("refreshSession: UNAUTHORISED because refresh token in request is undefined"); @@ -233,6 +235,7 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn antiCsrf = antiCsrf({ request: req, userContext, + tenantId: undefined, }); } if (antiCsrf === "VIA_CUSTOM_HEADER" && !disableAntiCsrf) { @@ -277,7 +280,8 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn 0, "accessTokenPath", req, - userContext + userContext, + undefined ); } } @@ -287,7 +291,7 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn // We clear the tokens in all token transfer methods we are not going to overwrite for (const transferMethod of constants_1.availableTokenTransferMethods) { if (transferMethod !== requestTransferMethod && refreshTokens[transferMethod] !== undefined) { - cookieAndHeaders_1.clearSession(config, res, transferMethod, req, userContext); + cookieAndHeaders_1.clearSession(config, res, transferMethod, req, userContext, session.getTenantId()); } } await session.attachToRequestResponse( @@ -310,7 +314,8 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn 0, "accessTokenPath", req, - userContext + userContext, + session.getTenantId() ); } return session; @@ -362,6 +367,7 @@ async function createNewSessionInRequest({ config.getCookieSameSite({ request: req, userContext, + tenantId, }) === "none" && !config.cookieSecure && !( @@ -400,7 +406,7 @@ async function createNewSessionInRequest({ transferMethod !== outputTransferMethod && cookieAndHeaders_1.getToken(req, "access", transferMethod) !== undefined ) { - cookieAndHeaders_1.clearSession(config, res, transferMethod, req, userContext); + cookieAndHeaders_1.clearSession(config, res, transferMethod, req, userContext, tenantId); } } logger_1.logDebugMessage("createNewSession: Cleared old tokens"); diff --git a/lib/build/recipe/session/types.d.ts b/lib/build/recipe/session/types.d.ts index 220ba2f20..173058de1 100644 --- a/lib/build/recipe/session/types.d.ts +++ b/lib/build/recipe/session/types.d.ts @@ -86,7 +86,11 @@ export declare type TypeNormalisedInput = { refreshTokenPath: NormalisedURLPath; accessTokenPath: NormalisedURLPath; cookieDomain: string | undefined; - getCookieSameSite: (input: { request: BaseRequest | undefined; userContext: any }) => "strict" | "lax" | "none"; + getCookieSameSite: (input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => "strict" | "lax" | "none"; cookieSecure: boolean; sessionExpiredStatusCode: number; errorHandlers: NormalisedErrorHandlers; @@ -94,7 +98,11 @@ export declare type TypeNormalisedInput = { | "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE" - | ((input: { request: BaseRequest | undefined; userContext: any }) => "VIA_CUSTOM_HEADER" | "NONE"); + | ((input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => "VIA_CUSTOM_HEADER" | "NONE"); getTokenTransferMethod: (input: { req: BaseRequest; forCreateNewSession: boolean; diff --git a/lib/build/recipe/session/utils.d.ts b/lib/build/recipe/session/utils.d.ts index 6459666f0..2cd774c41 100644 --- a/lib/build/recipe/session/utils.d.ts +++ b/lib/build/recipe/session/utils.d.ts @@ -53,7 +53,8 @@ export declare function setAccessTokenInResponse( config: TypeNormalisedInput, transferMethod: TokenTransferMethod, req: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ): void; export declare function getRequiredClaimValidators( session: SessionContainerInterface, diff --git a/lib/build/recipe/session/utils.js b/lib/build/recipe/session/utils.js index 6657eb33f..2068f4807 100644 --- a/lib/build/recipe/session/utils.js +++ b/lib/build/recipe/session/utils.js @@ -109,6 +109,7 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() ); @@ -139,10 +140,11 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { throw new Error("antiCsrf config must be one of 'NONE' or 'VIA_CUSTOM_HEADER' or 'VIA_TOKEN'"); } } - let antiCsrf = ({ request, userContext }) => { + let antiCsrf = ({ request, userContext, tenantId }) => { const sameSite = cookieSameSite({ request, userContext, + tenantId, }); if (sameSite === "none") { return "VIA_CUSTOM_HEADER"; @@ -229,7 +231,7 @@ function normaliseSameSiteOrThrowError(sameSite) { return sameSite; } exports.normaliseSameSiteOrThrowError = normaliseSameSiteOrThrowError; -function setAccessTokenInResponse(res, accessToken, frontToken, config, transferMethod, req, userContext) { +function setAccessTokenInResponse(res, accessToken, frontToken, config, transferMethod, req, userContext, tenantId) { cookieAndHeaders_1.setFrontTokenInHeaders(res, frontToken); cookieAndHeaders_1.setToken( config, @@ -243,7 +245,8 @@ function setAccessTokenInResponse(res, accessToken, frontToken, config, transfer Date.now() + constants_1.hundredYearsInMs, transferMethod, req, - userContext + userContext, + tenantId ); if (config.exposeAccessTokenToFrontendInCookieBasedAuth && transferMethod === "cookie") { cookieAndHeaders_1.setToken( @@ -258,7 +261,8 @@ function setAccessTokenInResponse(res, accessToken, frontToken, config, transfer Date.now() + constants_1.hundredYearsInMs, "header", req, - userContext + userContext, + tenantId ); } } diff --git a/lib/build/types.d.ts b/lib/build/types.d.ts index 6a924d65d..d347d054a 100644 --- a/lib/build/types.d.ts +++ b/lib/build/types.d.ts @@ -16,7 +16,11 @@ export declare type AppInfo = { }; export declare type NormalisedAppinfo = { appName: string; - getOrigin: (input: { request: BaseRequest | undefined; userContext: any }) => NormalisedURLDomain; + getOrigin: (input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => NormalisedURLDomain; apiDomain: NormalisedURLDomain; topLevelAPIDomain: string; getTopLevelWebsiteDomain: (input: { request: BaseRequest | undefined; userContext: any }) => string; diff --git a/lib/ts/recipe/dashboard/api/analytics.ts b/lib/ts/recipe/dashboard/api/analytics.ts index 720ba8783..b361fbf03 100644 --- a/lib/ts/recipe/dashboard/api/analytics.ts +++ b/lib/ts/recipe/dashboard/api/analytics.ts @@ -76,6 +76,7 @@ export default async function analyticsPost( websiteDomain: websiteDomain({ request: undefined, userContext: {}, + tenantId: undefined, }).getAsStringDangerous(), apiDomain: apiDomain.getAsStringDangerous(), appName, diff --git a/lib/ts/recipe/emailpassword/utils.ts b/lib/ts/recipe/emailpassword/utils.ts index 9a31c7348..718e004b2 100644 --- a/lib/ts/recipe/emailpassword/utils.ts +++ b/lib/ts/recipe/emailpassword/utils.ts @@ -262,6 +262,7 @@ export function getPasswordResetLink(input: { .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/ts/recipe/emailverification/utils.ts b/lib/ts/recipe/emailverification/utils.ts index 358876c4c..ad6a51108 100644 --- a/lib/ts/recipe/emailverification/utils.ts +++ b/lib/ts/recipe/emailverification/utils.ts @@ -77,6 +77,7 @@ export function getEmailVerifyLink(input: { .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/ts/recipe/passwordless/api/implementation.ts b/lib/ts/recipe/passwordless/api/implementation.ts index 1b34bdade..97f6d04a1 100644 --- a/lib/ts/recipe/passwordless/api/implementation.ts +++ b/lib/ts/recipe/passwordless/api/implementation.ts @@ -245,6 +245,7 @@ export default function getAPIImplementation(): APIInterface { .getOrigin({ request: input.options.req, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.options.appInfo.websiteBasePath.getAsStringDangerous() + @@ -389,6 +390,7 @@ export default function getAPIImplementation(): APIInterface { .getOrigin({ request: input.options.req, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + input.options.appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/ts/recipe/passwordless/recipe.ts b/lib/ts/recipe/passwordless/recipe.ts index d34b6f2d7..bed47c57b 100644 --- a/lib/ts/recipe/passwordless/recipe.ts +++ b/lib/ts/recipe/passwordless/recipe.ts @@ -249,6 +249,7 @@ export default class Recipe extends RecipeModule { .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() + appInfo.websiteBasePath.getAsStringDangerous() + diff --git a/lib/ts/recipe/session/cookieAndHeaders.ts b/lib/ts/recipe/session/cookieAndHeaders.ts index f30cdba0c..2de134a1c 100644 --- a/lib/ts/recipe/session/cookieAndHeaders.ts +++ b/lib/ts/recipe/session/cookieAndHeaders.ts @@ -34,7 +34,8 @@ export function clearSessionFromAllTokenTransferMethods( config: TypeNormalisedInput, res: BaseResponse, request: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ) { // We are clearing the session in all transfermethods to be sure to override cookies in case they have been already added to the response. // This is done to handle the following use-case: @@ -43,7 +44,7 @@ export function clearSessionFromAllTokenTransferMethods( // We can't know which to clear since we can't reliably query or remove the set-cookie header added to the response (causes issues in some frameworks, i.e.: hapi) // The safe solution in this case is to overwrite all the response cookies/headers with an empty value, which is what we are doing here for (const transferMethod of availableTokenTransferMethods) { - clearSession(config, res, transferMethod, request, userContext); + clearSession(config, res, transferMethod, request, userContext, tenantId); } } @@ -52,12 +53,13 @@ export function clearSession( res: BaseResponse, transferMethod: TokenTransferMethod, request: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ) { // If we can be specific about which transferMethod we want to clear, there is no reason to clear the other ones const tokenTypes: TokenType[] = ["access", "refresh"]; for (const token of tokenTypes) { - setToken(config, res, token, "", 0, transferMethod, request, userContext); + setToken(config, res, token, "", 0, transferMethod, request, userContext, tenantId); } res.removeHeader(antiCsrfHeaderKey); @@ -138,7 +140,8 @@ export function setToken( expires: number, transferMethod: TokenTransferMethod, req: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ) { logDebugMessage(`setToken: Setting ${tokenType} token as ${transferMethod}`); if (transferMethod === "cookie") { @@ -150,7 +153,8 @@ export function setToken( expires, tokenType === "refresh" ? "refreshTokenPath" : "accessTokenPath", req, - userContext + userContext, + tenantId ); } else if (transferMethod === "header") { setHeader(res, getResponseHeaderNameForTokenType(tokenType), value); @@ -181,13 +185,15 @@ export function setCookie( expires: number, pathType: "refreshTokenPath" | "accessTokenPath", req: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ) { let domain = config.cookieDomain; let secure = config.cookieSecure; let sameSite = config.getCookieSameSite({ request: req, userContext, + tenantId, }); let path = ""; if (pathType === "refreshTokenPath") { diff --git a/lib/ts/recipe/session/recipe.ts b/lib/ts/recipe/session/recipe.ts index 21e471548..0f5401076 100644 --- a/lib/ts/recipe/session/recipe.ts +++ b/lib/ts/recipe/session/recipe.ts @@ -208,7 +208,7 @@ export default class SessionRecipe extends RecipeModule { err.payload.clearTokens === true ) { logDebugMessage("errorHandler: Clearing tokens because of UNAUTHORISED response"); - clearSessionFromAllTokenTransferMethods(this.config, response, request, userContext); + clearSessionFromAllTokenTransferMethods(this.config, response, request, userContext, undefined); } return await this.config.errorHandlers.onUnauthorised(err.message, request, response); } else if (err.type === STError.TRY_REFRESH_TOKEN) { @@ -217,7 +217,7 @@ export default class SessionRecipe extends RecipeModule { } else if (err.type === STError.TOKEN_THEFT_DETECTED) { logDebugMessage("errorHandler: returning TOKEN_THEFT_DETECTED"); logDebugMessage("errorHandler: Clearing tokens because of TOKEN_THEFT_DETECTED response"); - clearSessionFromAllTokenTransferMethods(this.config, response, request, userContext); + clearSessionFromAllTokenTransferMethods(this.config, response, request, userContext, undefined); return await this.config.errorHandlers.onTokenTheftDetected( err.payload.sessionHandle, err.payload.userId, diff --git a/lib/ts/recipe/session/sessionClass.ts b/lib/ts/recipe/session/sessionClass.ts index fcbb9c8cf..8f650d58a 100644 --- a/lib/ts/recipe/session/sessionClass.ts +++ b/lib/ts/recipe/session/sessionClass.ts @@ -61,7 +61,8 @@ export default class Session implements SessionContainerInterface { this.reqResInfo.res, this.reqResInfo.transferMethod, this.reqResInfo.req, - userContext === undefined ? makeDefaultUserContextFromAPI(this.reqResInfo.req) : userContext + userContext === undefined ? makeDefaultUserContextFromAPI(this.reqResInfo.req) : userContext, + this.getTenantId() ); } } @@ -176,7 +177,8 @@ export default class Session implements SessionContainerInterface { this.helpers.config, this.reqResInfo.transferMethod, this.reqResInfo.req, - userContext === undefined ? makeDefaultUserContextFromAPI(this.reqResInfo.req) : userContext + userContext === undefined ? makeDefaultUserContextFromAPI(this.reqResInfo.req) : userContext, + this.getTenantId() ); } } else { @@ -288,7 +290,8 @@ export default class Session implements SessionContainerInterface { this.helpers.config, transferMethod, info.req, - userContext !== undefined ? userContext : makeDefaultUserContextFromAPI(info.req) + userContext !== undefined ? userContext : makeDefaultUserContextFromAPI(info.req), + this.getTenantId() ); if (this.refreshToken !== undefined) { setToken( @@ -299,7 +302,8 @@ export default class Session implements SessionContainerInterface { this.refreshToken.expiry, transferMethod, info.req, - userContext !== undefined ? userContext : makeDefaultUserContextFromAPI(info.req) + userContext !== undefined ? userContext : makeDefaultUserContextFromAPI(info.req), + this.getTenantId() ); } if (this.antiCsrfToken !== undefined) { diff --git a/lib/ts/recipe/session/sessionRequestFunctions.ts b/lib/ts/recipe/session/sessionRequestFunctions.ts index 0f58a948e..8caa5c260 100644 --- a/lib/ts/recipe/session/sessionRequestFunctions.ts +++ b/lib/ts/recipe/session/sessionRequestFunctions.ts @@ -132,6 +132,7 @@ export async function getSessionFromRequest({ antiCsrf = antiCsrf({ request: req, userContext, + tenantId: undefined, }); } @@ -257,7 +258,17 @@ export async function refreshSessionInRequest({ // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { logDebugMessage("refreshSession: cleared legacy id refresh token because refresh token was not found"); - setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath", req, userContext); + setCookie( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath", + req, + userContext, + undefined + ); } logDebugMessage("refreshSession: UNAUTHORISED because refresh token in request is undefined"); @@ -278,6 +289,7 @@ export async function refreshSessionInRequest({ antiCsrf = antiCsrf({ request: req, userContext, + tenantId: undefined, }); } @@ -314,7 +326,17 @@ export async function refreshSessionInRequest({ logDebugMessage( "refreshSession: cleared legacy id refresh token because refresh is clearing other tokens" ); - setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath", req, userContext); + setCookie( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath", + req, + userContext, + undefined + ); } } throw ex; @@ -324,7 +346,7 @@ export async function refreshSessionInRequest({ // We clear the tokens in all token transfer methods we are not going to overwrite for (const transferMethod of availableTokenTransferMethods) { if (transferMethod !== requestTransferMethod && refreshTokens[transferMethod] !== undefined) { - clearSession(config, res, transferMethod, req, userContext); + clearSession(config, res, transferMethod, req, userContext, session.getTenantId()); } } await session.attachToRequestResponse( @@ -341,7 +363,17 @@ export async function refreshSessionInRequest({ // This token isn't handled by getToken/setToken to limit the scope of this legacy/migration code if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { logDebugMessage("refreshSession: cleared legacy id refresh token after successful refresh"); - setCookie(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath", req, userContext); + setCookie( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath", + req, + userContext, + session.getTenantId() + ); } return session; @@ -419,6 +451,7 @@ export async function createNewSessionInRequest({ config.getCookieSameSite({ request: req, userContext, + tenantId, }) === "none" && !config.cookieSecure && !( @@ -456,7 +489,7 @@ export async function createNewSessionInRequest({ for (const transferMethod of availableTokenTransferMethods) { if (transferMethod !== outputTransferMethod && getToken(req, "access", transferMethod) !== undefined) { - clearSession(config, res, transferMethod, req, userContext); + clearSession(config, res, transferMethod, req, userContext, tenantId); } } logDebugMessage("createNewSession: Cleared old tokens"); diff --git a/lib/ts/recipe/session/types.ts b/lib/ts/recipe/session/types.ts index b3502fb59..211002ec3 100644 --- a/lib/ts/recipe/session/types.ts +++ b/lib/ts/recipe/session/types.ts @@ -111,7 +111,11 @@ export type TypeNormalisedInput = { refreshTokenPath: NormalisedURLPath; accessTokenPath: NormalisedURLPath; cookieDomain: string | undefined; - getCookieSameSite: (input: { request: BaseRequest | undefined; userContext: any }) => "strict" | "lax" | "none"; + getCookieSameSite: (input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => "strict" | "lax" | "none"; cookieSecure: boolean; sessionExpiredStatusCode: number; errorHandlers: NormalisedErrorHandlers; @@ -119,7 +123,11 @@ export type TypeNormalisedInput = { | "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE" - | ((input: { request: BaseRequest | undefined; userContext: any }) => "VIA_CUSTOM_HEADER" | "NONE"); + | ((input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => "VIA_CUSTOM_HEADER" | "NONE"); getTokenTransferMethod: (input: { req: BaseRequest; diff --git a/lib/ts/recipe/session/utils.ts b/lib/ts/recipe/session/utils.ts index 2e73b4f42..befd165b8 100644 --- a/lib/ts/recipe/session/utils.ts +++ b/lib/ts/recipe/session/utils.ts @@ -141,12 +141,18 @@ export function validateAndNormaliseUserInput( let cookieSameSite: (input: { request: BaseRequest | undefined; userContext: any; - }) => "strict" | "lax" | "none" = (input: { request: BaseRequest | undefined; userContext: any }) => { + tenantId: string | undefined; + }) => "strict" | "lax" | "none" = (input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => { let protocolOfWebsiteDomain = getURLProtocol( appInfo .getOrigin({ request: input.request, userContext: input.userContext, + tenantId: input.tenantId, }) .getAsStringDangerous() ); @@ -186,13 +192,15 @@ export function validateAndNormaliseUserInput( | "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE" - | ((input: { request: BaseRequest | undefined; userContext: any }) => "VIA_CUSTOM_HEADER" | "NONE") = ({ - request, - userContext, - }) => { + | ((input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => "VIA_CUSTOM_HEADER" | "NONE") = ({ request, userContext, tenantId }) => { const sameSite = cookieSameSite({ request, userContext, + tenantId, }); if (sameSite === "none") { @@ -287,7 +295,8 @@ export function setAccessTokenInResponse( config: TypeNormalisedInput, transferMethod: TokenTransferMethod, req: BaseRequest | undefined, - userContext: any + userContext: any, + tenantId: string | undefined ) { setFrontTokenInHeaders(res, frontToken); setToken( @@ -302,7 +311,8 @@ export function setAccessTokenInResponse( Date.now() + hundredYearsInMs, transferMethod, req, - userContext + userContext, + tenantId ); if (config.exposeAccessTokenToFrontendInCookieBasedAuth && transferMethod === "cookie") { @@ -318,7 +328,8 @@ export function setAccessTokenInResponse( Date.now() + hundredYearsInMs, "header", req, - userContext + userContext, + tenantId ); } } diff --git a/lib/ts/types.ts b/lib/ts/types.ts index 6699e29c0..98232dbf4 100644 --- a/lib/ts/types.ts +++ b/lib/ts/types.ts @@ -32,7 +32,11 @@ export type AppInfo = { export type NormalisedAppinfo = { appName: string; - getOrigin: (input: { request: BaseRequest | undefined; userContext: any }) => NormalisedURLDomain; + getOrigin: (input: { + request: BaseRequest | undefined; + userContext: any; + tenantId: string | undefined; + }) => NormalisedURLDomain; apiDomain: NormalisedURLDomain; topLevelAPIDomain: string; getTopLevelWebsiteDomain: (input: { request: BaseRequest | undefined; userContext: any }) => string;