diff --git a/lib/build/authUtils.d.ts b/lib/build/authUtils.d.ts index d939a65c8..0a6e95156 100644 --- a/lib/build/authUtils.d.ts +++ b/lib/build/authUtils.d.ts @@ -20,10 +20,14 @@ export declare const AuthUtils: { * } * ``` */ - getErrorStatusResponseWithReason(resp: { - status: string; - reason?: string; - }, errorCodeMap: Record | string | undefined>, errorStatus: T): { + getErrorStatusResponseWithReason( + resp: { + status: string; + reason?: string; + }, + errorCodeMap: Record | string | undefined>, + errorStatus: T + ): { status: T; reason: string; }; @@ -40,7 +44,19 @@ export declare const AuthUtils: { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should become primary but we couldn't make it primary because of a conflicting primary user. */ - preAuthChecks: ({ authenticatingAccountInfo, tenantId, isSignUp, isVerified, signInVerifiesLoginMethod, authenticatingUser, factorIds, skipSessionUserUpdateInCore, session, shouldTryLinkingWithSessionUser, userContext, }: { + preAuthChecks: ({ + authenticatingAccountInfo, + tenantId, + isSignUp, + isVerified, + signInVerifiesLoginMethod, + authenticatingUser, + factorIds, + skipSessionUserUpdateInCore, + session, + shouldTryLinkingWithSessionUser, + userContext, + }: { authenticatingAccountInfo: AccountInfoWithRecipeId; authenticatingUser: User | undefined; tenantId: string; @@ -52,18 +68,23 @@ export declare const AuthUtils: { session?: SessionContainerInterface; shouldTryLinkingWithSessionUser: boolean | undefined; userContext: UserContext; - }) => Promise<{ - status: "OK"; - validFactorIds: string[]; - isFirstFactor: boolean; - } | { - status: "SIGN_UP_NOT_ALLOWED"; - } | { - status: "SIGN_IN_NOT_ALLOWED"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + validFactorIds: string[]; + isFirstFactor: boolean; + } + | { + status: "SIGN_UP_NOT_ALLOWED"; + } + | { + status: "SIGN_IN_NOT_ALLOWED"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; /** * Runs the linking process and all check we need to before creating a session + creates the new session if necessary: * - runs the linking process which will: try to link to the session user, or link by account info or try to make the authenticated user primary @@ -81,7 +102,17 @@ export declare const AuthUtils: { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should be primary but we couldn't make it primary because of a conflicting primary user. */ - postAuthChecks: ({ authenticatedUser, recipeUserId, isSignUp, factorId, session, req, res, tenantId, userContext, }: { + postAuthChecks: ({ + authenticatedUser, + recipeUserId, + isSignUp, + factorId, + session, + req, + res, + tenantId, + userContext, + }: { authenticatedUser: User; recipeUserId: RecipeUserId; tenantId: string; @@ -91,13 +122,16 @@ export declare const AuthUtils: { userContext: UserContext; req: BaseRequest; res: BaseResponse; - }) => Promise<{ - status: "OK"; - session: SessionContainerInterface; - user: User; - } | { - status: "SIGN_IN_NOT_ALLOWED"; - }>; + }) => Promise< + | { + status: "OK"; + session: SessionContainerInterface; + user: User; + } + | { + status: "SIGN_IN_NOT_ALLOWED"; + } + >; /** * This function tries to find the authenticating user (we use this information to see if the current auth is sign in or up) * if a session was passed and the authenticating user was not found on the current tenant, it checks if the session user @@ -108,32 +142,45 @@ export declare const AuthUtils: { * because it'll make managing MFA factors (i.e.: secondary passwords) a lot easier for the app, and, * most importantly, this way all secondary factors are app-wide instead of mixing app-wide (totp) and tenant-wide (password) factors. */ - getAuthenticatingUserAndAddToCurrentTenantIfRequired: ({ recipeId, accountInfo, checkCredentialsOnTenant, tenantId, session, userContext, }: { + getAuthenticatingUserAndAddToCurrentTenantIfRequired: ({ + recipeId, + accountInfo, + checkCredentialsOnTenant, + tenantId, + session, + userContext, + }: { recipeId: string; - accountInfo: { - email: string; - thirdParty?: undefined; - phoneNumber?: undefined; - } | { - email?: undefined; - thirdParty?: undefined; - phoneNumber: string; - } | { - email?: undefined; - thirdParty: { - id: string; - userId: string; - }; - phoneNumber?: undefined; - }; + accountInfo: + | { + email: string; + thirdParty?: undefined; + phoneNumber?: undefined; + } + | { + email?: undefined; + thirdParty?: undefined; + phoneNumber: string; + } + | { + email?: undefined; + thirdParty: { + id: string; + userId: string; + }; + phoneNumber?: undefined; + }; tenantId: string; session: SessionContainerInterface | undefined; checkCredentialsOnTenant: (tenantId: string) => Promise; userContext: UserContext; - }) => Promise<{ - user: User; - loginMethod: LoginMethod; - } | undefined>; + }) => Promise< + | { + user: User; + loginMethod: LoginMethod; + } + | undefined + >; /** * This function checks if the current authentication attempt should be considered a first factor or not. * To do this it'll also need to (if a session was passed): @@ -147,24 +194,36 @@ export declare const AuthUtils: { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should be primary but we couldn't make it primary because of a conflicting primary user. */ - checkAuthTypeAndLinkingStatus: (session: SessionContainerInterface | undefined, shouldTryLinkingWithSessionUser: boolean | undefined, accountInfo: AccountInfoWithRecipeId, inputUser: User | undefined, skipSessionUserUpdateInCore: boolean, userContext: UserContext) => Promise<{ - status: "OK"; - isFirstFactor: true; - } | { - status: "OK"; - isFirstFactor: false; - inputUserAlreadyLinkedToSessionUser: true; - sessionUser: User; - } | { - status: "OK"; - isFirstFactor: false; - inputUserAlreadyLinkedToSessionUser: false; - sessionUser: User; - linkingToSessionUserRequiresVerification: boolean; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + checkAuthTypeAndLinkingStatus: ( + session: SessionContainerInterface | undefined, + shouldTryLinkingWithSessionUser: boolean | undefined, + accountInfo: AccountInfoWithRecipeId, + inputUser: User | undefined, + skipSessionUserUpdateInCore: boolean, + userContext: UserContext + ) => Promise< + | { + status: "OK"; + isFirstFactor: true; + } + | { + status: "OK"; + isFirstFactor: false; + inputUserAlreadyLinkedToSessionUser: true; + sessionUser: User; + } + | { + status: "OK"; + isFirstFactor: false; + inputUserAlreadyLinkedToSessionUser: false; + sessionUser: User; + linkingToSessionUserRequiresVerification: boolean; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; /** * This function checks the auth type (first factor or not), links by account info for first factor auths otherwise * it tries to link the input user to the session user @@ -179,20 +238,34 @@ export declare const AuthUtils: { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should be primary but we couldn't make it primary because of a conflicting primary user. */ - linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo: ({ tenantId, inputUser, recipeUserId, session, shouldTryLinkingWithSessionUser, userContext, }: { + linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo: ({ + tenantId, + inputUser, + recipeUserId, + session, + shouldTryLinkingWithSessionUser, + userContext, + }: { tenantId: string; inputUser: User; recipeUserId: RecipeUserId; session: SessionContainerInterface | undefined; shouldTryLinkingWithSessionUser: boolean | undefined; userContext: UserContext; - }) => Promise<{ - status: "OK"; - user: User; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + user: User; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; /** * This function loads the session user and tries to make it primary. * It returns: @@ -203,14 +276,22 @@ export declare const AuthUtils: { * * It throws INVALID_CLAIM_ERROR if shouldDoAutomaticAccountLinking returned `{ shouldAutomaticallyLink: false }` but the email verification status was wrong */ - tryAndMakeSessionUserIntoAPrimaryUser: (session: SessionContainerInterface, skipSessionUserUpdateInCore: boolean, userContext: UserContext) => Promise<{ - status: "OK"; - sessionUser: User; - } | { - status: "SHOULD_AUTOMATICALLY_LINK_FALSE"; - } | { - status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + tryAndMakeSessionUserIntoAPrimaryUser: ( + session: SessionContainerInterface, + skipSessionUserUpdateInCore: boolean, + userContext: UserContext + ) => Promise< + | { + status: "OK"; + sessionUser: User; + } + | { + status: "SHOULD_AUTOMATICALLY_LINK_FALSE"; + } + | { + status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; /** * This function tries linking by session, and doesn't attempt to make the authenticated user a primary or link it by account info * @@ -224,22 +305,45 @@ export declare const AuthUtils: { * - LINKING_TO_SESSION_USER_FAILED (INPUT_USER_IS_NOT_A_PRIMARY_USER): * if the session user is not primary. This can be resolved by making it primary and retrying the call. */ - tryLinkingBySession: ({ linkingToSessionUserRequiresVerification, authLoginMethod, authenticatedUser, sessionUser, userContext, }: { + tryLinkingBySession: ({ + linkingToSessionUserRequiresVerification, + authLoginMethod, + authenticatedUser, + sessionUser, + userContext, + }: { authenticatedUser: User; linkingToSessionUserRequiresVerification: boolean; sessionUser: User; authLoginMethod: LoginMethod; userContext: UserContext; - }) => Promise<{ - status: "OK"; - user: User; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; - }>; - filterOutInvalidFirstFactorsOrThrowIfAllAreInvalid: (factorIds: string[], tenantId: string, hasSession: boolean, userContext: UserContext) => Promise; - loadSessionInAuthAPIIfNeeded: (req: BaseRequest, res: BaseResponse, shouldTryLinkingWithSessionUser: boolean | undefined, userContext: UserContext) => Promise; + }) => Promise< + | { + status: "OK"; + user: User; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; + } + >; + filterOutInvalidFirstFactorsOrThrowIfAllAreInvalid: ( + factorIds: string[], + tenantId: string, + hasSession: boolean, + userContext: UserContext + ) => Promise; + loadSessionInAuthAPIIfNeeded: ( + req: BaseRequest, + res: BaseResponse, + shouldTryLinkingWithSessionUser: boolean | undefined, + userContext: UserContext + ) => Promise; }; diff --git a/lib/build/authUtils.js b/lib/build/authUtils.js index 61022b402..eaa967781 100644 --- a/lib/build/authUtils.js +++ b/lib/build/authUtils.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AuthUtils = void 0; const recipe_1 = __importDefault(require("./recipe/accountlinking/recipe")); @@ -40,8 +42,7 @@ exports.AuthUtils = { status: errorStatus, reason: reasons, }; - } - else if (typeof reasons === "object" && resp.reason !== undefined) { + } else if (typeof reasons === "object" && resp.reason !== undefined) { if (reasons[resp.reason]) { return { status: errorStatus, @@ -66,7 +67,19 @@ exports.AuthUtils = { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should become primary but we couldn't make it primary because of a conflicting primary user. */ - preAuthChecks: async function ({ authenticatingAccountInfo, tenantId, isSignUp, isVerified, signInVerifiesLoginMethod, authenticatingUser, factorIds, skipSessionUserUpdateInCore, session, shouldTryLinkingWithSessionUser, userContext, }) { + preAuthChecks: async function ({ + authenticatingAccountInfo, + tenantId, + isSignUp, + isVerified, + signInVerifiesLoginMethod, + authenticatingUser, + factorIds, + skipSessionUserUpdateInCore, + session, + shouldTryLinkingWithSessionUser, + userContext, + }) { let validFactorIds; // This would be an implementation error on our part, we only check it because TS doesn't if (factorIds.length === 0) { @@ -76,7 +89,14 @@ exports.AuthUtils = { // First we check if the app intends to link the inputUser or not, // to decide if this is a first factor auth or not and if it'll link to the session user // We also load the session user here if it is available. - const authTypeInfo = await exports.AuthUtils.checkAuthTypeAndLinkingStatus(session, shouldTryLinkingWithSessionUser, authenticatingAccountInfo, authenticatingUser, skipSessionUserUpdateInCore, userContext); + const authTypeInfo = await exports.AuthUtils.checkAuthTypeAndLinkingStatus( + session, + shouldTryLinkingWithSessionUser, + authenticatingAccountInfo, + authenticatingUser, + skipSessionUserUpdateInCore, + userContext + ); if (authTypeInfo.status !== "OK") { (0, logger_1.logDebugMessage)(`preAuthChecks returning ${authTypeInfo.status} from checkAuthType results`); return authTypeInfo; @@ -91,47 +111,66 @@ exports.AuthUtils = { // The filtered list can be used to select email templates. As an example: // If the flowType for passwordless is USER_INPUT_CODE_AND_MAGIC_LINK and firstFactors for the tenant we only have otp-email // then we do not want to include a link in the email. - const validFirstFactors = await exports.AuthUtils.filterOutInvalidFirstFactorsOrThrowIfAllAreInvalid(factorIds, tenantId, session !== undefined, userContext); + const validFirstFactors = await exports.AuthUtils.filterOutInvalidFirstFactorsOrThrowIfAllAreInvalid( + factorIds, + tenantId, + session !== undefined, + userContext + ); validFactorIds = validFirstFactors; - } - else { + } else { (0, logger_1.logDebugMessage)("preAuthChecks getting valid secondary factors"); // In this case the app will try to link the session user and the authenticating user after auth, // so we need to check if this is allowed by the MFA recipe (if initialized). - validFactorIds = await filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid(factorIds, authTypeInfo.inputUserAlreadyLinkedToSessionUser, authTypeInfo.sessionUser, session, userContext); + validFactorIds = await filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid( + factorIds, + authTypeInfo.inputUserAlreadyLinkedToSessionUser, + authTypeInfo.sessionUser, + session, + userContext + ); } if (!isSignUp && authenticatingUser === undefined) { - throw new Error("This should never happen: preAuthChecks called with isSignUp: false, authenticatingUser: undefined"); + throw new Error( + "This should never happen: preAuthChecks called with isSignUp: false, authenticatingUser: undefined" + ); } // If this is a sign up we check that the sign up is allowed if (isSignUp) { // We need this check in case the session user has verified an email address and now tries to add a password for it. - let verifiedInSessionUser = !authTypeInfo.isFirstFactor && - authTypeInfo.sessionUser.loginMethods.some((lm) => lm.verified && - (lm.hasSameEmailAs(authenticatingAccountInfo.email) || - lm.hasSamePhoneNumberAs(authenticatingAccountInfo.phoneNumber))); + let verifiedInSessionUser = + !authTypeInfo.isFirstFactor && + authTypeInfo.sessionUser.loginMethods.some( + (lm) => + lm.verified && + (lm.hasSameEmailAs(authenticatingAccountInfo.email) || + lm.hasSamePhoneNumberAs(authenticatingAccountInfo.phoneNumber)) + ); (0, logger_1.logDebugMessage)("preAuthChecks checking if the user is allowed to sign up"); - if (!(await recipe_1.default.getInstance().isSignUpAllowed({ - newUser: authenticatingAccountInfo, - isVerified: isVerified || signInVerifiesLoginMethod || verifiedInSessionUser, - tenantId, - session, - userContext, - }))) { + if ( + !(await recipe_1.default.getInstance().isSignUpAllowed({ + newUser: authenticatingAccountInfo, + isVerified: isVerified || signInVerifiesLoginMethod || verifiedInSessionUser, + tenantId, + session, + userContext, + })) + ) { return { status: "SIGN_UP_NOT_ALLOWED" }; } - } - else if (authenticatingUser !== undefined) { + } else if (authenticatingUser !== undefined) { // for sign ins, this is checked after the credentials have been verified (0, logger_1.logDebugMessage)("preAuthChecks checking if the user is allowed to sign in"); - if (!(await recipe_1.default.getInstance().isSignInAllowed({ - user: authenticatingUser, - accountInfo: authenticatingAccountInfo, - signInVerifiesLoginMethod, - tenantId, - session, - userContext, - }))) { + if ( + !(await recipe_1.default.getInstance().isSignInAllowed({ + user: authenticatingUser, + accountInfo: authenticatingAccountInfo, + signInVerifiesLoginMethod, + tenantId, + session, + userContext, + })) + ) { return { status: "SIGN_IN_NOT_ALLOWED" }; } } @@ -160,12 +199,28 @@ exports.AuthUtils = { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should be primary but we couldn't make it primary because of a conflicting primary user. */ - postAuthChecks: async function ({ authenticatedUser, recipeUserId, isSignUp, factorId, session, req, res, tenantId, userContext, }) { - (0, logger_1.logDebugMessage)(`postAuthChecks called ${session !== undefined ? "with" : "without"} a session to ${isSignUp ? "sign in" : "sign up"} with ${factorId}`); + postAuthChecks: async function ({ + authenticatedUser, + recipeUserId, + isSignUp, + factorId, + session, + req, + res, + tenantId, + userContext, + }) { + (0, logger_1.logDebugMessage)( + `postAuthChecks called ${session !== undefined ? "with" : "without"} a session to ${ + isSignUp ? "sign in" : "sign up" + } with ${factorId}` + ); const mfaInstance = recipe_2.default.getInstance(); let respSession = session; if (session !== undefined) { - const authenticatedUserLinkedToSessionUser = authenticatedUser.loginMethods.some((lm) => lm.recipeUserId.getAsString() === session.getRecipeUserId(userContext).getAsString()); + const authenticatedUserLinkedToSessionUser = authenticatedUser.loginMethods.some( + (lm) => lm.recipeUserId.getAsString() === session.getRecipeUserId(userContext).getAsString() + ); if (authenticatedUserLinkedToSessionUser) { (0, logger_1.logDebugMessage)(`postAuthChecks session and input user got linked`); if (mfaInstance !== undefined) { @@ -174,20 +229,34 @@ exports.AuthUtils = { // we mark it as completed in the session. await multifactorauth_1.default.markFactorAsCompleteInSession(respSession, factorId, userContext); } - } - else { + } else { // If the new user wasn't linked to the current one, we overwrite the session // Note: we could also get here if MFA is enabled, but the app didn't want to link the user to the session user. - respSession = await session_1.default.createNewSession(req, res, tenantId, recipeUserId, {}, {}, userContext); + respSession = await session_1.default.createNewSession( + req, + res, + tenantId, + recipeUserId, + {}, + {}, + userContext + ); if (mfaInstance !== undefined) { await multifactorauth_1.default.markFactorAsCompleteInSession(respSession, factorId, userContext); } } - } - else { + } else { (0, logger_1.logDebugMessage)(`postAuthChecks creating session for first factor sign in/up`); // If there is no input session, we do not need to do anything other checks and create a new session - respSession = await session_1.default.createNewSession(req, res, tenantId, recipeUserId, {}, {}, userContext); + respSession = await session_1.default.createNewSession( + req, + res, + tenantId, + recipeUserId, + {}, + {}, + userContext + ); // Here we can always mark the factor as completed, since we just created the session if (mfaInstance !== undefined) { await multifactorauth_1.default.markFactorAsCompleteInSession(respSession, factorId, userContext); @@ -205,33 +274,53 @@ exports.AuthUtils = { * because it'll make managing MFA factors (i.e.: secondary passwords) a lot easier for the app, and, * most importantly, this way all secondary factors are app-wide instead of mixing app-wide (totp) and tenant-wide (password) factors. */ - getAuthenticatingUserAndAddToCurrentTenantIfRequired: async ({ recipeId, accountInfo, checkCredentialsOnTenant, tenantId, session, userContext, }) => { + getAuthenticatingUserAndAddToCurrentTenantIfRequired: async ({ + recipeId, + accountInfo, + checkCredentialsOnTenant, + tenantId, + session, + userContext, + }) => { let i = 0; while (i++ < 300) { - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired called with ${JSON.stringify(accountInfo)}`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired called with ${JSON.stringify(accountInfo)}` + ); const existingUsers = await recipe_1.default.getInstance().recipeInterfaceImpl.listUsersByAccountInfo({ tenantId, accountInfo, doUnionOfAccountInfo: true, userContext: userContext, }); - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired got ${existingUsers.length} users from the core resp`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired got ${existingUsers.length} users from the core resp` + ); const usersWithMatchingLoginMethods = existingUsers .map((user) => ({ - user, - loginMethod: user.loginMethods.find((lm) => lm.recipeId === recipeId && - ((accountInfo.email !== undefined && lm.hasSameEmailAs(accountInfo.email)) || - lm.hasSamePhoneNumberAs(accountInfo.phoneNumber) || - lm.hasSameThirdPartyInfoAs(accountInfo.thirdParty))), - })) + user, + loginMethod: user.loginMethods.find( + (lm) => + lm.recipeId === recipeId && + ((accountInfo.email !== undefined && lm.hasSameEmailAs(accountInfo.email)) || + lm.hasSamePhoneNumberAs(accountInfo.phoneNumber) || + lm.hasSameThirdPartyInfoAs(accountInfo.thirdParty)) + ), + })) .filter(({ loginMethod }) => loginMethod !== undefined); - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired got ${usersWithMatchingLoginMethods.length} users with matching login methods`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired got ${usersWithMatchingLoginMethods.length} users with matching login methods` + ); if (usersWithMatchingLoginMethods.length > 1) { - throw new Error("You have found a bug. Please report it on https://github.com/supertokens/supertokens-node/issues"); + throw new Error( + "You have found a bug. Please report it on https://github.com/supertokens/supertokens-node/issues" + ); } let authenticatingUser = usersWithMatchingLoginMethods[0]; if (authenticatingUser === undefined && session !== undefined) { - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired checking session user`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired checking session user` + ); const sessionUser = await (0, _1.getUser)(session.getUserId(userContext), userContext); if (sessionUser === undefined) { throw new error_1.default({ @@ -243,16 +332,25 @@ exports.AuthUtils = { // and we know that that login method is associated with the current tenant. // This means that the user has no loginMethods we need to check (that only belong to other tenantIds) if (!sessionUser.isPrimaryUser) { - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired session user is non-primary so returning early without checking other tenants`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired session user is non-primary so returning early without checking other tenants` + ); return undefined; } - const matchingLoginMethodsFromSessionUser = sessionUser.loginMethods.filter((lm) => lm.recipeId === recipeId && - (lm.hasSameEmailAs(accountInfo.email) || - lm.hasSamePhoneNumberAs(accountInfo.phoneNumber) || - lm.hasSameThirdPartyInfoAs(accountInfo.thirdParty))); - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired session has ${matchingLoginMethodsFromSessionUser.length} matching login methods`); + const matchingLoginMethodsFromSessionUser = sessionUser.loginMethods.filter( + (lm) => + lm.recipeId === recipeId && + (lm.hasSameEmailAs(accountInfo.email) || + lm.hasSamePhoneNumberAs(accountInfo.phoneNumber) || + lm.hasSameThirdPartyInfoAs(accountInfo.thirdParty)) + ); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired session has ${matchingLoginMethodsFromSessionUser.length} matching login methods` + ); if (matchingLoginMethodsFromSessionUser.some((lm) => lm.tenantIds.includes(tenantId))) { - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired session has ${matchingLoginMethodsFromSessionUser.length} matching login methods`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired session has ${matchingLoginMethodsFromSessionUser.length} matching login methods` + ); // This can happen in a race condition where a user was created and linked with the session user // between listing the existing users and loading the session user // We can return early, this only means that someone did the same sharing this function was aiming to do @@ -264,21 +362,33 @@ exports.AuthUtils = { } let goToRetry = false; for (const lm of matchingLoginMethodsFromSessionUser) { - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired session checking credentials on ${lm.tenantIds[0]}`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired session checking credentials on ${lm.tenantIds[0]}` + ); if (await checkCredentialsOnTenant(lm.tenantIds[0])) { - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired associating user from ${lm.tenantIds[0]} with current tenant`); - const associateRes = await multitenancy_1.default.associateUserToTenant(tenantId, lm.recipeUserId, userContext); - (0, logger_1.logDebugMessage)(`getAuthenticatingUserAndAddToCurrentTenantIfRequired associating returned ${associateRes.status}`); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired associating user from ${lm.tenantIds[0]} with current tenant` + ); + const associateRes = await multitenancy_1.default.associateUserToTenant( + tenantId, + lm.recipeUserId, + userContext + ); + (0, logger_1.logDebugMessage)( + `getAuthenticatingUserAndAddToCurrentTenantIfRequired associating returned ${associateRes.status}` + ); if (associateRes.status === "OK") { // We know that this is what happens lm.tenantIds.push(tenantId); return { user: sessionUser, loginMethod: lm }; } - if (associateRes.status === "UNKNOWN_USER_ID_ERROR" || // This means that the recipe user was deleted + if ( + associateRes.status === "UNKNOWN_USER_ID_ERROR" || // This means that the recipe user was deleted // All below conditions mean that both the account list and the session user we loaded is outdated associateRes.status === "EMAIL_ALREADY_EXISTS_ERROR" || associateRes.status === "PHONE_NUMBER_ALREADY_EXISTS_ERROR" || - associateRes.status === "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR") { + associateRes.status === "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR" + ) { // In these cases we retry, because we know some info we are using is outdated // while some of these cases we could handle locally, it's cleaner to restart the process. goToRetry = true; @@ -303,7 +413,9 @@ exports.AuthUtils = { } return authenticatingUser; } - throw new Error("This should never happen: ran out of retries for getAuthenticatingUserAndAddToCurrentTenantIfRequired"); + throw new Error( + "This should never happen: ran out of retries for getAuthenticatingUserAndAddToCurrentTenantIfRequired" + ); }, /** * This function checks if the current authentication attempt should be considered a first factor or not. @@ -318,7 +430,14 @@ exports.AuthUtils = { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should be primary but we couldn't make it primary because of a conflicting primary user. */ - checkAuthTypeAndLinkingStatus: async function (session, shouldTryLinkingWithSessionUser, accountInfo, inputUser, skipSessionUserUpdateInCore, userContext) { + checkAuthTypeAndLinkingStatus: async function ( + session, + shouldTryLinkingWithSessionUser, + accountInfo, + inputUser, + skipSessionUserUpdateInCore, + userContext + ) { (0, logger_1.logDebugMessage)(`checkAuthTypeAndLinkingStatus called`); let sessionUser = undefined; if (session === undefined) { @@ -328,28 +447,35 @@ exports.AuthUtils = { message: "Session not found but shouldTryLinkingWithSessionUser is true", }); } - (0, logger_1.logDebugMessage)(`checkAuthTypeAndLinkingStatus returning first factor because there is no session`); + (0, logger_1.logDebugMessage)( + `checkAuthTypeAndLinkingStatus returning first factor because there is no session` + ); // If there is no active session we have nothing to link to - so this has to be a first factor sign in return { status: "OK", isFirstFactor: true }; - } - else { + } else { if (shouldTryLinkingWithSessionUser === false) { - (0, logger_1.logDebugMessage)(`checkAuthTypeAndLinkingStatus returning first factor because shouldTryLinkingWithSessionUser is false`); + (0, logger_1.logDebugMessage)( + `checkAuthTypeAndLinkingStatus returning first factor because shouldTryLinkingWithSessionUser is false` + ); // In our normal flows this should never happen - but some user overrides might do this. // Anyway, since shouldTryLinkingWithSessionUser explicitly set to false, it's safe to consider this a firstFactor return { status: "OK", isFirstFactor: true }; } if (!(0, utils_3.recipeInitDefinedShouldDoAutomaticAccountLinking)(recipe_1.default.getInstance().config)) { if (shouldTryLinkingWithSessionUser === true) { - throw new Error("Please initialise the account linking recipe and define shouldDoAutomaticAccountLinking to enable MFA"); - } - else { + throw new Error( + "Please initialise the account linking recipe and define shouldDoAutomaticAccountLinking to enable MFA" + ); + } else { // This is the legacy case where shouldTryLinkingWithSessionUser is undefined if (recipe_2.default.getInstance() !== undefined) { - throw new Error("Please initialise the account linking recipe and define shouldDoAutomaticAccountLinking to enable MFA"); - } - else { - (0, logger_1.logDebugMessage)(`checkAuthTypeAndLinkingStatus (legacy behaviour) returning first factor because MFA is not initialised and shouldDoAutomaticAccountLinking is not defined`); + throw new Error( + "Please initialise the account linking recipe and define shouldDoAutomaticAccountLinking to enable MFA" + ); + } else { + (0, logger_1.logDebugMessage)( + `checkAuthTypeAndLinkingStatus (legacy behaviour) returning first factor because MFA is not initialised and shouldDoAutomaticAccountLinking is not defined` + ); return { status: "OK", isFirstFactor: true }; } } @@ -361,7 +487,9 @@ exports.AuthUtils = { // - MFA may or may not be initialized // If the input and the session user are the same if (inputUser !== undefined && inputUser.id === session.getUserId()) { - (0, logger_1.logDebugMessage)(`checkAuthTypeAndLinkingStatus returning secondary factor, session and input user are the same`); + (0, logger_1.logDebugMessage)( + `checkAuthTypeAndLinkingStatus returning secondary factor, session and input user are the same` + ); // Then this is basically a user logging in with an already linked secondary account // Which is basically a factor completion in MFA terms. // Since the sessionUser and the inputUser are the same in this case, we can just return early @@ -372,14 +500,23 @@ exports.AuthUtils = { sessionUser: inputUser, }; } - (0, logger_1.logDebugMessage)(`checkAuthTypeAndLinkingStatus loading session user, ${inputUser === null || inputUser === void 0 ? void 0 : inputUser.id} === ${session.getUserId()}`); + (0, logger_1.logDebugMessage)( + `checkAuthTypeAndLinkingStatus loading session user, ${ + inputUser === null || inputUser === void 0 ? void 0 : inputUser.id + } === ${session.getUserId()}` + ); // We have to load the session user in order to get the account linking info - const sessionUserResult = await exports.AuthUtils.tryAndMakeSessionUserIntoAPrimaryUser(session, skipSessionUserUpdateInCore, userContext); + const sessionUserResult = await exports.AuthUtils.tryAndMakeSessionUserIntoAPrimaryUser( + session, + skipSessionUserUpdateInCore, + userContext + ); if (sessionUserResult.status === "SHOULD_AUTOMATICALLY_LINK_FALSE") { if (shouldTryLinkingWithSessionUser === true) { // tryAndMakeSessionUserIntoAPrimaryUser throws if it is an email verification iss throw new _1.Error({ - message: "shouldDoAutomaticAccountLinking returned false when making the session user primary but shouldTryLinkingWithSessionUser is true", + message: + "shouldDoAutomaticAccountLinking returned false when making the session user primary but shouldTryLinkingWithSessionUser is true", type: "BAD_INPUT_ERROR", }); } @@ -387,8 +524,9 @@ exports.AuthUtils = { status: "OK", isFirstFactor: true, }; - } - else if (sessionUserResult.status === "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR") { + } else if ( + sessionUserResult.status === "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + ) { return { status: "LINKING_TO_SESSION_USER_FAILED", reason: "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR", @@ -397,18 +535,30 @@ exports.AuthUtils = { sessionUser = sessionUserResult.sessionUser; // We check if the app intends to link these two accounts // Note: in some cases if the accountInfo already belongs to a primary user - const shouldLink = await recipe_1.default.getInstance().config.shouldDoAutomaticAccountLinking(accountInfo, sessionUser, session, session.getTenantId(), userContext); - (0, logger_1.logDebugMessage)(`checkAuthTypeAndLinkingStatus session user <-> input user shouldDoAutomaticAccountLinking returned ${JSON.stringify(shouldLink)}`); + const shouldLink = await recipe_1.default + .getInstance() + .config.shouldDoAutomaticAccountLinking( + accountInfo, + sessionUser, + session, + session.getTenantId(), + userContext + ); + (0, logger_1.logDebugMessage)( + `checkAuthTypeAndLinkingStatus session user <-> input user shouldDoAutomaticAccountLinking returned ${JSON.stringify( + shouldLink + )}` + ); if (shouldLink.shouldAutomaticallyLink === false) { if (shouldTryLinkingWithSessionUser === true) { throw new _1.Error({ - message: "shouldDoAutomaticAccountLinking returned false when making the session user primary but shouldTryLinkingWithSessionUser is true", + message: + "shouldDoAutomaticAccountLinking returned false when making the session user primary but shouldTryLinkingWithSessionUser is true", type: "BAD_INPUT_ERROR", }); } return { status: "OK", isFirstFactor: true }; - } - else { + } else { return { status: "OK", isFirstFactor: false, @@ -433,10 +583,19 @@ exports.AuthUtils = { * - LINKING_TO_SESSION_USER_FAILED (SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR): * if the session user should be primary but we couldn't make it primary because of a conflicting primary user. */ - linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo: async function ({ tenantId, inputUser, recipeUserId, session, shouldTryLinkingWithSessionUser, userContext, }) { + linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo: async function ({ + tenantId, + inputUser, + recipeUserId, + session, + shouldTryLinkingWithSessionUser, + userContext, + }) { (0, logger_1.logDebugMessage)("linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo called"); const retry = () => { - (0, logger_1.logDebugMessage)("linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo retrying...."); + (0, logger_1.logDebugMessage)( + "linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo retrying...." + ); return exports.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo({ tenantId, inputUser: inputUser, @@ -448,20 +607,35 @@ exports.AuthUtils = { }; // If we got here, we have a session and a primary session user // We can not assume the inputUser is non-primary, since we'll only check that seeing if the app wants to link to the session user or not. - const authLoginMethod = inputUser.loginMethods.find((lm) => lm.recipeUserId.getAsString() === recipeUserId.getAsString()); + const authLoginMethod = inputUser.loginMethods.find( + (lm) => lm.recipeUserId.getAsString() === recipeUserId.getAsString() + ); if (authLoginMethod === undefined) { - throw new Error("This should never happen: the recipeUserId and user is inconsistent in createPrimaryUserIdOrLinkByAccountInfo params"); + throw new Error( + "This should never happen: the recipeUserId and user is inconsistent in createPrimaryUserIdOrLinkByAccountInfo params" + ); } - const authTypeRes = await exports.AuthUtils.checkAuthTypeAndLinkingStatus(session, shouldTryLinkingWithSessionUser, authLoginMethod, inputUser, false, userContext); + const authTypeRes = await exports.AuthUtils.checkAuthTypeAndLinkingStatus( + session, + shouldTryLinkingWithSessionUser, + authLoginMethod, + inputUser, + false, + userContext + ); if (authTypeRes.status !== "OK") { return authTypeRes; } if (authTypeRes.isFirstFactor) { if (!(0, utils_3.recipeInitDefinedShouldDoAutomaticAccountLinking)(recipe_1.default.getInstance().config)) { - (0, logger_1.logDebugMessage)("linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo skipping link by account info because this is a first factor auth and the app hasn't defined shouldDoAutomaticAccountLinking"); + (0, logger_1.logDebugMessage)( + "linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo skipping link by account info because this is a first factor auth and the app hasn't defined shouldDoAutomaticAccountLinking" + ); return { status: "OK", user: inputUser }; } - (0, logger_1.logDebugMessage)("linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo trying to link by account info because this is a first factor auth"); + (0, logger_1.logDebugMessage)( + "linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo trying to link by account info because this is a first factor auth" + ); // We try and list all users that can be linked to the input user based on the account info // later we can use these when trying to link or when checking if linking to the session user is possible. const linkRes = await recipe_1.default.getInstance().tryLinkingByAccountInfoOrCreatePrimaryUser({ @@ -484,7 +658,9 @@ exports.AuthUtils = { user: authTypeRes.sessionUser, }; } - (0, logger_1.logDebugMessage)("linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo trying to link by session info"); + (0, logger_1.logDebugMessage)( + "linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo trying to link by session info" + ); const sessionLinkingRes = await exports.AuthUtils.tryLinkingBySession({ sessionUser: authTypeRes.sessionUser, authenticatedUser: inputUser, @@ -497,12 +673,10 @@ exports.AuthUtils = { // This means that although we made the session user primary above, some race condition undid that (e.g.: calling unlink concurrently with this func) // We can retry in this case, since we start by trying to make it into a primary user and throwing if we can't return retry(); - } - else { + } else { return sessionLinkingRes; } - } - else { + } else { // If we get here the status is OK, so we can just return it return sessionLinkingRes; } @@ -530,38 +704,62 @@ exports.AuthUtils = { (0, logger_1.logDebugMessage)(`tryAndMakeSessionUserIntoAPrimaryUser session user already primary`); // if the session user was already primary we can just return it return { status: "OK", sessionUser }; - } - else { + } else { // if the session user is not primary we try and make it one (0, logger_1.logDebugMessage)(`tryAndMakeSessionUserIntoAPrimaryUser not primary user yet`); // We could check here if the session user can even become a primary user, but that'd only mean one extra core call // without any added benefits, since the core already checks all pre-conditions // We do this check here instead of using the shouldBecomePrimaryUser util, because // here we handle the shouldRequireVerification case differently - const shouldDoAccountLinking = await recipe_1.default.getInstance().config.shouldDoAutomaticAccountLinking(sessionUser.loginMethods[0], undefined, session, session.getTenantId(userContext), userContext); - (0, logger_1.logDebugMessage)(`tryAndMakeSessionUserIntoAPrimaryUser shouldDoAccountLinking: ${JSON.stringify(shouldDoAccountLinking)}`); + const shouldDoAccountLinking = await recipe_1.default + .getInstance() + .config.shouldDoAutomaticAccountLinking( + sessionUser.loginMethods[0], + undefined, + session, + session.getTenantId(userContext), + userContext + ); + (0, logger_1.logDebugMessage)( + `tryAndMakeSessionUserIntoAPrimaryUser shouldDoAccountLinking: ${JSON.stringify( + shouldDoAccountLinking + )}` + ); if (shouldDoAccountLinking.shouldAutomaticallyLink) { if (skipSessionUserUpdateInCore) { return { status: "OK", sessionUser: sessionUser }; } if (shouldDoAccountLinking.shouldRequireVerification && !sessionUser.loginMethods[0].verified) { // We force-update the claim value if it is not set or different from what we just fetched from the DB - if ((await session.getClaimValue(emailverification_1.EmailVerificationClaim, userContext)) !== false) { - (0, logger_1.logDebugMessage)(`tryAndMakeSessionUserIntoAPrimaryUser updating emailverification status in session`); + if ( + (await session.getClaimValue(emailverification_1.EmailVerificationClaim, userContext)) !== false + ) { + (0, logger_1.logDebugMessage)( + `tryAndMakeSessionUserIntoAPrimaryUser updating emailverification status in session` + ); // This will let the frontend know if the value has been updated in the background await session.setClaimValue(emailverification_1.EmailVerificationClaim, false, userContext); } (0, logger_1.logDebugMessage)(`tryAndMakeSessionUserIntoAPrimaryUser throwing validation error`); // Then run the validation expecting it to fail. We run assertClaims instead of throwing the error locally // to make sure the error shape in the response will match what we'd return normally - await session.assertClaims([emailverification_1.EmailVerificationClaim.validators.isVerified()], userContext); - throw new Error("This should never happen: email verification claim validator passed after setting value to false"); + await session.assertClaims( + [emailverification_1.EmailVerificationClaim.validators.isVerified()], + userContext + ); + throw new Error( + "This should never happen: email verification claim validator passed after setting value to false" + ); } - const createPrimaryUserRes = await recipe_1.default.getInstance().recipeInterfaceImpl.createPrimaryUser({ - recipeUserId: sessionUser.loginMethods[0].recipeUserId, - userContext, - }); - (0, logger_1.logDebugMessage)(`tryAndMakeSessionUserIntoAPrimaryUser createPrimaryUser returned ${createPrimaryUserRes.status}`); + const createPrimaryUserRes = await recipe_1.default + .getInstance() + .recipeInterfaceImpl.createPrimaryUser({ + recipeUserId: sessionUser.loginMethods[0].recipeUserId, + userContext, + }); + (0, logger_1.logDebugMessage)( + `tryAndMakeSessionUserIntoAPrimaryUser createPrimaryUser returned ${createPrimaryUserRes.status}` + ); if (createPrimaryUserRes.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR") { // This means that the session user got primary since we loaded the session user info above // but this status means that the user id has also changed, so the session should be invalid @@ -569,17 +767,14 @@ exports.AuthUtils = { type: error_1.default.UNAUTHORISED, message: "Session user not found", }); - } - else if (createPrimaryUserRes.status === "OK") { + } else if (createPrimaryUserRes.status === "OK") { return { status: "OK", sessionUser: createPrimaryUserRes.user }; - } - else { + } else { // All other statuses signify that we can't make the session user primary // Which means we can't continue return createPrimaryUserRes; } - } - else { + } else { // This means that the app doesn't want to make the session user primary return { status: "SHOULD_AUTOMATICALLY_LINK_FALSE" }; } @@ -598,7 +793,13 @@ exports.AuthUtils = { * - LINKING_TO_SESSION_USER_FAILED (INPUT_USER_IS_NOT_A_PRIMARY_USER): * if the session user is not primary. This can be resolved by making it primary and retrying the call. */ - tryLinkingBySession: async function ({ linkingToSessionUserRequiresVerification, authLoginMethod, authenticatedUser, sessionUser, userContext, }) { + tryLinkingBySession: async function ({ + linkingToSessionUserRequiresVerification, + authLoginMethod, + authenticatedUser, + sessionUser, + userContext, + }) { (0, logger_1.logDebugMessage)("tryLinkingBySession called"); // If the input user has another user (and it's not the session user) it could be linked to based on account info then we can't link it to the session user. // However, we do not need to check this as the linkAccounts check will fail anyway and we do not want the extra core call in case it succeeds @@ -606,9 +807,13 @@ exports.AuthUtils = { // then we don't want to ask them to verify it again. // This is different from linking based on account info, but the presence of a session shows that the user has access to both accounts, // and intends to link these two accounts. - const sessionUserHasVerifiedAccountInfo = sessionUser.loginMethods.some((lm) => (lm.hasSameEmailAs(authLoginMethod.email) || lm.hasSamePhoneNumberAs(authLoginMethod.phoneNumber)) && - lm.verified); - const canLinkBasedOnVerification = !linkingToSessionUserRequiresVerification || authLoginMethod.verified || sessionUserHasVerifiedAccountInfo; + const sessionUserHasVerifiedAccountInfo = sessionUser.loginMethods.some( + (lm) => + (lm.hasSameEmailAs(authLoginMethod.email) || lm.hasSamePhoneNumberAs(authLoginMethod.phoneNumber)) && + lm.verified + ); + const canLinkBasedOnVerification = + !linkingToSessionUserRequiresVerification || authLoginMethod.verified || sessionUserHasVerifiedAccountInfo; if (!canLinkBasedOnVerification) { return { status: "LINKING_TO_SESSION_USER_FAILED", reason: "EMAIL_VERIFICATION_REQUIRED" }; } @@ -623,22 +828,25 @@ exports.AuthUtils = { if (linkAccountsResult.status === "OK") { (0, logger_1.logDebugMessage)("tryLinkingBySession successfully linked input user to session user"); return { status: "OK", user: linkAccountsResult.user }; - } - else if (linkAccountsResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR") { + } else if (linkAccountsResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR") { // this can happen because of a race condition wherein the recipe user ID get's linked to // some other primary user whilst the linking is going on. - (0, logger_1.logDebugMessage)("tryLinkingBySession linking to session user failed because of a race condition - input user linked to another user"); + (0, logger_1.logDebugMessage)( + "tryLinkingBySession linking to session user failed because of a race condition - input user linked to another user" + ); return { status: "LINKING_TO_SESSION_USER_FAILED", reason: linkAccountsResult.status }; - } - else if (linkAccountsResult.status === "INPUT_USER_IS_NOT_A_PRIMARY_USER") { - (0, logger_1.logDebugMessage)("tryLinkingBySession linking to session user failed because of a race condition - INPUT_USER_IS_NOT_A_PRIMARY_USER, should retry"); + } else if (linkAccountsResult.status === "INPUT_USER_IS_NOT_A_PRIMARY_USER") { + (0, logger_1.logDebugMessage)( + "tryLinkingBySession linking to session user failed because of a race condition - INPUT_USER_IS_NOT_A_PRIMARY_USER, should retry" + ); // This can be possible during a race condition wherein the primary user we created above // is somehow no more a primary user. This can happen if the unlink function was called in parallel // on that user. We can just retry, as that will try and make it a primary user again. return { status: "LINKING_TO_SESSION_USER_FAILED", reason: linkAccountsResult.status }; - } - else { - (0, logger_1.logDebugMessage)("tryLinkingBySession linking to session user failed because of a race condition - input user has another primary user it can be linked to"); + } else { + (0, logger_1.logDebugMessage)( + "tryLinkingBySession linking to session user failed because of a race condition - input user has another primary user it can be linked to" + ); // Status can only be "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" // It can come here if the recipe user ID can't be linked to the primary user ID because the email / phone number is associated with // some other primary user ID. @@ -658,12 +866,10 @@ exports.AuthUtils = { type: error_1.default.UNAUTHORISED, message: "Tenant not found", }); - } - else { + } else { throw new Error("Tenant not found error."); } - } - else if (validRes.status === "OK") { + } else if (validRes.status === "OK") { validFactorIds.push(id); } } @@ -673,11 +879,11 @@ exports.AuthUtils = { type: error_1.default.UNAUTHORISED, message: "A valid session is required to authenticate with secondary factors", }); - } - else { + } else { throw new error_2.default({ type: error_2.default.BAD_INPUT_ERROR, - message: "First factor sign in/up called for a non-first factor with an active session. This might indicate that you are trying to use this as a secondary factor, but disabled account linking.", + message: + "First factor sign in/up called for a non-first factor with an active session. This might indicate that you are trying to use this as a secondary factor, but disabled account linking.", }); } } @@ -685,26 +891,47 @@ exports.AuthUtils = { }, loadSessionInAuthAPIIfNeeded: async function (req, res, shouldTryLinkingWithSessionUser, userContext) { if (shouldTryLinkingWithSessionUser !== false) { - (0, logger_1.logDebugMessage)("loadSessionInAuthAPIIfNeeded: loading session because shouldTryLinkingWithSessionUser is not set to false so we may want to link later"); - return await session_1.default.getSession(req, res, { - // This is optional only if shouldTryLinkingWithSessionUser is undefined - // in the (old) 3.0 FDI, this flag didn't exist and we linking was based on the session presence and shouldDoAutomaticAccountLinking - sessionRequired: shouldTryLinkingWithSessionUser === true, - overrideGlobalClaimValidators: () => [], - }, userContext); + (0, logger_1.logDebugMessage)( + "loadSessionInAuthAPIIfNeeded: loading session because shouldTryLinkingWithSessionUser is not set to false so we may want to link later" + ); + return await session_1.default.getSession( + req, + res, + { + // This is optional only if shouldTryLinkingWithSessionUser is undefined + // in the (old) 3.0 FDI, this flag didn't exist and we linking was based on the session presence and shouldDoAutomaticAccountLinking + sessionRequired: shouldTryLinkingWithSessionUser === true, + overrideGlobalClaimValidators: () => [], + }, + userContext + ); } - (0, logger_1.logDebugMessage)("loadSessionInAuthAPIIfNeeded: skipping session loading because we are not linking and we would overwrite it anyway"); + (0, logger_1.logDebugMessage)( + "loadSessionInAuthAPIIfNeeded: skipping session loading because we are not linking and we would overwrite it anyway" + ); return undefined; }, }; -async function filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid(factorIds, inputUserAlreadyLinkedToSessionUser, sessionUser, session, userContext) { +async function filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid( + factorIds, + inputUserAlreadyLinkedToSessionUser, + sessionUser, + session, + userContext +) { if (session === undefined) { - throw new Error("This should never happen: filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid called without a session"); + throw new Error( + "This should never happen: filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid called without a session" + ); } if (sessionUser === undefined) { - throw new Error("This should never happen: filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid called without a sessionUser"); + throw new Error( + "This should never happen: filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid called without a sessionUser" + ); } - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid called for ${factorIds.join(", ")}`); + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid called for ${factorIds.join(", ")}` + ); const mfaInstance = recipe_2.default.getInstance(); if (mfaInstance !== undefined) { if (!inputUserAlreadyLinkedToSessionUser) { @@ -737,7 +964,9 @@ async function filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid(factorIds, in }; // If we are linking the input user to the session user, then we need to check if MFA allows it // From an MFA perspective this is a factor setup - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid checking if linking is allowed by the mfa recipe`); + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid checking if linking is allowed by the mfa recipe` + ); let caughtSetupFactorError; const validFactorIds = []; // In all apis besides passwordless createCode, we know exactly which factor we are signing into, so in those cases, @@ -748,35 +977,46 @@ async function filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid(factorIds, in // If the flowType for passwordless is USER_INPUT_CODE_AND_MAGIC_LINK and but only the otp-email factor is allowed to be set up // then we do not want to include a link in the email. for (const id of factorIds) { - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid checking assertAllowedToSetupFactorElseThrowInvalidClaimError`); + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid checking assertAllowedToSetupFactorElseThrowInvalidClaimError` + ); try { memoizedAllowedToSetupFactorInput.factorId = id; - await mfaInstance.recipeInterfaceImpl.assertAllowedToSetupFactorElseThrowInvalidClaimError(memoizedAllowedToSetupFactorInput); - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid ${id} valid because assertAllowedToSetupFactorElseThrowInvalidClaimError passed`); + await mfaInstance.recipeInterfaceImpl.assertAllowedToSetupFactorElseThrowInvalidClaimError( + memoizedAllowedToSetupFactorInput + ); + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid ${id} valid because assertAllowedToSetupFactorElseThrowInvalidClaimError passed` + ); // we add it to the valid factor ids list since it is either already set up or allowed to be set up validFactorIds.push(id); - } - catch (err) { - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid assertAllowedToSetupFactorElseThrowInvalidClaimError failed for ${id}`); + } catch (err) { + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid assertAllowedToSetupFactorElseThrowInvalidClaimError failed for ${id}` + ); caughtSetupFactorError = err; } } if (validFactorIds.length === 0) { - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid rethrowing error from assertAllowedToSetupFactorElseThrowInvalidClaimError because we found no valid factors`); + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid rethrowing error from assertAllowedToSetupFactorElseThrowInvalidClaimError because we found no valid factors` + ); // we can safely re-throw this since this should be an InvalidClaimError // if it's anything else, we do not really have a way of handling it anyway. throw caughtSetupFactorError; } return validFactorIds; - } - else { + } else { // If signing in will not change the user (no linking), then we can let the sign-in/up happen (if allowed by account linking checks) - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid allowing all factors because it'll not create new link`); + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid allowing all factors because it'll not create new link` + ); return factorIds; } - } - else { - (0, logger_1.logDebugMessage)(`filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid allowing all factors because MFA is not enabled`); + } else { + (0, logger_1.logDebugMessage)( + `filterOutInvalidSecondFactorsOrThrowIfAllAreInvalid allowing all factors because MFA is not enabled` + ); // If MFA is not enabled, we allow the user to connect any secondary account to the session user. return factorIds; } diff --git a/lib/build/combinedRemoteJWKSet.d.ts b/lib/build/combinedRemoteJWKSet.d.ts index 6545d12d7..482ef4756 100644 --- a/lib/build/combinedRemoteJWKSet.d.ts +++ b/lib/build/combinedRemoteJWKSet.d.ts @@ -15,4 +15,7 @@ export declare function resetCombinedJWKS(): void; */ export declare function getCombinedJWKS(config: { jwksRefreshIntervalSec: number; -}): (protectedHeader?: import("jose").JWSHeaderParameters, token?: import("jose").FlattenedJWSInput) => Promise; +}): ( + protectedHeader?: import("jose").JWSHeaderParameters, + token?: import("jose").FlattenedJWSInput +) => Promise; diff --git a/lib/build/combinedRemoteJWKSet.js b/lib/build/combinedRemoteJWKSet.js index 643a631c3..8ad30f64d 100644 --- a/lib/build/combinedRemoteJWKSet.js +++ b/lib/build/combinedRemoteJWKSet.js @@ -26,21 +26,24 @@ function getCombinedJWKS(config) { if (combinedJWKS === undefined) { const JWKS = querier_1.Querier.getNewInstanceOrThrowError(undefined) .getAllCoreUrlsForPath("/.well-known/jwks.json") - .map((url) => (0, jose_1.createRemoteJWKSet)(new URL(url), { - cacheMaxAge: config.jwksRefreshIntervalSec * 1000, - cooldownDuration: constants_1.JWKCacheCooldownInMs, - })); + .map((url) => + (0, jose_1.createRemoteJWKSet)(new URL(url), { + cacheMaxAge: config.jwksRefreshIntervalSec * 1000, + cooldownDuration: constants_1.JWKCacheCooldownInMs, + }) + ); combinedJWKS = async (...args) => { let lastError = undefined; if (JWKS.length === 0) { - throw Error("No SuperTokens core available to query. Please pass supertokens > connectionURI to the init function, or override all the functions of the recipe you are using."); + throw Error( + "No SuperTokens core available to query. Please pass supertokens > connectionURI to the init function, or override all the functions of the recipe you are using." + ); } for (const jwks of JWKS) { try { // We await before returning to make sure we catch the error return await jwks(...args); - } - catch (ex) { + } catch (ex) { lastError = ex; } } diff --git a/lib/build/customFramework.d.ts b/lib/build/customFramework.d.ts index 9b944d2cb..d7abeb160 100644 --- a/lib/build/customFramework.d.ts +++ b/lib/build/customFramework.d.ts @@ -14,8 +14,12 @@ export interface ParsableRequest { formData: () => Promise; json: () => Promise; } -export declare function getCookieFromRequest(request: RequestType): Record; -export declare function getQueryFromRequest(request: RequestType): Record; +export declare function getCookieFromRequest( + request: RequestType +): Record; +export declare function getQueryFromRequest( + request: RequestType +): Record; export declare function handleAuthAPIRequest(): (req: Request) => Promise; /** * A helper function to retrieve session details on the server side. @@ -24,15 +28,33 @@ export declare function handleAuthAPIRequest(): (req: Request) => Promise(request: RequestType): Promise<{ +export declare function getSessionForSSR( + request: RequestType +): Promise<{ accessTokenPayload: JWTPayload | undefined; hasToken: boolean; error: Error | undefined; }>; -export declare function getSessionForSSRUsingAccessToken(accessToken: string | undefined): Promise<{ +export declare function getSessionForSSRUsingAccessToken( + accessToken: string | undefined +): Promise<{ accessTokenPayload: JWTPayload | undefined; hasToken: boolean; error: Error | undefined; }>; -export declare function withSession(request: RequestType, handler: (error: Error | undefined, session: SessionContainer | undefined) => Promise, options?: VerifySessionOptions, userContext?: Record): Promise; -export declare function withPreParsedRequestResponse(req: RequestType, handler: (baseRequest: PreParsedRequest, baseResponse: CollectingResponse) => Promise): Promise; +export declare function withSession< + RequestType extends ParsableRequest = Request, + ResponseType extends Response = Response +>( + request: RequestType, + handler: (error: Error | undefined, session: SessionContainer | undefined) => Promise, + options?: VerifySessionOptions, + userContext?: Record +): Promise; +export declare function withPreParsedRequestResponse< + RequestType extends ParsableRequest = Request, + ResponseType extends Response = Response +>( + req: RequestType, + handler: (baseRequest: PreParsedRequest, baseResponse: CollectingResponse) => Promise +): Promise; diff --git a/lib/build/customFramework.js b/lib/build/customFramework.js index b8326afcc..9e2ab68ff 100644 --- a/lib/build/customFramework.js +++ b/lib/build/customFramework.js @@ -4,9 +4,11 @@ * that can be used to easily integrate the SDK with most * frameworks if they are not directly supported. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getCookieFromRequest = getCookieFromRequest; exports.getQueryFromRequest = getQueryFromRequest; @@ -123,12 +125,10 @@ async function getSessionForSSRUsingAccessToken(accessToken) { return { accessTokenPayload: decoded.userData, hasToken, error: undefined }; } return { accessTokenPayload: undefined, hasToken, error: undefined }; - } - catch (error) { + } catch (error) { return { accessTokenPayload: undefined, hasToken, error: undefined }; } - } - catch (error) { + } catch (error) { return { accessTokenPayload: undefined, hasToken, error: error }; } } @@ -138,8 +138,7 @@ async function withSession(request, handler, options, userContext) { const session = await session_1.default.getSession(baseRequest, baseResponse, options, userContext); return handler(undefined, session); }); - } - catch (error) { + } catch (error) { return await handler(error, undefined); } } @@ -149,8 +148,7 @@ async function withPreParsedRequestResponse(req, handler) { let userResponse; try { userResponse = await handler(baseRequest, baseResponse); - } - catch (err) { + } catch (err) { userResponse = await handleError(err, baseRequest, baseResponse); } return addCookies(baseResponse, userResponse); @@ -163,14 +161,17 @@ function addCookies(baseResponse, userResponse) { let didAddHeaders = false; for (const respCookie of baseResponse.cookies) { didAddCookies = true; - userResponse.headers.append("Set-Cookie", (0, cookie_1.serialize)(respCookie.key, respCookie.value, { - domain: respCookie.domain, - expires: new Date(respCookie.expires), - httpOnly: respCookie.httpOnly, - path: respCookie.path, - sameSite: respCookie.sameSite, - secure: respCookie.secure, - })); + userResponse.headers.append( + "Set-Cookie", + (0, cookie_1.serialize)(respCookie.key, respCookie.value, { + domain: respCookie.domain, + expires: new Date(respCookie.expires), + httpOnly: respCookie.httpOnly, + path: respCookie.path, + sameSite: respCookie.sameSite, + secure: respCookie.secure, + }) + ); } baseResponse.headers.forEach((value, key) => { didAddHeaders = true; diff --git a/lib/build/error.d.ts b/lib/build/error.d.ts index 354527199..41083aef0 100644 --- a/lib/build/error.d.ts +++ b/lib/build/error.d.ts @@ -6,14 +6,18 @@ export default class SuperTokensError extends Error { payload: any; fromRecipe: string | undefined; private errMagic; - constructor(options: { - message: string; - payload?: any; - type: string; - } | { - message: string; - type: "BAD_INPUT_ERROR"; - payload: undefined; - }); + constructor( + options: + | { + message: string; + payload?: any; + type: string; + } + | { + message: string; + type: "BAD_INPUT_ERROR"; + payload: undefined; + } + ); static isErrorFromSuperTokens(obj: any): obj is SuperTokensError; } diff --git a/lib/build/framework/awsLambda/framework.d.ts b/lib/build/framework/awsLambda/framework.d.ts index c3821dac8..cbbc266ff 100644 --- a/lib/build/framework/awsLambda/framework.d.ts +++ b/lib/build/framework/awsLambda/framework.d.ts @@ -1,5 +1,11 @@ // @ts-nocheck -import type { APIGatewayProxyEventV2, APIGatewayProxyEvent, APIGatewayProxyResult, APIGatewayProxyStructuredResultV2, Handler } from "aws-lambda"; +import type { + APIGatewayProxyEventV2, + APIGatewayProxyEvent, + APIGatewayProxyResult, + APIGatewayProxyStructuredResultV2, + Handler, +} from "aws-lambda"; import { HTTPMethod } from "../../types"; import { BaseRequest } from "../request"; import { BaseResponse } from "../response"; @@ -50,13 +56,24 @@ export declare class AWSResponse extends BaseResponse { sendHTMLResponse: (html: string) => void; setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; removeHeader: (key: string) => void; - setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; /** * @param {number} statusCode */ setStatusCode: (statusCode: number) => void; sendJSONResponse: (content: any) => void; - sendResponse: (response?: APIGatewayProxyResult | APIGatewayProxyStructuredResultV2) => APIGatewayProxyResult | APIGatewayProxyStructuredResultV2; + sendResponse: ( + response?: APIGatewayProxyResult | APIGatewayProxyStructuredResultV2 + ) => APIGatewayProxyResult | APIGatewayProxyStructuredResultV2; } export interface SessionEventV2 extends SupertokensLambdaEventV2 { session?: SessionContainerInterface; diff --git a/lib/build/framework/awsLambda/framework.js b/lib/build/framework/awsLambda/framework.js index 51bd56b2f..aea3638c5 100644 --- a/lib/build/framework/awsLambda/framework.js +++ b/lib/build/framework/awsLambda/framework.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AWSWrapper = exports.middleware = exports.AWSResponse = exports.AWSRequest = void 0; const utils_1 = require("../../utils"); @@ -17,13 +19,11 @@ class AWSRequest extends request_1.BaseRequest { this.getFormDataFromRequestBody = async () => { if (this.event.body === null || this.event.body === undefined) { return {}; - } - else { + } else { try { const parsedUrlEncodedFormData = Object.fromEntries(new URLSearchParams(this.event.body).entries()); return parsedUrlEncodedFormData === undefined ? {} : parsedUrlEncodedFormData; - } - catch (err) { + } catch (err) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, message: "API input error: Please make sure to pass valid url encoded form in the request body", @@ -34,8 +34,7 @@ class AWSRequest extends request_1.BaseRequest { this.getJSONFromRequestBody = async () => { if (this.event.body === null || this.event.body === undefined) { return {}; - } - else { + } else { const parsedJSONBody = JSON.parse(this.event.body); return parsedJSONBody === undefined ? {} : parsedJSONBody; } @@ -59,15 +58,20 @@ class AWSRequest extends request_1.BaseRequest { }; this.getCookieValue = (key) => { let cookies = this.event.cookies; - if ((this.event.headers === undefined || this.event.headers === null) && - (cookies === undefined || cookies === null)) { + if ( + (this.event.headers === undefined || this.event.headers === null) && + (cookies === undefined || cookies === null) + ) { return undefined; } let value = (0, utils_2.getCookieValueFromHeaders)(this.event.headers, key); if (value === undefined && cookies !== undefined && cookies !== null) { - value = (0, utils_2.getCookieValueFromHeaders)({ - cookie: cookies.join(";"), - }, key); + value = (0, utils_2.getCookieValueFromHeaders)( + { + cookie: cookies.join(";"), + }, + key + ); } return value; }; @@ -75,7 +79,9 @@ class AWSRequest extends request_1.BaseRequest { if (this.event.headers === undefined || this.event.headers === null) { return undefined; } - return (0, utils_2.normalizeHeaderValue)((0, utils_1.getFromObjectCaseInsensitive)(key, this.event.headers)); + return (0, utils_2.normalizeHeaderValue)( + (0, utils_1.getFromObjectCaseInsensitive)(key, this.event.headers) + ); }; this.getOriginalURL = () => { let path = this.event.path; @@ -118,10 +124,21 @@ class AWSResponse extends response_1.BaseResponse { }); }; this.removeHeader = (key) => { - this.event.supertokens.response.headers = this.event.supertokens.response.headers.filter((header) => header.key.toLowerCase() !== key.toLowerCase()); + this.event.supertokens.response.headers = this.event.supertokens.response.headers.filter( + (header) => header.key.toLowerCase() !== key.toLowerCase() + ); }; this.setCookie = (key, value, domain, secure, httpOnly, expires, path, sameSite) => { - let serialisedCookie = (0, utils_2.serializeCookieValue)(key, value, domain, secure, httpOnly, expires, path, sameSite); + let serialisedCookie = (0, utils_2.serializeCookieValue)( + key, + value, + domain, + secure, + httpOnly, + expires, + path, + sameSite + ); this.event.supertokens.response.cookies = [ ...this.event.supertokens.response.cookies.filter((c) => !c.startsWith(key + "=")), serialisedCookie, @@ -175,13 +192,14 @@ class AWSResponse extends response_1.BaseResponse { For example if the caller is trying to add front token to the access control exposed headers property we do not want to append if something else had already added it */ - if (typeof currentValue !== "string" || - !currentValue.includes(supertokensHeaders[i].value.toString())) { + if ( + typeof currentValue !== "string" || + !currentValue.includes(supertokensHeaders[i].value.toString()) + ) { let newValue = `${currentValue}, ${supertokensHeaders[i].value}`; headers[supertokensHeaders[i].key] = newValue; } - } - else { + } else { headers[supertokensHeaders[i].key] = supertokensHeaders[i].value; } } @@ -191,26 +209,28 @@ class AWSResponse extends response_1.BaseResponse { cookies = []; } cookies.push(...supertokensCookies); - let result = Object.assign(Object.assign({}, response), { cookies, - body, - statusCode, - headers }); + let result = Object.assign(Object.assign({}, response), { cookies, body, statusCode, headers }); return result; - } - else { + } else { let multiValueHeaders = response.multiValueHeaders; if (multiValueHeaders === undefined) { multiValueHeaders = {}; } let headsersInMultiValueHeaders = Object.keys(multiValueHeaders); - let cookieHeader = headsersInMultiValueHeaders.find((h) => h.toLowerCase() === constants_1.COOKIE_HEADER.toLowerCase()); + let cookieHeader = headsersInMultiValueHeaders.find( + (h) => h.toLowerCase() === constants_1.COOKIE_HEADER.toLowerCase() + ); if (cookieHeader === undefined) { multiValueHeaders[constants_1.COOKIE_HEADER] = supertokensCookies; - } - else { + } else { multiValueHeaders[cookieHeader].push(...supertokensCookies); } - let result = Object.assign(Object.assign({}, response), { multiValueHeaders, body: body, statusCode: statusCode, headers }); + let result = Object.assign(Object.assign({}, response), { + multiValueHeaders, + body: body, + statusCode: statusCode, + headers, + }); return result; } }; @@ -253,8 +273,7 @@ const middleware = (handler) => { error: `The middleware couldn't serve the API path ${request.getOriginalURL()}, method: ${request.getMethod()}. If this is an unexpected behaviour, please create an issue here: https://github.com/supertokens/supertokens-node/issues`, }); return response.sendResponse(); - } - catch (err) { + } catch (err) { await supertokens.errorHandler(err, request, response, userContext); if (response.responseSet) { return response.sendResponse(); diff --git a/lib/build/framework/constants.d.ts b/lib/build/framework/constants.d.ts index e9b796f53..79db4b944 100644 --- a/lib/build/framework/constants.d.ts +++ b/lib/build/framework/constants.d.ts @@ -1,3 +1,4 @@ // @ts-nocheck export declare const COOKIE_HEADER = "Set-Cookie"; -export declare const BROTLI_DECOMPRESSION_ERROR_MESSAGE = "Brotli decompression not implement, Please add a middleware that handles decompression before the SuperTokens middleware."; +export declare const BROTLI_DECOMPRESSION_ERROR_MESSAGE = + "Brotli decompression not implement, Please add a middleware that handles decompression before the SuperTokens middleware."; diff --git a/lib/build/framework/constants.js b/lib/build/framework/constants.js index ae0e26999..1038b6933 100644 --- a/lib/build/framework/constants.js +++ b/lib/build/framework/constants.js @@ -17,4 +17,5 @@ exports.BROTLI_DECOMPRESSION_ERROR_MESSAGE = exports.COOKIE_HEADER = void 0; */ exports.COOKIE_HEADER = "Set-Cookie"; // Define error message for brotli decompression not being supported -exports.BROTLI_DECOMPRESSION_ERROR_MESSAGE = "Brotli decompression not implement, Please add a middleware that handles decompression before the SuperTokens middleware."; +exports.BROTLI_DECOMPRESSION_ERROR_MESSAGE = + "Brotli decompression not implement, Please add a middleware that handles decompression before the SuperTokens middleware."; diff --git a/lib/build/framework/custom/framework.d.ts b/lib/build/framework/custom/framework.d.ts index b1dbf6ff5..02374da39 100644 --- a/lib/build/framework/custom/framework.d.ts +++ b/lib/build/framework/custom/framework.d.ts @@ -46,7 +46,16 @@ export declare class CollectingResponse extends BaseResponse { sendHTMLResponse: (html: string) => void; setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; removeHeader: (key: string) => void; - setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; /** * @param {number} statusCode */ @@ -54,22 +63,47 @@ export declare class CollectingResponse extends BaseResponse { sendJSONResponse: (content: any) => void; } export type NextFunction = (err?: any) => void; -export declare const middleware: (wrapRequest?: (req: OrigReqType) => BaseRequest, wrapResponse?: (req: OrigRespType) => BaseResponse) => (request: OrigReqType, response: OrigRespType, next?: NextFunction) => Promise<{ - handled: boolean; - error?: undefined; -} | { - error: any; - handled?: undefined; -}>; -export declare const errorHandler: () => (err: any, request: BaseRequest, response: BaseResponse, next: NextFunction) => Promise; +export declare const middleware: ( + wrapRequest?: (req: OrigReqType) => BaseRequest, + wrapResponse?: (req: OrigRespType) => BaseResponse +) => ( + request: OrigReqType, + response: OrigRespType, + next?: NextFunction +) => Promise< + | { + handled: boolean; + error?: undefined; + } + | { + error: any; + handled?: undefined; + } +>; +export declare const errorHandler: () => ( + err: any, + request: BaseRequest, + response: BaseResponse, + next: NextFunction +) => Promise; export declare const CustomFrameworkWrapper: { - middleware: (wrapRequest?: (req: OrigReqType) => BaseRequest, wrapResponse?: (req: OrigRespType) => BaseResponse) => (request: OrigReqType, response: OrigRespType, next?: NextFunction) => Promise<{ - handled: boolean; - error?: undefined; - } | { - error: any; - handled?: undefined; - }>; + middleware: ( + wrapRequest?: (req: OrigReqType) => BaseRequest, + wrapResponse?: (req: OrigRespType) => BaseResponse + ) => ( + request: OrigReqType, + response: OrigRespType, + next?: NextFunction + ) => Promise< + | { + handled: boolean; + error?: undefined; + } + | { + error: any; + handled?: undefined; + } + >; errorHandler: () => (err: any, request: BaseRequest, response: BaseResponse, next: NextFunction) => Promise; }; export {}; diff --git a/lib/build/framework/custom/framework.js b/lib/build/framework/custom/framework.js index b9f4c61f5..6999891c8 100644 --- a/lib/build/framework/custom/framework.js +++ b/lib/build/framework/custom/framework.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CustomFrameworkWrapper = exports.errorHandler = exports.middleware = exports.CollectingResponse = exports.PreParsedRequest = void 0; const utils_1 = require("../../utils"); @@ -87,8 +89,7 @@ class CollectingResponse extends response_1.BaseResponse { if (!((_a = this.headers.get(key)) === null || _a === void 0 ? void 0 : _a.includes(value))) { this.headers.append(key, value); } - } - else { + } else { this.headers.set(key, value); } }; @@ -112,8 +113,7 @@ class CollectingResponse extends response_1.BaseResponse { // Still, if available we are using the built-in (node 18+) if (typeof Headers === "undefined") { this.headers = new nodeHeaders_1.default(null); - } - else { + } else { this.headers = new Headers(); } this.statusCode = 200; @@ -138,21 +138,18 @@ const middleware = (wrapRequest = identity, wrapResponse = identity) => { return { handled: false }; } return { handled: true }; - } - catch (err) { + } catch (err) { if (supertokens) { try { await supertokens.errorHandler(err, wrappedReq, wrappedResp, userContext); return { handled: true }; - } - catch (_a) { + } catch (_a) { if (next) { next(err); } return { error: err }; } - } - else { + } else { if (next) { next(err); } @@ -169,8 +166,7 @@ const errorHandler = () => { try { await supertokens.errorHandler(err, request, response, userContext); return next(); - } - catch (err) { + } catch (err) { return next(err); } }; diff --git a/lib/build/framework/custom/index.d.ts b/lib/build/framework/custom/index.d.ts index e7390aec6..f7935dcc6 100644 --- a/lib/build/framework/custom/index.d.ts +++ b/lib/build/framework/custom/index.d.ts @@ -1,10 +1,25 @@ // @ts-nocheck export { PreParsedRequest, CollectingResponse } from "./framework"; -export declare const middleware: (wrapRequest?: (req: OrigReqType) => import("..").BaseRequest, wrapResponse?: (req: OrigRespType) => import("..").BaseResponse) => (request: OrigReqType, response: OrigRespType, next?: import("./framework").NextFunction) => Promise<{ - handled: boolean; - error?: undefined; -} | { - error: any; - handled?: undefined; -}>; -export declare const errorHandler: () => (err: any, request: import("..").BaseRequest, response: import("..").BaseResponse, next: import("./framework").NextFunction) => Promise; +export declare const middleware: ( + wrapRequest?: (req: OrigReqType) => import("..").BaseRequest, + wrapResponse?: (req: OrigRespType) => import("..").BaseResponse +) => ( + request: OrigReqType, + response: OrigRespType, + next?: import("./framework").NextFunction +) => Promise< + | { + handled: boolean; + error?: undefined; + } + | { + error: any; + handled?: undefined; + } +>; +export declare const errorHandler: () => ( + err: any, + request: import("..").BaseRequest, + response: import("..").BaseResponse, + next: import("./framework").NextFunction +) => Promise; diff --git a/lib/build/framework/custom/index.js b/lib/build/framework/custom/index.js index acd4ab523..31170e351 100644 --- a/lib/build/framework/custom/index.js +++ b/lib/build/framework/custom/index.js @@ -17,7 +17,17 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.errorHandler = exports.middleware = exports.CollectingResponse = exports.PreParsedRequest = void 0; const framework_1 = require("./framework"); var framework_2 = require("./framework"); -Object.defineProperty(exports, "PreParsedRequest", { enumerable: true, get: function () { return framework_2.PreParsedRequest; } }); -Object.defineProperty(exports, "CollectingResponse", { enumerable: true, get: function () { return framework_2.CollectingResponse; } }); +Object.defineProperty(exports, "PreParsedRequest", { + enumerable: true, + get: function () { + return framework_2.PreParsedRequest; + }, +}); +Object.defineProperty(exports, "CollectingResponse", { + enumerable: true, + get: function () { + return framework_2.CollectingResponse; + }, +}); exports.middleware = framework_1.CustomFrameworkWrapper.middleware; exports.errorHandler = framework_1.CustomFrameworkWrapper.errorHandler; diff --git a/lib/build/framework/custom/nodeHeaders.js b/lib/build/framework/custom/nodeHeaders.js index dfcd01a69..912319a02 100644 --- a/lib/build/framework/custom/nodeHeaders.js +++ b/lib/build/framework/custom/nodeHeaders.js @@ -57,19 +57,16 @@ class Headers extends URLSearchParams { for (const [name, values] of Object.entries(raw)) { result.push(...values.map((value) => [name, value])); } - } - else if (init == null) { + } else if (init == null) { // eslint-disable-line no-eq-null, eqeqeq // No op - } - else if (typeof init === "object" && !(0, utils_1.isBoxedPrimitive)(init)) { + } else if (typeof init === "object" && !(0, utils_1.isBoxedPrimitive)(init)) { const method = init[Symbol.iterator]; // eslint-disable-next-line no-eq-null, eqeqeq if (method == null) { // Record result.push(...Object.entries(init)); - } - else { + } else { if (typeof method !== "function") { throw new TypeError("Header pairs must be iterable"); } @@ -77,30 +74,31 @@ class Headers extends URLSearchParams { // Note: per spec we have to first exhaust the lists then process them result = [...init] .map((pair) => { - if (typeof pair !== "object" || (0, utils_1.isBoxedPrimitive)(pair)) { - throw new TypeError("Each header pair must be an iterable object"); - } - return [...pair]; - }) + if (typeof pair !== "object" || (0, utils_1.isBoxedPrimitive)(pair)) { + throw new TypeError("Each header pair must be an iterable object"); + } + return [...pair]; + }) .map((pair) => { - if (pair.length !== 2) { - throw new TypeError("Each header pair must be a name/value tuple"); - } - return [...pair]; - }); + if (pair.length !== 2) { + throw new TypeError("Each header pair must be a name/value tuple"); + } + return [...pair]; + }); } - } - else { - throw new TypeError("Failed to construct 'Headers': The provided value is not of type '(sequence> or record)"); + } else { + throw new TypeError( + "Failed to construct 'Headers': The provided value is not of type '(sequence> or record)" + ); } // Validate and lowercase result = result.length > 0 ? result.map(([name, value]) => { - validateHeaderName(name); - validateHeaderValue(name, String(value)); - return [String(name).toLowerCase(), String(value)]; - }) + validateHeaderName(name); + validateHeaderValue(name, String(value)); + return [String(name).toLowerCase(), String(value)]; + }) : undefined; super(result); // Returning a Proxy that will lowercase key names, validate parameters and sort keys @@ -113,7 +111,11 @@ class Headers extends URLSearchParams { return (name, value) => { validateHeaderName(name); validateHeaderValue(name, String(value)); - return URLSearchParams.prototype[p].call(receiver, String(name).toLowerCase(), String(value)); + return URLSearchParams.prototype[p].call( + receiver, + String(name).toLowerCase(), + String(value) + ); }; case "delete": case "has": @@ -193,8 +195,7 @@ class Headers extends URLSearchParams { // This hack makes specifying custom Host header possible. if (key === "host") { result[key] = values[0]; - } - else { + } else { result[key] = values.length > 1 ? values : values[0]; } return result; @@ -206,32 +207,36 @@ exports.default = Headers; * Re-shaping object for Web IDL tests * Only need to do it for overridden methods */ -Object.defineProperties(Headers.prototype, ["get", "entries", "forEach", "values"].reduce((result, property) => { - result[property] = { enumerable: true }; - return result; -}, {})); +Object.defineProperties( + Headers.prototype, + ["get", "entries", "forEach", "values"].reduce((result, property) => { + result[property] = { enumerable: true }; + return result; + }, {}) +); /** * Create a Headers object from an http.IncomingMessage.rawHeaders, ignoring those that do * not conform to HTTP grammar productions. * @param {import('http').IncomingMessage['rawHeaders']} headers */ function fromRawHeaders(headers = []) { - return new Headers(headers - // Split into pairs - .reduce((result, value, index, array) => { - if (index % 2 === 0) { - result.push(array.slice(index, index + 2)); - } - return result; - }, []) - .filter(([name, value]) => { - try { - validateHeaderName(name); - validateHeaderValue(name, String(value)); - return true; - } - catch (_a) { - return false; - } - })); + return new Headers( + headers + // Split into pairs + .reduce((result, value, index, array) => { + if (index % 2 === 0) { + result.push(array.slice(index, index + 2)); + } + return result; + }, []) + .filter(([name, value]) => { + try { + validateHeaderName(name); + validateHeaderValue(name, String(value)); + return true; + } catch (_a) { + return false; + } + }) + ); } diff --git a/lib/build/framework/express/framework.d.ts b/lib/build/framework/express/framework.d.ts index b98f2fbe6..40cbcad7b 100644 --- a/lib/build/framework/express/framework.d.ts +++ b/lib/build/framework/express/framework.d.ts @@ -23,7 +23,16 @@ export declare class ExpressResponse extends BaseResponse { sendHTMLResponse: (html: string) => void; setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; removeHeader: (key: string) => void; - setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; /** * @param {number} statusCode */ diff --git a/lib/build/framework/express/framework.js b/lib/build/framework/express/framework.js index 4e17824c5..01527b4d3 100644 --- a/lib/build/framework/express/framework.js +++ b/lib/build/framework/express/framework.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExpressWrapper = exports.errorHandler = exports.middleware = exports.ExpressResponse = exports.ExpressRequest = void 0; const utils_1 = require("../../utils"); @@ -84,7 +86,17 @@ class ExpressResponse extends response_1.BaseResponse { this.response.removeHeader(key); }; this.setCookie = (key, value, domain, secure, httpOnly, expires, path, sameSite) => { - (0, utils_2.setCookieForServerResponse)(this.response, key, value, domain, secure, httpOnly, expires, path, sameSite); + (0, utils_2.setCookieForServerResponse)( + this.response, + key, + value, + domain, + secure, + httpOnly, + expires, + path, + sameSite + ); }; /** * @param {number} statusCode @@ -117,17 +129,14 @@ const middleware = () => { if (!result) { return next(); } - } - catch (err) { + } catch (err) { if (supertokens) { try { await supertokens.errorHandler(err, request, response, userContext); - } - catch (_a) { + } catch (_a) { next(err); } - } - else { + } else { next(err); } } @@ -142,8 +151,7 @@ const errorHandler = () => { const userContext = (0, utils_1.makeDefaultUserContextFromAPI)(request); try { await supertokens.errorHandler(err, request, response, userContext); - } - catch (err) { + } catch (err) { return next(err); } }; diff --git a/lib/build/framework/express/index.d.ts b/lib/build/framework/express/index.d.ts index 8ff22112c..9bf873aa2 100644 --- a/lib/build/framework/express/index.d.ts +++ b/lib/build/framework/express/index.d.ts @@ -1,6 +1,15 @@ // @ts-nocheck export type { SessionRequest } from "./framework"; -export declare const middleware: () => (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => Promise; -export declare const errorHandler: () => (err: any, req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => Promise; +export declare const middleware: () => ( + req: import("express").Request, + res: import("express").Response, + next: import("express").NextFunction +) => Promise; +export declare const errorHandler: () => ( + err: any, + req: import("express").Request, + res: import("express").Response, + next: import("express").NextFunction +) => Promise; export declare const wrapRequest: (unwrapped: any) => import("..").BaseRequest; export declare const wrapResponse: (unwrapped: any) => import("..").BaseResponse; diff --git a/lib/build/framework/fastify/framework.d.ts b/lib/build/framework/fastify/framework.d.ts index 977a93ac1..29b8a93d2 100644 --- a/lib/build/framework/fastify/framework.d.ts +++ b/lib/build/framework/fastify/framework.d.ts @@ -23,7 +23,16 @@ export declare class FastifyResponse extends BaseResponse { sendHTMLResponse: (html: string) => void; setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; removeHeader: (key: string) => void; - setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; /** * @param {number} statusCode */ diff --git a/lib/build/framework/fastify/framework.js b/lib/build/framework/fastify/framework.js index 855e8e5b7..9b9d4c5d3 100644 --- a/lib/build/framework/fastify/framework.js +++ b/lib/build/framework/fastify/framework.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FastifyWrapper = exports.errorHandler = exports.FastifyResponse = exports.FastifyRequest = void 0; const utils_1 = require("../../utils"); @@ -50,7 +52,9 @@ class FastifyRequest extends request_1.BaseRequest { return (0, utils_2.getCookieValueFromHeaders)(this.request.headers, key); }; this.getHeaderValue = (key) => { - return (0, utils_2.normalizeHeaderValue)((0, utils_1.getFromObjectCaseInsensitive)(key, this.request.headers)); + return (0, utils_2.normalizeHeaderValue)( + (0, utils_1.getFromObjectCaseInsensitive)(key, this.request.headers) + ); }; this.getOriginalURL = () => { return this.request.url; @@ -76,8 +80,7 @@ class FastifyResponse extends response_1.BaseResponse { // we have the this.response.header for compatibility with nextJS if (existingValue === undefined) { this.response.header(key, value); - } - else if (allowDuplicateKey) { + } else if (allowDuplicateKey) { /** We only want to append if it does not already exist For example if the caller is trying to add front token to the access control exposed headers property @@ -86,13 +89,11 @@ class FastifyResponse extends response_1.BaseResponse { if (typeof existingValue !== "string" || !existingValue.includes(value)) { this.response.header(key, existingValue + ", " + value); } - } - else { + } else { // we overwrite the current one with the new one this.response.header(key, value); } - } - catch (err) { + } catch (err) { throw new Error("Error while setting header with key: " + key + " and value: " + value); } }; @@ -100,12 +101,19 @@ class FastifyResponse extends response_1.BaseResponse { this.response.removeHeader(key); }; this.setCookie = (key, value, domain, secure, httpOnly, expires, path, sameSite) => { - let serialisedCookie = (0, utils_2.serializeCookieValue)(key, value, domain, secure, httpOnly, expires, path, sameSite); + let serialisedCookie = (0, utils_2.serializeCookieValue)( + key, + value, + domain, + secure, + httpOnly, + expires, + path, + sameSite + ); let oldHeaders = this.response.getHeader(constants_1.COOKIE_HEADER); - if (oldHeaders === undefined) - oldHeaders = []; - else if (!(oldHeaders instanceof Array)) - oldHeaders = [oldHeaders.toString()]; + if (oldHeaders === undefined) oldHeaders = []; + else if (!(oldHeaders instanceof Array)) oldHeaders = [oldHeaders.toString()]; this.response.removeHeader(constants_1.COOKIE_HEADER); this.response.header(constants_1.COOKIE_HEADER, [ ...oldHeaders.filter((h) => !h.startsWith(key + "=")), @@ -143,8 +151,7 @@ function plugin(fastify, _, done) { const userContext = (0, utils_1.makeDefaultUserContextFromAPI)(request); try { await supertokens.middleware(request, response, userContext); - } - catch (err) { + } catch (err) { await supertokens.errorHandler(err, request, response, userContext); } }); diff --git a/lib/build/framework/fastify/index.d.ts b/lib/build/framework/fastify/index.d.ts index 298385da8..b8cc44a0e 100644 --- a/lib/build/framework/fastify/index.d.ts +++ b/lib/build/framework/fastify/index.d.ts @@ -1,6 +1,10 @@ // @ts-nocheck export type { SessionRequest } from "./framework"; export declare const plugin: import("./types").FastifyPluginCallback; -export declare const errorHandler: () => (err: any, req: import("./types").FastifyRequest, res: import("./types").FastifyReply) => Promise; +export declare const errorHandler: () => ( + err: any, + req: import("./types").FastifyRequest, + res: import("./types").FastifyReply +) => Promise; export declare const wrapRequest: (unwrapped: any) => import("..").BaseRequest; export declare const wrapResponse: (unwrapped: any) => import("..").BaseResponse; diff --git a/lib/build/framework/fastify/types.d.ts b/lib/build/framework/fastify/types.d.ts index 6bbe029c1..5927fbaef 100644 --- a/lib/build/framework/fastify/types.d.ts +++ b/lib/build/framework/fastify/types.d.ts @@ -19,7 +19,15 @@ export interface FastifyReply { getHeader(key: any): number | string | string[] | undefined; type(contentType: string): FastifyReply; } -export interface FastifyInstance { +export interface FastifyInstance< + Instance = unknown, + Request extends FastifyRequest = FastifyRequest, + Reply extends FastifyReply = FastifyReply +> { addHook(this: Instance, name: string, hook: (req: Request, reply: Reply) => void): Instance; } -export type FastifyPluginCallback = (instance: Instance, opts: unknown, done: (err?: Error) => void) => void; +export type FastifyPluginCallback = ( + instance: Instance, + opts: unknown, + done: (err?: Error) => void +) => void; diff --git a/lib/build/framework/hapi/framework.d.ts b/lib/build/framework/hapi/framework.d.ts index 9cbdd0324..c7dafc2da 100644 --- a/lib/build/framework/hapi/framework.d.ts +++ b/lib/build/framework/hapi/framework.d.ts @@ -17,7 +17,12 @@ export declare class HapiRequest extends BaseRequest { getOriginalURL: () => string; } export interface ExtendedResponseToolkit extends ResponseToolkit { - lazyHeaderBindings: (h: ResponseToolkit, key: string, value: string | undefined, allowDuplicateKey: boolean) => void; + lazyHeaderBindings: ( + h: ResponseToolkit, + key: string, + value: string | undefined, + allowDuplicateKey: boolean + ) => void; } export declare class HapiResponse extends BaseResponse { private response; @@ -29,7 +34,16 @@ export declare class HapiResponse extends BaseResponse { sendHTMLResponse: (html: string) => void; setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; removeHeader: (key: string) => void; - setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; /** * @param {number} statusCode */ diff --git a/lib/build/framework/hapi/framework.js b/lib/build/framework/hapi/framework.js index 296e26a08..2d4caed3d 100644 --- a/lib/build/framework/hapi/framework.js +++ b/lib/build/framework/hapi/framework.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HapiWrapper = exports.HapiResponse = exports.HapiRequest = void 0; const utils_1 = require("../../utils"); @@ -73,8 +75,7 @@ class HapiResponse extends response_1.BaseResponse { this.setHeader = (key, value, allowDuplicateKey) => { try { this.response.lazyHeaderBindings(this.response, key, value, allowDuplicateKey); - } - catch (err) { + } catch (err) { throw new Error("Error while setting header with key: " + key + " and value: " + value); } }; @@ -89,12 +90,11 @@ class HapiResponse extends response_1.BaseResponse { path: path, domain, ttl: expires - now, - isSameSite: (sameSite === "lax" ? "Lax" : sameSite === "none" ? "None" : "Strict"), + isSameSite: sameSite === "lax" ? "Lax" : sameSite === "none" ? "None" : "Strict", }; if (expires > now) { this.response.state(key, value, cookieOptions); - } - else { + } else { this.response.unstate(key, cookieOptions); } }; @@ -149,8 +149,7 @@ const plugin = { (request.app.lazyHeaders || []).forEach(({ key, value, allowDuplicateKey }) => { if (request.response.isBoom) { request.response.output.headers[key] = value; - } - else { + } else { request.response.header(key, value, { append: allowDuplicateKey }); } }); @@ -170,8 +169,7 @@ const plugin = { return resObj.takeover(); } return h.continue; - } - catch (e) { + } catch (e) { return h.continue; } } @@ -182,9 +180,10 @@ const plugin = { const anyApp = h.request.app; anyApp.lazyHeaders = anyApp.lazyHeaders || []; if (value === undefined) { - anyApp.lazyHeaders = anyApp.lazyHeaders.filter((header) => header.key.toLowerCase() !== key.toLowerCase()); - } - else { + anyApp.lazyHeaders = anyApp.lazyHeaders.filter( + (header) => header.key.toLowerCase() !== key.toLowerCase() + ); + } else { anyApp.lazyHeaders.push({ key, value, allowDuplicateKey }); } }); diff --git a/lib/build/framework/index.js b/lib/build/framework/index.js index 7bac42c57..0b0db4217 100644 --- a/lib/build/framework/index.js +++ b/lib/build/framework/index.js @@ -1,37 +1,56 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); + })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.awsLambda = exports.koa = exports.loopback = exports.hapi = exports.fastify = exports.express = exports.BaseResponse = exports.BaseRequest = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -49,9 +68,19 @@ exports.awsLambda = exports.koa = exports.loopback = exports.hapi = exports.fast * under the License. */ var request_1 = require("./request"); -Object.defineProperty(exports, "BaseRequest", { enumerable: true, get: function () { return request_1.BaseRequest; } }); +Object.defineProperty(exports, "BaseRequest", { + enumerable: true, + get: function () { + return request_1.BaseRequest; + }, +}); var response_1 = require("./response"); -Object.defineProperty(exports, "BaseResponse", { enumerable: true, get: function () { return response_1.BaseResponse; } }); +Object.defineProperty(exports, "BaseResponse", { + enumerable: true, + get: function () { + return response_1.BaseResponse; + }, +}); const expressFramework = __importStar(require("./express")); const fastifyFramework = __importStar(require("./fastify")); const hapiFramework = __importStar(require("./hapi")); diff --git a/lib/build/framework/koa/framework.d.ts b/lib/build/framework/koa/framework.d.ts index 1df307ab7..a9dff8f43 100644 --- a/lib/build/framework/koa/framework.d.ts +++ b/lib/build/framework/koa/framework.d.ts @@ -24,7 +24,16 @@ export declare class KoaResponse extends BaseResponse { sendHTMLResponse: (html: string) => void; setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; removeHeader: (key: string) => void; - setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; /** * @param {number} statusCode */ diff --git a/lib/build/framework/koa/framework.js b/lib/build/framework/koa/framework.js index c06d81622..844635622 100644 --- a/lib/build/framework/koa/framework.js +++ b/lib/build/framework/koa/framework.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.KoaWrapper = exports.middleware = exports.KoaResponse = exports.KoaRequest = void 0; const utils_1 = require("../../utils"); @@ -78,8 +80,7 @@ class KoaResponse extends response_1.BaseResponse { let existingValue = existingHeaders[key.toLowerCase()]; if (existingValue === undefined) { this.ctx.set(key, value); - } - else if (allowDuplicateKey) { + } else if (allowDuplicateKey) { /** We only want to append if it does not already exist For example if the caller is trying to add front token to the access control exposed headers property @@ -88,13 +89,11 @@ class KoaResponse extends response_1.BaseResponse { if (typeof existingValue !== "string" || !existingValue.includes(value)) { this.ctx.set(key, existingValue + ", " + value); } - } - else { + } else { // we overwrite the current one with the new one this.ctx.set(key, value); } - } - catch (err) { + } catch (err) { throw new Error("Error while setting header with key: " + key + " and value: " + value); } }; @@ -143,8 +142,7 @@ const middleware = () => { if (!result) { return await next(); } - } - catch (err) { + } catch (err) { return await supertokens.errorHandler(err, request, response, userContext); } }; diff --git a/lib/build/framework/loopback/framework.d.ts b/lib/build/framework/loopback/framework.d.ts index 1ffe0dba4..12eb9c293 100644 --- a/lib/build/framework/loopback/framework.d.ts +++ b/lib/build/framework/loopback/framework.d.ts @@ -23,7 +23,16 @@ export declare class LoopbackResponse extends BaseResponse { sendHTMLResponse: (html: string) => void; setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; removeHeader: (key: string) => void; - setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; setStatusCode: (statusCode: number) => void; sendJSONResponse: (content: any) => void; } diff --git a/lib/build/framework/loopback/framework.js b/lib/build/framework/loopback/framework.js index 8cf674b25..243931a6e 100644 --- a/lib/build/framework/loopback/framework.js +++ b/lib/build/framework/loopback/framework.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LoopbackWrapper = exports.middleware = exports.LoopbackResponse = exports.LoopbackRequest = void 0; const utils_1 = require("../../utils"); @@ -77,7 +79,17 @@ class LoopbackResponse extends response_1.BaseResponse { this.response.removeHeader(key); }; this.setCookie = (key, value, domain, secure, httpOnly, expires, path, sameSite) => { - (0, utils_2.setCookieForServerResponse)(this.response, key, value, domain, secure, httpOnly, expires, path, sameSite); + (0, utils_2.setCookieForServerResponse)( + this.response, + key, + value, + domain, + secure, + httpOnly, + expires, + path, + sameSite + ); }; this.setStatusCode = (statusCode) => { if (!this.response.writableEnded) { @@ -106,8 +118,7 @@ const middleware = async (ctx, next) => { return await next(); } return; - } - catch (err) { + } catch (err) { return await supertokens.errorHandler(err, request, response, userContext); } }; diff --git a/lib/build/framework/request.js b/lib/build/framework/request.js index c99c91879..edaa6e780 100644 --- a/lib/build/framework/request.js +++ b/lib/build/framework/request.js @@ -46,20 +46,16 @@ class BaseRequest { if (contentType) { if (contentType.startsWith("application/json")) { return await this.getJSONBody(); - } - else if (contentType.startsWith("application/x-www-form-urlencoded")) { + } else if (contentType.startsWith("application/x-www-form-urlencoded")) { return await this.getFormData(); } - } - else { + } else { try { return await this.getJSONBody(); - } - catch (_a) { + } catch (_a) { try { return await this.getFormData(); - } - catch (_b) { + } catch (_b) { throw new Error("Unable to parse body as JSON or Form Data."); } } diff --git a/lib/build/framework/response.d.ts b/lib/build/framework/response.d.ts index 328749bf0..8cf7a67d3 100644 --- a/lib/build/framework/response.d.ts +++ b/lib/build/framework/response.d.ts @@ -5,7 +5,16 @@ export declare abstract class BaseResponse { constructor(); abstract setHeader: (key: string, value: string, allowDuplicateKey: boolean) => void; abstract removeHeader: (key: string) => void; - abstract setCookie: (key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none") => void; + abstract setCookie: ( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" + ) => void; abstract setStatusCode: (statusCode: number) => void; abstract sendJSONResponse: (content: any) => void; abstract sendHTMLResponse: (html: string) => void; diff --git a/lib/build/framework/utils.d.ts b/lib/build/framework/utils.d.ts index eb31479d9..c8af391d3 100644 --- a/lib/build/framework/utils.d.ts +++ b/lib/build/framework/utils.d.ts @@ -9,9 +9,17 @@ export declare function getHeaderValueFromIncomingMessage(request: IncomingMessa export declare function normalizeHeaderValue(value: string | string[] | undefined): string | undefined; export declare function parseJSONBodyFromRequest(req: IncomingMessage): Promise; export declare function parseURLEncodedFormData(req: IncomingMessage): Promise; -export declare function assertThatBodyParserHasBeenUsedForExpressLikeRequest(method: HTTPMethod, request: Request): Promise; +export declare function assertThatBodyParserHasBeenUsedForExpressLikeRequest( + method: HTTPMethod, + request: Request +): Promise; export declare function assertFormDataBodyParserHasBeenUsedForExpressLikeRequest(request: Request): Promise; -export declare function setHeaderForExpressLikeResponse(res: Response, key: string, value: string, allowDuplicateKey: boolean): void; +export declare function setHeaderForExpressLikeResponse( + res: Response, + key: string, + value: string, + allowDuplicateKey: boolean +): void; /** * * @param res @@ -23,7 +31,30 @@ export declare function setHeaderForExpressLikeResponse(res: Response, key: stri * @param expires * @param path */ -export declare function setCookieForServerResponse(res: ServerResponse, key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none"): ServerResponse; -export declare function getCookieValueToSetInHeader(prev: string | string[] | undefined, val: string | string[], key: string): string | string[]; -export declare function serializeCookieValue(key: string, value: string, domain: string | undefined, secure: boolean, httpOnly: boolean, expires: number, path: string, sameSite: "strict" | "lax" | "none"): string; +export declare function setCookieForServerResponse( + res: ServerResponse, + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" +): ServerResponse; +export declare function getCookieValueToSetInHeader( + prev: string | string[] | undefined, + val: string | string[], + key: string +): string | string[]; +export declare function serializeCookieValue( + key: string, + value: string, + domain: string | undefined, + secure: boolean, + httpOnly: boolean, + expires: number, + path: string, + sameSite: "strict" | "lax" | "none" +): string; export declare function isBoxedPrimitive(value: any): boolean; diff --git a/lib/build/framework/utils.js b/lib/build/framework/utils.js index 5fa78657d..554516439 100644 --- a/lib/build/framework/utils.js +++ b/lib/build/framework/utils.js @@ -13,16 +13,43 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __asyncValues = + (this && this.__asyncValues) || + function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], + i; + return m + ? m.call(o) + : ((o = typeof __values === "function" ? __values(o) : o[Symbol.iterator]()), + (i = {}), + verb("next"), + verb("throw"), + verb("return"), + (i[Symbol.asyncIterator] = function () { + return this; + }), + i); + function verb(n) { + i[n] = + o[n] && + function (v) { + return new Promise(function (resolve, reject) { + (v = o[n](v)), settle(resolve, reject, v.done, v.value); + }); + }; + } + function settle(resolve, reject, d, v) { + Promise.resolve(v).then(function (v) { + resolve({ value: v, done: d }); + }, reject); + } + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getCookieValueFromHeaders = getCookieValueFromHeaders; exports.getCookieValueFromIncomingMessage = getCookieValueFromIncomingMessage; @@ -53,49 +80,56 @@ async function inflate(stream) { if (encoding === "gzip" || encoding === "deflate") { const inflator = new pako_1.default.Inflate(); try { - for (var _g = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = await stream_1.next(), _a = stream_1_1.done, !_a; _g = true) { + for ( + var _g = true, stream_1 = __asyncValues(stream), stream_1_1; + (stream_1_1 = await stream_1.next()), (_a = stream_1_1.done), !_a; + _g = true + ) { _c = stream_1_1.value; _g = false; const chunk = _c; inflator.push(chunk, false); } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { try { if (!_g && !_a && (_b = stream_1.return)) await _b.call(stream_1); + } finally { + if (e_1) throw e_1.error; } - finally { if (e_1) throw e_1.error; } } if (inflator.err) { throw new Error(`Decompression error: ${inflator.msg}`); } decompressedData = inflator.result; - } - else if (encoding === "br") { + } else if (encoding === "br") { throw new Error(constants_1.BROTLI_DECOMPRESSION_ERROR_MESSAGE); - } - else { + } else { // Handle identity or unsupported encoding decompressedData = (0, utils_1.getBuffer)().concat([]); try { - for (var _h = true, stream_2 = __asyncValues(stream), stream_2_1; stream_2_1 = await stream_2.next(), _d = stream_2_1.done, !_d; _h = true) { + for ( + var _h = true, stream_2 = __asyncValues(stream), stream_2_1; + (stream_2_1 = await stream_2.next()), (_d = stream_2_1.done), !_d; + _h = true + ) { _f = stream_2_1.value; _h = false; const chunk = _f; decompressedData = (0, utils_1.getBuffer)().concat([decompressedData, chunk]); } - } - catch (e_2_1) { e_2 = { error: e_2_1 }; } - finally { + } catch (e_2_1) { + e_2 = { error: e_2_1 }; + } finally { try { if (!_h && !_d && (_e = stream_2.return)) await _e.call(stream_2); + } finally { + if (e_2) throw e_2.error; } - finally { if (e_2) throw e_2.error; } } } - if (typeof decompressedData === "string") - return decompressedData; + if (typeof decompressedData === "string") return decompressedData; return new TextDecoder().decode(decompressedData); } function getCookieValueFromHeaders(headers, key) { @@ -142,8 +176,7 @@ function JSONCookie(str) { } try { return JSON.parse(str.slice(2)); - } - catch (err) { + } catch (err) { return undefined; } } @@ -170,8 +203,7 @@ function JSONCookies(obj) { function getCharset(req) { try { return (content_type_1.default.parse(req).parameters.charset || "").toLowerCase(); - } - catch (e) { + } catch (e) { return undefined; } } @@ -197,12 +229,10 @@ async function parseURLEncodedFormData(req) { if (key in body) { if (body[key] instanceof Array) { body[key].push(val); - } - else { + } else { body[key] = [body[key], val]; } - } - else { + } else { body[key] = val; } } @@ -214,27 +244,25 @@ async function assertThatBodyParserHasBeenUsedForExpressLikeRequest(method, requ if (typeof request.body === "string") { try { request.body = JSON.parse(request.body); - } - catch (err) { + } catch (err) { if (request.body === "") { request.body = {}; - } - else { + } else { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, message: "API input error: Please make sure to pass a valid JSON input in the request body", }); } } - } - else if (request.body === undefined || + } else if ( + request.body === undefined || (0, utils_1.isBuffer)(request.body) || - (Object.keys(request.body).length === 0 && request.readable)) { + (Object.keys(request.body).length === 0 && request.readable) + ) { try { // parsing it again to make sure that the request is parsed atleast once by a json parser request.body = await parseJSONBodyFromRequest(request); - } - catch (err) { + } catch (err) { // If the error message matches the brotli decompression // related error, then throw that error. if (err.message === constants_1.BROTLI_DECOMPRESSION_ERROR_MESSAGE) { @@ -255,27 +283,25 @@ async function assertFormDataBodyParserHasBeenUsedForExpressLikeRequest(request) if (typeof request.body === "string") { try { request.body = Object.fromEntries(new URLSearchParams(request.body).entries()); - } - catch (err) { + } catch (err) { if (request.body === "") { request.body = {}; - } - else { + } else { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, message: "API input error: Please make sure to pass valid url encoded form in the request body", }); } } - } - else if (request.body === undefined || + } else if ( + request.body === undefined || (0, utils_1.isBuffer)(request.body) || - (Object.keys(request.body).length === 0 && request.readable)) { + (Object.keys(request.body).length === 0 && request.readable) + ) { try { // parsing it again to make sure that the request is parsed atleast once by a form data parser request.body = await parseURLEncodedFormData(request); - } - catch (_a) { + } catch (_a) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, message: "API input error: Please make sure to pass valid url encoded form in the request body", @@ -292,12 +318,10 @@ function setHeaderForExpressLikeResponse(res, key, value, allowDuplicateKey) { if (existingValue === undefined) { if (res.header !== undefined) { res.header(key, value); - } - else { + } else { res.setHeader(key, value); } - } - else if (allowDuplicateKey) { + } else if (allowDuplicateKey) { /** We only want to append if it does not already exist For example if the caller is trying to add front token to the access control exposed headers property @@ -306,29 +330,27 @@ function setHeaderForExpressLikeResponse(res, key, value, allowDuplicateKey) { if (typeof existingValue !== "string" || !existingValue.includes(value)) { if (res.header !== undefined) { res.header(key, existingValue + ", " + value); - } - else { + } else { res.setHeader(key, existingValue + ", " + value); } } - } - else { + } else { // we overwrite the current one with the new one if (res.header !== undefined) { res.header(key, value); - } - else { + } else { res.setHeader(key, value); } } - } - catch (err) { - throw new Error("Error while setting header with key: " + - key + - " and value: " + - value + - "\nError: " + - ((_a = err.message) !== null && _a !== void 0 ? _a : err)); + } catch (err) { + throw new Error( + "Error while setting header with key: " + + key + + " and value: " + + value + + "\nError: " + + ((_a = err.message) !== null && _a !== void 0 ? _a : err) + ); } } /** @@ -343,7 +365,12 @@ function setHeaderForExpressLikeResponse(res, key, value, allowDuplicateKey) { * @param path */ function setCookieForServerResponse(res, key, value, domain, secure, httpOnly, expires, path, sameSite) { - return appendToServerResponse(res, constants_1.COOKIE_HEADER, serializeCookieValue(key, value, domain, secure, httpOnly, expires, path, sameSite), key); + return appendToServerResponse( + res, + constants_1.COOKIE_HEADER, + serializeCookieValue(key, value, domain, secure, httpOnly, expires, path, sameSite), + key + ); } /** * Append additional header `field` with value `val`. @@ -374,8 +401,7 @@ function getCookieValueToSetInHeader(prev, val, key) { } } prev = removedDuplicate; - } - else { + } else { if (prev.startsWith(key)) { prev = undefined; } diff --git a/lib/build/index.d.ts b/lib/build/index.d.ts index 3c4474bef..2bbc7017d 100644 --- a/lib/build/index.d.ts +++ b/lib/build/index.d.ts @@ -11,7 +11,11 @@ export default class SuperTokensWrapper { static RecipeUserId: typeof RecipeUserId; static User: typeof User; static getAllCORSHeaders(): string[]; - static getUserCount(includeRecipeIds?: string[], tenantId?: string, userContext?: Record): Promise; + static getUserCount( + includeRecipeIds?: string[], + tenantId?: string, + userContext?: Record + ): Promise; static getUsersOldestFirst(input: { tenantId: string; limit?: number; @@ -44,25 +48,31 @@ export default class SuperTokensWrapper { externalUserIdInfo?: string; force?: boolean; userContext?: Record; - }): Promise<{ - status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR"; - } | { - status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR"; - doesSuperTokensUserIdExist: boolean; - doesExternalUserIdExist: boolean; - }>; + }): Promise< + | { + status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR"; + } + | { + status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR"; + doesSuperTokensUserIdExist: boolean; + doesExternalUserIdExist: boolean; + } + >; static getUserIdMapping(input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"; userContext?: Record; - }): Promise<{ - status: "OK"; - superTokensUserId: string; - externalUserId: string; - externalUserIdInfo: string | undefined; - } | { - status: "UNKNOWN_MAPPING_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + superTokensUserId: string; + externalUserId: string; + externalUserIdInfo: string | undefined; + } + | { + status: "UNKNOWN_MAPPING_ERROR"; + } + >; static deleteUserIdMapping(input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"; @@ -81,12 +91,23 @@ export default class SuperTokensWrapper { status: "OK" | "UNKNOWN_MAPPING_ERROR"; }>; static getUser(userId: string, userContext?: Record): Promise; - static listUsersByAccountInfo(tenantId: string, accountInfo: AccountInfo, doUnionOfAccountInfo?: boolean, userContext?: Record): Promise; - static deleteUser(userId: string, removeAllLinkedAccounts?: boolean, userContext?: Record): Promise<{ + static listUsersByAccountInfo( + tenantId: string, + accountInfo: AccountInfo, + doUnionOfAccountInfo?: boolean, + userContext?: Record + ): Promise; + static deleteUser( + userId: string, + removeAllLinkedAccounts?: boolean, + userContext?: Record + ): Promise<{ status: "OK"; }>; static convertToRecipeUserId(recipeUserId: string): RecipeUserId; - static getRequestFromUserContext(userContext: UserContext | undefined): import("./framework").BaseRequest | undefined; + static getRequestFromUserContext( + userContext: UserContext | undefined + ): import("./framework").BaseRequest | undefined; } export declare let init: typeof SuperTokens.init; export declare let getAllCORSHeaders: typeof SuperTokensWrapper.getAllCORSHeaders; diff --git a/lib/build/index.js b/lib/build/index.js index de93fb066..1008717ae 100644 --- a/lib/build/index.js +++ b/lib/build/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.User = exports.RecipeUserId = exports.Error = exports.getRequestFromUserContext = exports.convertToRecipeUserId = exports.listUsersByAccountInfo = exports.getUser = exports.updateOrDeleteUserIdMappingInfo = exports.deleteUserIdMapping = exports.getUserIdMapping = exports.createUserIdMapping = exports.deleteUser = exports.getUsersNewestFirst = exports.getUsersOldestFirst = exports.getUserCount = exports.getAllCORSHeaders = exports.init = void 0; const supertokens_1 = __importDefault(require("./supertokens")); @@ -30,25 +32,51 @@ class SuperTokensWrapper { return supertokens_1.default.getInstanceOrThrowError().getAllCORSHeaders(); } static getUserCount(includeRecipeIds, tenantId, userContext) { - return supertokens_1.default.getInstanceOrThrowError().getUserCount(includeRecipeIds, tenantId, (0, utils_1.getUserContext)(userContext)); + return supertokens_1.default + .getInstanceOrThrowError() + .getUserCount(includeRecipeIds, tenantId, (0, utils_1.getUserContext)(userContext)); } static getUsersOldestFirst(input) { - return recipe_1.default.getInstance().recipeInterfaceImpl.getUsers(Object.assign(Object.assign({ timeJoinedOrder: "ASC" }, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default.getInstance().recipeInterfaceImpl.getUsers( + Object.assign(Object.assign({ timeJoinedOrder: "ASC" }, input), { + userContext: (0, utils_1.getUserContext)(input.userContext), + }) + ); } static getUsersNewestFirst(input) { - return recipe_1.default.getInstance().recipeInterfaceImpl.getUsers(Object.assign(Object.assign({ timeJoinedOrder: "DESC" }, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default.getInstance().recipeInterfaceImpl.getUsers( + Object.assign(Object.assign({ timeJoinedOrder: "DESC" }, input), { + userContext: (0, utils_1.getUserContext)(input.userContext), + }) + ); } static createUserIdMapping(input) { - return supertokens_1.default.getInstanceOrThrowError().createUserIdMapping(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return supertokens_1.default + .getInstanceOrThrowError() + .createUserIdMapping( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static getUserIdMapping(input) { - return supertokens_1.default.getInstanceOrThrowError().getUserIdMapping(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return supertokens_1.default + .getInstanceOrThrowError() + .getUserIdMapping( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static deleteUserIdMapping(input) { - return supertokens_1.default.getInstanceOrThrowError().deleteUserIdMapping(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return supertokens_1.default + .getInstanceOrThrowError() + .deleteUserIdMapping( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static updateOrDeleteUserIdMappingInfo(input) { - return supertokens_1.default.getInstanceOrThrowError().updateOrDeleteUserIdMappingInfo(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return supertokens_1.default + .getInstanceOrThrowError() + .updateOrDeleteUserIdMappingInfo( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static async getUser(userId, userContext) { return await recipe_1.default.getInstance().recipeInterfaceImpl.getUser({ @@ -99,6 +127,16 @@ exports.convertToRecipeUserId = SuperTokensWrapper.convertToRecipeUserId; exports.getRequestFromUserContext = SuperTokensWrapper.getRequestFromUserContext; exports.Error = SuperTokensWrapper.Error; var recipeUserId_2 = require("./recipeUserId"); -Object.defineProperty(exports, "RecipeUserId", { enumerable: true, get: function () { return __importDefault(recipeUserId_2).default; } }); +Object.defineProperty(exports, "RecipeUserId", { + enumerable: true, + get: function () { + return __importDefault(recipeUserId_2).default; + }, +}); var user_2 = require("./user"); -Object.defineProperty(exports, "User", { enumerable: true, get: function () { return user_2.User; } }); +Object.defineProperty(exports, "User", { + enumerable: true, + get: function () { + return user_2.User; + }, +}); diff --git a/lib/build/ingredients/emaildelivery/index.js b/lib/build/ingredients/emaildelivery/index.js index e728e628a..958cd35a2 100644 --- a/lib/build/ingredients/emaildelivery/index.js +++ b/lib/build/ingredients/emaildelivery/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); class EmailDelivery { diff --git a/lib/build/ingredients/emaildelivery/services/smtp.d.ts b/lib/build/ingredients/emaildelivery/services/smtp.d.ts index 1c1801722..fe1ecc442 100644 --- a/lib/build/ingredients/emaildelivery/services/smtp.d.ts +++ b/lib/build/ingredients/emaildelivery/services/smtp.d.ts @@ -23,9 +23,11 @@ export type TypeInputSendRawEmail = GetContentResult & { }; export type ServiceInterface = { sendRawEmail: (input: TypeInputSendRawEmail) => Promise; - getContent: (input: T & { - userContext: UserContext; - }) => Promise; + getContent: ( + input: T & { + userContext: UserContext; + } + ) => Promise; }; export type TypeInput = { smtpSettings: SMTPServiceConfig; diff --git a/lib/build/ingredients/emaildelivery/types.d.ts b/lib/build/ingredients/emaildelivery/types.d.ts index c3f22fc81..dc0cc134a 100644 --- a/lib/build/ingredients/emaildelivery/types.d.ts +++ b/lib/build/ingredients/emaildelivery/types.d.ts @@ -2,19 +2,27 @@ import OverrideableBuilder from "supertokens-js-override"; import { UserContext } from "../../types"; export type EmailDeliveryInterface = { - sendEmail: (input: T & { - tenantId: string; - userContext: UserContext; - }) => Promise; + sendEmail: ( + input: T & { + tenantId: string; + userContext: UserContext; + } + ) => Promise; }; /** * config class parameter when parent Recipe create a new EmailDeliveryIngredient object via constructor */ export interface TypeInput { service?: EmailDeliveryInterface; - override?: (originalImplementation: EmailDeliveryInterface, builder: OverrideableBuilder>) => EmailDeliveryInterface; + override?: ( + originalImplementation: EmailDeliveryInterface, + builder: OverrideableBuilder> + ) => EmailDeliveryInterface; } export interface TypeInputWithService { service: EmailDeliveryInterface; - override?: (originalImplementation: EmailDeliveryInterface, builder: OverrideableBuilder>) => EmailDeliveryInterface; + override?: ( + originalImplementation: EmailDeliveryInterface, + builder: OverrideableBuilder> + ) => EmailDeliveryInterface; } diff --git a/lib/build/ingredients/smsdelivery/index.js b/lib/build/ingredients/smsdelivery/index.js index 6a0c5d4dc..a52608dc0 100644 --- a/lib/build/ingredients/smsdelivery/index.js +++ b/lib/build/ingredients/smsdelivery/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); class SmsDelivery { diff --git a/lib/build/ingredients/smsdelivery/services/twilio.d.ts b/lib/build/ingredients/smsdelivery/services/twilio.d.ts index 92adf2c50..2e0090276 100644 --- a/lib/build/ingredients/smsdelivery/services/twilio.d.ts +++ b/lib/build/ingredients/smsdelivery/services/twilio.d.ts @@ -10,33 +10,40 @@ import { UserContext } from "../../../types"; * if none of "from" and "messagingServiceSid" is passed, error * should be thrown. */ -export type TwilioServiceConfig = { - accountSid: string; - authToken: string; - from: string; - opts?: ClientOpts; -} | { - accountSid: string; - authToken: string; - messagingServiceSid: string; - opts?: ClientOpts; -}; +export type TwilioServiceConfig = + | { + accountSid: string; + authToken: string; + from: string; + opts?: ClientOpts; + } + | { + accountSid: string; + authToken: string; + messagingServiceSid: string; + opts?: ClientOpts; + }; export interface GetContentResult { body: string; toPhoneNumber: string; } export type TypeInputSendRawSms = GetContentResult & { userContext: UserContext; -} & ({ - from: string; -} | { - messagingServiceSid: string; -}); +} & ( + | { + from: string; + } + | { + messagingServiceSid: string; + } + ); export type ServiceInterface = { sendRawSms: (input: TypeInputSendRawSms) => Promise; - getContent: (input: T & { - userContext: UserContext; - }) => Promise; + getContent: ( + input: T & { + userContext: UserContext; + } + ) => Promise; }; export type TypeInput = { twilioSettings: TwilioServiceConfig; diff --git a/lib/build/ingredients/smsdelivery/services/twilio.js b/lib/build/ingredients/smsdelivery/services/twilio.js index e799068f3..41bec10df 100644 --- a/lib/build/ingredients/smsdelivery/services/twilio.js +++ b/lib/build/ingredients/smsdelivery/services/twilio.js @@ -3,9 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.normaliseUserInputConfig = normaliseUserInputConfig; function normaliseUserInputConfig(input) { let from = "from" in input.twilioSettings ? input.twilioSettings.from : undefined; - let messagingServiceSid = "messagingServiceSid" in input.twilioSettings ? input.twilioSettings.messagingServiceSid : undefined; - if ((from === undefined && messagingServiceSid === undefined) || - (from !== undefined && messagingServiceSid !== undefined)) { + let messagingServiceSid = + "messagingServiceSid" in input.twilioSettings ? input.twilioSettings.messagingServiceSid : undefined; + if ( + (from === undefined && messagingServiceSid === undefined) || + (from !== undefined && messagingServiceSid !== undefined) + ) { throw Error(`Please pass exactly one of "from" and "messagingServiceSid" config for twilioSettings.`); } return input; diff --git a/lib/build/ingredients/smsdelivery/types.d.ts b/lib/build/ingredients/smsdelivery/types.d.ts index 071543527..07465bf95 100644 --- a/lib/build/ingredients/smsdelivery/types.d.ts +++ b/lib/build/ingredients/smsdelivery/types.d.ts @@ -2,19 +2,27 @@ import OverrideableBuilder from "supertokens-js-override"; import { UserContext } from "../../types"; export type SmsDeliveryInterface = { - sendSms: (input: T & { - tenantId: string; - userContext: UserContext; - }) => Promise; + sendSms: ( + input: T & { + tenantId: string; + userContext: UserContext; + } + ) => Promise; }; /** * config class parameter when parent Recipe create a new SmsDeliveryIngredient object via constructor */ export interface TypeInput { service?: SmsDeliveryInterface; - override?: (originalImplementation: SmsDeliveryInterface, builder: OverrideableBuilder>) => SmsDeliveryInterface; + override?: ( + originalImplementation: SmsDeliveryInterface, + builder: OverrideableBuilder> + ) => SmsDeliveryInterface; } export interface TypeInputWithService { service: SmsDeliveryInterface; - override?: (originalImplementation: SmsDeliveryInterface, builder: OverrideableBuilder>) => SmsDeliveryInterface; + override?: ( + originalImplementation: SmsDeliveryInterface, + builder: OverrideableBuilder> + ) => SmsDeliveryInterface; } diff --git a/lib/build/logger.js b/lib/build/logger.js index 6a6c45fc1..21db59782 100644 --- a/lib/build/logger.js +++ b/lib/build/logger.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.logDebugMessage = logDebugMessage; exports.enableDebugLogs = enableDebugLogs; @@ -28,7 +30,11 @@ const SUPERTOKENS_DEBUG_NAMESPACE = "com.supertokens"; */ function logDebugMessage(message) { if (debug_1.default.enabled(SUPERTOKENS_DEBUG_NAMESPACE)) { - (0, debug_1.default)(SUPERTOKENS_DEBUG_NAMESPACE)(`{t: "${new Date().toISOString()}", message: \"${message}\", file: \"${getFileLocation()}\" sdkVer: "${version_1.version}"}`); + (0, debug_1.default)(SUPERTOKENS_DEBUG_NAMESPACE)( + `{t: "${new Date().toISOString()}", message: \"${message}\", file: \"${getFileLocation()}\" sdkVer: "${ + version_1.version + }"}` + ); console.log(); } } diff --git a/lib/build/nextjs.d.ts b/lib/build/nextjs.d.ts index 29a0e3975..2741fae6f 100644 --- a/lib/build/nextjs.d.ts +++ b/lib/build/nextjs.d.ts @@ -16,18 +16,32 @@ type PartialNextRequest = { }; }; export default class NextJS { - static superTokensNextWrapper(middleware: (next: (middlewareError?: any) => void) => Promise, request: any, response: any): Promise; + static superTokensNextWrapper( + middleware: (next: (middlewareError?: any) => void) => Promise, + request: any, + response: any + ): Promise; static getAppDirRequestHandler(): (req: Request) => Promise; - static getSSRSession(cookies: Array<{ - name: string; - value: string; - }>): Promise<{ + static getSSRSession( + cookies: Array<{ + name: string; + value: string; + }> + ): Promise<{ accessTokenPayload: JWTPayload | undefined; hasToken: boolean; error: Error | undefined; }>; - static withSession(req: NextRequest, handler: (error: Error | undefined, session: SessionContainer | undefined) => Promise, options?: VerifySessionOptions, userContext?: Record): Promise; - static withPreParsedRequestResponse(req: NextRequest, handler: (baseRequest: PreParsedRequest, baseResponse: CollectingResponse) => Promise): Promise; + static withSession( + req: NextRequest, + handler: (error: Error | undefined, session: SessionContainer | undefined) => Promise, + options?: VerifySessionOptions, + userContext?: Record + ): Promise; + static withPreParsedRequestResponse( + req: NextRequest, + handler: (baseRequest: PreParsedRequest, baseResponse: CollectingResponse) => Promise + ): Promise; } export declare let superTokensNextWrapper: typeof NextJS.superTokensNextWrapper; export declare let getAppDirRequestHandler: typeof NextJS.getAppDirRequestHandler; diff --git a/lib/build/nextjs.js b/lib/build/nextjs.js index 30e946109..b8a9fdaeb 100644 --- a/lib/build/nextjs.js +++ b/lib/build/nextjs.js @@ -42,8 +42,7 @@ class NextJS { if (!callbackCalled && !response.finished && !response.headersSent) { return resolve(result); } - } - catch (err) { + } catch (err) { await (0, express_1.errorHandler)()(err, request, response, (errorHandlerError) => { if (errorHandlerError !== undefined) { return reject(errorHandlerError); @@ -58,7 +57,10 @@ class NextJS { } static async getSSRSession(cookies) { var _a; - let accessToken = (_a = cookies.find((cookie) => cookie.name === "sAccessToken")) === null || _a === void 0 ? void 0 : _a.value; + let accessToken = + (_a = cookies.find((cookie) => cookie.name === "sAccessToken")) === null || _a === void 0 + ? void 0 + : _a.value; return await (0, customFramework_1.getSessionForSSRUsingAccessToken)(accessToken); } static async withSession(req, handler, options, userContext) { diff --git a/lib/build/normalisedURLDomain.js b/lib/build/normalisedURLDomain.js index e841580d4..89d6da095 100644 --- a/lib/build/normalisedURLDomain.js +++ b/lib/build/normalisedURLDomain.js @@ -34,17 +34,14 @@ function normaliseURLDomainOrThrowError(input, ignoreProtocol = false) { if (ignoreProtocol) { if (urlObj.hostname.startsWith("localhost") || (0, utils_1.isAnIpAddress)(urlObj.hostname)) { input = "http://" + urlObj.host; - } - else { + } else { input = "https://" + urlObj.host; } - } - else { + } else { input = urlObj.protocol + "//" + urlObj.host; } return input; - } - catch (err) { } + } catch (err) {} // not a valid URL if (input.startsWith("/")) { throw Error("Please provide a valid domain name"); @@ -54,16 +51,17 @@ function normaliseURLDomainOrThrowError(input, ignoreProtocol = false) { } // If the input contains a . it means they have given a domain name. // So we try assuming that they have given a domain name - if ((input.indexOf(".") !== -1 || input.startsWith("localhost")) && + if ( + (input.indexOf(".") !== -1 || input.startsWith("localhost")) && !input.startsWith("http://") && - !input.startsWith("https://")) { + !input.startsWith("https://") + ) { input = "https://" + input; // at this point, it should be a valid URL. So we test that before doing a recursive call try { new URL(input); return normaliseURLDomainOrThrowError(input, true); - } - catch (err) { } + } catch (err) {} } throw Error("Please provide a valid domain name"); } diff --git a/lib/build/normalisedURLPath.js b/lib/build/normalisedURLPath.js index db02d9d5b..64d1a7944 100644 --- a/lib/build/normalisedURLPath.js +++ b/lib/build/normalisedURLPath.js @@ -48,14 +48,15 @@ function normaliseURLPathOrThrowError(input) { return input.substr(0, input.length - 1); } return input; - } - catch (err) { } + } catch (err) {} // not a valid URL // If the input contains a . it means they have given a domain name. // So we try assuming that they have given a domain name + path - if ((domainGiven(input) || input.startsWith("localhost")) && + if ( + (domainGiven(input) || input.startsWith("localhost")) && !input.startsWith("http://") && - !input.startsWith("https://")) { + !input.startsWith("https://") + ) { input = "http://" + input; return normaliseURLPathOrThrowError(input); } @@ -67,8 +68,7 @@ function normaliseURLPathOrThrowError(input) { // test that we can convert this to prevent an infinite loop new URL("http://example.com" + input); return normaliseURLPathOrThrowError("http://example.com" + input); - } - catch (err) { + } catch (err) { throw Error("Please provide a valid URL path"); } } @@ -80,12 +80,10 @@ function domainGiven(input) { try { let url = new URL(input); return url.hostname.indexOf(".") !== -1; - } - catch (ignored) { } + } catch (ignored) {} try { let url = new URL("http://" + input); return url.hostname.indexOf(".") !== -1; - } - catch (ignored) { } + } catch (ignored) {} return false; } diff --git a/lib/build/processState.d.ts b/lib/build/processState.d.ts index 078848436..138e253bf 100644 --- a/lib/build/processState.d.ts +++ b/lib/build/processState.d.ts @@ -8,7 +8,7 @@ export declare enum PROCESS_STATE { IS_SIGN_UP_ALLOWED_CALLED = 5, IS_SIGN_IN_ALLOWED_CALLED = 6, IS_SIGN_IN_UP_ALLOWED_HELPER_CALLED = 7, - ADDING_NO_CACHE_HEADER_IN_FETCH = 8 + ADDING_NO_CACHE_HEADER_IN_FETCH = 8, } export declare class ProcessState { history: PROCESS_STATE[]; diff --git a/lib/build/processState.js b/lib/build/processState.js index 3790cb6db..60a591c6b 100644 --- a/lib/build/processState.js +++ b/lib/build/processState.js @@ -18,15 +18,16 @@ exports.ProcessState = exports.PROCESS_STATE = void 0; const utils_1 = require("./utils"); var PROCESS_STATE; (function (PROCESS_STATE) { - PROCESS_STATE[PROCESS_STATE["CALLING_SERVICE_IN_VERIFY"] = 0] = "CALLING_SERVICE_IN_VERIFY"; - PROCESS_STATE[PROCESS_STATE["CALLING_SERVICE_IN_GET_API_VERSION"] = 1] = "CALLING_SERVICE_IN_GET_API_VERSION"; - PROCESS_STATE[PROCESS_STATE["CALLING_SERVICE_IN_REQUEST_HELPER"] = 2] = "CALLING_SERVICE_IN_REQUEST_HELPER"; - PROCESS_STATE[PROCESS_STATE["MULTI_JWKS_VALIDATION"] = 3] = "MULTI_JWKS_VALIDATION"; - PROCESS_STATE[PROCESS_STATE["IS_SIGN_IN_UP_ALLOWED_NO_PRIMARY_USER_EXISTS"] = 4] = "IS_SIGN_IN_UP_ALLOWED_NO_PRIMARY_USER_EXISTS"; - PROCESS_STATE[PROCESS_STATE["IS_SIGN_UP_ALLOWED_CALLED"] = 5] = "IS_SIGN_UP_ALLOWED_CALLED"; - PROCESS_STATE[PROCESS_STATE["IS_SIGN_IN_ALLOWED_CALLED"] = 6] = "IS_SIGN_IN_ALLOWED_CALLED"; - PROCESS_STATE[PROCESS_STATE["IS_SIGN_IN_UP_ALLOWED_HELPER_CALLED"] = 7] = "IS_SIGN_IN_UP_ALLOWED_HELPER_CALLED"; - PROCESS_STATE[PROCESS_STATE["ADDING_NO_CACHE_HEADER_IN_FETCH"] = 8] = "ADDING_NO_CACHE_HEADER_IN_FETCH"; + PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_VERIFY"] = 0)] = "CALLING_SERVICE_IN_VERIFY"; + PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_GET_API_VERSION"] = 1)] = "CALLING_SERVICE_IN_GET_API_VERSION"; + PROCESS_STATE[(PROCESS_STATE["CALLING_SERVICE_IN_REQUEST_HELPER"] = 2)] = "CALLING_SERVICE_IN_REQUEST_HELPER"; + PROCESS_STATE[(PROCESS_STATE["MULTI_JWKS_VALIDATION"] = 3)] = "MULTI_JWKS_VALIDATION"; + PROCESS_STATE[(PROCESS_STATE["IS_SIGN_IN_UP_ALLOWED_NO_PRIMARY_USER_EXISTS"] = 4)] = + "IS_SIGN_IN_UP_ALLOWED_NO_PRIMARY_USER_EXISTS"; + PROCESS_STATE[(PROCESS_STATE["IS_SIGN_UP_ALLOWED_CALLED"] = 5)] = "IS_SIGN_UP_ALLOWED_CALLED"; + PROCESS_STATE[(PROCESS_STATE["IS_SIGN_IN_ALLOWED_CALLED"] = 6)] = "IS_SIGN_IN_ALLOWED_CALLED"; + PROCESS_STATE[(PROCESS_STATE["IS_SIGN_IN_UP_ALLOWED_HELPER_CALLED"] = 7)] = "IS_SIGN_IN_UP_ALLOWED_HELPER_CALLED"; + PROCESS_STATE[(PROCESS_STATE["ADDING_NO_CACHE_HEADER_IN_FETCH"] = 8)] = "ADDING_NO_CACHE_HEADER_IN_FETCH"; })(PROCESS_STATE || (exports.PROCESS_STATE = PROCESS_STATE = {})); class ProcessState { constructor() { @@ -56,12 +57,10 @@ class ProcessState { if (result === undefined) { if (Date.now() - startTime > timeInMS) { resolve(undefined); - } - else { + } else { setTimeout(tryAndGet, 1000); } - } - else { + } else { resolve(result); } } diff --git a/lib/build/querier.d.ts b/lib/build/querier.d.ts index 4b7f18d1c..17d12763b 100644 --- a/lib/build/querier.d.ts +++ b/lib/build/querier.d.ts @@ -20,18 +20,42 @@ export declare class Querier { static reset(): void; getHostsAliveForTesting: () => Set; static getNewInstanceOrThrowError(rIdToCore?: string): Querier; - static init(hosts?: { - domain: NormalisedURLDomain; - basePath: NormalisedURLPath; - }[], apiKey?: string, networkInterceptor?: NetworkInterceptor, disableCache?: boolean): void; + static init( + hosts?: { + domain: NormalisedURLDomain; + basePath: NormalisedURLPath; + }[], + apiKey?: string, + networkInterceptor?: NetworkInterceptor, + disableCache?: boolean + ): void; sendPostRequest: (path: NormalisedURLPath, body: any, userContext: UserContext) => Promise; - sendDeleteRequest: (path: NormalisedURLPath, body: any, params: any | undefined, userContext: UserContext) => Promise; - sendGetRequest: (path: NormalisedURLPath, params: Record, userContext: UserContext) => Promise; - sendGetRequestWithResponseHeaders: (path: NormalisedURLPath, params: Record, inpHeaders: Record | undefined, userContext: UserContext) => Promise<{ + sendDeleteRequest: ( + path: NormalisedURLPath, + body: any, + params: any | undefined, + userContext: UserContext + ) => Promise; + sendGetRequest: ( + path: NormalisedURLPath, + params: Record, + userContext: UserContext + ) => Promise; + sendGetRequestWithResponseHeaders: ( + path: NormalisedURLPath, + params: Record, + inpHeaders: Record | undefined, + userContext: UserContext + ) => Promise<{ body: any; headers: Headers; }>; - sendPutRequest: (path: NormalisedURLPath, body: any, params: Record, userContext: UserContext) => Promise; + sendPutRequest: ( + path: NormalisedURLPath, + body: any, + params: Record, + userContext: UserContext + ) => Promise; sendPatchRequest: (path: NormalisedURLPath, body: any, userContext: UserContext) => Promise; invalidateCoreCallCache: (userContext: UserContext, updGlobalCacheTagIfNecessary?: boolean) => void; getAllCoreUrlsForPath(path: string): string[]; diff --git a/lib/build/querier.js b/lib/build/querier.js index 6ea88c7a6..770bdf523 100644 --- a/lib/build/querier.js +++ b/lib/build/querier.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Querier = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -34,7 +36,9 @@ class Querier { if (Querier.apiVersion !== undefined) { return Querier.apiVersion; } - processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.CALLING_SERVICE_IN_GET_API_VERSION); + processState_1.ProcessState.getInstance().addState( + processState_1.PROCESS_STATE.CALLING_SERVICE_IN_GET_API_VERSION + ); const st = supertokens_1.default.getInstanceOrThrowError(); const appInfo = st.appInfo; const request = st.getRequestFromUserContext(userContext); @@ -43,33 +47,46 @@ class Querier { websiteDomain: appInfo.getOrigin({ request, userContext }).getAsStringDangerous(), }; const queryParams = new URLSearchParams(queryParamsObj).toString(); - let { body: response } = await this.sendRequestHelper(new normalisedURLPath_1.default("/apiversion"), "GET", async (url) => { - let headers = {}; - if (Querier.apiKey !== undefined) { - headers = { - "api-key": Querier.apiKey, - }; - } - if (Querier.networkInterceptor !== undefined) { - let request = Querier.networkInterceptor({ - url: url, - method: "get", - headers: headers, - params: queryParamsObj, - }, userContext); - url = request.url; - headers = request.headers; - } - let response = await (0, utils_1.doFetch)(url + `?${queryParams}`, { - method: "GET", - headers, - }); - return response; - }, ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0); + let { body: response } = await this.sendRequestHelper( + new normalisedURLPath_1.default("/apiversion"), + "GET", + async (url) => { + let headers = {}; + if (Querier.apiKey !== undefined) { + headers = { + "api-key": Querier.apiKey, + }; + } + if (Querier.networkInterceptor !== undefined) { + let request = Querier.networkInterceptor( + { + url: url, + method: "get", + headers: headers, + params: queryParamsObj, + }, + userContext + ); + url = request.url; + headers = request.headers; + } + let response = await (0, utils_1.doFetch)(url + `?${queryParams}`, { + method: "GET", + headers, + }); + return response; + }, + ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0 + ); let cdiSupportedByServer = response.versions; - let supportedVersion = (0, utils_1.getLargestVersionFromIntersection)(cdiSupportedByServer, version_1.cdiSupported); + let supportedVersion = (0, utils_1.getLargestVersionFromIntersection)( + cdiSupportedByServer, + version_1.cdiSupported + ); if (supportedVersion === undefined) { - throw Error("The running SuperTokens core version is not compatible with this NodeJS SDK. Please visit https://supertokens.io/docs/community/compatibility to find the right versions"); + throw Error( + "The running SuperTokens core version is not compatible with this NodeJS SDK. Please visit https://supertokens.io/docs/community/compatibility to find the right versions" + ); } Querier.apiVersion = supportedVersion; return Querier.apiVersion; @@ -84,258 +101,335 @@ class Querier { this.sendPostRequest = async (path, body, userContext) => { var _a; this.invalidateCoreCallCache(userContext); - const { body: respBody } = await this.sendRequestHelper(path, "POST", async (url) => { - let apiVersion = await this.getAPIVersion(userContext); - let headers = { - "cdi-version": apiVersion, - }; - headers["content-type"] = "application/json; charset=utf-8"; - if (Querier.apiKey !== undefined) { - headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); - } - if (path.isARecipePath() && this.rIdToCore !== undefined) { - headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); - } - if (Querier.networkInterceptor !== undefined) { - let request = Querier.networkInterceptor({ - url: url, - method: "post", - headers: headers, - body: body, - }, userContext); - url = request.url; - headers = request.headers; - if (request.body !== undefined) { - body = request.body; + const { body: respBody } = await this.sendRequestHelper( + path, + "POST", + async (url) => { + let apiVersion = await this.getAPIVersion(userContext); + let headers = { + "cdi-version": apiVersion, + }; + headers["content-type"] = "application/json; charset=utf-8"; + if (Querier.apiKey !== undefined) { + headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); } - } - return (0, utils_1.doFetch)(url, { - method: "POST", - body: body !== undefined ? JSON.stringify(body) : undefined, - headers, - }); - }, ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0); + if (path.isARecipePath() && this.rIdToCore !== undefined) { + headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); + } + if (Querier.networkInterceptor !== undefined) { + let request = Querier.networkInterceptor( + { + url: url, + method: "post", + headers: headers, + body: body, + }, + userContext + ); + url = request.url; + headers = request.headers; + if (request.body !== undefined) { + body = request.body; + } + } + return (0, utils_1.doFetch)(url, { + method: "POST", + body: body !== undefined ? JSON.stringify(body) : undefined, + headers, + }); + }, + ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0 + ); return respBody; }; // path should start with "/" this.sendDeleteRequest = async (path, body, params, userContext) => { var _a; this.invalidateCoreCallCache(userContext); - const { body: respBody } = await this.sendRequestHelper(path, "DELETE", async (url) => { - let apiVersion = await this.getAPIVersion(userContext); - let headers = { "cdi-version": apiVersion, "content-type": "application/json; charset=utf-8" }; - if (Querier.apiKey !== undefined) { - headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); - } - if (path.isARecipePath() && this.rIdToCore !== undefined) { - headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); - } - if (Querier.networkInterceptor !== undefined) { - let request = Querier.networkInterceptor({ - url: url, - method: "delete", - headers: headers, - params: params, - body: body, - }, userContext); - url = request.url; - headers = request.headers; - if (request.body !== undefined) { - body = request.body; + const { body: respBody } = await this.sendRequestHelper( + path, + "DELETE", + async (url) => { + let apiVersion = await this.getAPIVersion(userContext); + let headers = { "cdi-version": apiVersion, "content-type": "application/json; charset=utf-8" }; + if (Querier.apiKey !== undefined) { + headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); } - if (request.params !== undefined) { - params = request.params; + if (path.isARecipePath() && this.rIdToCore !== undefined) { + headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); } - } - const finalURL = new URL(url); - const searchParams = new URLSearchParams(params); - finalURL.search = searchParams.toString(); - return (0, utils_1.doFetch)(finalURL.toString(), { - method: "DELETE", - body: body !== undefined ? JSON.stringify(body) : undefined, - headers, - }); - }, ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0); + if (Querier.networkInterceptor !== undefined) { + let request = Querier.networkInterceptor( + { + url: url, + method: "delete", + headers: headers, + params: params, + body: body, + }, + userContext + ); + url = request.url; + headers = request.headers; + if (request.body !== undefined) { + body = request.body; + } + if (request.params !== undefined) { + params = request.params; + } + } + const finalURL = new URL(url); + const searchParams = new URLSearchParams(params); + finalURL.search = searchParams.toString(); + return (0, utils_1.doFetch)(finalURL.toString(), { + method: "DELETE", + body: body !== undefined ? JSON.stringify(body) : undefined, + headers, + }); + }, + ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0 + ); return respBody; }; // path should start with "/" this.sendGetRequest = async (path, params, userContext) => { var _a; - const { body: respBody } = await this.sendRequestHelper(path, "GET", async (url) => { - var _a, _b, _c, _d; - let apiVersion = await this.getAPIVersion(userContext); - let headers = { "cdi-version": apiVersion }; - if (Querier.apiKey !== undefined) { - headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); - } - if (path.isARecipePath() && this.rIdToCore !== undefined) { - headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); - } - /* CACHE CHECK BEGIN */ - const sortedKeys = Object.keys(params).sort(); - const sortedHeaderKeys = Object.keys(headers).sort(); - let uniqueKey = path.getAsStringDangerous(); - for (const key of sortedKeys) { - const value = params[key]; - uniqueKey += `;${key}=${value}`; - } - uniqueKey += ";hdrs"; - for (const key of sortedHeaderKeys) { - const value = headers[key]; - uniqueKey += `;${key}=${value}`; - } - // If globalCacheTag doesn't match the current one (or if it's not defined), we invalidate the cache, because that means - // that there was a non-GET call that didn't have a proper userContext passed to it. - // However, we do not want to invalidate all global caches for a GET call even if it was made without a proper user context. - if (((_a = userContext._default) === null || _a === void 0 ? void 0 : _a.globalCacheTag) !== Querier.globalCacheTag) { - this.invalidateCoreCallCache(userContext, false); - } - if (!Querier.disableCache && uniqueKey in ((_c = (_b = userContext._default) === null || _b === void 0 ? void 0 : _b.coreCallCache) !== null && _c !== void 0 ? _c : {})) { - return userContext._default.coreCallCache[uniqueKey]; - } - /* CACHE CHECK END */ - if (Querier.networkInterceptor !== undefined) { - let request = Querier.networkInterceptor({ - url: url, - method: "get", - headers: headers, - params: params, - }, userContext); - url = request.url; - headers = request.headers; - if (request.params !== undefined) { - params = request.params; + const { body: respBody } = await this.sendRequestHelper( + path, + "GET", + async (url) => { + var _a, _b, _c, _d; + let apiVersion = await this.getAPIVersion(userContext); + let headers = { "cdi-version": apiVersion }; + if (Querier.apiKey !== undefined) { + headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); + } + if (path.isARecipePath() && this.rIdToCore !== undefined) { + headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); + } + /* CACHE CHECK BEGIN */ + const sortedKeys = Object.keys(params).sort(); + const sortedHeaderKeys = Object.keys(headers).sort(); + let uniqueKey = path.getAsStringDangerous(); + for (const key of sortedKeys) { + const value = params[key]; + uniqueKey += `;${key}=${value}`; + } + uniqueKey += ";hdrs"; + for (const key of sortedHeaderKeys) { + const value = headers[key]; + uniqueKey += `;${key}=${value}`; + } + // If globalCacheTag doesn't match the current one (or if it's not defined), we invalidate the cache, because that means + // that there was a non-GET call that didn't have a proper userContext passed to it. + // However, we do not want to invalidate all global caches for a GET call even if it was made without a proper user context. + if ( + ((_a = userContext._default) === null || _a === void 0 ? void 0 : _a.globalCacheTag) !== + Querier.globalCacheTag + ) { + this.invalidateCoreCallCache(userContext, false); + } + if ( + !Querier.disableCache && + uniqueKey in + ((_c = + (_b = userContext._default) === null || _b === void 0 ? void 0 : _b.coreCallCache) !== + null && _c !== void 0 + ? _c + : {}) + ) { + return userContext._default.coreCallCache[uniqueKey]; + } + /* CACHE CHECK END */ + if (Querier.networkInterceptor !== undefined) { + let request = Querier.networkInterceptor( + { + url: url, + method: "get", + headers: headers, + params: params, + }, + userContext + ); + url = request.url; + headers = request.headers; + if (request.params !== undefined) { + params = request.params; + } + } + const finalURL = new URL(url); + const searchParams = new URLSearchParams( + Object.entries(params).filter(([_, value]) => value !== undefined) + ); + finalURL.search = searchParams.toString(); + // Update cache and return + let response = await (0, utils_1.doFetch)(finalURL.toString(), { + method: "GET", + headers, + }); + if (response.status === 302) { + return response; + } + if (response.status === 200 && !Querier.disableCache) { + // If the request was successful, we save the result into the cache + // plus we update the cache tag + userContext._default = Object.assign(Object.assign({}, userContext._default), { + coreCallCache: Object.assign( + Object.assign( + {}, + (_d = userContext._default) === null || _d === void 0 ? void 0 : _d.coreCallCache + ), + { [uniqueKey]: response } + ), + globalCacheTag: Querier.globalCacheTag, + }); } - } - const finalURL = new URL(url); - const searchParams = new URLSearchParams(Object.entries(params).filter(([_, value]) => value !== undefined)); - finalURL.search = searchParams.toString(); - // Update cache and return - let response = await (0, utils_1.doFetch)(finalURL.toString(), { - method: "GET", - headers, - }); - if (response.status === 302) { return response; - } - if (response.status === 200 && !Querier.disableCache) { - // If the request was successful, we save the result into the cache - // plus we update the cache tag - userContext._default = Object.assign(Object.assign({}, userContext._default), { coreCallCache: Object.assign(Object.assign({}, (_d = userContext._default) === null || _d === void 0 ? void 0 : _d.coreCallCache), { [uniqueKey]: response }), globalCacheTag: Querier.globalCacheTag }); - } - return response; - }, ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0); + }, + ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0 + ); return respBody; }; this.sendGetRequestWithResponseHeaders = async (path, params, inpHeaders, userContext) => { var _a; - return await this.sendRequestHelper(path, "GET", async (url) => { - let apiVersion = await this.getAPIVersion(userContext); - let headers = inpHeaders !== null && inpHeaders !== void 0 ? inpHeaders : {}; - headers["cdi-version"] = apiVersion; - if (Querier.apiKey !== undefined) { - headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); - } - if (path.isARecipePath() && this.rIdToCore !== undefined) { - headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); - } - if (Querier.networkInterceptor !== undefined) { - let request = Querier.networkInterceptor({ - url: url, - method: "get", - headers: headers, - params: params, - }, userContext); - url = request.url; - headers = request.headers; - if (request.params !== undefined) { - params = request.params; + return await this.sendRequestHelper( + path, + "GET", + async (url) => { + let apiVersion = await this.getAPIVersion(userContext); + let headers = inpHeaders !== null && inpHeaders !== void 0 ? inpHeaders : {}; + headers["cdi-version"] = apiVersion; + if (Querier.apiKey !== undefined) { + headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); } - } - const finalURL = new URL(url); - const searchParams = new URLSearchParams(Object.entries(params).filter(([_, value]) => value !== undefined)); - finalURL.search = searchParams.toString(); - return (0, utils_1.doFetch)(finalURL.toString(), { - method: "GET", - headers, - }); - }, ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0); + if (path.isARecipePath() && this.rIdToCore !== undefined) { + headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); + } + if (Querier.networkInterceptor !== undefined) { + let request = Querier.networkInterceptor( + { + url: url, + method: "get", + headers: headers, + params: params, + }, + userContext + ); + url = request.url; + headers = request.headers; + if (request.params !== undefined) { + params = request.params; + } + } + const finalURL = new URL(url); + const searchParams = new URLSearchParams( + Object.entries(params).filter(([_, value]) => value !== undefined) + ); + finalURL.search = searchParams.toString(); + return (0, utils_1.doFetch)(finalURL.toString(), { + method: "GET", + headers, + }); + }, + ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0 + ); }; // path should start with "/" this.sendPutRequest = async (path, body, params, userContext) => { var _a; this.invalidateCoreCallCache(userContext); - const { body: respBody } = await this.sendRequestHelper(path, "PUT", async (url) => { - let apiVersion = await this.getAPIVersion(userContext); - let headers = { "cdi-version": apiVersion, "content-type": "application/json; charset=utf-8" }; - if (Querier.apiKey !== undefined) { - headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); - } - if (path.isARecipePath() && this.rIdToCore !== undefined) { - headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); - } - if (Querier.networkInterceptor !== undefined) { - let request = Querier.networkInterceptor({ - url: url, - method: "put", - headers: headers, - body: body, - params: params, - }, userContext); - url = request.url; - headers = request.headers; - if (request.body !== undefined) { - body = request.body; + const { body: respBody } = await this.sendRequestHelper( + path, + "PUT", + async (url) => { + let apiVersion = await this.getAPIVersion(userContext); + let headers = { "cdi-version": apiVersion, "content-type": "application/json; charset=utf-8" }; + if (Querier.apiKey !== undefined) { + headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); } - } - const finalURL = new URL(url); - const searchParams = new URLSearchParams(Object.entries(params).filter(([_, value]) => value !== undefined)); - finalURL.search = searchParams.toString(); - return (0, utils_1.doFetch)(finalURL.toString(), { - method: "PUT", - body: body !== undefined ? JSON.stringify(body) : undefined, - headers, - }); - }, ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0); + if (path.isARecipePath() && this.rIdToCore !== undefined) { + headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); + } + if (Querier.networkInterceptor !== undefined) { + let request = Querier.networkInterceptor( + { + url: url, + method: "put", + headers: headers, + body: body, + params: params, + }, + userContext + ); + url = request.url; + headers = request.headers; + if (request.body !== undefined) { + body = request.body; + } + } + const finalURL = new URL(url); + const searchParams = new URLSearchParams( + Object.entries(params).filter(([_, value]) => value !== undefined) + ); + finalURL.search = searchParams.toString(); + return (0, utils_1.doFetch)(finalURL.toString(), { + method: "PUT", + body: body !== undefined ? JSON.stringify(body) : undefined, + headers, + }); + }, + ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0 + ); return respBody; }; // path should start with "/" this.sendPatchRequest = async (path, body, userContext) => { var _a; this.invalidateCoreCallCache(userContext); - const { body: respBody } = await this.sendRequestHelper(path, "PATCH", async (url) => { - let apiVersion = await this.getAPIVersion(userContext); - let headers = { "cdi-version": apiVersion, "content-type": "application/json; charset=utf-8" }; - if (Querier.apiKey !== undefined) { - headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); - } - if (path.isARecipePath() && this.rIdToCore !== undefined) { - headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); - } - if (Querier.networkInterceptor !== undefined) { - let request = Querier.networkInterceptor({ - url: url, - method: "patch", - headers: headers, - body: body, - }, userContext); - url = request.url; - headers = request.headers; - if (request.body !== undefined) { - body = request.body; + const { body: respBody } = await this.sendRequestHelper( + path, + "PATCH", + async (url) => { + let apiVersion = await this.getAPIVersion(userContext); + let headers = { "cdi-version": apiVersion, "content-type": "application/json; charset=utf-8" }; + if (Querier.apiKey !== undefined) { + headers = Object.assign(Object.assign({}, headers), { "api-key": Querier.apiKey }); } - } - return (0, utils_1.doFetch)(url, { - method: "PATCH", - body: body !== undefined ? JSON.stringify(body) : undefined, - headers, - }); - }, ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0); + if (path.isARecipePath() && this.rIdToCore !== undefined) { + headers = Object.assign(Object.assign({}, headers), { rid: this.rIdToCore }); + } + if (Querier.networkInterceptor !== undefined) { + let request = Querier.networkInterceptor( + { + url: url, + method: "patch", + headers: headers, + body: body, + }, + userContext + ); + url = request.url; + headers = request.headers; + if (request.body !== undefined) { + body = request.body; + } + } + return (0, utils_1.doFetch)(url, { + method: "PATCH", + body: body !== undefined ? JSON.stringify(body) : undefined, + headers, + }); + }, + ((_a = this.__hosts) === null || _a === void 0 ? void 0 : _a.length) || 0 + ); return respBody; }; this.invalidateCoreCallCache = (userContext, updGlobalCacheTagIfNecessary = true) => { var _a; - if (updGlobalCacheTagIfNecessary && ((_a = userContext._default) === null || _a === void 0 ? void 0 : _a.keepCacheAlive) !== true) { + if ( + updGlobalCacheTagIfNecessary && + ((_a = userContext._default) === null || _a === void 0 ? void 0 : _a.keepCacheAlive) !== true + ) { Querier.globalCacheTag = Date.now(); } userContext._default = Object.assign(Object.assign({}, userContext._default), { coreCallCache: {} }); @@ -344,7 +438,9 @@ class Querier { this.sendRequestHelper = async (path, method, requestFunc, numberOfTries, retryInfoMap) => { var _a; if (this.__hosts === undefined) { - throw Error("No SuperTokens core available to query. Please pass supertokens > connectionURI to the init function, or override all the functions of the recipe you are using."); + throw Error( + "No SuperTokens core available to query. Please pass supertokens > connectionURI to the init function, or override all the functions of the recipe you are using." + ); } if (numberOfTries === 0) { throw Error("No SuperTokens core available to query"); @@ -363,7 +459,9 @@ class Querier { Querier.lastTriedIndex++; Querier.lastTriedIndex = Querier.lastTriedIndex % this.__hosts.length; try { - processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.CALLING_SERVICE_IN_REQUEST_HELPER); + processState_1.ProcessState.getInstance().addState( + processState_1.PROCESS_STATE.CALLING_SERVICE_IN_REQUEST_HELPER + ); (0, logger_1.logDebugMessage)(`core-call: ${method} ${url}`); let response = await requestFunc(url); if ((0, utils_1.isTestEnv)()) { @@ -372,17 +470,22 @@ class Querier { if (response.status !== 200) { throw response; } - if ((_a = response.headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.startsWith("text")) { + if ( + (_a = response.headers.get("content-type")) === null || _a === void 0 + ? void 0 + : _a.startsWith("text") + ) { return { body: await response.clone().text(), headers: response.headers }; } return { body: await response.clone().json(), headers: response.headers }; - } - catch (err) { - if (err.message !== undefined && + } catch (err) { + if ( + err.message !== undefined && (err.message.includes("Failed to fetch") || err.message.includes("fetch failed") || err.message.includes("ECONNREFUSED") || - err.code === "ECONNREFUSED")) { + err.code === "ECONNREFUSED") + ) { return this.sendRequestHelper(path, method, requestFunc, numberOfTries - 1, retryInfoMap); } if ("status" in err && "text" in err) { @@ -396,14 +499,16 @@ class Querier { return this.sendRequestHelper(path, method, requestFunc, numberOfTries, retryInfoMap); } } - throw new Error("SuperTokens core threw an error for a " + - method + - " request to path: '" + - path.getAsStringDangerous() + - "' with status code: " + - err.status + - " and message: " + - (await err.text())); + throw new Error( + "SuperTokens core threw an error for a " + + method + + " request to path: '" + + path.getAsStringDangerous() + + "' with status code: " + + err.status + + " and message: " + + (await err.text()) + ); } throw err; } diff --git a/lib/build/recipe/accountlinking/index.d.ts b/lib/build/recipe/accountlinking/index.d.ts index 602f24222..6c8b57705 100644 --- a/lib/build/recipe/accountlinking/index.d.ts +++ b/lib/build/recipe/accountlinking/index.d.ts @@ -14,7 +14,12 @@ export default class Wrapper { * same as the input recipeUserId if it was made into a primary user, or if there was * no linking that happened. */ - static createPrimaryUserIdOrLinkAccounts(tenantId: string, recipeUserId: RecipeUserId, session?: SessionContainerInterface, userContext?: Record): Promise; + static createPrimaryUserIdOrLinkAccounts( + tenantId: string, + recipeUserId: RecipeUserId, + session?: SessionContainerInterface, + userContext?: Record + ): Promise; /** * This function returns the primary user that the input recipe ID can be * linked to. It can be used to determine which primary account the linking @@ -24,64 +29,121 @@ export default class Wrapper { * that the input recipe ID can be linked to, and therefore it can be made * into a primary user itself. */ - static getPrimaryUserThatCanBeLinkedToRecipeUserId(tenantId: string, recipeUserId: RecipeUserId, userContext?: Record): Promise; - static canCreatePrimaryUser(recipeUserId: RecipeUserId, userContext?: Record): Promise<{ - status: "OK"; - wasAlreadyAPrimaryUser: boolean; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - }>; - static createPrimaryUser(recipeUserId: RecipeUserId, userContext?: Record): Promise<{ - status: "OK"; - user: import("../../types").User; - wasAlreadyAPrimaryUser: boolean; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - } | { - status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - }>; - static canLinkAccounts(recipeUserId: RecipeUserId, primaryUserId: string, userContext?: Record): Promise<{ - status: "OK"; - accountsAlreadyLinked: boolean; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - description: string; - primaryUserId: string; - } | { - status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - } | { - status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; - }>; - static linkAccounts(recipeUserId: RecipeUserId, primaryUserId: string, userContext?: Record): Promise<{ - status: "OK"; - accountsAlreadyLinked: boolean; - user: import("../../types").User; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - user: import("../../types").User; - } | { - status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - } | { - status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; - }>; - static unlinkAccount(recipeUserId: RecipeUserId, userContext?: Record): Promise<{ + static getPrimaryUserThatCanBeLinkedToRecipeUserId( + tenantId: string, + recipeUserId: RecipeUserId, + userContext?: Record + ): Promise; + static canCreatePrimaryUser( + recipeUserId: RecipeUserId, + userContext?: Record + ): Promise< + | { + status: "OK"; + wasAlreadyAPrimaryUser: boolean; + } + | { + status: + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + >; + static createPrimaryUser( + recipeUserId: RecipeUserId, + userContext?: Record + ): Promise< + | { + status: "OK"; + user: import("../../types").User; + wasAlreadyAPrimaryUser: boolean; + } + | { + status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + } + | { + status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + >; + static canLinkAccounts( + recipeUserId: RecipeUserId, + primaryUserId: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + accountsAlreadyLinked: boolean; + } + | { + status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + description: string; + primaryUserId: string; + } + | { + status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + | { + status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; + } + >; + static linkAccounts( + recipeUserId: RecipeUserId, + primaryUserId: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + accountsAlreadyLinked: boolean; + user: import("../../types").User; + } + | { + status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + user: import("../../types").User; + } + | { + status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + | { + status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; + } + >; + static unlinkAccount( + recipeUserId: RecipeUserId, + userContext?: Record + ): Promise<{ status: "OK"; wasRecipeUserDeleted: boolean; wasLinked: boolean; }>; - static isSignUpAllowed(tenantId: string, newUser: AccountInfoWithRecipeId, isVerified: boolean, session?: SessionContainerInterface, userContext?: Record): Promise; - static isSignInAllowed(tenantId: string, recipeUserId: RecipeUserId, session?: SessionContainerInterface, userContext?: Record): Promise; - static isEmailChangeAllowed(recipeUserId: RecipeUserId, newEmail: string, isVerified: boolean, session?: SessionContainerInterface, userContext?: Record): Promise; + static isSignUpAllowed( + tenantId: string, + newUser: AccountInfoWithRecipeId, + isVerified: boolean, + session?: SessionContainerInterface, + userContext?: Record + ): Promise; + static isSignInAllowed( + tenantId: string, + recipeUserId: RecipeUserId, + session?: SessionContainerInterface, + userContext?: Record + ): Promise; + static isEmailChangeAllowed( + recipeUserId: RecipeUserId, + newEmail: string, + isVerified: boolean, + session?: SessionContainerInterface, + userContext?: Record + ): Promise; } export declare const init: typeof Recipe.init; export declare const canCreatePrimaryUser: typeof Wrapper.canCreatePrimaryUser; diff --git a/lib/build/recipe/accountlinking/index.js b/lib/build/recipe/accountlinking/index.js index 0d49c7637..181ce7d7b 100644 --- a/lib/build/recipe/accountlinking/index.js +++ b/lib/build/recipe/accountlinking/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isEmailChangeAllowed = exports.isSignInAllowed = exports.isSignUpAllowed = exports.getPrimaryUserThatCanBeLinkedToRecipeUserId = exports.createPrimaryUserIdOrLinkAccounts = exports.unlinkAccount = exports.linkAccounts = exports.canLinkAccounts = exports.createPrimaryUser = exports.canCreatePrimaryUser = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); diff --git a/lib/build/recipe/accountlinking/recipe.d.ts b/lib/build/recipe/accountlinking/recipe.d.ts index 95485e9a9..b605c86e7 100644 --- a/lib/build/recipe/accountlinking/recipe.d.ts +++ b/lib/build/recipe/accountlinking/recipe.d.ts @@ -13,26 +13,54 @@ export default class Recipe extends RecipeModule { static RECIPE_ID: "accountlinking"; config: TypeNormalisedInput; recipeInterfaceImpl: RecipeInterface; - constructor(recipeId: string, appInfo: NormalisedAppinfo, config: TypeInput | undefined, _recipes: {}, _ingredients: {}); + constructor( + recipeId: string, + appInfo: NormalisedAppinfo, + config: TypeInput | undefined, + _recipes: {}, + _ingredients: {} + ); static init(config?: TypeInput): RecipeListFunction; static getInstance(): Recipe; getAPIsHandled(): APIHandled[]; - handleAPIRequest(_id: string, _tenantId: string, _req: BaseRequest, _response: BaseResponse, _path: normalisedURLPath, _method: HTTPMethod): Promise; + handleAPIRequest( + _id: string, + _tenantId: string, + _req: BaseRequest, + _response: BaseResponse, + _path: normalisedURLPath, + _method: HTTPMethod + ): Promise; handleError(error: error, _request: BaseRequest, _response: BaseResponse): Promise; getAllCORSHeaders(): string[]; isErrorFromThisRecipe(err: any): err is error; static reset(): void; - getPrimaryUserThatCanBeLinkedToRecipeUserId: ({ tenantId, user, userContext, }: { + getPrimaryUserThatCanBeLinkedToRecipeUserId: ({ + tenantId, + user, + userContext, + }: { tenantId: string; user: User; userContext: UserContext; }) => Promise; - getOldestUserThatCanBeLinkedToRecipeUser: ({ tenantId, user, userContext, }: { + getOldestUserThatCanBeLinkedToRecipeUser: ({ + tenantId, + user, + userContext, + }: { tenantId: string; user: User; userContext: UserContext; }) => Promise; - isSignInAllowed: ({ user, accountInfo, tenantId, session, signInVerifiesLoginMethod, userContext, }: { + isSignInAllowed: ({ + user, + accountInfo, + tenantId, + session, + signInVerifiesLoginMethod, + userContext, + }: { user: User; accountInfo: AccountInfoWithRecipeId | LoginMethod; session: SessionContainerInterface | undefined; @@ -40,14 +68,28 @@ export default class Recipe extends RecipeModule { tenantId: string; userContext: UserContext; }) => Promise; - isSignUpAllowed: ({ newUser, isVerified, session, tenantId, userContext, }: { + isSignUpAllowed: ({ + newUser, + isVerified, + session, + tenantId, + userContext, + }: { newUser: AccountInfoWithRecipeId; isVerified: boolean; session: SessionContainerInterface | undefined; tenantId: string; userContext: UserContext; }) => Promise; - isSignInUpAllowedHelper: ({ accountInfo, isVerified, session, tenantId, isSignIn, user, userContext, }: { + isSignInUpAllowedHelper: ({ + accountInfo, + isVerified, + session, + tenantId, + isSignIn, + user, + userContext, + }: { accountInfo: AccountInfoWithRecipeId | LoginMethod; isVerified: boolean; session: SessionContainerInterface | undefined; @@ -62,27 +104,43 @@ export default class Recipe extends RecipeModule { isVerified: boolean; session: SessionContainerInterface | undefined; userContext: UserContext; - }) => Promise<{ - allowed: true; - } | { - allowed: false; - reason: "PRIMARY_USER_CONFLICT" | "ACCOUNT_TAKEOVER_RISK"; - }>; + }) => Promise< + | { + allowed: true; + } + | { + allowed: false; + reason: "PRIMARY_USER_CONFLICT" | "ACCOUNT_TAKEOVER_RISK"; + } + >; verifyEmailForRecipeUserIfLinkedAccountsAreVerified: (input: { user: User; recipeUserId: RecipeUserId; userContext: UserContext; }) => Promise; - shouldBecomePrimaryUser(user: User, tenantId: string, session: SessionContainerInterface | undefined, userContext: UserContext): Promise; - tryLinkingByAccountInfoOrCreatePrimaryUser({ inputUser, session, tenantId, userContext, }: { + shouldBecomePrimaryUser( + user: User, + tenantId: string, + session: SessionContainerInterface | undefined, + userContext: UserContext + ): Promise; + tryLinkingByAccountInfoOrCreatePrimaryUser({ + inputUser, + session, + tenantId, + userContext, + }: { tenantId: string; inputUser: User; session: SessionContainerInterface | undefined; userContext: UserContext; - }): Promise<{ - status: "OK"; - user: User; - } | { - status: "NO_LINK"; - }>; + }): Promise< + | { + status: "OK"; + user: User; + } + | { + status: "NO_LINK"; + } + >; } diff --git a/lib/build/recipe/accountlinking/recipe.js b/lib/build/recipe/accountlinking/recipe.js index 25d0f4316..577189851 100644 --- a/lib/build/recipe/accountlinking/recipe.js +++ b/lib/build/recipe/accountlinking/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipeModule_1 = __importDefault(require("../../recipeModule")); const utils_1 = require("./utils"); @@ -31,7 +33,7 @@ const utils_2 = require("../../utils"); class Recipe extends recipeModule_1.default { constructor(recipeId, appInfo, config, _recipes, _ingredients) { super(recipeId, appInfo); - this.getPrimaryUserThatCanBeLinkedToRecipeUserId = async ({ tenantId, user, userContext, }) => { + this.getPrimaryUserThatCanBeLinkedToRecipeUserId = async ({ tenantId, user, userContext }) => { // first we check if this user itself is a primary user or not. If it is, we return that. if (user.isPrimaryUser) { return user; @@ -43,9 +45,13 @@ class Recipe extends recipeModule_1.default { doUnionOfAccountInfo: true, userContext, }); - (0, logger_1.logDebugMessage)(`getPrimaryUserThatCanBeLinkedToRecipeUserId found ${users.length} matching users`); + (0, logger_1.logDebugMessage)( + `getPrimaryUserThatCanBeLinkedToRecipeUserId found ${users.length} matching users` + ); let pUsers = users.filter((u) => u.isPrimaryUser); - (0, logger_1.logDebugMessage)(`getPrimaryUserThatCanBeLinkedToRecipeUserId found ${pUsers.length} matching primary users`); + (0, logger_1.logDebugMessage)( + `getPrimaryUserThatCanBeLinkedToRecipeUserId found ${pUsers.length} matching primary users` + ); if (pUsers.length > 1) { // this means that the new user has account info such that it's // spread across multiple primary user IDs. In this case, even @@ -73,7 +79,7 @@ class Recipe extends recipeModule_1.default { } return pUsers.length === 0 ? undefined : pUsers[0]; }; - this.getOldestUserThatCanBeLinkedToRecipeUser = async ({ tenantId, user, userContext, }) => { + this.getOldestUserThatCanBeLinkedToRecipeUser = async ({ tenantId, user, userContext }) => { // first we check if this user itself is a primary user or not. If it is, we return that since it cannot be linked to anything else if (user.isPrimaryUser) { return user; @@ -85,14 +91,24 @@ class Recipe extends recipeModule_1.default { doUnionOfAccountInfo: true, userContext, }); - (0, logger_1.logDebugMessage)(`getOldestUserThatCanBeLinkedToRecipeUser found ${users.length} matching users`); + (0, logger_1.logDebugMessage)( + `getOldestUserThatCanBeLinkedToRecipeUser found ${users.length} matching users` + ); // finally select the oldest one - const oldestUser = users.length === 0 - ? undefined - : users.reduce((min, curr) => (min.timeJoined < curr.timeJoined ? min : curr)); + const oldestUser = + users.length === 0 + ? undefined + : users.reduce((min, curr) => (min.timeJoined < curr.timeJoined ? min : curr)); return oldestUser; }; - this.isSignInAllowed = async ({ user, accountInfo, tenantId, session, signInVerifiesLoginMethod, userContext, }) => { + this.isSignInAllowed = async ({ + user, + accountInfo, + tenantId, + session, + signInVerifiesLoginMethod, + userContext, + }) => { processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.IS_SIGN_IN_ALLOWED_CALLED); if (user.isPrimaryUser || user.loginMethods[0].verified || signInVerifiesLoginMethod) { return true; @@ -107,7 +123,7 @@ class Recipe extends recipeModule_1.default { userContext, }); }; - this.isSignUpAllowed = async ({ newUser, isVerified, session, tenantId, userContext, }) => { + this.isSignUpAllowed = async ({ newUser, isVerified, session, tenantId, userContext }) => { processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.IS_SIGN_UP_ALLOWED_CALLED); if (newUser.email !== undefined && newUser.phoneNumber !== undefined) { // we do this check cause below when we call listUsersByAccountInfo, @@ -124,8 +140,18 @@ class Recipe extends recipeModule_1.default { isSignIn: false, }); }; - this.isSignInUpAllowedHelper = async ({ accountInfo, isVerified, session, tenantId, isSignIn, user, userContext, }) => { - processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.IS_SIGN_IN_UP_ALLOWED_HELPER_CALLED); + this.isSignInUpAllowedHelper = async ({ + accountInfo, + isVerified, + session, + tenantId, + isSignIn, + user, + userContext, + }) => { + processState_1.ProcessState.getInstance().addState( + processState_1.PROCESS_STATE.IS_SIGN_IN_UP_ALLOWED_HELPER_CALLED + ); // since this is a recipe level user, we have to do the following checks // before allowing sign in. We do these checks cause sign in also attempts // account linking: @@ -153,15 +179,21 @@ class Recipe extends recipeModule_1.default { userContext, }); if (users.length === 0) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true because no user with given account info"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true because no user with given account info" + ); // this is a brand new email / phone number, so we allow sign up. return true; } if (isSignIn && user === undefined) { - throw new Error("This should never happen: isSignInUpAllowedHelper called with isSignIn: true, user: undefined"); + throw new Error( + "This should never happen: isSignInUpAllowedHelper called with isSignIn: true, user: undefined" + ); } if (users.length === 1 && isSignIn && user !== undefined && users[0].id === user.id) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true because this is sign in and there is only a single user with the given account info"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true because this is sign in and there is only a single user with the given account info" + ); return true; } // now we check if there exists some primary user with the same email / phone number @@ -182,13 +214,23 @@ class Recipe extends recipeModule_1.default { // account which is unverified sends an email verification email, the legit user might // click on the link and that account (which was unverified and could have been controlled // by an attacker), will end up getting linked to this account. - let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking(accountInfo, undefined, session, tenantId, userContext); + let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking( + accountInfo, + undefined, + session, + tenantId, + userContext + ); if (!shouldDoAccountLinking.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true because account linking is disabled"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true because account linking is disabled" + ); return true; } if (!shouldDoAccountLinking.shouldRequireVerification) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true because dec does not require email verification"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true because dec does not require email verification" + ); // the dev says they do not care about verification before account linking // so we are OK with the risk mentioned above. return true; @@ -204,16 +246,24 @@ class Recipe extends recipeModule_1.default { } let thisIterationIsVerified = false; if (accountInfo.email !== undefined) { - if (currUser.loginMethods[0].hasSameEmailAs(accountInfo.email) && - currUser.loginMethods[0].verified) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper found same email for another user and verified"); + if ( + currUser.loginMethods[0].hasSameEmailAs(accountInfo.email) && + currUser.loginMethods[0].verified + ) { + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper found same email for another user and verified" + ); thisIterationIsVerified = true; } } if (accountInfo.phoneNumber !== undefined) { - if (currUser.loginMethods[0].hasSamePhoneNumberAs(accountInfo.phoneNumber) && - currUser.loginMethods[0].verified) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper found same phone number for another user and verified"); + if ( + currUser.loginMethods[0].hasSamePhoneNumberAs(accountInfo.phoneNumber) && + currUser.loginMethods[0].verified + ) { + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper found same phone number for another user and verified" + ); thisIterationIsVerified = true; } } @@ -224,35 +274,52 @@ class Recipe extends recipeModule_1.default { // users will just see an email already exists error and then will try another // login method. They can also still just go through the password reset flow // and then gain access to their email password account (which can then be verified). - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning false cause one of the other recipe level users is not verified"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning false cause one of the other recipe level users is not verified" + ); shouldAllow = false; break; } } - processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.IS_SIGN_IN_UP_ALLOWED_NO_PRIMARY_USER_EXISTS); + processState_1.ProcessState.getInstance().addState( + processState_1.PROCESS_STATE.IS_SIGN_IN_UP_ALLOWED_NO_PRIMARY_USER_EXISTS + ); (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning " + shouldAllow); return shouldAllow; - } - else { + } else { if (primaryUsers.length > 1) { - throw new Error("You have found a bug. Please report to https://github.com/supertokens/supertokens-node/issues"); + throw new Error( + "You have found a bug. Please report to https://github.com/supertokens/supertokens-node/issues" + ); } let primaryUser = primaryUsers[0]; (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper primary user found"); - let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking(accountInfo, primaryUser, session, tenantId, userContext); + let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking( + accountInfo, + primaryUser, + session, + tenantId, + userContext + ); if (!shouldDoAccountLinking.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true because account linking is disabled"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true because account linking is disabled" + ); return true; } if (!shouldDoAccountLinking.shouldRequireVerification) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true because dec does not require email verification"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true because dec does not require email verification" + ); // the dev says they do not care about verification before account linking // so we can link this new user to the primary user post recipe user creation // even if that user's email / phone number is not verified. return true; } if (!isVerified) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning false because new user's email is not verified, and primary user with the same email was found."); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning false because new user's email is not verified, and primary user with the same email was found." + ); // this will exist early with a false here cause it means that // if we come here, the newUser will be linked to the primary user post email // verification. Whilst this seems OK, there is a risk that the actual user might @@ -283,19 +350,24 @@ class Recipe extends recipeModule_1.default { let lM = primaryUser.loginMethods[i]; if (lM.email !== undefined) { if (lM.hasSameEmailAs(accountInfo.email) && lM.verified) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true cause found same email for primary user and verified"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true cause found same email for primary user and verified" + ); return true; } } if (lM.phoneNumber !== undefined) { if (lM.hasSamePhoneNumberAs(accountInfo.phoneNumber) && lM.verified) { - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning true cause found same phone number for primary user and verified"); + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning true cause found same phone number for primary user and verified" + ); return true; } } } - (0, logger_1.logDebugMessage)("isSignInUpAllowedHelper returning false cause primary user does not have the same email or phone number that is verified" - //"isSignInUpAllowedHelper returning false because new user's email is not verified, and primary user with the same email was found." + (0, logger_1.logDebugMessage)( + "isSignInUpAllowedHelper returning false cause primary user does not have the same email or phone number that is verified" + //"isSignInUpAllowedHelper returning false because new user's email is not verified, and primary user with the same email was found." ); return false; } @@ -333,67 +405,105 @@ class Recipe extends recipeModule_1.default { if (inputUser.isPrimaryUser) { // this is condition one from the above comment. if (otherPrimaryUserForNewEmail.length !== 0) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: returning false cause email change will lead to two primary users having same email on ${tenantId}`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: returning false cause email change will lead to two primary users having same email on ${tenantId}` + ); return { allowed: false, reason: "PRIMARY_USER_CONFLICT" }; } if (input.isVerified) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is primary, new email is verified and doesn't belong to any other primary user`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is primary, new email is verified and doesn't belong to any other primary user` + ); continue; } if (inputUser.loginMethods.some((lm) => lm.hasSameEmailAs(input.newEmail) && lm.verified)) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is primary, new email is verified in another login method and doesn't belong to any other primary user`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is primary, new email is verified in another login method and doesn't belong to any other primary user` + ); continue; } if (otherUsersWithNewEmail.length === 0) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is primary and the new email doesn't belong to any other user (primary or non-primary)`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is primary and the new email doesn't belong to any other user (primary or non-primary)` + ); continue; } - const shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking(otherUsersWithNewEmail[0].loginMethods[0], inputUser, input.session, tenantId, input.userContext); + const shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking( + otherUsersWithNewEmail[0].loginMethods[0], + inputUser, + input.session, + tenantId, + input.userContext + ); if (!shouldDoAccountLinking.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause linking is disabled`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause linking is disabled` + ); continue; } if (!shouldDoAccountLinking.shouldRequireVerification) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause linking is doesn't require email verification`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause linking is doesn't require email verification` + ); continue; } - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: returning false because the user hasn't verified the new email address and there exists another user with it on ${tenantId} and linking requires verification`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: returning false because the user hasn't verified the new email address and there exists another user with it on ${tenantId} and linking requires verification` + ); return { allowed: false, reason: "ACCOUNT_TAKEOVER_RISK" }; - } - else { + } else { if (input.isVerified) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary and new email is verified`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary and new email is verified` + ); continue; } if (inputUser.loginMethods[0].hasSameEmailAs(input.newEmail)) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary and new email is same as the older one`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary and new email is same as the older one` + ); continue; } if (otherPrimaryUserForNewEmail.length === 1) { - let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking(inputUser.loginMethods[0], otherPrimaryUserForNewEmail[0], input.session, tenantId, input.userContext); + let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking( + inputUser.loginMethods[0], + otherPrimaryUserForNewEmail[0], + input.session, + tenantId, + input.userContext + ); if (!shouldDoAccountLinking.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary there exists a primary user exists with the new email, but the dev does not have account linking enabled.`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary there exists a primary user exists with the new email, but the dev does not have account linking enabled.` + ); continue; } if (!shouldDoAccountLinking.shouldRequireVerification) { - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary there exists a primary user exists with the new email, but the dev does not require email verification.`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary there exists a primary user exists with the new email, but the dev does not require email verification.` + ); continue; } - (0, logger_1.logDebugMessage)("isEmailChangeAllowed: returning false cause input user is not a primary there exists a primary user exists with the new email."); + (0, logger_1.logDebugMessage)( + "isEmailChangeAllowed: returning false cause input user is not a primary there exists a primary user exists with the new email." + ); return { allowed: false, reason: "ACCOUNT_TAKEOVER_RISK" }; } - (0, logger_1.logDebugMessage)(`isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary no primary user exists with the new email`); + (0, logger_1.logDebugMessage)( + `isEmailChangeAllowed: can change on ${tenantId} cause input user is not a primary no primary user exists with the new email` + ); continue; } } - (0, logger_1.logDebugMessage)("isEmailChangeAllowed: returning true cause email change can happen on all tenants the user is part of"); + (0, logger_1.logDebugMessage)( + "isEmailChangeAllowed: returning true cause email change can happen on all tenants the user is part of" + ); return { allowed: true }; }; this.verifyEmailForRecipeUserIfLinkedAccountsAreVerified = async (input) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (ignored) { + } catch (ignored) { // if email verification recipe is not initialized, we do a no-op return; } @@ -426,15 +536,17 @@ class Recipe extends recipeModule_1.default { } }); if (shouldVerifyEmail) { - let resp = await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createEmailVerificationToken({ - // While the token we create here is tenant specific, the verification status is not - // So we can use any tenantId the user is associated with here as long as we use the - // same in the verifyEmailUsingToken call - tenantId: input.user.tenantIds[0], - recipeUserId: input.recipeUserId, - email: recipeUserEmail, - userContext: input.userContext, - }); + let resp = await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.createEmailVerificationToken({ + // While the token we create here is tenant specific, the verification status is not + // So we can use any tenantId the user is associated with here as long as we use the + // same in the verifyEmailUsingToken call + tenantId: input.user.tenantIds[0], + recipeUserId: input.recipeUserId, + email: recipeUserEmail, + userContext: input.userContext, + }); if (resp.status === "OK") { // we purposely pass in false below cause we don't want account // linking to happen @@ -452,19 +564,34 @@ class Recipe extends recipeModule_1.default { }; this.config = (0, utils_1.validateAndNormaliseUserInput)(appInfo, config); { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.config, this)); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + this.config, + this + ) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } } static init(config) { return (appInfo, _isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : []), {}, { - emailDelivery: undefined, - }); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ), + {}, + { + emailDelivery: undefined, + } + ); return Recipe.instance; - } - else { + } else { throw new Error("AccountLinking recipe has already been initialised. Please check your code for bugs."); } }; @@ -476,7 +603,10 @@ class Recipe extends recipeModule_1.default { // is not in the recipeList). static getInstance() { if (Recipe.instance === undefined) { - Recipe.init()(supertokens_1.default.getInstanceOrThrowError().appInfo, supertokens_1.default.getInstanceOrThrowError().isInServerlessEnv, [] // ?? + Recipe.init()( + supertokens_1.default.getInstanceOrThrowError().appInfo, + supertokens_1.default.getInstanceOrThrowError().isInServerlessEnv, + [] // ?? ); } return Recipe.instance; @@ -507,19 +637,29 @@ class Recipe extends recipeModule_1.default { Recipe.instance = undefined; } async shouldBecomePrimaryUser(user, tenantId, session, userContext) { - const shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking(user.loginMethods[0], undefined, session, tenantId, userContext); + const shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking( + user.loginMethods[0], + undefined, + session, + tenantId, + userContext + ); if (!shouldDoAccountLinking.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)("shouldBecomePrimaryUser returning false because shouldAutomaticallyLink is false"); + (0, logger_1.logDebugMessage)( + "shouldBecomePrimaryUser returning false because shouldAutomaticallyLink is false" + ); return false; } if (shouldDoAccountLinking.shouldRequireVerification && !user.loginMethods[0].verified) { - (0, logger_1.logDebugMessage)("shouldBecomePrimaryUser returning false because shouldRequireVerification is true but the login method is not verified"); + (0, logger_1.logDebugMessage)( + "shouldBecomePrimaryUser returning false because shouldRequireVerification is true but the login method is not verified" + ); return false; } (0, logger_1.logDebugMessage)("shouldBecomePrimaryUser returning true"); return true; } - async tryLinkingByAccountInfoOrCreatePrimaryUser({ inputUser, session, tenantId, userContext, }) { + async tryLinkingByAccountInfoOrCreatePrimaryUser({ inputUser, session, tenantId, userContext }) { let tries = 0; while (tries++ < 100) { const primaryUserThatCanBeLinkedToTheInputUser = await this.getPrimaryUserThatCanBeLinkedToRecipeUserId({ @@ -528,26 +668,47 @@ class Recipe extends recipeModule_1.default { userContext, }); if (primaryUserThatCanBeLinkedToTheInputUser !== undefined) { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: got primary user we can try linking"); + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: got primary user we can try linking" + ); // we check if the inputUser and primaryUserThatCanBeLinkedToTheInputUser are linked based on recipeIds because the inputUser obj could be outdated - if (!primaryUserThatCanBeLinkedToTheInputUser.loginMethods.some((lm) => lm.recipeUserId.getAsString() === inputUser.loginMethods[0].recipeUserId.getAsString())) { + if ( + !primaryUserThatCanBeLinkedToTheInputUser.loginMethods.some( + (lm) => lm.recipeUserId.getAsString() === inputUser.loginMethods[0].recipeUserId.getAsString() + ) + ) { // If we got a primary user that can be linked to the input user and they are is not linked, we try to link them. // The input user in this case cannot be linked to anything else, otherwise multiple primary users would have the same email // we can use the 0 index cause targetUser is not a primary user. - let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking(inputUser.loginMethods[0], primaryUserThatCanBeLinkedToTheInputUser, session, tenantId, userContext); + let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking( + inputUser.loginMethods[0], + primaryUserThatCanBeLinkedToTheInputUser, + session, + tenantId, + userContext + ); // We already checked if factor setup is allowed by this point, but maybe we should check again? if (!shouldDoAccountLinking.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldAutomaticallyLink is false"); + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldAutomaticallyLink is false" + ); return { status: "NO_LINK" }; } - const accountInfoVerifiedInPrimUser = primaryUserThatCanBeLinkedToTheInputUser.loginMethods.some((lm) => (inputUser.loginMethods[0].email !== undefined && - lm.hasSameEmailAs(inputUser.loginMethods[0].email)) || - (inputUser.loginMethods[0].phoneNumber !== undefined && - lm.hasSamePhoneNumberAs(inputUser.loginMethods[0].phoneNumber) && - lm.verified)); - if (shouldDoAccountLinking.shouldRequireVerification && - (!inputUser.loginMethods[0].verified || !accountInfoVerifiedInPrimUser)) { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldRequireVerification is true but the login method is not verified in the new or the primary user"); + const accountInfoVerifiedInPrimUser = primaryUserThatCanBeLinkedToTheInputUser.loginMethods.some( + (lm) => + (inputUser.loginMethods[0].email !== undefined && + lm.hasSameEmailAs(inputUser.loginMethods[0].email)) || + (inputUser.loginMethods[0].phoneNumber !== undefined && + lm.hasSamePhoneNumberAs(inputUser.loginMethods[0].phoneNumber) && + lm.verified) + ); + if ( + shouldDoAccountLinking.shouldRequireVerification && + (!inputUser.loginMethods[0].verified || !accountInfoVerifiedInPrimUser) + ) { + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldRequireVerification is true but the login method is not verified in the new or the primary user" + ); return { status: "NO_LINK" }; } (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser linking"); @@ -559,29 +720,34 @@ class Recipe extends recipeModule_1.default { if (linkAccountsResult.status === "OK") { (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser successfully linked"); return { status: "OK", user: linkAccountsResult.user }; - } - else if (linkAccountsResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR") { + } else if ( + linkAccountsResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + ) { // this can happen cause of a race condition wherein the recipe user ID get's linked to // some other primary user whilst this function is running. // We can return this directly, because: // 1. a retry would result in the same // 2. the tryLinkingByAccountInfoOrCreatePrimaryUser doesn't specify where it should be linked // and we can't linked it to anything here after it became primary/linked to another primary user - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser already linked to another user"); + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser already linked to another user" + ); return { status: "OK", user: linkAccountsResult.user, }; - } - else if (linkAccountsResult.status === "INPUT_USER_IS_NOT_A_PRIMARY_USER") { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition"); + } else if (linkAccountsResult.status === "INPUT_USER_IS_NOT_A_PRIMARY_USER") { + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition" + ); // this can be possible during a race condition wherein the primary user // that we fetched somehow is no more a primary user. This can happen if // the unlink function was called in parallel on that user. So we can just retry continue; - } - else { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition"); + } else { + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition" + ); // status is "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" // it can come here if the recipe user ID can't be linked to the primary user ID cause // the email / phone number is associated with some other primary user ID. @@ -602,11 +768,20 @@ class Recipe extends recipeModule_1.default { tenantId, userContext, }); - if (oldestUserThatCanBeLinkedToTheInputUser !== undefined && - oldestUserThatCanBeLinkedToTheInputUser.id !== inputUser.id) { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: got an older user we can try linking"); + if ( + oldestUserThatCanBeLinkedToTheInputUser !== undefined && + oldestUserThatCanBeLinkedToTheInputUser.id !== inputUser.id + ) { + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: got an older user we can try linking" + ); // We know that the older user isn't primary, otherwise we'd hit the branch above. - let shouldMakeOlderUserPrimary = await this.shouldBecomePrimaryUser(oldestUserThatCanBeLinkedToTheInputUser, tenantId, session, userContext); + let shouldMakeOlderUserPrimary = await this.shouldBecomePrimaryUser( + oldestUserThatCanBeLinkedToTheInputUser, + tenantId, + session, + userContext + ); // if the app doesn't want to make the older user primary, we can't link to it // so we fall back to trying the newer user primary (and not linking) if (shouldMakeOlderUserPrimary) { @@ -614,24 +789,38 @@ class Recipe extends recipeModule_1.default { recipeUserId: oldestUserThatCanBeLinkedToTheInputUser.loginMethods[0].recipeUserId, userContext, }); - if (createPrimaryUserResult.status === - "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" || - createPrimaryUserResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR") { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: retrying because createPrimaryUser returned " + - createPrimaryUserResult.status); + if ( + createPrimaryUserResult.status === + "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" || + createPrimaryUserResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR" + ) { + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: retrying because createPrimaryUser returned " + + createPrimaryUserResult.status + ); continue; } // If we got a primary user that can be linked to the input user and they are is not linked, we try to link them. // The input user in this case cannot be linked to anything else, otherwise multiple primary users would have the same email // we can use the 0 index cause targetUser is not a primary user. - let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking(inputUser.loginMethods[0], createPrimaryUserResult.user, session, tenantId, userContext); + let shouldDoAccountLinking = await this.config.shouldDoAutomaticAccountLinking( + inputUser.loginMethods[0], + createPrimaryUserResult.user, + session, + tenantId, + userContext + ); // We already checked if factor setup is allowed by this point, but maybe we should check again? if (!shouldDoAccountLinking.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldAutomaticallyLink is false"); + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldAutomaticallyLink is false" + ); return { status: "NO_LINK" }; } if (shouldDoAccountLinking.shouldRequireVerification && !inputUser.loginMethods[0].verified) { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldRequireVerification is true but the login method is not verified"); + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: not linking because shouldRequireVerification is true but the login method is not verified" + ); return { status: "NO_LINK" }; } (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser linking"); @@ -643,29 +832,34 @@ class Recipe extends recipeModule_1.default { if (linkAccountsResult.status === "OK") { (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser successfully linked"); return { status: "OK", user: linkAccountsResult.user }; - } - else if (linkAccountsResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR") { + } else if ( + linkAccountsResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + ) { // this can happen cause of a race condition wherein the recipe user ID get's linked to // some other primary user whilst this function is running. // We can return this directly, because: // 1. a retry would result in the same // 2. the tryLinkingByAccountInfoOrCreatePrimaryUser doesn't specify where it should be linked // and we can't linked it to anything here after it became primary/linked to another primary user - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser already linked to another user"); + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser already linked to another user" + ); return { status: "OK", user: linkAccountsResult.user, }; - } - else if (linkAccountsResult.status === "INPUT_USER_IS_NOT_A_PRIMARY_USER") { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition"); + } else if (linkAccountsResult.status === "INPUT_USER_IS_NOT_A_PRIMARY_USER") { + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition" + ); // this can be possible during a race condition wherein the primary user // that we fetched somehow is no more a primary user. This can happen if // the unlink function was called in parallel on that user. So we can just retry continue; - } - else { - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition"); + } else { + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser linking failed because of a race condition" + ); // status is "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" // it can come here if the recipe user ID can't be linked to the primary user ID cause // the email / phone number is associated with some other primary user ID. @@ -677,7 +871,9 @@ class Recipe extends recipeModule_1.default { } } } - (0, logger_1.logDebugMessage)("tryLinkingByAccountInfoOrCreatePrimaryUser: trying to make the current user primary"); + (0, logger_1.logDebugMessage)( + "tryLinkingByAccountInfoOrCreatePrimaryUser: trying to make the current user primary" + ); // In this case we have no other account we can link to, so we check if the current user should become a primary user if (await this.shouldBecomePrimaryUser(inputUser, tenantId, session, userContext)) { let createPrimaryUserResult = await this.recipeInterfaceImpl.createPrimaryUser({ @@ -689,14 +885,15 @@ class Recipe extends recipeModule_1.default { // meaning that the recipe user ID is already linked to another primary user id (race condition), or that some other // primary user ID exists with the same email / phone number (again, race condition). // In this case we call a retry in createPrimaryUserIdOrLinkByAccountInfo - if (createPrimaryUserResult.status === - "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" || - createPrimaryUserResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR") { + if ( + createPrimaryUserResult.status === + "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" || + createPrimaryUserResult.status === "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR" + ) { continue; } return createPrimaryUserResult; - } - else { + } else { // If not we return it unchanged return { status: "OK", user: inputUser }; } diff --git a/lib/build/recipe/accountlinking/recipeImplementation.d.ts b/lib/build/recipe/accountlinking/recipeImplementation.d.ts index ca08e95b6..76484c9cd 100644 --- a/lib/build/recipe/accountlinking/recipeImplementation.d.ts +++ b/lib/build/recipe/accountlinking/recipeImplementation.d.ts @@ -2,4 +2,8 @@ import { RecipeInterface, TypeNormalisedInput } from "./types"; import { Querier } from "../../querier"; import type AccountLinkingRecipe from "./recipe"; -export default function getRecipeImplementation(querier: Querier, config: TypeNormalisedInput, recipeInstance: AccountLinkingRecipe): RecipeInterface; +export default function getRecipeImplementation( + querier: Querier, + config: TypeNormalisedInput, + recipeInstance: AccountLinkingRecipe +): RecipeInterface; diff --git a/lib/build/recipe/accountlinking/recipeImplementation.js b/lib/build/recipe/accountlinking/recipeImplementation.js index 65ec0ee3a..823f6be52 100644 --- a/lib/build/recipe/accountlinking/recipeImplementation.js +++ b/lib/build/recipe/accountlinking/recipeImplementation.js @@ -13,53 +13,97 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeImplementation; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const user_1 = require("../../user"); function getRecipeImplementation(querier, config, recipeInstance) { return { - getUsers: async function ({ tenantId, timeJoinedOrder, limit, paginationToken, includeRecipeIds, query, userContext, }) { + getUsers: async function ({ + tenantId, + timeJoinedOrder, + limit, + paginationToken, + includeRecipeIds, + query, + userContext, + }) { let includeRecipeIdsStr = undefined; if (includeRecipeIds !== undefined) { includeRecipeIdsStr = includeRecipeIds.join(","); } - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`${tenantId !== null && tenantId !== void 0 ? tenantId : "public"}/users`), Object.assign({ includeRecipeIds: includeRecipeIdsStr, timeJoinedOrder: timeJoinedOrder, limit: limit, paginationToken: paginationToken }, query), userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default( + `${tenantId !== null && tenantId !== void 0 ? tenantId : "public"}/users` + ), + Object.assign( + { + includeRecipeIds: includeRecipeIdsStr, + timeJoinedOrder: timeJoinedOrder, + limit: limit, + paginationToken: paginationToken, + }, + query + ), + userContext + ); return { users: response.users.map((u) => new user_1.User(u)), nextPaginationToken: response.nextPaginationToken, }; }, - canCreatePrimaryUser: async function ({ recipeUserId, userContext, }) { - return await querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/accountlinking/user/primary/check"), { - recipeUserId: recipeUserId.getAsString(), - }, userContext); + canCreatePrimaryUser: async function ({ recipeUserId, userContext }) { + return await querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/accountlinking/user/primary/check"), + { + recipeUserId: recipeUserId.getAsString(), + }, + userContext + ); }, - createPrimaryUser: async function ({ recipeUserId, userContext, }) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/accountlinking/user/primary"), { - recipeUserId: recipeUserId.getAsString(), - }, userContext); + createPrimaryUser: async function ({ recipeUserId, userContext }) { + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/accountlinking/user/primary"), + { + recipeUserId: recipeUserId.getAsString(), + }, + userContext + ); if (response.status === "OK") { response.user = new user_1.User(response.user); } return response; }, - canLinkAccounts: async function ({ recipeUserId, primaryUserId, userContext, }) { - let result = await querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/accountlinking/user/link/check"), { - recipeUserId: recipeUserId.getAsString(), - primaryUserId, - }, userContext); + canLinkAccounts: async function ({ recipeUserId, primaryUserId, userContext }) { + let result = await querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/accountlinking/user/link/check"), + { + recipeUserId: recipeUserId.getAsString(), + primaryUserId, + }, + userContext + ); return result; }, - linkAccounts: async function ({ recipeUserId, primaryUserId, userContext, }) { - const accountsLinkingResult = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/accountlinking/user/link"), { - recipeUserId: recipeUserId.getAsString(), - primaryUserId, - }, userContext); - if (["OK", "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"].includes(accountsLinkingResult.status)) { + linkAccounts: async function ({ recipeUserId, primaryUserId, userContext }) { + const accountsLinkingResult = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/accountlinking/user/link"), + { + recipeUserId: recipeUserId.getAsString(), + primaryUserId, + }, + userContext + ); + if ( + ["OK", "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"].includes( + accountsLinkingResult.status + ) + ) { accountsLinkingResult.user = new user_1.User(accountsLinkingResult.user); } if (accountsLinkingResult.status === "OK") { @@ -78,7 +122,9 @@ function getRecipeImplementation(querier, config, recipeInstance) { throw Error("this error should never be thrown"); } user = updatedUser; - let loginMethodInfo = user.loginMethods.find((u) => u.recipeUserId.getAsString() === recipeUserId.getAsString()); + let loginMethodInfo = user.loginMethods.find( + (u) => u.recipeUserId.getAsString() === recipeUserId.getAsString() + ); if (loginMethodInfo === undefined) { throw Error("this error should never be thrown"); } @@ -88,37 +134,55 @@ function getRecipeImplementation(querier, config, recipeInstance) { } return accountsLinkingResult; }, - unlinkAccount: async function ({ recipeUserId, userContext, }) { - let accountsUnlinkingResult = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/accountlinking/user/unlink"), { - recipeUserId: recipeUserId.getAsString(), - }, userContext); + unlinkAccount: async function ({ recipeUserId, userContext }) { + let accountsUnlinkingResult = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/accountlinking/user/unlink"), + { + recipeUserId: recipeUserId.getAsString(), + }, + userContext + ); return accountsUnlinkingResult; }, getUser: async function ({ userId, userContext }) { - let result = await querier.sendGetRequest(new normalisedURLPath_1.default("/user/id"), { - userId, - }, userContext); + let result = await querier.sendGetRequest( + new normalisedURLPath_1.default("/user/id"), + { + userId, + }, + userContext + ); if (result.status === "OK") { return new user_1.User(result.user); } return undefined; }, - listUsersByAccountInfo: async function ({ tenantId, accountInfo, doUnionOfAccountInfo, userContext, }) { + listUsersByAccountInfo: async function ({ tenantId, accountInfo, doUnionOfAccountInfo, userContext }) { var _a, _b; - let result = await querier.sendGetRequest(new normalisedURLPath_1.default(`${tenantId !== null && tenantId !== void 0 ? tenantId : "public"}/users/by-accountinfo`), { - email: accountInfo.email, - phoneNumber: accountInfo.phoneNumber, - thirdPartyId: (_a = accountInfo.thirdParty) === null || _a === void 0 ? void 0 : _a.id, - thirdPartyUserId: (_b = accountInfo.thirdParty) === null || _b === void 0 ? void 0 : _b.userId, - doUnionOfAccountInfo, - }, userContext); + let result = await querier.sendGetRequest( + new normalisedURLPath_1.default( + `${tenantId !== null && tenantId !== void 0 ? tenantId : "public"}/users/by-accountinfo` + ), + { + email: accountInfo.email, + phoneNumber: accountInfo.phoneNumber, + thirdPartyId: (_a = accountInfo.thirdParty) === null || _a === void 0 ? void 0 : _a.id, + thirdPartyUserId: (_b = accountInfo.thirdParty) === null || _b === void 0 ? void 0 : _b.userId, + doUnionOfAccountInfo, + }, + userContext + ); return result.users.map((u) => new user_1.User(u)); }, - deleteUser: async function ({ userId, removeAllLinkedAccounts, userContext, }) { - return await querier.sendPostRequest(new normalisedURLPath_1.default("/user/remove"), { - userId, - removeAllLinkedAccounts, - }, userContext); + deleteUser: async function ({ userId, removeAllLinkedAccounts, userContext }) { + return await querier.sendPostRequest( + new normalisedURLPath_1.default("/user/remove"), + { + userId, + removeAllLinkedAccounts, + }, + userContext + ); }, }; } diff --git a/lib/build/recipe/accountlinking/types.d.ts b/lib/build/recipe/accountlinking/types.d.ts index 001de1514..b4c7ba42f 100644 --- a/lib/build/recipe/accountlinking/types.d.ts +++ b/lib/build/recipe/accountlinking/types.d.ts @@ -5,30 +5,54 @@ import RecipeUserId from "../../recipeUserId"; import { SessionContainerInterface } from "../session/types"; export type TypeInput = { onAccountLinked?: (user: User, newAccountInfo: RecipeLevelUser, userContext: UserContext) => Promise; - shouldDoAutomaticAccountLinking?: (newAccountInfo: AccountInfoWithRecipeId & { - recipeUserId?: RecipeUserId; - }, user: User | undefined, session: SessionContainerInterface | undefined, tenantId: string, userContext: UserContext) => Promise<{ - shouldAutomaticallyLink: false; - } | { - shouldAutomaticallyLink: true; - shouldRequireVerification: boolean; - }>; + shouldDoAutomaticAccountLinking?: ( + newAccountInfo: AccountInfoWithRecipeId & { + recipeUserId?: RecipeUserId; + }, + user: User | undefined, + session: SessionContainerInterface | undefined, + tenantId: string, + userContext: UserContext + ) => Promise< + | { + shouldAutomaticallyLink: false; + } + | { + shouldAutomaticallyLink: true; + shouldRequireVerification: boolean; + } + >; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; }; }; export type TypeNormalisedInput = { onAccountLinked: (user: User, newAccountInfo: RecipeLevelUser, userContext: UserContext) => Promise; - shouldDoAutomaticAccountLinking: (newAccountInfo: AccountInfoWithRecipeId & { - recipeUserId?: RecipeUserId; - }, user: User | undefined, session: SessionContainerInterface | undefined, tenantId: string, userContext: UserContext) => Promise<{ - shouldAutomaticallyLink: false; - } | { - shouldAutomaticallyLink: true; - shouldRequireVerification: boolean; - }>; + shouldDoAutomaticAccountLinking: ( + newAccountInfo: AccountInfoWithRecipeId & { + recipeUserId?: RecipeUserId; + }, + user: User | undefined, + session: SessionContainerInterface | undefined, + tenantId: string, + userContext: UserContext + ) => Promise< + | { + shouldAutomaticallyLink: false; + } + | { + shouldAutomaticallyLink: true; + shouldRequireVerification: boolean; + } + >; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; }; }; export type RecipeInterface = { @@ -49,66 +73,85 @@ export type RecipeInterface = { canCreatePrimaryUser: (input: { recipeUserId: RecipeUserId; userContext: UserContext; - }) => Promise<{ - status: "OK"; - wasAlreadyAPrimaryUser: boolean; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - }>; + }) => Promise< + | { + status: "OK"; + wasAlreadyAPrimaryUser: boolean; + } + | { + status: + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + >; createPrimaryUser: (input: { recipeUserId: RecipeUserId; userContext: UserContext; - }) => Promise<{ - status: "OK"; - user: User; - wasAlreadyAPrimaryUser: boolean; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - } | { - status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - }>; + }) => Promise< + | { + status: "OK"; + user: User; + wasAlreadyAPrimaryUser: boolean; + } + | { + status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + } + | { + status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + >; canLinkAccounts: (input: { recipeUserId: RecipeUserId; primaryUserId: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - accountsAlreadyLinked: boolean; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - description: string; - primaryUserId: string; - } | { - status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - } | { - status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; - }>; + }) => Promise< + | { + status: "OK"; + accountsAlreadyLinked: boolean; + } + | { + status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + description: string; + primaryUserId: string; + } + | { + status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + | { + status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; + } + >; linkAccounts: (input: { recipeUserId: RecipeUserId; primaryUserId: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - accountsAlreadyLinked: boolean; - user: User; - } | { - status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - user: User; - } | { - status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - primaryUserId: string; - description: string; - } | { - status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; - }>; + }) => Promise< + | { + status: "OK"; + accountsAlreadyLinked: boolean; + user: User; + } + | { + status: "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + user: User; + } + | { + status: "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + primaryUserId: string; + description: string; + } + | { + status: "INPUT_USER_IS_NOT_A_PRIMARY_USER"; + } + >; unlinkAccount: (input: { recipeUserId: RecipeUserId; userContext: UserContext; @@ -117,10 +160,7 @@ export type RecipeInterface = { wasRecipeUserDeleted: boolean; wasLinked: boolean; }>; - getUser: (input: { - userId: string; - userContext: UserContext; - }) => Promise; + getUser: (input: { userId: string; userContext: UserContext }) => Promise; listUsersByAccountInfo: (input: { tenantId: string; accountInfo: AccountInfo; diff --git a/lib/build/recipe/accountlinking/utils.js b/lib/build/recipe/accountlinking/utils.js index 4bd714895..9a86c8015 100644 --- a/lib/build/recipe/accountlinking/utils.js +++ b/lib/build/recipe/accountlinking/utils.js @@ -16,7 +16,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.recipeInitDefinedShouldDoAutomaticAccountLinking = recipeInitDefinedShouldDoAutomaticAccountLinking; exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; -async function defaultOnAccountLinked() { } +async function defaultOnAccountLinked() {} async function defaultShouldDoAutomaticAccountLinking() { return { shouldAutomaticallyLink: false, @@ -26,9 +26,15 @@ function recipeInitDefinedShouldDoAutomaticAccountLinking(config) { return config.shouldDoAutomaticAccountLinking !== defaultShouldDoAutomaticAccountLinking; } function validateAndNormaliseUserInput(_, config) { - let onAccountLinked = (config === null || config === void 0 ? void 0 : config.onAccountLinked) || defaultOnAccountLinked; - let shouldDoAutomaticAccountLinking = (config === null || config === void 0 ? void 0 : config.shouldDoAutomaticAccountLinking) || defaultShouldDoAutomaticAccountLinking; - let override = Object.assign({ functions: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let onAccountLinked = + (config === null || config === void 0 ? void 0 : config.onAccountLinked) || defaultOnAccountLinked; + let shouldDoAutomaticAccountLinking = + (config === null || config === void 0 ? void 0 : config.shouldDoAutomaticAccountLinking) || + defaultShouldDoAutomaticAccountLinking; + let override = Object.assign( + { functions: (originalImplementation) => originalImplementation }, + config === null || config === void 0 ? void 0 : config.override + ); return { override, onAccountLinked, diff --git a/lib/build/recipe/dashboard/api/analytics.d.ts b/lib/build/recipe/dashboard/api/analytics.d.ts index d28219314..7a3a834cd 100644 --- a/lib/build/recipe/dashboard/api/analytics.d.ts +++ b/lib/build/recipe/dashboard/api/analytics.d.ts @@ -4,4 +4,9 @@ import { UserContext } from "../../../types"; export type Response = { status: "OK"; }; -export default function analyticsPost(_: APIInterface, ___: string, options: APIOptions, userContext: UserContext): Promise; +export default function analyticsPost( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/analytics.js b/lib/build/recipe/dashboard/api/analytics.js index 71db967bb..abb9d745c 100644 --- a/lib/build/recipe/dashboard/api/analytics.js +++ b/lib/build/recipe/dashboard/api/analytics.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = analyticsPost; const supertokens_1 = __importDefault(require("../../../supertokens")); @@ -52,9 +54,10 @@ async function analyticsPost(_, ___, options, userContext) { if (response.exists) { telemetryId = response.telemetryId; } - numberOfUsers = await supertokens_1.default.getInstanceOrThrowError().getUserCount(undefined, undefined, userContext); - } - catch (_) { + numberOfUsers = await supertokens_1.default + .getInstanceOrThrowError() + .getUserCount(undefined, undefined, userContext); + } catch (_) { // If either telemetry id API or user count fetch fails, no event should be sent return { status: "OK", @@ -84,8 +87,7 @@ async function analyticsPost(_, ___, options, userContext) { "content-type": "application/json; charset=utf-8", }, }); - } - catch (e) { + } catch (e) { // Ignored } return { diff --git a/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts b/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts index d8c92a94d..eb8ad8d0e 100644 --- a/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts +++ b/lib/build/recipe/dashboard/api/apiKeyProtector.d.ts @@ -1,4 +1,10 @@ // @ts-nocheck import { UserContext } from "../../../types"; import { APIFunction, APIInterface, APIOptions } from "../types"; -export default function apiKeyProtector(apiImplementation: APIInterface, tenantId: string, options: APIOptions, apiFunction: APIFunction, userContext: UserContext): Promise; +export default function apiKeyProtector( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + apiFunction: APIFunction, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/apiKeyProtector.js b/lib/build/recipe/dashboard/api/apiKeyProtector.js index a7e9feddc..4825b948e 100644 --- a/lib/build/recipe/dashboard/api/apiKeyProtector.js +++ b/lib/build/recipe/dashboard/api/apiKeyProtector.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = apiKeyProtector; const error_1 = __importDefault(require("../error")); @@ -14,8 +16,7 @@ async function apiKeyProtector(apiImplementation, tenantId, options, apiFunction config: options.config, userContext, }); - } - catch (e) { + } catch (e) { if (error_1.default.isErrorFromSuperTokens(e) && e.type === error_1.default.OPERATION_NOT_ALLOWED) { options.res.setStatusCode(403); options.res.sendJSONResponse({ diff --git a/lib/build/recipe/dashboard/api/dashboard.d.ts b/lib/build/recipe/dashboard/api/dashboard.d.ts index 560d91749..252a4acf3 100644 --- a/lib/build/recipe/dashboard/api/dashboard.d.ts +++ b/lib/build/recipe/dashboard/api/dashboard.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { UserContext } from "../../../types"; import { APIInterface, APIOptions } from "../types"; -export default function dashboard(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function dashboard( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/implementation.js b/lib/build/recipe/dashboard/api/implementation.js index f5851a26f..d27d45f51 100644 --- a/lib/build/recipe/dashboard/api/implementation.js +++ b/lib/build/recipe/dashboard/api/implementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIImplementation; const normalisedURLDomain_1 = __importDefault(require("../../../normalisedURLDomain")); @@ -30,18 +32,25 @@ function getAPIImplementation() { const bundleBasePathString = await input.options.recipeImplementation.getDashboardBundleLocation({ userContext: input.userContext, }); - const bundleDomain = new normalisedURLDomain_1.default(bundleBasePathString).getAsStringDangerous() + + const bundleDomain = + new normalisedURLDomain_1.default(bundleBasePathString).getAsStringDangerous() + new normalisedURLPath_1.default(bundleBasePathString).getAsStringDangerous(); let connectionURI = ""; const superTokensInstance = supertokens_1.default.getInstanceOrThrowError(); const authMode = input.options.config.authMode; if (superTokensInstance.supertokens !== undefined) { connectionURI = - new normalisedURLDomain_1.default(superTokensInstance.supertokens.connectionURI.split(";")[0]).getAsStringDangerous() + - new normalisedURLPath_1.default(superTokensInstance.supertokens.connectionURI.split(";")[0]).getAsStringDangerous(); + new normalisedURLDomain_1.default( + superTokensInstance.supertokens.connectionURI.split(";")[0] + ).getAsStringDangerous() + + new normalisedURLPath_1.default( + superTokensInstance.supertokens.connectionURI.split(";")[0] + ).getAsStringDangerous(); } let isSearchEnabled = false; - const cdiVersion = await querier_1.Querier.getNewInstanceOrThrowError(input.options.recipeId).getAPIVersion(input.userContext); + const cdiVersion = await querier_1.Querier.getNewInstanceOrThrowError(input.options.recipeId).getAPIVersion( + input.userContext + ); if ((0, utils_1.maxVersion)("2.20", cdiVersion) === cdiVersion) { // Only enable search if CDI version is 2.20 or above isSearchEnabled = true; @@ -67,8 +76,8 @@ function getAPIImplementation() { }); window.staticBasePath = "${bundleDomain}/static" window.dashboardAppPath = "${input.options.appInfo.apiBasePath - .appendPath(new normalisedURLPath_1.default(constants_1.DASHBOARD_API)) - .getAsStringDangerous()}" + .appendPath(new normalisedURLPath_1.default(constants_1.DASHBOARD_API)) + .getAsStringDangerous()}" window.connectionURI = "${connectionURI}" window.authMode = "${authMode}" window.isSearchEnabled = "${isSearchEnabled}" diff --git a/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.d.ts b/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.d.ts index 9f8ff7b86..10331dfb0 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.d.ts @@ -1,13 +1,21 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; - createdNew: boolean; -} | { - status: "UNKNOWN_TENANT_ERROR"; -} | { - status: "BOXY_ERROR"; - message: string; -}; -export default function createOrUpdateThirdPartyConfig(_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + createdNew: boolean; + } + | { + status: "UNKNOWN_TENANT_ERROR"; + } + | { + status: "BOXY_ERROR"; + message: string; + }; +export default function createOrUpdateThirdPartyConfig( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js b/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js index 178c73067..da9585eb5 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js +++ b/lib/build/recipe/dashboard/api/multitenancy/createOrUpdateThirdPartyConfig.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = createOrUpdateThirdPartyConfig; const multitenancy_1 = __importDefault(require("../../../multitenancy")); @@ -24,11 +26,23 @@ async function createOrUpdateThirdPartyConfig(_, tenantId, options, userContext) if (tenantRes.thirdParty.providers.length === 0) { // This means that the tenant was using the static list of providers, we need to add them all before adding the new one const mtRecipe = recipe_1.default.getInstance(); - const staticProviders = (_a = mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.staticThirdPartyProviders) !== null && _a !== void 0 ? _a : []; - for (const provider of staticProviders.filter((provider) => provider.includeInNonPublicTenantsByDefault === true || tenantId === constants_1.DEFAULT_TENANT_ID)) { - await multitenancy_1.default.createOrUpdateThirdPartyConfig(tenantId, { - thirdPartyId: provider.config.thirdPartyId, - }, undefined, userContext); + const staticProviders = + (_a = mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.staticThirdPartyProviders) !== null && + _a !== void 0 + ? _a + : []; + for (const provider of staticProviders.filter( + (provider) => + provider.includeInNonPublicTenantsByDefault === true || tenantId === constants_1.DEFAULT_TENANT_ID + )) { + await multitenancy_1.default.createOrUpdateThirdPartyConfig( + tenantId, + { + thirdPartyId: provider.config.thirdPartyId, + }, + undefined, + userContext + ); // delay after each provider to avoid rate limiting await new Promise((r) => setTimeout(r, 500)); // 500ms } @@ -37,14 +51,17 @@ async function createOrUpdateThirdPartyConfig(_, tenantId, options, userContext) const boxyURL = providerConfig.clients[0].additionalConfig.boxyURL; const boxyAPIKey = providerConfig.clients[0].additionalConfig.boxyAPIKey; providerConfig.clients[0].additionalConfig.boxyAPIKey = undefined; - if (boxyAPIKey && + if ( + boxyAPIKey && (providerConfig.clients[0].additionalConfig.samlInputType === "xml" || - providerConfig.clients[0].additionalConfig.samlInputType === "url")) { + providerConfig.clients[0].additionalConfig.samlInputType === "url") + ) { const requestBody = { name: "", label: "", description: "", - tenant: providerConfig.clients[0].additionalConfig.boxyTenant || + tenant: + providerConfig.clients[0].additionalConfig.boxyTenant || `${tenantId}-${providerConfig.thirdPartyId}`, product: providerConfig.clients[0].additionalConfig.boxyProduct || "supertokens", defaultRedirectUrl: providerConfig.clients[0].additionalConfig.redirectURLs[0], @@ -58,10 +75,14 @@ async function createOrUpdateThirdPartyConfig(_, tenantId, options, userContext) const normalisedDomain = new normalisedURLDomain_1.default(boxyURL); const normalisedBasePath = new normalisedURLPath_1.default(boxyURL); const connectionsPath = new normalisedURLPath_1.default("/api/v1/saml/config"); - const resp = await (0, thirdpartyUtils_1.doPostRequest)(normalisedDomain.getAsStringDangerous() + - normalisedBasePath.appendPath(connectionsPath).getAsStringDangerous(), requestBody, { - Authorization: `Api-Key ${boxyAPIKey}`, - }); + const resp = await (0, thirdpartyUtils_1.doPostRequest)( + normalisedDomain.getAsStringDangerous() + + normalisedBasePath.appendPath(connectionsPath).getAsStringDangerous(), + requestBody, + { + Authorization: `Api-Key ${boxyAPIKey}`, + } + ); if (resp.status !== 200) { if (resp.status === 401) { return { @@ -81,6 +102,11 @@ async function createOrUpdateThirdPartyConfig(_, tenantId, options, userContext) providerConfig.clients[0].clientSecret = resp.jsonResponse.clientSecret; } } - const thirdPartyRes = await multitenancy_1.default.createOrUpdateThirdPartyConfig(tenantId, providerConfig, undefined, userContext); + const thirdPartyRes = await multitenancy_1.default.createOrUpdateThirdPartyConfig( + tenantId, + providerConfig, + undefined, + userContext + ); return thirdPartyRes; } diff --git a/lib/build/recipe/dashboard/api/multitenancy/createTenant.d.ts b/lib/build/recipe/dashboard/api/multitenancy/createTenant.d.ts index ff8c4293b..7e5bad952 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/createTenant.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/createTenant.d.ts @@ -1,13 +1,21 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; - createdNew: boolean; -} | { - status: "MULTITENANCY_NOT_ENABLED_IN_CORE_ERROR" | "TENANT_ID_ALREADY_EXISTS_ERROR"; -} | { - status: "INVALID_TENANT_ID_ERROR"; - message: string; -}; -export default function createTenant(_: APIInterface, __: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + createdNew: boolean; + } + | { + status: "MULTITENANCY_NOT_ENABLED_IN_CORE_ERROR" | "TENANT_ID_ALREADY_EXISTS_ERROR"; + } + | { + status: "INVALID_TENANT_ID_ERROR"; + message: string; + }; +export default function createTenant( + _: APIInterface, + __: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/createTenant.js b/lib/build/recipe/dashboard/api/multitenancy/createTenant.js index bc65e4453..d03d62f55 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/createTenant.js +++ b/lib/build/recipe/dashboard/api/multitenancy/createTenant.js @@ -1,25 +1,28 @@ "use strict"; -var __rest = (this && this.__rest) || function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __rest = + (this && this.__rest) || + function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; + } + return t; + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = createTenant; const multitenancy_1 = __importDefault(require("../../../multitenancy")); const error_1 = __importDefault(require("../../../../error")); async function createTenant(_, __, options, userContext) { const requestBody = await options.req.getJSONBody(); - const { tenantId } = requestBody, config = __rest(requestBody, ["tenantId"]); + const { tenantId } = requestBody, + config = __rest(requestBody, ["tenantId"]); if (typeof tenantId !== "string" || tenantId === "") { throw new error_1.default({ message: "Missing required parameter 'tenantId'", @@ -29,8 +32,7 @@ async function createTenant(_, __, options, userContext) { let tenantRes; try { tenantRes = await multitenancy_1.default.createOrUpdateTenant(tenantId, config, userContext); - } - catch (err) { + } catch (err) { const errMsg = err.message; if (errMsg.includes("SuperTokens core threw an error for a ")) { if (errMsg.includes("with status code: 402")) { diff --git a/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.d.ts b/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.d.ts index b8c3cb3c6..ee98ec2ec 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.d.ts @@ -1,10 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; - didExist: boolean; -} | { - status: "CANNOT_DELETE_PUBLIC_TENANT_ERROR"; -}; -export default function deleteTenant(_: APIInterface, tenantId: string, __: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + didExist: boolean; + } + | { + status: "CANNOT_DELETE_PUBLIC_TENANT_ERROR"; + }; +export default function deleteTenant( + _: APIInterface, + tenantId: string, + __: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.js b/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.js index 0c3ba1fee..0d00947b9 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.js +++ b/lib/build/recipe/dashboard/api/multitenancy/deleteTenant.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = deleteTenant; const multitenancy_1 = __importDefault(require("../../../multitenancy")); @@ -9,8 +11,7 @@ async function deleteTenant(_, tenantId, __, userContext) { try { const deleteTenantRes = await multitenancy_1.default.deleteTenant(tenantId, userContext); return deleteTenantRes; - } - catch (err) { + } catch (err) { const errMsg = err.message; if (errMsg.includes("SuperTokens core threw an error for a ") && errMsg.includes("with status code: 403")) { return { diff --git a/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.d.ts b/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.d.ts index 6bcebed16..f554ce80b 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.d.ts @@ -1,10 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; - didConfigExist: boolean; -} | { - status: "UNKNOWN_TENANT_ERROR"; -}; -export default function deleteThirdPartyConfig(_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + didConfigExist: boolean; + } + | { + status: "UNKNOWN_TENANT_ERROR"; + }; +export default function deleteThirdPartyConfig( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js b/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js index 8bd135115..ce6b819d7 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js +++ b/lib/build/recipe/dashboard/api/multitenancy/deleteThirdPartyConfig.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = deleteThirdPartyConfig; const multitenancy_1 = __importDefault(require("../../../multitenancy")); @@ -28,17 +30,28 @@ async function deleteThirdPartyConfig(_, tenantId, options, userContext) { if (thirdPartyIdsFromCore.length === 0) { // this means that the tenant was using the static list of providers, we need to add them all before deleting one const mtRecipe = recipe_1.default.getInstance(); - const staticProviders = (_a = mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.staticThirdPartyProviders) !== null && _a !== void 0 ? _a : []; - for (const provider of staticProviders.filter((provider) => provider.includeInNonPublicTenantsByDefault === true || tenantId === constants_1.DEFAULT_TENANT_ID)) { + const staticProviders = + (_a = mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.staticThirdPartyProviders) !== null && + _a !== void 0 + ? _a + : []; + for (const provider of staticProviders.filter( + (provider) => + provider.includeInNonPublicTenantsByDefault === true || tenantId === constants_1.DEFAULT_TENANT_ID + )) { const providerId = provider.config.thirdPartyId; - await multitenancy_1.default.createOrUpdateThirdPartyConfig(tenantId, { - thirdPartyId: providerId, - }, undefined, userContext); + await multitenancy_1.default.createOrUpdateThirdPartyConfig( + tenantId, + { + thirdPartyId: providerId, + }, + undefined, + userContext + ); // delay after each provider to avoid rate limiting await new Promise((r) => setTimeout(r, 500)); // 500ms } - } - else if (thirdPartyIdsFromCore.length === 1 && thirdPartyIdsFromCore[0] === thirdPartyId) { + } else if (thirdPartyIdsFromCore.length === 1 && thirdPartyIdsFromCore[0] === thirdPartyId) { if (tenantRes.firstFactors === undefined) { // add all static first factors except thirdparty await multitenancy_1.default.createOrUpdateTenant(tenantId, { @@ -50,8 +63,7 @@ async function deleteThirdPartyConfig(_, tenantId, options, userContext) { multifactorauth_1.FactorIds.LINK_EMAIL, ], }); - } - else if (tenantRes.firstFactors.includes("thirdparty")) { + } else if (tenantRes.firstFactors.includes("thirdparty")) { // add all static first factors except thirdparty const newFirstFactors = tenantRes.firstFactors.filter((factor) => factor !== "thirdparty"); await multitenancy_1.default.createOrUpdateTenant(tenantId, { diff --git a/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.d.ts b/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.d.ts index 9ab079a5a..b1b64593a 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.d.ts @@ -1,22 +1,29 @@ // @ts-nocheck import { APIInterface, APIOptions, CoreConfigFieldInfo } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; - tenant: { - tenantId: string; - thirdParty: { - providers: { - thirdPartyId: string; - name: string; - }[]; - }; - firstFactors: string[]; - requiredSecondaryFactors?: string[] | null; - coreConfig: CoreConfigFieldInfo[]; - userCount: number; - }; -} | { - status: "UNKNOWN_TENANT_ERROR"; -}; -export default function getTenantInfo(_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + tenant: { + tenantId: string; + thirdParty: { + providers: { + thirdPartyId: string; + name: string; + }[]; + }; + firstFactors: string[]; + requiredSecondaryFactors?: string[] | null; + coreConfig: CoreConfigFieldInfo[]; + userCount: number; + }; + } + | { + status: "UNKNOWN_TENANT_ERROR"; + }; +export default function getTenantInfo( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.js b/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.js index 17ca3f3d3..c7db30d08 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.js +++ b/lib/build/recipe/dashboard/api/multitenancy/getTenantInfo.js @@ -1,18 +1,20 @@ "use strict"; -var __rest = (this && this.__rest) || function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __rest = + (this && this.__rest) || + function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; + } + return t; + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getTenantInfo; const multitenancy_1 = __importDefault(require("../../../multitenancy")); @@ -31,35 +33,65 @@ async function getTenantInfo(_, tenantId, options, userContext) { status: "UNKNOWN_TENANT_ERROR", }; } - let { status } = tenantRes, tenantConfig = __rest(tenantRes, ["status"]); + let { status } = tenantRes, + tenantConfig = __rest(tenantRes, ["status"]); let firstFactors = (0, utils_1.getNormalisedFirstFactorsBasedOnTenantConfigFromCoreAndSDKInit)(tenantConfig); if (tenantRes === undefined) { return { status: "UNKNOWN_TENANT_ERROR", }; } - const userCount = await supertokens_1.default.getInstanceOrThrowError().getUserCount(undefined, tenantId, userContext); - const providersFromCore = (_a = tenantRes === null || tenantRes === void 0 ? void 0 : tenantRes.thirdParty) === null || _a === void 0 ? void 0 : _a.providers; + const userCount = await supertokens_1.default + .getInstanceOrThrowError() + .getUserCount(undefined, tenantId, userContext); + const providersFromCore = + (_a = tenantRes === null || tenantRes === void 0 ? void 0 : tenantRes.thirdParty) === null || _a === void 0 + ? void 0 + : _a.providers; const mtRecipe = recipe_1.default.getInstance(); - const staticProviders = (_b = mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.staticThirdPartyProviders) !== null && _b !== void 0 ? _b : []; - const mergedProvidersFromCoreAndStatic = (0, configUtils_1.mergeProvidersFromCoreAndStatic)(providersFromCore, staticProviders, tenantId === constants_1.DEFAULT_TENANT_ID); + const staticProviders = + (_b = mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.staticThirdPartyProviders) !== null && + _b !== void 0 + ? _b + : []; + const mergedProvidersFromCoreAndStatic = (0, configUtils_1.mergeProvidersFromCoreAndStatic)( + providersFromCore, + staticProviders, + tenantId === constants_1.DEFAULT_TENANT_ID + ); let querier = querier_1.Querier.getNewInstanceOrThrowError(options.recipeId); - let coreConfig = await querier.sendGetRequest(new normalisedURLPath_1.default(`/${tenantId}/recipe/dashboard/tenant/core-config`), {}, userContext); + let coreConfig = await querier.sendGetRequest( + new normalisedURLPath_1.default(`/${tenantId}/recipe/dashboard/tenant/core-config`), + {}, + userContext + ); const tenant = { tenantId, thirdParty: { - providers: await Promise.all(mergedProvidersFromCoreAndStatic.map(async (provider) => { - try { - const providerInstance = await (0, configUtils_1.findAndCreateProviderInstance)(mergedProvidersFromCoreAndStatic, provider.config.thirdPartyId, provider.config.clients[0].clientType, userContext); - return { thirdPartyId: provider.config.thirdPartyId, name: providerInstance === null || providerInstance === void 0 ? void 0 : providerInstance.config.name }; - } - catch (_) { - return { - thirdPartyId: provider.config.thirdPartyId, - name: provider.config.thirdPartyId, - }; - } - })), + providers: await Promise.all( + mergedProvidersFromCoreAndStatic.map(async (provider) => { + try { + const providerInstance = await (0, configUtils_1.findAndCreateProviderInstance)( + mergedProvidersFromCoreAndStatic, + provider.config.thirdPartyId, + provider.config.clients[0].clientType, + userContext + ); + return { + thirdPartyId: provider.config.thirdPartyId, + name: + providerInstance === null || providerInstance === void 0 + ? void 0 + : providerInstance.config.name, + }; + } catch (_) { + return { + thirdPartyId: provider.config.thirdPartyId, + name: provider.config.thirdPartyId, + }; + } + }) + ), }, firstFactors: firstFactors, requiredSecondaryFactors: tenantRes.requiredSecondaryFactors, diff --git a/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.d.ts b/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.d.ts index 5bf7964fe..0af08fa57 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.d.ts @@ -2,14 +2,21 @@ import { APIInterface, APIOptions } from "../../types"; import { ProviderConfig } from "../../../thirdparty/types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; - providerConfig: ProviderConfig & { - isGetAuthorisationRedirectUrlOverridden: boolean; - isExchangeAuthCodeForOAuthTokensOverridden: boolean; - isGetUserInfoOverridden: boolean; - }; -} | { - status: "UNKNOWN_TENANT_ERROR"; -}; -export default function getThirdPartyConfig(_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + providerConfig: ProviderConfig & { + isGetAuthorisationRedirectUrlOverridden: boolean; + isExchangeAuthCodeForOAuthTokensOverridden: boolean; + isGetUserInfoOverridden: boolean; + }; + } + | { + status: "UNKNOWN_TENANT_ERROR"; + }; +export default function getThirdPartyConfig( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.js b/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.js index 21711460d..42aedc930 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.js +++ b/lib/build/recipe/dashboard/api/multitenancy/getThirdPartyConfig.js @@ -1,18 +1,20 @@ "use strict"; -var __rest = (this && this.__rest) || function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __rest = + (this && this.__rest) || + function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; + } + return t; + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getThirdPartyConfig; const multitenancy_1 = __importDefault(require("../../../multitenancy")); @@ -33,10 +35,13 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { if (thirdPartyId === undefined) { throw new Error("Please provide thirdPartyId"); } - let providersFromCore = (_a = tenantRes === null || tenantRes === void 0 ? void 0 : tenantRes.thirdParty) === null || _a === void 0 ? void 0 : _a.providers; + let providersFromCore = + (_a = tenantRes === null || tenantRes === void 0 ? void 0 : tenantRes.thirdParty) === null || _a === void 0 + ? void 0 + : _a.providers; const mtRecipe = recipe_1.default.getInstance(); let staticProviders = (mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.staticThirdPartyProviders) - ? mtRecipe.staticThirdPartyProviders.map((provider) => (Object.assign({}, provider))) + ? mtRecipe.staticThirdPartyProviders.map((provider) => Object.assign({}, provider)) : []; let additionalConfig = undefined; // filter out providers that is not matching thirdPartyId @@ -55,14 +60,12 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { if (oktaDomain !== undefined) { additionalConfig = { oktaDomain }; } - } - else if (thirdPartyId === "active-directory") { + } else if (thirdPartyId === "active-directory") { const directoryId = options.req.getKeyValueFromQuery("directoryId"); if (directoryId !== undefined) { additionalConfig = { directoryId }; } - } - else if (thirdPartyId === "boxy-saml") { + } else if (thirdPartyId === "boxy-saml") { let boxyURL = options.req.getKeyValueFromQuery("boxyUrl"); let boxyAPIKey = options.req.getKeyValueFromQuery("boxyAPIKey"); if (boxyURL !== undefined) { @@ -71,8 +74,7 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { additionalConfig = Object.assign(Object.assign({}, additionalConfig), { boxyAPIKey }); } } - } - else if (thirdPartyId === "google-workspaces") { + } else if (thirdPartyId === "google-workspaces") { const hd = options.req.getKeyValueFromQuery("hd"); if (hd !== undefined) { additionalConfig = { hd }; @@ -83,7 +85,14 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { providersFromCore[0].authorizationEndpoint = undefined; providersFromCore[0].tokenEndpoint = undefined; providersFromCore[0].userInfoEndpoint = undefined; - providersFromCore[0].clients = ((_b = providersFromCore[0].clients) !== null && _b !== void 0 ? _b : []).map((client) => (Object.assign(Object.assign({}, client), { additionalConfig: Object.assign(Object.assign({}, client.additionalConfig), additionalConfig) }))); + providersFromCore[0].clients = ((_b = providersFromCore[0].clients) !== null && _b !== void 0 + ? _b + : [] + ).map((client) => + Object.assign(Object.assign({}, client), { + additionalConfig: Object.assign(Object.assign({}, client.additionalConfig), additionalConfig), + }) + ); } } // filter out other providers from static @@ -102,17 +111,38 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { additionalConfig = { teamId: "", keyId: "", - privateKey: "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", + privateKey: + "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", }; } if (staticProviders.length === 1) { // modify additional config if query param is passed if (additionalConfig !== undefined) { // we set these to undefined so that these can be computed using the query param that was provided - staticProviders[0] = Object.assign(Object.assign({}, staticProviders[0]), { config: Object.assign(Object.assign({}, staticProviders[0].config), { oidcDiscoveryEndpoint: undefined, authorizationEndpoint: undefined, tokenEndpoint: undefined, userInfoEndpoint: undefined, clients: ((_c = staticProviders[0].config.clients) !== null && _c !== void 0 ? _c : []).map((client) => (Object.assign(Object.assign({}, client), { additionalConfig: Object.assign(Object.assign({}, client.additionalConfig), additionalConfig) }))) }) }); + staticProviders[0] = Object.assign(Object.assign({}, staticProviders[0]), { + config: Object.assign(Object.assign({}, staticProviders[0].config), { + oidcDiscoveryEndpoint: undefined, + authorizationEndpoint: undefined, + tokenEndpoint: undefined, + userInfoEndpoint: undefined, + clients: ((_c = staticProviders[0].config.clients) !== null && _c !== void 0 ? _c : []).map( + (client) => + Object.assign(Object.assign({}, client), { + additionalConfig: Object.assign( + Object.assign({}, client.additionalConfig), + additionalConfig + ), + }) + ), + }), + }); } } - let mergedProvidersFromCoreAndStatic = (0, configUtils_1.mergeProvidersFromCoreAndStatic)(providersFromCore, staticProviders, true); + let mergedProvidersFromCoreAndStatic = (0, configUtils_1.mergeProvidersFromCoreAndStatic)( + providersFromCore, + staticProviders, + true + ); if (mergedProvidersFromCoreAndStatic.length !== 1) { throw new Error("should never come here!"); } @@ -120,7 +150,10 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { if (mergedProvider.config.thirdPartyId === thirdPartyId) { if (mergedProvider.config.clients === undefined || mergedProvider.config.clients.length === 0) { mergedProvider.config.clients = [ - Object.assign({ clientId: "nonguessable-temporary-client-id" }, (additionalConfig !== undefined ? { additionalConfig } : {})), + Object.assign( + { clientId: "nonguessable-temporary-client-id" }, + additionalConfig !== undefined ? { additionalConfig } : {} + ), ]; } } @@ -137,8 +170,22 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { let foundCorrectConfig = false; for (const client of (_d = provider.config.clients) !== null && _d !== void 0 ? _d : []) { try { - const providerInstance = await (0, configUtils_1.findAndCreateProviderInstance)(mergedProvidersFromCoreAndStatic, thirdPartyId, client.clientType, userContext); - const _f = providerInstance.config, { clientId, clientSecret, clientType, scope, additionalConfig, forcePKCE } = _f, commonConfig = __rest(_f, ["clientId", "clientSecret", "clientType", "scope", "additionalConfig", "forcePKCE"]); + const providerInstance = await (0, configUtils_1.findAndCreateProviderInstance)( + mergedProvidersFromCoreAndStatic, + thirdPartyId, + client.clientType, + userContext + ); + const _f = providerInstance.config, + { clientId, clientSecret, clientType, scope, additionalConfig, forcePKCE } = _f, + commonConfig = __rest(_f, [ + "clientId", + "clientSecret", + "clientType", + "scope", + "additionalConfig", + "forcePKCE", + ]); clients.push({ clientId, clientSecret, @@ -154,8 +201,10 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { if (beforeOverride.getAuthorisationRedirectURL !== afterOverride.getAuthorisationRedirectURL) { isGetAuthorisationRedirectUrlOverridden = true; } - if (beforeOverride.exchangeAuthCodeForOAuthTokens !== - afterOverride.exchangeAuthCodeForOAuthTokens) { + if ( + beforeOverride.exchangeAuthCodeForOAuthTokens !== + afterOverride.exchangeAuthCodeForOAuthTokens + ) { isExchangeAuthCodeForOAuthTokensOverridden = true; } if (beforeOverride.getUserInfo !== afterOverride.getUserInfo) { @@ -163,8 +212,7 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { } } foundCorrectConfig = true; - } - catch (err) { + } catch (err) { // ignore the error clients.push(client); } @@ -175,13 +223,20 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { break; } } - if ((additionalConfig === null || additionalConfig === void 0 ? void 0 : additionalConfig.privateKey) !== undefined) { + if ( + (additionalConfig === null || additionalConfig === void 0 ? void 0 : additionalConfig.privateKey) !== undefined + ) { additionalConfig.privateKey = ""; } const tempClients = clients.filter((client) => client.clientId === "nonguessable-temporary-client-id"); const finalClients = clients.filter((client) => client.clientId !== "nonguessable-temporary-client-id"); if (finalClients.length === 0) { - finalClients.push(Object.assign(Object.assign(Object.assign({}, tempClients[0]), { clientId: "", clientSecret: "" }), (additionalConfig !== undefined ? { additionalConfig } : {}))); + finalClients.push( + Object.assign( + Object.assign(Object.assign({}, tempClients[0]), { clientId: "", clientSecret: "" }), + additionalConfig !== undefined ? { additionalConfig } : {} + ) + ); } // fill in boxy info from boxy instance if (thirdPartyId.startsWith("boxy-saml")) { @@ -192,26 +247,40 @@ async function getThirdPartyConfig(_, tenantId, options, userContext) { const normalisedDomain = new normalisedURLDomain_1.default(boxyURL); const normalisedBasePath = new normalisedURLPath_1.default(boxyURL); const connectionsPath = new normalisedURLPath_1.default("/api/v1/saml/config"); - const resp = await (0, thirdpartyUtils_1.doGetRequest)(normalisedDomain.getAsStringDangerous() + - normalisedBasePath.appendPath(connectionsPath).getAsStringDangerous(), { - clientID: finalClients[0].clientId, - }, { - Authorization: `Api-Key ${boxyAPIKey}`, - }); + const resp = await (0, thirdpartyUtils_1.doGetRequest)( + normalisedDomain.getAsStringDangerous() + + normalisedBasePath.appendPath(connectionsPath).getAsStringDangerous(), + { + clientID: finalClients[0].clientId, + }, + { + Authorization: `Api-Key ${boxyAPIKey}`, + } + ); if (resp.status === 200) { // we don't care about non 200 status codes since we are just trying to populate whatever possible if (resp.jsonResponse === undefined) { throw new Error("should never happen"); } - finalClients[0].additionalConfig = Object.assign(Object.assign({}, finalClients[0].additionalConfig), { redirectURLs: resp.jsonResponse.redirectUrl, boxyTenant: resp.jsonResponse.tenant, boxyProduct: resp.jsonResponse.product }); + finalClients[0].additionalConfig = Object.assign( + Object.assign({}, finalClients[0].additionalConfig), + { + redirectURLs: resp.jsonResponse.redirectUrl, + boxyTenant: resp.jsonResponse.tenant, + boxyProduct: resp.jsonResponse.product, + } + ); } } } } return { status: "OK", - providerConfig: Object.assign(Object.assign({}, commonProviderConfig), { clients: finalClients, isGetAuthorisationRedirectUrlOverridden, + providerConfig: Object.assign(Object.assign({}, commonProviderConfig), { + clients: finalClients, + isGetAuthorisationRedirectUrlOverridden, isExchangeAuthCodeForOAuthTokensOverridden, - isGetUserInfoOverridden }), + isGetUserInfoOverridden, + }), }; } diff --git a/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.d.ts b/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.d.ts index 85ea271db..bdf50de30 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.d.ts @@ -9,5 +9,10 @@ export type Response = { status: "OK"; tenants: TenantWithLoginMethods[]; }; -export default function listAllTenantsWithLoginMethods(_: APIInterface, __: string, ___: APIOptions, userContext: UserContext): Promise; +export default function listAllTenantsWithLoginMethods( + _: APIInterface, + __: string, + ___: APIOptions, + userContext: UserContext +): Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.js b/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.js index 82e56afc7..aa63d5f74 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.js +++ b/lib/build/recipe/dashboard/api/multitenancy/listAllTenantsWithLoginMethods.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = listAllTenantsWithLoginMethods; const recipe_1 = __importDefault(require("../../../multitenancy/recipe")); diff --git a/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.d.ts b/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.d.ts index 84441afeb..b13fbfcec 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.d.ts @@ -1,12 +1,20 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; -} | { - status: "UNKNOWN_TENANT_ERROR"; -} | { - status: "INVALID_CONFIG_ERROR"; - message: string; -}; -export default function updateTenantCoreConfig(_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + } + | { + status: "UNKNOWN_TENANT_ERROR"; + } + | { + status: "INVALID_CONFIG_ERROR"; + message: string; + }; +export default function updateTenantCoreConfig( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.js b/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.js index a990c8713..0446b8fa1 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.js +++ b/lib/build/recipe/dashboard/api/multitenancy/updateTenantCoreConfig.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = updateTenantCoreConfig; const recipe_1 = __importDefault(require("../../../multitenancy/recipe")); @@ -25,8 +27,7 @@ async function updateTenantCoreConfig(_, tenantId, options, userContext) { }, userContext, }); - } - catch (err) { + } catch (err) { const errMsg = err.message; if (errMsg.includes("SuperTokens core threw an error for a ") && errMsg.includes("with status code: 400")) { return { diff --git a/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.d.ts b/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.d.ts index 771c7e759..c25c1fdd6 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.d.ts @@ -1,12 +1,20 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; -} | { - status: "RECIPE_NOT_CONFIGURED_ON_BACKEND_SDK_ERROR"; - message: string; -} | { - status: "UNKNOWN_TENANT_ERROR"; -}; -export default function updateTenantFirstFactor(_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + } + | { + status: "RECIPE_NOT_CONFIGURED_ON_BACKEND_SDK_ERROR"; + message: string; + } + | { + status: "UNKNOWN_TENANT_ERROR"; + }; +export default function updateTenantFirstFactor( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.js b/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.js index c2edae758..69d013fe8 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.js +++ b/lib/build/recipe/dashboard/api/multitenancy/updateTenantFirstFactor.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = updateTenantFirstFactor; const recipe_1 = __importDefault(require("../../../multitenancy/recipe")); @@ -11,14 +13,18 @@ async function updateTenantFirstFactor(_, tenantId, options, userContext) { const { factorId, enable } = requestBody; const mtRecipe = recipe_1.default.getInstance(); if (enable === true) { - if (!(mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.allAvailableFirstFactors.includes(factorId))) { + if ( + !(mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.allAvailableFirstFactors.includes(factorId)) + ) { return { status: "RECIPE_NOT_CONFIGURED_ON_BACKEND_SDK_ERROR", message: (0, utils_1.getFactorNotAvailableMessage)(factorId, mtRecipe.allAvailableFirstFactors), }; } } - const tenantRes = await (mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.recipeInterfaceImpl.getTenant({ tenantId, userContext })); + const tenantRes = await (mtRecipe === null || mtRecipe === void 0 + ? void 0 + : mtRecipe.recipeInterfaceImpl.getTenant({ tenantId, userContext })); if (tenantRes === undefined) { return { status: "UNKNOWN_TENANT_ERROR", @@ -29,17 +35,18 @@ async function updateTenantFirstFactor(_, tenantId, options, userContext) { if (!firstFactors.includes(factorId)) { firstFactors.push(factorId); } - } - else { + } else { firstFactors = firstFactors.filter((f) => f !== factorId); } - await (mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.recipeInterfaceImpl.createOrUpdateTenant({ - tenantId, - config: { - firstFactors, - }, - userContext, - })); + await (mtRecipe === null || mtRecipe === void 0 + ? void 0 + : mtRecipe.recipeInterfaceImpl.createOrUpdateTenant({ + tenantId, + config: { + firstFactors, + }, + userContext, + })); return { status: "OK", }; diff --git a/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.d.ts b/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.d.ts index 65f4b5186..547901072 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.d.ts @@ -1,15 +1,24 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -export type Response = { - status: "OK"; - isMFARequirementsForAuthOverridden: boolean; -} | { - status: "RECIPE_NOT_CONFIGURED_ON_BACKEND_SDK_ERROR"; - message: string; -} | { - status: "MFA_NOT_INITIALIZED_ERROR"; -} | { - status: "UNKNOWN_TENANT_ERROR"; -}; -export default function updateTenantSecondaryFactor(_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export type Response = + | { + status: "OK"; + isMFARequirementsForAuthOverridden: boolean; + } + | { + status: "RECIPE_NOT_CONFIGURED_ON_BACKEND_SDK_ERROR"; + message: string; + } + | { + status: "MFA_NOT_INITIALIZED_ERROR"; + } + | { + status: "UNKNOWN_TENANT_ERROR"; + }; +export default function updateTenantSecondaryFactor( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.js b/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.js index 864c02612..1879a6083 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.js +++ b/lib/build/recipe/dashboard/api/multitenancy/updateTenantSecondaryFactor.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = updateTenantSecondaryFactor; const recipe_1 = __importDefault(require("../../../multitenancy/recipe")); @@ -17,7 +19,9 @@ async function updateTenantSecondaryFactor(_, tenantId, options, userContext) { status: "MFA_NOT_INITIALIZED_ERROR", }; } - const tenantRes = await (mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.recipeInterfaceImpl.getTenant({ tenantId, userContext })); + const tenantRes = await (mtRecipe === null || mtRecipe === void 0 + ? void 0 + : mtRecipe.recipeInterfaceImpl.getTenant({ tenantId, userContext })); if (tenantRes === undefined) { return { status: "UNKNOWN_TENANT_ERROR", @@ -32,22 +36,25 @@ async function updateTenantSecondaryFactor(_, tenantId, options, userContext) { }; } } - let secondaryFactors = (0, utils_1.getNormalisedRequiredSecondaryFactorsBasedOnTenantConfigFromCoreAndSDKInit)(tenantRes); + let secondaryFactors = (0, utils_1.getNormalisedRequiredSecondaryFactorsBasedOnTenantConfigFromCoreAndSDKInit)( + tenantRes + ); if (enable === true) { if (!secondaryFactors.includes(factorId)) { secondaryFactors.push(factorId); } - } - else { + } else { secondaryFactors = secondaryFactors.filter((f) => f !== factorId); } - await (mtRecipe === null || mtRecipe === void 0 ? void 0 : mtRecipe.recipeInterfaceImpl.createOrUpdateTenant({ - tenantId, - config: { - requiredSecondaryFactors: secondaryFactors.length > 0 ? secondaryFactors : null, - }, - userContext, - })); + await (mtRecipe === null || mtRecipe === void 0 + ? void 0 + : mtRecipe.recipeInterfaceImpl.createOrUpdateTenant({ + tenantId, + config: { + requiredSecondaryFactors: secondaryFactors.length > 0 ? secondaryFactors : null, + }, + userContext, + })); return { status: "OK", isMFARequirementsForAuthOverridden: mfaInstance.isGetMfaRequirementsForAuthOverridden, diff --git a/lib/build/recipe/dashboard/api/multitenancy/utils.d.ts b/lib/build/recipe/dashboard/api/multitenancy/utils.d.ts index 53cd451e2..76df5b8c0 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/utils.d.ts +++ b/lib/build/recipe/dashboard/api/multitenancy/utils.d.ts @@ -1,6 +1,10 @@ // @ts-nocheck import { TenantConfig } from "../../../multitenancy/types"; -export declare function getNormalisedFirstFactorsBasedOnTenantConfigFromCoreAndSDKInit(tenantDetailsFromCore: TenantConfig): string[]; -export declare function getNormalisedRequiredSecondaryFactorsBasedOnTenantConfigFromCoreAndSDKInit(tenantDetailsFromCore: TenantConfig): string[]; +export declare function getNormalisedFirstFactorsBasedOnTenantConfigFromCoreAndSDKInit( + tenantDetailsFromCore: TenantConfig +): string[]; +export declare function getNormalisedRequiredSecondaryFactorsBasedOnTenantConfigFromCoreAndSDKInit( + tenantDetailsFromCore: TenantConfig +): string[]; export declare function factorIdToRecipe(factorId: string): string; export declare function getFactorNotAvailableMessage(factorId: string, availableFactors: string[]): string; diff --git a/lib/build/recipe/dashboard/api/multitenancy/utils.js b/lib/build/recipe/dashboard/api/multitenancy/utils.js index 386be375e..551f68a80 100644 --- a/lib/build/recipe/dashboard/api/multitenancy/utils.js +++ b/lib/build/recipe/dashboard/api/multitenancy/utils.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getNormalisedFirstFactorsBasedOnTenantConfigFromCoreAndSDKInit = getNormalisedFirstFactorsBasedOnTenantConfigFromCoreAndSDKInit; exports.getNormalisedRequiredSecondaryFactorsBasedOnTenantConfigFromCoreAndSDKInit = getNormalisedRequiredSecondaryFactorsBasedOnTenantConfigFromCoreAndSDKInit; @@ -16,11 +18,9 @@ function getNormalisedFirstFactorsBasedOnTenantConfigFromCoreAndSDKInit(tenantDe let mtInstance = recipe_1.default.getInstanceOrThrowError(); if (tenantDetailsFromCore.firstFactors !== undefined) { firstFactors = tenantDetailsFromCore.firstFactors; // highest priority, config from core - } - else if (mtInstance.staticFirstFactors !== undefined) { + } else if (mtInstance.staticFirstFactors !== undefined) { firstFactors = mtInstance.staticFirstFactors; // next priority, static config - } - else { + } else { // Fallback to all available factors (de-duplicated) firstFactors = Array.from(new Set(mtInstance.allAvailableFirstFactors)); } @@ -31,12 +31,14 @@ function getNormalisedFirstFactorsBasedOnTenantConfigFromCoreAndSDKInit(tenantDe // enabled recipes in all cases irrespective of whether they are using MFA or not let validFirstFactors = []; for (const factorId of firstFactors) { - if ((0, utils_1.isFactorConfiguredForTenant)({ - tenantConfig: tenantDetailsFromCore, - allAvailableFirstFactors: mtInstance.allAvailableFirstFactors, - firstFactors: firstFactors, - factorId, - })) { + if ( + (0, utils_1.isFactorConfiguredForTenant)({ + tenantConfig: tenantDetailsFromCore, + allAvailableFirstFactors: mtInstance.allAvailableFirstFactors, + firstFactors: firstFactors, + factorId, + }) + ) { validFirstFactors.push(factorId); } } @@ -48,7 +50,12 @@ function getNormalisedRequiredSecondaryFactorsBasedOnTenantConfigFromCoreAndSDKI return []; } let secondaryFactors = mfaInstance.getAllAvailableSecondaryFactorIds(tenantDetailsFromCore); - secondaryFactors = secondaryFactors.filter((factorId) => { var _a; return ((_a = tenantDetailsFromCore.requiredSecondaryFactors) !== null && _a !== void 0 ? _a : []).includes(factorId); }); + secondaryFactors = secondaryFactors.filter((factorId) => { + var _a; + return ((_a = tenantDetailsFromCore.requiredSecondaryFactors) !== null && _a !== void 0 ? _a : []).includes( + factorId + ); + }); return secondaryFactors; } function factorIdToRecipe(factorId) { @@ -68,11 +75,18 @@ function getFactorNotAvailableMessage(factorId, availableFactors) { if (recipeName !== "Passwordless") { return `Please initialise ${recipeName} recipe to be able to use this login method`; } - const passwordlessFactors = [multifactorauth_1.FactorIds.LINK_EMAIL, multifactorauth_1.FactorIds.LINK_PHONE, multifactorauth_1.FactorIds.OTP_EMAIL, multifactorauth_1.FactorIds.OTP_PHONE]; + const passwordlessFactors = [ + multifactorauth_1.FactorIds.LINK_EMAIL, + multifactorauth_1.FactorIds.LINK_PHONE, + multifactorauth_1.FactorIds.OTP_EMAIL, + multifactorauth_1.FactorIds.OTP_PHONE, + ]; const passwordlessFactorsNotAvailable = passwordlessFactors.filter((f) => !availableFactors.includes(f)); if (passwordlessFactorsNotAvailable.length === 4) { return `Please initialise Passwordless recipe to be able to use this login method`; } const [flowType, contactMethod] = factorId.split("-"); - return `Please ensure that Passwordless recipe is initialised with contactMethod: ${contactMethod.toUpperCase()} and flowType: ${flowType === "otp" ? "USER_INPUT_CODE" : "MAGIC_LINK"}`; + return `Please ensure that Passwordless recipe is initialised with contactMethod: ${contactMethod.toUpperCase()} and flowType: ${ + flowType === "otp" ? "USER_INPUT_CODE" : "MAGIC_LINK" + }`; } diff --git a/lib/build/recipe/dashboard/api/search/tagsGet.d.ts b/lib/build/recipe/dashboard/api/search/tagsGet.d.ts index f3b35ac65..df311a403 100644 --- a/lib/build/recipe/dashboard/api/search/tagsGet.d.ts +++ b/lib/build/recipe/dashboard/api/search/tagsGet.d.ts @@ -5,5 +5,10 @@ type TagsResponse = { status: "OK"; tags: string[]; }; -export declare const getSearchTags: (_: APIInterface, ___: string, options: APIOptions, userContext: UserContext) => Promise; +export declare const getSearchTags: ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/search/tagsGet.js b/lib/build/recipe/dashboard/api/search/tagsGet.js index 4075a32d1..06c87156f 100644 --- a/lib/build/recipe/dashboard/api/search/tagsGet.js +++ b/lib/build/recipe/dashboard/api/search/tagsGet.js @@ -13,16 +13,22 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSearchTags = void 0; const querier_1 = require("../../../../querier"); const normalisedURLPath_1 = __importDefault(require("../../../../normalisedURLPath")); const getSearchTags = async (_, ___, options, userContext) => { let querier = querier_1.Querier.getNewInstanceOrThrowError(options.recipeId); - let tagsResponse = await querier.sendGetRequest(new normalisedURLPath_1.default("/user/search/tags"), {}, userContext); + let tagsResponse = await querier.sendGetRequest( + new normalisedURLPath_1.default("/user/search/tags"), + {}, + userContext + ); return tagsResponse; }; exports.getSearchTags = getSearchTags; diff --git a/lib/build/recipe/dashboard/api/signIn.js b/lib/build/recipe/dashboard/api/signIn.js index d744fac76..0020ae9c3 100644 --- a/lib/build/recipe/dashboard/api/signIn.js +++ b/lib/build/recipe/dashboard/api/signIn.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = signIn; const utils_1 = require("../../../utils"); @@ -37,10 +39,14 @@ async function signIn(_, options, userContext) { }); } let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); - const signInResponse = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/dashboard/signin"), { - email, - password, - }, userContext); + const signInResponse = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/dashboard/signin"), + { + email, + password, + }, + userContext + ); (0, utils_1.send200Response)(options.res, signInResponse); return true; } diff --git a/lib/build/recipe/dashboard/api/signOut.d.ts b/lib/build/recipe/dashboard/api/signOut.d.ts index 46f4609ac..b10c8509a 100644 --- a/lib/build/recipe/dashboard/api/signOut.d.ts +++ b/lib/build/recipe/dashboard/api/signOut.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../types"; import { UserContext } from "../../../types"; -export default function signOut(_: APIInterface, ___: string, options: APIOptions, userContext: UserContext): Promise; +export default function signOut( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/signOut.js b/lib/build/recipe/dashboard/api/signOut.js index 47739527c..9416698f8 100644 --- a/lib/build/recipe/dashboard/api/signOut.js +++ b/lib/build/recipe/dashboard/api/signOut.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = signOut; const utils_1 = require("../../../utils"); @@ -25,11 +27,16 @@ async function signOut(_, ___, options, userContext) { var _a; if (options.config.authMode === "api-key") { (0, utils_1.send200Response)(options.res, { status: "OK" }); - } - else { - const sessionIdFormAuthHeader = (_a = options.req.getHeaderValue("authorization")) === null || _a === void 0 ? void 0 : _a.split(" ")[1]; + } else { + const sessionIdFormAuthHeader = + (_a = options.req.getHeaderValue("authorization")) === null || _a === void 0 ? void 0 : _a.split(" ")[1]; let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); - const sessionDeleteResponse = await querier.sendDeleteRequest(new normalisedURLPath_1.default("/recipe/dashboard/session"), {}, { sessionId: sessionIdFormAuthHeader }, userContext); + const sessionDeleteResponse = await querier.sendDeleteRequest( + new normalisedURLPath_1.default("/recipe/dashboard/session"), + {}, + { sessionId: sessionIdFormAuthHeader }, + userContext + ); (0, utils_1.send200Response)(options.res, sessionDeleteResponse); } return true; diff --git a/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.d.ts b/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.d.ts index 556fa1650..5ce6dad3f 100644 --- a/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.d.ts +++ b/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.d.ts @@ -2,18 +2,27 @@ import { APIInterface, APIOptions } from "../../../types"; import { User, UserContext } from "../../../../../types"; import RecipeUserId from "../../../../../recipeUserId"; -type Response = { - status: "OK"; - user: User; - recipeUserId: RecipeUserId; -} | { - status: "EMAIL_ALREADY_EXISTS_ERROR" | "FEATURE_NOT_ENABLED_ERROR"; -} | { - status: "EMAIL_VALIDATION_ERROR"; - message: string; -} | { - status: "PASSWORD_VALIDATION_ERROR"; - message: string; -}; -export declare const createEmailPasswordUser: (_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext) => Promise; +type Response = + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_ALREADY_EXISTS_ERROR" | "FEATURE_NOT_ENABLED_ERROR"; + } + | { + status: "EMAIL_VALIDATION_ERROR"; + message: string; + } + | { + status: "PASSWORD_VALIDATION_ERROR"; + message: string; + }; +export declare const createEmailPasswordUser: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.js b/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.js index 0d082488d..cf84423bc 100644 --- a/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.js +++ b/lib/build/recipe/dashboard/api/user/create/emailpasswordUser.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createEmailPasswordUser = void 0; const error_1 = __importDefault(require("../../../../../error")); @@ -25,8 +27,7 @@ const createEmailPasswordUser = async (_, tenantId, options, userContext) => { let emailPassword = undefined; try { emailPassword = recipe_1.default.getInstanceOrThrowError(); - } - catch (error) { + } catch (error) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; @@ -66,9 +67,10 @@ const createEmailPasswordUser = async (_, tenantId, options, userContext) => { // For some reason TS complains if I check the other status codes then throw... if (response.status === "OK" || response.status === "EMAIL_ALREADY_EXISTS_ERROR") { return response; - } - else { - throw new Error("This should never happen: EmailPassword.signUp threw a session user related error without passing a session"); + } else { + throw new Error( + "This should never happen: EmailPassword.signUp threw a session user related error without passing a session" + ); } }; exports.createEmailPasswordUser = createEmailPasswordUser; diff --git a/lib/build/recipe/dashboard/api/user/create/passwordlessUser.d.ts b/lib/build/recipe/dashboard/api/user/create/passwordlessUser.d.ts index f7b049d53..9c199f983 100644 --- a/lib/build/recipe/dashboard/api/user/create/passwordlessUser.d.ts +++ b/lib/build/recipe/dashboard/api/user/create/passwordlessUser.d.ts @@ -2,19 +2,28 @@ import { APIInterface, APIOptions } from "../../../types"; import { User } from "../../../../../types"; import RecipeUserId from "../../../../../recipeUserId"; -type Response = { - status: string; - createdNewRecipeUser: boolean; - user: User; - recipeUserId: RecipeUserId; -} | { - status: "FEATURE_NOT_ENABLED_ERROR"; -} | { - status: "EMAIL_VALIDATION_ERROR"; - message: string; -} | { - status: "PHONE_VALIDATION_ERROR"; - message: string; -}; -export declare const createPasswordlessUser: (_: APIInterface, tenantId: string, options: APIOptions, __: any) => Promise; +type Response = + | { + status: string; + createdNewRecipeUser: boolean; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "FEATURE_NOT_ENABLED_ERROR"; + } + | { + status: "EMAIL_VALIDATION_ERROR"; + message: string; + } + | { + status: "PHONE_VALIDATION_ERROR"; + message: string; + }; +export declare const createPasswordlessUser: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + __: any +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/user/create/passwordlessUser.js b/lib/build/recipe/dashboard/api/user/create/passwordlessUser.js index 39ad99c0c..103b20e32 100644 --- a/lib/build/recipe/dashboard/api/user/create/passwordlessUser.js +++ b/lib/build/recipe/dashboard/api/user/create/passwordlessUser.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createPasswordlessUser = void 0; const error_1 = __importDefault(require("../../../../../error")); @@ -26,8 +28,7 @@ const createPasswordlessUser = async (_, tenantId, options, __) => { let passwordlessRecipe = undefined; try { passwordlessRecipe = recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; @@ -41,9 +42,11 @@ const createPasswordlessUser = async (_, tenantId, options, __) => { message: "Please provide exactly one of email or phoneNumber", }); } - if (email !== undefined && + if ( + email !== undefined && (passwordlessRecipe.config.contactMethod === "EMAIL" || - passwordlessRecipe.config.contactMethod === "EMAIL_OR_PHONE")) { + passwordlessRecipe.config.contactMethod === "EMAIL_OR_PHONE") + ) { email = email.trim(); let validationError = undefined; validationError = await passwordlessRecipe.config.validateEmailAddress(email, tenantId); @@ -54,9 +57,11 @@ const createPasswordlessUser = async (_, tenantId, options, __) => { }; } } - if (phoneNumber !== undefined && + if ( + phoneNumber !== undefined && (passwordlessRecipe.config.contactMethod === "PHONE" || - passwordlessRecipe.config.contactMethod === "EMAIL_OR_PHONE")) { + passwordlessRecipe.config.contactMethod === "EMAIL_OR_PHONE") + ) { let validationError = undefined; validationError = await passwordlessRecipe.config.validatePhoneNumber(phoneNumber, tenantId); if (validationError !== undefined) { @@ -70,11 +75,12 @@ const createPasswordlessUser = async (_, tenantId, options, __) => { // this can come here if the user has provided their own impl of validatePhoneNumber and // the phone number is valid according to their impl, but not according to the libphonenumber-js lib. phoneNumber = phoneNumber.trim(); - } - else { + } else { phoneNumber = parsedPhoneNumber.format("E.164"); } } - return await passwordless_1.default.signInUp(email !== undefined ? { email, tenantId } : { phoneNumber: phoneNumber, tenantId }); + return await passwordless_1.default.signInUp( + email !== undefined ? { email, tenantId } : { phoneNumber: phoneNumber, tenantId } + ); }; exports.createPasswordlessUser = createPasswordlessUser; diff --git a/lib/build/recipe/dashboard/api/userdetails/userDelete.js b/lib/build/recipe/dashboard/api/userdetails/userDelete.js index a0fc1546b..53ae0bc2b 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userDelete.js +++ b/lib/build/recipe/dashboard/api/userdetails/userDelete.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userDelete = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -12,7 +14,8 @@ const userDelete = async (_, ___, options, __) => { if (removeAllLinkedAccountsQueryValue !== undefined) { removeAllLinkedAccountsQueryValue = removeAllLinkedAccountsQueryValue.trim().toLowerCase(); } - const removeAllLinkedAccounts = removeAllLinkedAccountsQueryValue === undefined ? undefined : removeAllLinkedAccountsQueryValue === "true"; + const removeAllLinkedAccounts = + removeAllLinkedAccountsQueryValue === undefined ? undefined : removeAllLinkedAccountsQueryValue === "true"; if (userId === undefined || userId === "") { throw new error_1.default({ message: "Missing required parameter 'userId'", diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js index 675e92f01..affe7a2ae 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyGet.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userEmailVerifyGet = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -19,13 +21,16 @@ const userEmailVerifyGet = async (_, ___, options, userContext) => { } try { recipe_1.default.getInstanceOrThrowError(); - } - catch (e) { + } catch (e) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; } - const response = await emailverification_1.default.isEmailVerified(new recipeUserId_1.default(recipeUserId), undefined, userContext); + const response = await emailverification_1.default.isEmailVerified( + new recipeUserId_1.default(recipeUserId), + undefined, + userContext + ); return { status: "OK", isVerified: response, diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts index 25ab453cb..4135817f5 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.d.ts @@ -4,5 +4,10 @@ import { UserContext } from "../../../../types"; type Response = { status: "OK"; }; -export declare const userEmailVerifyPut: (_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext) => Promise; +export declare const userEmailVerifyPut: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js index fed7bba1e..604be3c27 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyPut.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userEmailVerifyPut = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -24,20 +26,33 @@ const userEmailVerifyPut = async (_, tenantId, options, userContext) => { }); } if (verified) { - const tokenResponse = await emailverification_1.default.createEmailVerificationToken(tenantId, new recipeUserId_1.default(recipeUserId), undefined, userContext); + const tokenResponse = await emailverification_1.default.createEmailVerificationToken( + tenantId, + new recipeUserId_1.default(recipeUserId), + undefined, + userContext + ); if (tokenResponse.status === "EMAIL_ALREADY_VERIFIED_ERROR") { return { status: "OK", }; } - const verifyResponse = await emailverification_1.default.verifyEmailUsingToken(tenantId, tokenResponse.token, undefined, userContext); + const verifyResponse = await emailverification_1.default.verifyEmailUsingToken( + tenantId, + tokenResponse.token, + undefined, + userContext + ); if (verifyResponse.status === "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR") { // This should never happen because we consume the token immediately after creating it throw new Error("Should not come here"); } - } - else { - await emailverification_1.default.unverifyEmail(new recipeUserId_1.default(recipeUserId), undefined, userContext); + } else { + await emailverification_1.default.unverifyEmail( + new recipeUserId_1.default(recipeUserId), + undefined, + userContext + ); } return { status: "OK", diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts index d9a55694e..22a89ae87 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.d.ts @@ -4,5 +4,10 @@ import { UserContext } from "../../../../types"; type Response = { status: "OK" | "EMAIL_ALREADY_VERIFIED_ERROR"; }; -export declare const userEmailVerifyTokenPost: (_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext) => Promise; +export declare const userEmailVerifyTokenPost: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js index b962d045d..7d65748c8 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js +++ b/lib/build/recipe/dashboard/api/userdetails/userEmailVerifyTokenPost.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userEmailVerifyTokenPost = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -23,6 +25,12 @@ const userEmailVerifyTokenPost = async (_, tenantId, options, userContext) => { type: error_1.default.BAD_INPUT_ERROR, }); } - return await emailverification_1.default.sendEmailVerificationEmail(tenantId, user.id, (0, __1.convertToRecipeUserId)(recipeUserId), undefined, userContext); + return await emailverification_1.default.sendEmailVerificationEmail( + tenantId, + user.id, + (0, __1.convertToRecipeUserId)(recipeUserId), + undefined, + userContext + ); }; exports.userEmailVerifyTokenPost = userEmailVerifyTokenPost; diff --git a/lib/build/recipe/dashboard/api/userdetails/userGet.js b/lib/build/recipe/dashboard/api/userdetails/userGet.js index 5206897f4..00dbdfffd 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userGet.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userGet = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -24,18 +26,23 @@ const userGet = async (_, ___, options, userContext) => { } try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "OK", - user: Object.assign(Object.assign({}, user.toJson()), { firstName: "FEATURE_NOT_ENABLED", lastName: "FEATURE_NOT_ENABLED" }), + user: Object.assign(Object.assign({}, user.toJson()), { + firstName: "FEATURE_NOT_ENABLED", + lastName: "FEATURE_NOT_ENABLED", + }), }; } const userMetaData = await usermetadata_1.default.getUserMetadata(userId, userContext); const { first_name, last_name } = userMetaData.metadata; return { status: "OK", - user: Object.assign(Object.assign({}, user.toJson()), { firstName: first_name === undefined ? "" : first_name, lastName: last_name === undefined ? "" : last_name }), + user: Object.assign(Object.assign({}, user.toJson()), { + firstName: first_name === undefined ? "" : first_name, + lastName: last_name === undefined ? "" : last_name, + }), }; }; exports.userGet = userGet; diff --git a/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js b/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js index 5e8a80c5b..b2e71cdce 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userMetadataGet.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userMetaDataGet = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -17,8 +19,7 @@ const userMetaDataGet = async (_, ___, options, userContext) => { } try { recipe_1.default.getInstanceOrThrowError(); - } - catch (e) { + } catch (e) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts index 858230f62..a4cbbfe32 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.d.ts @@ -4,5 +4,10 @@ import { UserContext } from "../../../../types"; type Response = { status: "OK"; }; -export declare const userMetadataPut: (_: APIInterface, ___: string, options: APIOptions, userContext: UserContext) => Promise; +export declare const userMetadataPut: ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js index 38a4df027..0b77de89f 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userMetadataPut.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userMetadataPut = void 0; const recipe_1 = __importDefault(require("../../../usermetadata/recipe")); @@ -37,8 +39,7 @@ const userMetadataPut = async (_, ___, options, userContext) => { if (parsedData === null) { throw new Error(); } - } - catch (e) { + } catch (e) { throw new error_1.default({ message: "'data' must be a valid JSON body", type: error_1.default.BAD_INPUT_ERROR, diff --git a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts index 390248856..1b69cd932 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.d.ts @@ -1,11 +1,18 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -type Response = { - status: "OK"; -} | { - status: "INVALID_PASSWORD_ERROR"; - error: string; -}; -export declare const userPasswordPut: (_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext) => Promise; +type Response = + | { + status: "OK"; + } + | { + status: "INVALID_PASSWORD_ERROR"; + error: string; + }; +export declare const userPasswordPut: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js index dfc2230b1..9045520c5 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userPasswordPut.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userPasswordPut = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -29,13 +31,14 @@ const userPasswordPut = async (_, tenantId, options, userContext) => { tenantIdForPasswordPolicy: tenantId, userContext, }); - if (updateResponse.status === "UNKNOWN_USER_ID_ERROR" || + if ( + updateResponse.status === "UNKNOWN_USER_ID_ERROR" || updateResponse.status === "EMAIL_ALREADY_EXISTS_ERROR" || - updateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { + updateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR" + ) { // Techincally it can but its an edge case so we assume that it wont throw new Error("Should never come here"); - } - else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { return { status: "INVALID_PASSWORD_ERROR", error: updateResponse.failureReason, diff --git a/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts b/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts index 1e1d65b33..ff9d4f276 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userPut.d.ts @@ -1,24 +1,36 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; import { UserContext } from "../../../../types"; -type Response = { - status: "OK"; -} | { - status: "EMAIL_ALREADY_EXISTS_ERROR"; -} | { - status: "INVALID_EMAIL_ERROR"; - error: string; -} | { - status: "PHONE_ALREADY_EXISTS_ERROR"; -} | { - status: "INVALID_PHONE_ERROR"; - error: string; -} | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; - error: string; -} | { - status: "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR"; - error: string; -}; -export declare const userPut: (_: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext) => Promise; +type Response = + | { + status: "OK"; + } + | { + status: "EMAIL_ALREADY_EXISTS_ERROR"; + } + | { + status: "INVALID_EMAIL_ERROR"; + error: string; + } + | { + status: "PHONE_ALREADY_EXISTS_ERROR"; + } + | { + status: "INVALID_PHONE_ERROR"; + error: string; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + error: string; + } + | { + status: "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR"; + error: string; + }; +export declare const userPut: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userPut.js b/lib/build/recipe/dashboard/api/userdetails/userPut.js index 9baf89b1e..fc3ede3fe 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userPut.js +++ b/lib/build/recipe/dashboard/api/userdetails/userPut.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userPut = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -17,7 +19,9 @@ const utils_2 = require("../../../passwordless/utils"); const recipeUserId_1 = __importDefault(require("../../../../recipeUserId")); const updateEmailForRecipeId = async (recipeId, recipeUserId, email, tenantId, userContext) => { if (recipeId === "emailpassword") { - let emailFormFields = recipe_1.default.getInstanceOrThrowError().config.signUpFeature.formFields.filter((field) => field.id === constants_1.FORM_FIELD_EMAIL_ID); + let emailFormFields = recipe_1.default + .getInstanceOrThrowError() + .config.signUpFeature.formFields.filter((field) => field.id === constants_1.FORM_FIELD_EMAIL_ID); let validationError = await emailFormFields[0].validate(email, tenantId, userContext); if (validationError !== undefined) { return { @@ -34,14 +38,12 @@ const updateEmailForRecipeId = async (recipeId, recipeUserId, email, tenantId, u return { status: "EMAIL_ALREADY_EXISTS_ERROR", }; - } - else if (emailUpdateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { + } else if (emailUpdateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { return { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", reason: emailUpdateResponse.reason, }; - } - else if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { + } else if (emailUpdateResponse.status === "UNKNOWN_USER_ID_ERROR") { throw new Error("Should never come here"); } return { @@ -58,8 +60,7 @@ const updateEmailForRecipeId = async (recipeId, recipeUserId, email, tenantId, u isValidEmail = false; validationError = validationResult; } - } - else { + } else { const validationResult = await passwordlessConfig.validateEmailAddress(email, tenantId); if (validationResult !== undefined) { isValidEmail = false; @@ -85,8 +86,10 @@ const updateEmailForRecipeId = async (recipeId, recipeUserId, email, tenantId, u status: "EMAIL_ALREADY_EXISTS_ERROR", }; } - if (updateResult.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR" || - updateResult.status === "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR") { + if ( + updateResult.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR" || + updateResult.status === "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR" + ) { return { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", reason: updateResult.reason, @@ -111,8 +114,7 @@ const updatePhoneForRecipeId = async (recipeUserId, phone, tenantId, userContext isValidPhone = false; validationError = validationResult; } - } - else { + } else { const validationResult = await passwordlessConfig.validatePhoneNumber(phone, tenantId); if (validationResult !== undefined) { isValidPhone = false; @@ -198,7 +200,11 @@ const userPut = async (_, tenantId, options, userContext) => { type: error_1.default.BAD_INPUT_ERROR, }); } - let userResponse = await (0, utils_1.getUserForRecipeId)(new recipeUserId_1.default(recipeUserId), recipeId, userContext); + let userResponse = await (0, utils_1.getUserForRecipeId)( + new recipeUserId_1.default(recipeUserId), + recipeId, + userContext + ); if (userResponse.user === undefined || userResponse.recipe === undefined) { throw new Error("Should never come here"); } @@ -207,8 +213,7 @@ const userPut = async (_, tenantId, options, userContext) => { try { recipe_3.default.getInstanceOrThrowError(); isRecipeInitialised = true; - } - catch (_) { + } catch (_) { // no op } if (isRecipeInitialised) { @@ -223,7 +228,13 @@ const userPut = async (_, tenantId, options, userContext) => { } } if (email.trim() !== "") { - const emailUpdateResponse = await updateEmailForRecipeId(userResponse.recipe, new recipeUserId_1.default(recipeUserId), email.trim(), tenantId, userContext); + const emailUpdateResponse = await updateEmailForRecipeId( + userResponse.recipe, + new recipeUserId_1.default(recipeUserId), + email.trim(), + tenantId, + userContext + ); if (emailUpdateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { return { error: emailUpdateResponse.reason, @@ -235,7 +246,12 @@ const userPut = async (_, tenantId, options, userContext) => { } } if (phone.trim() !== "") { - const phoneUpdateResponse = await updatePhoneForRecipeId(new recipeUserId_1.default(recipeUserId), phone.trim(), tenantId, userContext); + const phoneUpdateResponse = await updatePhoneForRecipeId( + new recipeUserId_1.default(recipeUserId), + phone.trim(), + tenantId, + userContext + ); if (phoneUpdateResponse.status === "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR") { return { error: phoneUpdateResponse.reason, diff --git a/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js b/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js index c9ac1cab9..2528cf4ff 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userSessionsGet.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userSessionsGet = void 0; const error_1 = __importDefault(require("../../../../error")); @@ -18,20 +20,21 @@ const userSessionsGet = async (_, ___, options, userContext) => { let sessions = []; let sessionInfoPromises = []; for (let i = 0; i < response.length; i++) { - sessionInfoPromises.push(new Promise(async (res, rej) => { - try { - const sessionResponse = await session_1.default.getSessionInformation(response[i], userContext); - if (sessionResponse !== undefined) { - const accessTokenPayload = sessionResponse.customClaimsInAccessTokenPayload; - delete sessionResponse.customClaimsInAccessTokenPayload; - sessions[i] = Object.assign(Object.assign({}, sessionResponse), { accessTokenPayload }); + sessionInfoPromises.push( + new Promise(async (res, rej) => { + try { + const sessionResponse = await session_1.default.getSessionInformation(response[i], userContext); + if (sessionResponse !== undefined) { + const accessTokenPayload = sessionResponse.customClaimsInAccessTokenPayload; + delete sessionResponse.customClaimsInAccessTokenPayload; + sessions[i] = Object.assign(Object.assign({}, sessionResponse), { accessTokenPayload }); + } + res(); + } catch (e) { + rej(e); } - res(); - } - catch (e) { - rej(e); - } - })); + }) + ); } await Promise.all(sessionInfoPromises); return { diff --git a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts index cb19dcf25..2da7a484d 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.d.ts @@ -4,5 +4,10 @@ import { UserContext } from "../../../../types"; type Response = { status: "OK"; }; -export declare const userSessionsPost: (_: APIInterface, ___: string, options: APIOptions, userContext: UserContext) => Promise; +export declare const userSessionsPost: ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js index f744843f6..51ab7f94a 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js +++ b/lib/build/recipe/dashboard/api/userdetails/userSessionsPost.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userSessionsPost = void 0; const error_1 = __importDefault(require("../../../../error")); diff --git a/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.d.ts b/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.d.ts index 86a009a73..b7c3067df 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.d.ts +++ b/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.d.ts @@ -4,5 +4,10 @@ import { UserContext } from "../../../../types"; type Response = { status: "OK"; }; -export declare const userUnlink: (_: APIInterface, ___: string, options: APIOptions, userContext: UserContext) => Promise; +export declare const userUnlink: ( + _: APIInterface, + ___: string, + options: APIOptions, + userContext: UserContext +) => Promise; export {}; diff --git a/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.js b/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.js index 7a4934507..11283fce1 100644 --- a/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.js +++ b/lib/build/recipe/dashboard/api/userdetails/userUnlinkGet.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.userUnlink = void 0; const error_1 = __importDefault(require("../../../../error")); diff --git a/lib/build/recipe/dashboard/api/userroles/addRoleToUser.d.ts b/lib/build/recipe/dashboard/api/userroles/addRoleToUser.d.ts index 64a486f8d..8485ed162 100644 --- a/lib/build/recipe/dashboard/api/userroles/addRoleToUser.d.ts +++ b/lib/build/recipe/dashboard/api/userroles/addRoleToUser.d.ts @@ -1,9 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; -declare const addRoleToUser: (_: APIInterface, tenantId: string, options: APIOptions, __: any) => Promise<{ - status: "OK"; - didUserAlreadyHaveRole: boolean; -} | { - status: "UNKNOWN_ROLE_ERROR" | "FEATURE_NOT_ENABLED_ERROR"; -}>; +declare const addRoleToUser: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + __: any +) => Promise< + | { + status: "OK"; + didUserAlreadyHaveRole: boolean; + } + | { + status: "UNKNOWN_ROLE_ERROR" | "FEATURE_NOT_ENABLED_ERROR"; + } +>; export default addRoleToUser; diff --git a/lib/build/recipe/dashboard/api/userroles/addRoleToUser.js b/lib/build/recipe/dashboard/api/userroles/addRoleToUser.js index 4f2319581..c7b1e0397 100644 --- a/lib/build/recipe/dashboard/api/userroles/addRoleToUser.js +++ b/lib/build/recipe/dashboard/api/userroles/addRoleToUser.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipe_1 = __importDefault(require("../../../userroles/recipe")); const userroles_1 = __importDefault(require("../../../userroles")); @@ -9,8 +11,7 @@ const error_1 = __importDefault(require("../../../../error")); const addRoleToUser = async (_, tenantId, options, __) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userroles/getRolesForUser.d.ts b/lib/build/recipe/dashboard/api/userroles/getRolesForUser.d.ts index 1dcc29877..0de8b9c3e 100644 --- a/lib/build/recipe/dashboard/api/userroles/getRolesForUser.d.ts +++ b/lib/build/recipe/dashboard/api/userroles/getRolesForUser.d.ts @@ -1,9 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; -declare const getRolesForUser: (_: APIInterface, tenantId: string, options: APIOptions, __: any) => Promise<{ - status: "OK"; - roles: string[]; -} | { - status: "FEATURE_NOT_ENABLED_ERROR"; -}>; +declare const getRolesForUser: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + __: any +) => Promise< + | { + status: "OK"; + roles: string[]; + } + | { + status: "FEATURE_NOT_ENABLED_ERROR"; + } +>; export default getRolesForUser; diff --git a/lib/build/recipe/dashboard/api/userroles/getRolesForUser.js b/lib/build/recipe/dashboard/api/userroles/getRolesForUser.js index a9b079815..be76ed593 100644 --- a/lib/build/recipe/dashboard/api/userroles/getRolesForUser.js +++ b/lib/build/recipe/dashboard/api/userroles/getRolesForUser.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const userroles_1 = __importDefault(require("../../../userroles")); const recipe_1 = __importDefault(require("../../../userroles/recipe")); @@ -10,8 +12,7 @@ const getRolesForUser = async (_, tenantId, options, __) => { const userId = options.req.getKeyValueFromQuery("userId"); try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.d.ts b/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.d.ts index 2c4b06094..206ddc1af 100644 --- a/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.d.ts +++ b/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.d.ts @@ -1,9 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../../types"; -declare const getPermissionsForRole: (_: APIInterface, ___: string, options: APIOptions, __: any) => Promise<{ - status: "OK"; - permissions: string[]; -} | { - status: "FEATURE_NOT_ENABLED_ERROR" | "UNKNOWN_ROLE_ERROR"; -}>; +declare const getPermissionsForRole: ( + _: APIInterface, + ___: string, + options: APIOptions, + __: any +) => Promise< + | { + status: "OK"; + permissions: string[]; + } + | { + status: "FEATURE_NOT_ENABLED_ERROR" | "UNKNOWN_ROLE_ERROR"; + } +>; export default getPermissionsForRole; diff --git a/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.js b/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.js index 329519039..fac738710 100644 --- a/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.js +++ b/lib/build/recipe/dashboard/api/userroles/permissions/getPermissionsForRole.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipe_1 = __importDefault(require("../../../../userroles/recipe")); const userroles_1 = __importDefault(require("../../../../userroles")); @@ -9,8 +11,7 @@ const error_1 = __importDefault(require("../../../../../error")); const getPermissionsForRole = async (_, ___, options, __) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.d.ts b/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.d.ts index ec4a827ad..e4904b004 100644 --- a/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.d.ts +++ b/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.d.ts @@ -1,6 +1,11 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../../types"; -declare const removePermissionsFromRole: (_: APIInterface, ___: string, options: APIOptions, __: any) => Promise<{ +declare const removePermissionsFromRole: ( + _: APIInterface, + ___: string, + options: APIOptions, + __: any +) => Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR" | "FEATURE_NOT_ENABLED_ERROR"; }>; export default removePermissionsFromRole; diff --git a/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.js b/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.js index 73209a3f4..cab2e0a91 100644 --- a/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.js +++ b/lib/build/recipe/dashboard/api/userroles/permissions/removePermissions.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipe_1 = __importDefault(require("../../../../userroles/recipe")); const userroles_1 = __importDefault(require("../../../../userroles")); @@ -9,8 +11,7 @@ const error_1 = __importDefault(require("../../../../../error")); const removePermissionsFromRole = async (_, ___, options, __) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userroles/removeUserRole.d.ts b/lib/build/recipe/dashboard/api/userroles/removeUserRole.d.ts index f771637d1..bdf782e49 100644 --- a/lib/build/recipe/dashboard/api/userroles/removeUserRole.d.ts +++ b/lib/build/recipe/dashboard/api/userroles/removeUserRole.d.ts @@ -1,9 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../types"; -declare const removeUserRole: (_: APIInterface, tenantId: string, options: APIOptions, __: any) => Promise<{ - status: "OK"; - didUserHaveRole: boolean; -} | { - status: "UNKNOWN_ROLE_ERROR" | "FEATURE_NOT_ENABLED_ERROR"; -}>; +declare const removeUserRole: ( + _: APIInterface, + tenantId: string, + options: APIOptions, + __: any +) => Promise< + | { + status: "OK"; + didUserHaveRole: boolean; + } + | { + status: "UNKNOWN_ROLE_ERROR" | "FEATURE_NOT_ENABLED_ERROR"; + } +>; export default removeUserRole; diff --git a/lib/build/recipe/dashboard/api/userroles/removeUserRole.js b/lib/build/recipe/dashboard/api/userroles/removeUserRole.js index 750534243..025c93fcd 100644 --- a/lib/build/recipe/dashboard/api/userroles/removeUserRole.js +++ b/lib/build/recipe/dashboard/api/userroles/removeUserRole.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipe_1 = __importDefault(require("../../../userroles/recipe")); const userroles_1 = __importDefault(require("../../../userroles")); @@ -9,8 +11,7 @@ const error_1 = __importDefault(require("../../../../error")); const removeUserRole = async (_, tenantId, options, __) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.d.ts b/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.d.ts index 7193f19c2..75663bcb0 100644 --- a/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.d.ts +++ b/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.d.ts @@ -1,9 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../../types"; -declare const createRoleOrAddPermissions: (_: APIInterface, __: string, options: APIOptions, ___: any) => Promise<{ - status: "OK"; - createdNewRole: boolean; -} | { - status: "FEATURE_NOT_ENABLED_ERROR"; -}>; +declare const createRoleOrAddPermissions: ( + _: APIInterface, + __: string, + options: APIOptions, + ___: any +) => Promise< + | { + status: "OK"; + createdNewRole: boolean; + } + | { + status: "FEATURE_NOT_ENABLED_ERROR"; + } +>; export default createRoleOrAddPermissions; diff --git a/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.js b/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.js index f2f3f2310..1540fe51d 100644 --- a/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.js +++ b/lib/build/recipe/dashboard/api/userroles/roles/createRoleOrAddPermissions.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipe_1 = __importDefault(require("../../../../userroles/recipe")); const userroles_1 = __importDefault(require("../../../../userroles")); @@ -9,8 +11,7 @@ const error_1 = __importDefault(require("../../../../../error")); const createRoleOrAddPermissions = async (_, __, options, ___) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.d.ts b/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.d.ts index 4dd5dc9af..14e5cf5b7 100644 --- a/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.d.ts +++ b/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.d.ts @@ -1,9 +1,17 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../../../types"; -declare const deleteRole: (_: APIInterface, ___: string, options: APIOptions, __: any) => Promise<{ - status: "OK"; - didRoleExist: boolean; -} | { - status: "FEATURE_NOT_ENABLED_ERROR"; -}>; +declare const deleteRole: ( + _: APIInterface, + ___: string, + options: APIOptions, + __: any +) => Promise< + | { + status: "OK"; + didRoleExist: boolean; + } + | { + status: "FEATURE_NOT_ENABLED_ERROR"; + } +>; export default deleteRole; diff --git a/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.js b/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.js index ac282b88c..3814268fb 100644 --- a/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.js +++ b/lib/build/recipe/dashboard/api/userroles/roles/deleteRole.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipe_1 = __importDefault(require("../../../../userroles/recipe")); const userroles_1 = __importDefault(require("../../../../userroles")); @@ -9,8 +11,7 @@ const error_1 = __importDefault(require("../../../../../error")); const deleteRole = async (_, ___, options, __) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/userroles/roles/getAllRoles.js b/lib/build/recipe/dashboard/api/userroles/roles/getAllRoles.js index c85556ed7..bce2b636d 100644 --- a/lib/build/recipe/dashboard/api/userroles/roles/getAllRoles.js +++ b/lib/build/recipe/dashboard/api/userroles/roles/getAllRoles.js @@ -1,15 +1,16 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const userroles_1 = __importDefault(require("../../../../userroles")); const recipe_1 = __importDefault(require("../../../../userroles/recipe")); const getAllRoles = async (_, __, ____) => { try { recipe_1.default.getInstanceOrThrowError(); - } - catch (_) { + } catch (_) { return { status: "FEATURE_NOT_ENABLED_ERROR", }; diff --git a/lib/build/recipe/dashboard/api/usersCountGet.d.ts b/lib/build/recipe/dashboard/api/usersCountGet.d.ts index aed96ed79..68e1efd3a 100644 --- a/lib/build/recipe/dashboard/api/usersCountGet.d.ts +++ b/lib/build/recipe/dashboard/api/usersCountGet.d.ts @@ -5,4 +5,9 @@ export type Response = { status: "OK"; count: number; }; -export default function usersCountGet(_: APIInterface, tenantId: string, __: APIOptions, userContext: UserContext): Promise; +export default function usersCountGet( + _: APIInterface, + tenantId: string, + __: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/dashboard/api/usersCountGet.js b/lib/build/recipe/dashboard/api/usersCountGet.js index d1185587b..9068c3923 100644 --- a/lib/build/recipe/dashboard/api/usersCountGet.js +++ b/lib/build/recipe/dashboard/api/usersCountGet.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = usersCountGet; const supertokens_1 = __importDefault(require("../../../supertokens")); diff --git a/lib/build/recipe/dashboard/api/usersGet.d.ts b/lib/build/recipe/dashboard/api/usersGet.d.ts index 9170759cc..47458b359 100644 --- a/lib/build/recipe/dashboard/api/usersGet.d.ts +++ b/lib/build/recipe/dashboard/api/usersGet.d.ts @@ -6,6 +6,8 @@ export type Response = { users: UserWithFirstAndLastName[]; }; export default function usersGet(_: APIInterface, tenantId: string, options: APIOptions): Promise; -export declare function getSearchParamsFromURL(path: string): { +export declare function getSearchParamsFromURL( + path: string +): { [key: string]: string; }; diff --git a/lib/build/recipe/dashboard/api/usersGet.js b/lib/build/recipe/dashboard/api/usersGet.js index 5577428df..317655a75 100644 --- a/lib/build/recipe/dashboard/api/usersGet.js +++ b/lib/build/recipe/dashboard/api/usersGet.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = usersGet; exports.getSearchParamsFromURL = getSearchParamsFromURL; @@ -30,24 +32,24 @@ async function usersGet(_, tenantId, options) { } let paginationToken = options.req.getKeyValueFromQuery("paginationToken"); const query = getSearchParamsFromURL(options.req.getOriginalURL()); - let usersResponse = timeJoinedOrder === "DESC" - ? await (0, __1.getUsersNewestFirst)({ - tenantId, - query, - limit: parseInt(limit), - paginationToken, - }) - : await (0, __1.getUsersOldestFirst)({ - tenantId, - query, - limit: parseInt(limit), - paginationToken, - }); + let usersResponse = + timeJoinedOrder === "DESC" + ? await (0, __1.getUsersNewestFirst)({ + tenantId, + query, + limit: parseInt(limit), + paginationToken, + }) + : await (0, __1.getUsersOldestFirst)({ + tenantId, + query, + limit: parseInt(limit), + paginationToken, + }); // If the UserMetaData recipe has been initialised, fetch first and last name try { recipe_1.default.getInstanceOrThrowError(); - } - catch (e) { + } catch (e) { // Recipe has not been initialised, return without first name and last name return { status: "OK", @@ -59,18 +61,23 @@ async function usersGet(_, tenantId, options) { let metaDataFetchPromises = []; for (let i = 0; i < usersResponse.users.length; i++) { const userObj = usersResponse.users[i].toJson(); - metaDataFetchPromises.push(() => new Promise(async (resolve, reject) => { - try { - const userMetaDataResponse = await usermetadata_1.default.getUserMetadata(userObj.id); - const { first_name, last_name } = userMetaDataResponse.metadata; - updatedUsersArray[i] = Object.assign(Object.assign({}, userObj), { firstName: first_name, lastName: last_name }); - resolve(true); - } - catch (e) { - // Something went wrong when fetching user meta data - reject(e); - } - })); + metaDataFetchPromises.push( + () => + new Promise(async (resolve, reject) => { + try { + const userMetaDataResponse = await usermetadata_1.default.getUserMetadata(userObj.id); + const { first_name, last_name } = userMetaDataResponse.metadata; + updatedUsersArray[i] = Object.assign(Object.assign({}, userObj), { + firstName: first_name, + lastName: last_name, + }); + resolve(true); + } catch (e) { + // Something went wrong when fetching user meta data + reject(e); + } + }) + ); } let promiseArrayStartPosition = 0; let batchSize = 5; diff --git a/lib/build/recipe/dashboard/api/validateKey.js b/lib/build/recipe/dashboard/api/validateKey.js index 4ba0288d1..4ed22d4b9 100644 --- a/lib/build/recipe/dashboard/api/validateKey.js +++ b/lib/build/recipe/dashboard/api/validateKey.js @@ -22,8 +22,7 @@ async function validateKey(_, options, userContext) { options.res.sendJSONResponse({ status: "OK", }); - } - else { + } else { (0, utils_1.sendUnauthorisedAccess)(options.res); } return true; diff --git a/lib/build/recipe/dashboard/error.js b/lib/build/recipe/dashboard/error.js index 38952dadd..98945279a 100644 --- a/lib/build/recipe/dashboard/error.js +++ b/lib/build/recipe/dashboard/error.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. * diff --git a/lib/build/recipe/dashboard/index.js b/lib/build/recipe/dashboard/index.js index 4174947ef..4f4892019 100644 --- a/lib/build/recipe/dashboard/index.js +++ b/lib/build/recipe/dashboard/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.init = void 0; /* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved. @@ -19,8 +21,7 @@ exports.init = void 0; * under the License. */ const recipe_1 = __importDefault(require("./recipe")); -class Wrapper { -} +class Wrapper {} Wrapper.init = recipe_1.default.init; exports.default = Wrapper; exports.init = Wrapper.init; diff --git a/lib/build/recipe/dashboard/recipe.d.ts b/lib/build/recipe/dashboard/recipe.d.ts index 84986f992..25343ea75 100644 --- a/lib/build/recipe/dashboard/recipe.d.ts +++ b/lib/build/recipe/dashboard/recipe.d.ts @@ -17,7 +17,15 @@ export default class Recipe extends RecipeModule { static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, tenantId: string, req: BaseRequest, res: BaseResponse, __: NormalisedURLPath, ___: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + tenantId: string, + req: BaseRequest, + res: BaseResponse, + __: NormalisedURLPath, + ___: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: error, _: BaseRequest, __: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is error; diff --git a/lib/build/recipe/dashboard/recipe.js b/lib/build/recipe/dashboard/recipe.js index 4bd9782f9..90a9a6df1 100644 --- a/lib/build/recipe/dashboard/recipe.js +++ b/lib/build/recipe/dashboard/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); const recipeModule_1 = __importDefault(require("../../recipeModule")); @@ -75,265 +77,355 @@ class Recipe extends recipeModule_1.default { return [ { id: constants_1.DASHBOARD_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)("/")), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)("/") + ), disabled: false, method: "get", }, { id: constants_1.DASHBOARD_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)("/roles")), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)("/roles") + ), disabled: false, method: "get", }, { id: constants_1.DASHBOARD_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)("/tenants")), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)("/tenants") + ), disabled: false, method: "get", }, { id: constants_1.SIGN_IN_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.SIGN_IN_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.SIGN_IN_API) + ), disabled: false, method: "post", }, { id: constants_1.VALIDATE_KEY_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.VALIDATE_KEY_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.VALIDATE_KEY_API) + ), disabled: false, method: "post", }, { id: constants_1.SIGN_OUT_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.SIGN_OUT_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.SIGN_OUT_API) + ), disabled: false, method: "post", }, { id: constants_1.USERS_LIST_GET_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERS_LIST_GET_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERS_LIST_GET_API) + ), disabled: false, method: "get", }, { id: constants_1.USERS_COUNT_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERS_COUNT_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERS_COUNT_API) + ), disabled: false, method: "get", }, { id: constants_1.USER_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API) + ), disabled: false, method: "get", }, { id: constants_1.USER_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API) + ), disabled: false, method: "post", }, { id: constants_1.USER_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API) + ), disabled: false, method: "put", }, { id: constants_1.USER_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_API) + ), disabled: false, method: "delete", }, { id: constants_1.USER_EMAIL_VERIFY_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_EMAIL_VERIFY_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_EMAIL_VERIFY_API) + ), disabled: false, method: "get", }, { id: constants_1.USER_EMAIL_VERIFY_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_EMAIL_VERIFY_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_EMAIL_VERIFY_API) + ), disabled: false, method: "put", }, { id: constants_1.USER_METADATA_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_METADATA_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_METADATA_API) + ), disabled: false, method: "get", }, { id: constants_1.USER_METADATA_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_METADATA_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_METADATA_API) + ), disabled: false, method: "put", }, { id: constants_1.USER_SESSIONS_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_SESSIONS_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_SESSIONS_API) + ), disabled: false, method: "get", }, { id: constants_1.USER_SESSIONS_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_SESSIONS_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_SESSIONS_API) + ), disabled: false, method: "post", }, { id: constants_1.USER_PASSWORD_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_PASSWORD_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_PASSWORD_API) + ), disabled: false, method: "put", }, { id: constants_1.USER_EMAIL_VERIFY_TOKEN_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_EMAIL_VERIFY_TOKEN_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USER_EMAIL_VERIFY_TOKEN_API) + ), disabled: false, method: "post", }, { id: constants_1.SEARCH_TAGS_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.SEARCH_TAGS_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.SEARCH_TAGS_API) + ), disabled: false, method: "get", }, { id: constants_1.DASHBOARD_ANALYTICS_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.DASHBOARD_ANALYTICS_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.DASHBOARD_ANALYTICS_API) + ), disabled: false, method: "post", }, { id: constants_1.UNLINK_USER, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.UNLINK_USER)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.UNLINK_USER) + ), disabled: false, method: "get", }, { id: constants_1.USERROLES_LIST_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_LIST_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_LIST_API) + ), disabled: false, method: "get", }, { id: constants_1.USERROLES_ROLE_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_ROLE_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_ROLE_API) + ), disabled: false, method: "put", }, { id: constants_1.USERROLES_ROLE_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_ROLE_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_ROLE_API) + ), disabled: false, method: "delete", }, { id: constants_1.USERROLES_PERMISSIONS_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_PERMISSIONS_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_PERMISSIONS_API) + ), disabled: false, method: "get", }, { id: constants_1.USERROLES_PERMISSIONS_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_PERMISSIONS_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_PERMISSIONS_API) + ), disabled: false, method: "put", }, { id: constants_1.USERROLES_REMOVE_PERMISSIONS_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_REMOVE_PERMISSIONS_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_REMOVE_PERMISSIONS_API) + ), disabled: false, method: "put", }, { id: constants_1.USERROLES_USER_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_USER_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_USER_API) + ), disabled: false, method: "put", }, { id: constants_1.USERROLES_USER_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_USER_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_USER_API) + ), disabled: false, method: "get", }, { id: constants_1.USERROLES_USER_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_USER_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.USERROLES_USER_API) + ), disabled: false, method: "delete", }, { id: constants_1.CREATE_EMAIL_PASSWORD_USER, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.CREATE_EMAIL_PASSWORD_USER)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.CREATE_EMAIL_PASSWORD_USER) + ), disabled: false, method: "post", }, { id: constants_1.CREATE_PASSWORDLESS_USER, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.CREATE_PASSWORDLESS_USER)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.CREATE_PASSWORDLESS_USER) + ), disabled: false, method: "post", }, { id: constants_1.LIST_TENANTS_WITH_LOGIN_METHODS, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.LIST_TENANTS_WITH_LOGIN_METHODS)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.LIST_TENANTS_WITH_LOGIN_METHODS) + ), disabled: false, method: "get", }, { id: constants_1.TENANT_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_API) + ), disabled: false, method: "get", }, { id: constants_1.TENANT_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_API) + ), disabled: false, method: "delete", }, { id: constants_1.TENANT_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_API) + ), disabled: false, method: "post", }, { id: constants_1.UPDATE_TENANT_FIRST_FACTOR_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.UPDATE_TENANT_FIRST_FACTOR_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.UPDATE_TENANT_FIRST_FACTOR_API) + ), disabled: false, method: "put", }, { id: constants_1.UPDATE_TENANT_REQUIRED_SECONDARY_FACTOR_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.UPDATE_TENANT_REQUIRED_SECONDARY_FACTOR_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)( + constants_1.UPDATE_TENANT_REQUIRED_SECONDARY_FACTOR_API + ) + ), disabled: false, method: "put", }, { id: constants_1.UPDATE_TENANT_CORE_CONFIG_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.UPDATE_TENANT_CORE_CONFIG_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.UPDATE_TENANT_CORE_CONFIG_API) + ), disabled: false, method: "put", }, { id: constants_1.TENANT_THIRD_PARTY_CONFIG_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_THIRD_PARTY_CONFIG_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_THIRD_PARTY_CONFIG_API) + ), disabled: false, method: "get", }, { id: constants_1.TENANT_THIRD_PARTY_CONFIG_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_THIRD_PARTY_CONFIG_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_THIRD_PARTY_CONFIG_API) + ), disabled: false, method: "put", }, { id: constants_1.TENANT_THIRD_PARTY_CONFIG_API, - pathWithoutApiBasePath: new normalisedURLPath_1.default((0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_THIRD_PARTY_CONFIG_API)), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + (0, utils_1.getApiPathWithDashboardBase)(constants_1.TENANT_THIRD_PARTY_CONFIG_API) + ), disabled: false, method: "delete", }, @@ -363,11 +455,9 @@ class Recipe extends recipeModule_1.default { let apiFunction; if (id === constants_1.USERS_LIST_GET_API) { apiFunction = usersGet_1.default; - } - else if (id === constants_1.USERS_COUNT_API) { + } else if (id === constants_1.USERS_COUNT_API) { apiFunction = usersCountGet_1.default; - } - else if (id === constants_1.USER_API) { + } else if (id === constants_1.USER_API) { if (req.getMethod() === "get") { apiFunction = userGet_1.userGet; } @@ -377,69 +467,55 @@ class Recipe extends recipeModule_1.default { if (req.getMethod() === "put") { apiFunction = userPut_1.userPut; } - } - else if (id === constants_1.USER_EMAIL_VERIFY_API) { + } else if (id === constants_1.USER_EMAIL_VERIFY_API) { if (req.getMethod() === "get") { apiFunction = userEmailVerifyGet_1.userEmailVerifyGet; } if (req.getMethod() === "put") { apiFunction = userEmailVerifyPut_1.userEmailVerifyPut; } - } - else if (id === constants_1.USER_METADATA_API) { + } else if (id === constants_1.USER_METADATA_API) { if (req.getMethod() === "get") { apiFunction = userMetadataGet_1.userMetaDataGet; } if (req.getMethod() === "put") { apiFunction = userMetadataPut_1.userMetadataPut; } - } - else if (id === constants_1.USER_SESSIONS_API) { + } else if (id === constants_1.USER_SESSIONS_API) { if (req.getMethod() === "get") { apiFunction = userSessionsGet_1.userSessionsGet; } if (req.getMethod() === "post") { apiFunction = userSessionsPost_1.userSessionsPost; } - } - else if (id === constants_1.USER_PASSWORD_API) { + } else if (id === constants_1.USER_PASSWORD_API) { apiFunction = userPasswordPut_1.userPasswordPut; - } - else if (id === constants_1.USER_EMAIL_VERIFY_TOKEN_API) { + } else if (id === constants_1.USER_EMAIL_VERIFY_TOKEN_API) { apiFunction = userEmailVerifyTokenPost_1.userEmailVerifyTokenPost; - } - else if (id === constants_1.SEARCH_TAGS_API) { + } else if (id === constants_1.SEARCH_TAGS_API) { apiFunction = tagsGet_1.getSearchTags; - } - else if (id === constants_1.SIGN_OUT_API) { + } else if (id === constants_1.SIGN_OUT_API) { apiFunction = signOut_1.default; - } - else if (id === constants_1.DASHBOARD_ANALYTICS_API && req.getMethod() === "post") { + } else if (id === constants_1.DASHBOARD_ANALYTICS_API && req.getMethod() === "post") { apiFunction = analytics_1.default; - } - else if (id === constants_1.UNLINK_USER) { + } else if (id === constants_1.UNLINK_USER) { apiFunction = userUnlinkGet_1.userUnlink; - } - else if (id === constants_1.USERROLES_LIST_API) { + } else if (id === constants_1.USERROLES_LIST_API) { apiFunction = getAllRoles_1.default; - } - else if (id === constants_1.USERROLES_ROLE_API) { + } else if (id === constants_1.USERROLES_ROLE_API) { if (req.getMethod() === "put") { apiFunction = createRoleOrAddPermissions_1.default; } if (req.getMethod() === "delete") { apiFunction = deleteRole_1.default; } - } - else if (id === constants_1.USERROLES_PERMISSIONS_API) { + } else if (id === constants_1.USERROLES_PERMISSIONS_API) { if (req.getMethod() === "get") { apiFunction = getPermissionsForRole_1.default; } - } - else if (id === constants_1.USERROLES_REMOVE_PERMISSIONS_API) { + } else if (id === constants_1.USERROLES_REMOVE_PERMISSIONS_API) { apiFunction = removePermissions_1.default; - } - else if (id === constants_1.USERROLES_USER_API) { + } else if (id === constants_1.USERROLES_USER_API) { if (req.getMethod() === "put") { apiFunction = addRoleToUser_1.default; } @@ -449,23 +525,19 @@ class Recipe extends recipeModule_1.default { if (req.getMethod() === "delete") { apiFunction = removeUserRole_1.default; } - } - else if (id === constants_1.CREATE_EMAIL_PASSWORD_USER) { + } else if (id === constants_1.CREATE_EMAIL_PASSWORD_USER) { if (req.getMethod() === "post") { apiFunction = emailpasswordUser_1.createEmailPasswordUser; } - } - else if (id === constants_1.CREATE_PASSWORDLESS_USER) { + } else if (id === constants_1.CREATE_PASSWORDLESS_USER) { if (req.getMethod() === "post") { apiFunction = passwordlessUser_1.createPasswordlessUser; } - } - else if (id === constants_1.LIST_TENANTS_WITH_LOGIN_METHODS) { + } else if (id === constants_1.LIST_TENANTS_WITH_LOGIN_METHODS) { if (req.getMethod() === "get") { apiFunction = listAllTenantsWithLoginMethods_1.default; } - } - else if (id === constants_1.TENANT_API) { + } else if (id === constants_1.TENANT_API) { if (req.getMethod() === "post") { apiFunction = createTenant_1.default; } @@ -475,17 +547,13 @@ class Recipe extends recipeModule_1.default { if (req.getMethod() === "delete") { apiFunction = deleteTenant_1.default; } - } - else if (id === constants_1.UPDATE_TENANT_FIRST_FACTOR_API) { + } else if (id === constants_1.UPDATE_TENANT_FIRST_FACTOR_API) { apiFunction = updateTenantFirstFactor_1.default; - } - else if (id === constants_1.UPDATE_TENANT_REQUIRED_SECONDARY_FACTOR_API) { + } else if (id === constants_1.UPDATE_TENANT_REQUIRED_SECONDARY_FACTOR_API) { apiFunction = updateTenantSecondaryFactor_1.default; - } - else if (id === constants_1.UPDATE_TENANT_CORE_CONFIG_API) { + } else if (id === constants_1.UPDATE_TENANT_CORE_CONFIG_API) { apiFunction = updateTenantCoreConfig_1.default; - } - else if (id === constants_1.TENANT_THIRD_PARTY_CONFIG_API) { + } else if (id === constants_1.TENANT_THIRD_PARTY_CONFIG_API) { if (req.getMethod() === "get") { apiFunction = getThirdPartyConfig_1.default; } @@ -531,10 +599,18 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return Recipe.instance; - } - else { + } else { throw new Error("Dashboard recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/dashboard/recipeImplementation.js b/lib/build/recipe/dashboard/recipeImplementation.js index 4a519c021..125bf9b39 100644 --- a/lib/build/recipe/dashboard/recipeImplementation.js +++ b/lib/build/recipe/dashboard/recipeImplementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeImplementation; const error_1 = __importDefault(require("./error")); @@ -37,10 +39,17 @@ function getRecipeImplementation() { if (!input.config.apiKey) { // make the check for the API endpoint here with querier let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); - const authHeaderValue = (_a = input.req.getHeaderValue("authorization")) === null || _a === void 0 ? void 0 : _a.split(" ")[1]; - const sessionVerificationResponse = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/dashboard/session/verify"), { - sessionId: authHeaderValue, - }, input.userContext); + const authHeaderValue = + (_a = input.req.getHeaderValue("authorization")) === null || _a === void 0 + ? void 0 + : _a.split(" ")[1]; + const sessionVerificationResponse = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/dashboard/session/verify"), + { + sessionId: authHeaderValue, + }, + input.userContext + ); if (sessionVerificationResponse.status !== "OK") { return false; } @@ -59,16 +68,22 @@ function getRecipeImplementation() { return true; } if (admins.length === 0) { - (0, logger_1.logDebugMessage)("User Dashboard: Throwing OPERATION_NOT_ALLOWED because user is not an admin"); + (0, logger_1.logDebugMessage)( + "User Dashboard: Throwing OPERATION_NOT_ALLOWED because user is not an admin" + ); throw new error_1.default(); } const userEmail = sessionVerificationResponse.email; if (userEmail === undefined || typeof userEmail !== "string") { - (0, logger_1.logDebugMessage)("User Dashboard: Returning Unauthorised because no email was returned from the core. Should never come here"); + (0, logger_1.logDebugMessage)( + "User Dashboard: Returning Unauthorised because no email was returned from the core. Should never come here" + ); return false; } if (!admins.includes(userEmail)) { - (0, logger_1.logDebugMessage)("User Dashboard: Throwing OPERATION_NOT_ALLOWED because user is not an admin"); + (0, logger_1.logDebugMessage)( + "User Dashboard: Throwing OPERATION_NOT_ALLOWED because user is not an admin" + ); throw new error_1.default(); } } diff --git a/lib/build/recipe/dashboard/types.d.ts b/lib/build/recipe/dashboard/types.d.ts index afcc685a7..4e8c747d8 100644 --- a/lib/build/recipe/dashboard/types.d.ts +++ b/lib/build/recipe/dashboard/types.d.ts @@ -6,7 +6,10 @@ export type TypeInput = { apiKey?: string; admins?: string[]; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -15,14 +18,15 @@ export type TypeNormalisedInput = { admins?: string[]; authMode: AuthMode; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type RecipeInterface = { - getDashboardBundleLocation(input: { - userContext: UserContext; - }): Promise; + getDashboardBundleLocation(input: { userContext: UserContext }): Promise; shouldAllowAccess(input: { req: BaseRequest; config: TypeNormalisedInput; @@ -39,12 +43,14 @@ export type APIOptions = { appInfo: NormalisedAppinfo; }; export type APIInterface = { - dashboardGET: undefined | ((input: { - options: APIOptions; - userContext: UserContext; - }) => Promise); + dashboardGET: undefined | ((input: { options: APIOptions; userContext: UserContext }) => Promise); }; -export type APIFunction = (apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext) => Promise; +export type APIFunction = ( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +) => Promise; export type RecipeIdForUser = "emailpassword" | "thirdparty" | "passwordless"; export type AuthMode = "api-key" | "email-password"; export type UserWithFirstAndLastName = User & { diff --git a/lib/build/recipe/dashboard/utils.d.ts b/lib/build/recipe/dashboard/utils.d.ts index 3302c7ae6..f742b1cd6 100644 --- a/lib/build/recipe/dashboard/utils.d.ts +++ b/lib/build/recipe/dashboard/utils.d.ts @@ -6,7 +6,11 @@ import { UserContext } from "../../types"; export declare function validateAndNormaliseUserInput(config?: TypeInput): TypeNormalisedInput; export declare function sendUnauthorisedAccess(res: BaseResponse): void; export declare function isValidRecipeId(recipeId: string): recipeId is RecipeIdForUser; -export declare function getUserForRecipeId(recipeUserId: RecipeUserId, recipeId: string, userContext: UserContext): Promise<{ +export declare function getUserForRecipeId( + recipeUserId: RecipeUserId, + recipeId: string, + userContext: UserContext +): Promise<{ user: UserWithFirstAndLastName | undefined; recipe: "emailpassword" | "thirdparty" | "passwordless" | undefined; }>; diff --git a/lib/build/recipe/dashboard/utils.js b/lib/build/recipe/dashboard/utils.js index 7872812d8..7c76fab82 100644 --- a/lib/build/recipe/dashboard/utils.js +++ b/lib/build/recipe/dashboard/utils.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; exports.sendUnauthorisedAccess = sendUnauthorisedAccess; @@ -31,15 +33,28 @@ const recipe_3 = __importDefault(require("../thirdparty/recipe")); const recipe_4 = __importDefault(require("../passwordless/recipe")); const logger_1 = require("../../logger"); function validateAndNormaliseUserInput(config) { - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, (config === undefined ? {} : config.override)); - if ((config === null || config === void 0 ? void 0 : config.apiKey) !== undefined && (config === null || config === void 0 ? void 0 : config.admins) !== undefined) { + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === undefined ? {} : config.override + ); + if ( + (config === null || config === void 0 ? void 0 : config.apiKey) !== undefined && + (config === null || config === void 0 ? void 0 : config.admins) !== undefined + ) { (0, logger_1.logDebugMessage)("User Dashboard: Providing 'admins' has no effect when using an apiKey."); } let admins; if ((config === null || config === void 0 ? void 0 : config.admins) !== undefined) { admins = config.admins.map((email) => (0, utils_1.normaliseEmail)(email)); } - return Object.assign(Object.assign({}, config), { override, authMode: config !== undefined && config.apiKey ? "api-key" : "email-password", admins }); + return Object.assign(Object.assign({}, config), { + override, + authMode: config !== undefined && config.apiKey ? "api-key" : "email-password", + admins, + }); } function sendUnauthorisedAccess(res) { (0, utils_1.sendNon200ResponseWithMessage)(res, "Unauthorised access", 401); @@ -70,7 +85,9 @@ async function _getUserForRecipeId(recipeUserId, recipeId, userContext) { recipe: undefined, }; } - const loginMethod = user.loginMethods.find((m) => m.recipeId === recipeId && m.recipeUserId.getAsString() === recipeUserId.getAsString()); + const loginMethod = user.loginMethods.find( + (m) => m.recipeId === recipeId && m.recipeUserId.getAsString() === recipeUserId.getAsString() + ); if (loginMethod === undefined) { return { user: undefined, @@ -82,26 +99,21 @@ async function _getUserForRecipeId(recipeUserId, recipeId, userContext) { // we detect if this recipe has been init or not.. recipe_2.default.getInstanceOrThrowError(); recipe = "emailpassword"; - } - catch (e) { + } catch (e) { // No - op } - } - else if (recipeId === recipe_3.default.RECIPE_ID) { + } else if (recipeId === recipe_3.default.RECIPE_ID) { try { recipe_3.default.getInstanceOrThrowError(); recipe = "thirdparty"; - } - catch (e) { + } catch (e) { // No - op } - } - else if (recipeId === recipe_4.default.RECIPE_ID) { + } else if (recipeId === recipe_4.default.RECIPE_ID) { try { recipe_4.default.getInstanceOrThrowError(); recipe = "passwordless"; - } - catch (e) { + } catch (e) { // No - op } } @@ -113,7 +125,8 @@ async function _getUserForRecipeId(recipeUserId, recipeId, userContext) { async function validateApiKey(input) { let apiKeyHeaderValue = input.req.getHeaderValue("authorization"); // We receieve the api key as `Bearer API_KEY`, this retrieves just the key - apiKeyHeaderValue = apiKeyHeaderValue === null || apiKeyHeaderValue === void 0 ? void 0 : apiKeyHeaderValue.split(" ")[1]; + apiKeyHeaderValue = + apiKeyHeaderValue === null || apiKeyHeaderValue === void 0 ? void 0 : apiKeyHeaderValue.split(" ")[1]; if (apiKeyHeaderValue === undefined) { return false; } diff --git a/lib/build/recipe/emailpassword/api/emailExists.d.ts b/lib/build/recipe/emailpassword/api/emailExists.d.ts index 478175dec..2f55b6d3b 100644 --- a/lib/build/recipe/emailpassword/api/emailExists.d.ts +++ b/lib/build/recipe/emailpassword/api/emailExists.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function emailExists(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function emailExists( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/emailpassword/api/emailExists.js b/lib/build/recipe/emailpassword/api/emailExists.js index e49388b68..2e77eb6a1 100644 --- a/lib/build/recipe/emailpassword/api/emailExists.js +++ b/lib/build/recipe/emailpassword/api/emailExists.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = emailExists; const utils_1 = require("../../../utils"); diff --git a/lib/build/recipe/emailpassword/api/generatePasswordResetToken.d.ts b/lib/build/recipe/emailpassword/api/generatePasswordResetToken.d.ts index 9ce0acc4b..146d43586 100644 --- a/lib/build/recipe/emailpassword/api/generatePasswordResetToken.d.ts +++ b/lib/build/recipe/emailpassword/api/generatePasswordResetToken.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function generatePasswordResetToken(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function generatePasswordResetToken( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js b/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js index 8b1c16ee4..432f4b9b0 100644 --- a/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js +++ b/lib/build/recipe/emailpassword/api/generatePasswordResetToken.js @@ -24,7 +24,12 @@ async function generatePasswordResetToken(apiImplementation, tenantId, options, } const requestBody = await options.req.getJSONBody(); // step 1 - let formFields = await (0, utils_2.validateFormFieldsOrThrowError)(options.config.resetPasswordUsingTokenFeature.formFieldsForGenerateTokenForm, requestBody.formFields, tenantId, userContext); + let formFields = await (0, utils_2.validateFormFieldsOrThrowError)( + options.config.resetPasswordUsingTokenFeature.formFieldsForGenerateTokenForm, + requestBody.formFields, + tenantId, + userContext + ); let result = await apiImplementation.generatePasswordResetTokenPOST({ formFields, tenantId, diff --git a/lib/build/recipe/emailpassword/api/implementation.js b/lib/build/recipe/emailpassword/api/implementation.js index bb442f86d..4f855f50e 100644 --- a/lib/build/recipe/emailpassword/api/implementation.js +++ b/lib/build/recipe/emailpassword/api/implementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIImplementation; const logger_1 = require("../../../logger"); @@ -14,7 +16,7 @@ const authUtils_1 = require("../../../authUtils"); const utils_2 = require("../../thirdparty/utils"); function getAPIImplementation() { return { - emailExistsGET: async function ({ email, tenantId, userContext, }) { + emailExistsGET: async function ({ email, tenantId, userContext }) { // even if the above returns true, we still need to check if there // exists an email password user with the same email cause the function // above does not check for that. @@ -26,22 +28,27 @@ function getAPIImplementation() { doUnionOfAccountInfo: false, userContext, }); - let emailPasswordUserExists = users.find((u) => { - return (u.loginMethods.find((lm) => lm.recipeId === "emailpassword" && lm.hasSameEmailAs(email)) !== - undefined); - }) !== undefined; + let emailPasswordUserExists = + users.find((u) => { + return ( + u.loginMethods.find((lm) => lm.recipeId === "emailpassword" && lm.hasSameEmailAs(email)) !== + undefined + ); + }) !== undefined; return { status: "OK", exists: emailPasswordUserExists, }; }, - generatePasswordResetTokenPOST: async function ({ formFields, tenantId, options, userContext, }) { + generatePasswordResetTokenPOST: async function ({ formFields, tenantId, options, userContext }) { // NOTE: Check for email being a non-string value. This check will likely // never evaluate to `true` as there is an upper-level check for the type // in validation but kept here to be safe. const emailAsUnknown = formFields.filter((f) => f.id === "email")[0].value; if (typeof emailAsUnknown !== "string") - throw new Error("Should never come here since we already check that the email value is a string in validateFormFieldsOrThrowError"); + throw new Error( + "Should never come here since we already check that the email value is a string in validateFormFieldsOrThrowError" + ); const email = emailAsUnknown; // this function will be reused in different parts of the flow below.. async function generateAndSendPasswordResetToken(primaryUserId, recipeUserId) { @@ -53,7 +60,11 @@ function getAPIImplementation() { userContext, }); if (response.status === "UNKNOWN_USER_ID_ERROR") { - (0, logger_1.logDebugMessage)(`Password reset email not sent, unknown user id: ${recipeUserId === undefined ? primaryUserId : recipeUserId.getAsString()}`); + (0, logger_1.logDebugMessage)( + `Password reset email not sent, unknown user id: ${ + recipeUserId === undefined ? primaryUserId : recipeUserId.getAsString() + }` + ); return { status: "OK", }; @@ -96,7 +107,9 @@ function getAPIImplementation() { // for later use. let emailPasswordAccount = undefined; for (let i = 0; i < users.length; i++) { - let emailPasswordAccountTmp = users[i].loginMethods.find((l) => l.recipeId === "emailpassword" && l.hasSameEmailAs(email)); + let emailPasswordAccountTmp = users[i].loginMethods.find( + (l) => l.recipeId === "emailpassword" && l.hasSameEmailAs(email) + ); if (emailPasswordAccountTmp !== undefined) { emailPasswordAccount = emailPasswordAccountTmp; break; @@ -104,23 +117,43 @@ function getAPIImplementation() { } // we find the primary user ID from the user's list for later use. let linkingCandidate = users.find((u) => u.isPrimaryUser); - (0, logger_1.logDebugMessage)("generatePasswordResetTokenPOST: primary linking candidate: " + (linkingCandidate === null || linkingCandidate === void 0 ? void 0 : linkingCandidate.id)); + (0, logger_1.logDebugMessage)( + "generatePasswordResetTokenPOST: primary linking candidate: " + + (linkingCandidate === null || linkingCandidate === void 0 ? void 0 : linkingCandidate.id) + ); (0, logger_1.logDebugMessage)("generatePasswordResetTokenPOST: linking candidate count " + users.length); // If there is no existing primary user and there is a single option to link // we see if that user can become primary (and a candidate for linking) if (linkingCandidate === undefined && users.length > 0) { // If the only user that exists with this email is a non-primary emailpassword user, then we can just let them reset their password, because: // we are not going to link anything and there is no risk of account takeover. - if (users.length === 1 && + if ( + users.length === 1 && users[0].loginMethods[0].recipeUserId.getAsString() === - (emailPasswordAccount === null || emailPasswordAccount === void 0 ? void 0 : emailPasswordAccount.recipeUserId.getAsString())) { - return await generateAndSendPasswordResetToken(emailPasswordAccount.recipeUserId.getAsString(), emailPasswordAccount.recipeUserId); + (emailPasswordAccount === null || emailPasswordAccount === void 0 + ? void 0 + : emailPasswordAccount.recipeUserId.getAsString()) + ) { + return await generateAndSendPasswordResetToken( + emailPasswordAccount.recipeUserId.getAsString(), + emailPasswordAccount.recipeUserId + ); } const oldestUser = users.sort((a, b) => a.timeJoined - b.timeJoined)[0]; - (0, logger_1.logDebugMessage)(`generatePasswordResetTokenPOST: oldest recipe level-linking candidate: ${oldestUser.id} (w/ ${oldestUser.loginMethods[0].verified ? "verified" : "unverified"} email)`); + (0, logger_1.logDebugMessage)( + `generatePasswordResetTokenPOST: oldest recipe level-linking candidate: ${oldestUser.id} (w/ ${ + oldestUser.loginMethods[0].verified ? "verified" : "unverified" + } email)` + ); // Otherwise, we check if the user can become primary. - const shouldBecomePrimaryUser = await recipe_1.default.getInstance().shouldBecomePrimaryUser(oldestUser, tenantId, undefined, userContext); - (0, logger_1.logDebugMessage)(`generatePasswordResetTokenPOST: recipe level-linking candidate ${shouldBecomePrimaryUser ? "can" : "can not"} become primary`); + const shouldBecomePrimaryUser = await recipe_1.default + .getInstance() + .shouldBecomePrimaryUser(oldestUser, tenantId, undefined, userContext); + (0, logger_1.logDebugMessage)( + `generatePasswordResetTokenPOST: recipe level-linking candidate ${ + shouldBecomePrimaryUser ? "can" : "can not" + } become primary` + ); if (shouldBecomePrimaryUser) { linkingCandidate = oldestUser; } @@ -134,7 +167,10 @@ function getAPIImplementation() { status: "OK", }; } - return await generateAndSendPasswordResetToken(emailPasswordAccount.recipeUserId.getAsString(), emailPasswordAccount.recipeUserId); + return await generateAndSendPasswordResetToken( + emailPasswordAccount.recipeUserId.getAsString(), + emailPasswordAccount.recipeUserId + ); } /* This security measure helps prevent the following attack: @@ -158,48 +194,63 @@ function getAPIImplementation() { // First we check if there is any login method in which the input email is verified. // If that is the case, then it's proven that the user owns the email and we can // trust linking of the email password account. - let emailVerified = linkingCandidate.loginMethods.find((lm) => { - return lm.hasSameEmailAs(email) && lm.verified; - }) !== undefined; + let emailVerified = + linkingCandidate.loginMethods.find((lm) => { + return lm.hasSameEmailAs(email) && lm.verified; + }) !== undefined; // then, we check if the primary user has any other email / phone number // associated with this account - and if it does, then it means that // there is a risk of account takeover, so we do not allow the token to be generated - let hasOtherEmailOrPhone = linkingCandidate.loginMethods.find((lm) => { - // we do the extra undefined check below cause - // hasSameEmailAs returns false if the lm.email is undefined, and - // we want to check that the email is different as opposed to email - // not existing in lm. - return (lm.email !== undefined && !lm.hasSameEmailAs(email)) || lm.phoneNumber !== undefined; - }) !== undefined; + let hasOtherEmailOrPhone = + linkingCandidate.loginMethods.find((lm) => { + // we do the extra undefined check below cause + // hasSameEmailAs returns false if the lm.email is undefined, and + // we want to check that the email is different as opposed to email + // not existing in lm. + return (lm.email !== undefined && !lm.hasSameEmailAs(email)) || lm.phoneNumber !== undefined; + }) !== undefined; // If we allow this to pass, then: // 1. the if (!emailVerified && hasOtherEmailOrPhone) { return { status: "PASSWORD_RESET_NOT_ALLOWED", - reason: "Reset password link was not created because of account take over risk. Please contact support. (ERR_CODE_001)", + reason: + "Reset password link was not created because of account take over risk. Please contact support. (ERR_CODE_001)", }; } if (linkingCandidate.isPrimaryUser && emailPasswordAccount !== undefined) { // If a primary user has the input email as verified or has no other emails then it is always allowed to reset their own password: // - there is no risk of account takeover, because they have verified this email or haven't linked it to anything else (checked above this block) // - there will be no linking as a result of this action, so we do not need to check for linking (checked here by seeing that the two accounts are already linked) - let areTheTwoAccountsLinked = linkingCandidate.loginMethods.find((lm) => { - return lm.recipeUserId.getAsString() === emailPasswordAccount.recipeUserId.getAsString(); - }) !== undefined; + let areTheTwoAccountsLinked = + linkingCandidate.loginMethods.find((lm) => { + return lm.recipeUserId.getAsString() === emailPasswordAccount.recipeUserId.getAsString(); + }) !== undefined; if (areTheTwoAccountsLinked) { - return await generateAndSendPasswordResetToken(linkingCandidate.id, emailPasswordAccount.recipeUserId); + return await generateAndSendPasswordResetToken( + linkingCandidate.id, + emailPasswordAccount.recipeUserId + ); } } // Here we know that the two accounts are NOT linked. We now need to check for an // extra security measure here to make sure that the input email in the primary user // is verified, and if not, we need to make sure that there is no other email / phone number // associated with the primary user account. If there is, then we do not proceed. - let shouldDoAccountLinkingResponse = await recipe_1.default.getInstance().config.shouldDoAutomaticAccountLinking(emailPasswordAccount !== undefined - ? emailPasswordAccount - : { - recipeId: "emailpassword", - email, - }, linkingCandidate, undefined, tenantId, userContext); + let shouldDoAccountLinkingResponse = await recipe_1.default + .getInstance() + .config.shouldDoAutomaticAccountLinking( + emailPasswordAccount !== undefined + ? emailPasswordAccount + : { + recipeId: "emailpassword", + email, + }, + linkingCandidate, + undefined, + tenantId, + userContext + ); // Now we need to check that if there exists any email password user at all // for the input email. If not, then it implies that when the token is consumed, // then we will create a new user - so we should only generate the token if @@ -213,7 +264,9 @@ function getAPIImplementation() { // code consume cannot be linked to the primary user - therefore, we should // not generate a password reset token if (!shouldDoAccountLinkingResponse.shouldAutomaticallyLink) { - (0, logger_1.logDebugMessage)(`Password reset email not sent, since email password user didn't exist, and account linking not enabled`); + (0, logger_1.logDebugMessage)( + `Password reset email not sent, since email password user didn't exist, and account linking not enabled` + ); return { status: "OK", }; @@ -233,9 +286,10 @@ function getAPIImplementation() { // we will be creating a new email password account when the token // is consumed and linking it to this primary user. return await generateAndSendPasswordResetToken(linkingCandidate.id, undefined); - } - else { - (0, logger_1.logDebugMessage)(`Password reset email not sent, isSignUpAllowed returned false for email: ${email}`); + } else { + (0, logger_1.logDebugMessage)( + `Password reset email not sent, isSignUpAllowed returned false for email: ${email}` + ); return { status: "OK", }; @@ -246,21 +300,26 @@ function getAPIImplementation() { // here we will go ahead with the token generation cause // even when the token is consumed, we will not be linking the accounts // so no need to check for anything - return await generateAndSendPasswordResetToken(emailPasswordAccount.recipeUserId.getAsString(), emailPasswordAccount.recipeUserId); + return await generateAndSendPasswordResetToken( + emailPasswordAccount.recipeUserId.getAsString(), + emailPasswordAccount.recipeUserId + ); } // Here we accounted for both `shouldRequireVerification` by the above checks (where we return ERR_CODE_001) return await generateAndSendPasswordResetToken(linkingCandidate.id, emailPasswordAccount.recipeUserId); }, - passwordResetPOST: async function ({ formFields, token, tenantId, options, userContext, }) { + passwordResetPOST: async function ({ formFields, token, tenantId, options, userContext }) { async function markEmailAsVerified(recipeUserId, email) { const emailVerificationInstance = recipe_2.default.getInstance(); if (emailVerificationInstance) { - const tokenResponse = await emailVerificationInstance.recipeInterfaceImpl.createEmailVerificationToken({ - tenantId, - recipeUserId, - email, - userContext, - }); + const tokenResponse = await emailVerificationInstance.recipeInterfaceImpl.createEmailVerificationToken( + { + tenantId, + recipeUserId, + email, + userContext, + } + ); if (tokenResponse.status === "OK") { await emailVerificationInstance.recipeInterfaceImpl.verifyEmailUsingToken({ tenantId, @@ -282,24 +341,23 @@ function getAPIImplementation() { password: newPassword, userContext, }); - if (updateResponse.status === "EMAIL_ALREADY_EXISTS_ERROR" || - updateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { + if ( + updateResponse.status === "EMAIL_ALREADY_EXISTS_ERROR" || + updateResponse.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR" + ) { throw new Error("This should never come here because we are not updating the email"); - } - else if (updateResponse.status === "UNKNOWN_USER_ID_ERROR") { + } else if (updateResponse.status === "UNKNOWN_USER_ID_ERROR") { // This should happen only cause of a race condition where the user // might be deleted before token creation and consumption. return { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR", }; - } - else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { + } else if (updateResponse.status === "PASSWORD_POLICY_VIOLATED_ERROR") { return { status: "PASSWORD_POLICY_VIOLATED_ERROR", failureReason: updateResponse.failureReason, }; - } - else { + } else { // status: "OK" // If the update was successful, we try to mark the email as verified. // We do this because we assume that the password reset token was delivered by email (and to the appropriate email address) @@ -311,7 +369,10 @@ function getAPIImplementation() { // If we verified (and linked) the existing user with the original password, User M would get access to the current user and any linked users. await markEmailAsVerified(recipeUserId, emailForWhomTokenWasGenerated); // We refresh the user information here, because the verification status may be updated, which is used during linking. - const updatedUserAfterEmailVerification = await (0, __1.getUser)(recipeUserId.getAsString(), userContext); + const updatedUserAfterEmailVerification = await (0, __1.getUser)( + recipeUserId.getAsString(), + userContext + ); if (updatedUserAfterEmailVerification === undefined) { throw new Error("Should never happen - user deleted after during password reset"); } @@ -334,7 +395,8 @@ function getAPIImplementation() { session: undefined, userContext, }); - const userAfterWeTriedLinking = linkRes.status === "OK" ? linkRes.user : updatedUserAfterEmailVerification; + const userAfterWeTriedLinking = + linkRes.status === "OK" ? linkRes.user : updatedUserAfterEmailVerification; return { status: "OK", email: emailForWhomTokenWasGenerated, @@ -347,7 +409,9 @@ function getAPIImplementation() { // in validation but kept here to be safe. const newPasswordAsUnknown = formFields.filter((f) => f.id === "password")[0].value; if (typeof newPasswordAsUnknown !== "string") - throw new Error("Should never come here since we already check that the password value is a string in validateFormFieldsOrThrowError"); + throw new Error( + "Should never come here since we already check that the password value is a string in validateFormFieldsOrThrowError" + ); let newPassword = newPasswordAsUnknown; let tokenConsumptionResponse = await options.recipeImplementation.consumePasswordResetToken({ token, @@ -379,32 +443,40 @@ function getAPIImplementation() { // primary user id (userIdForWhomTokenWasGenerated), in this case, // we still don't allow password update, cause the user should try again // and the token should be regenerated for the right recipe user. - return (lm.recipeUserId.getAsString() === userIdForWhomTokenWasGenerated && lm.recipeId === "emailpassword"); + return ( + lm.recipeUserId.getAsString() === userIdForWhomTokenWasGenerated && lm.recipeId === "emailpassword" + ); }); if (tokenGeneratedForEmailPasswordUser) { if (!existingUser.isPrimaryUser) { // If this is a recipe level emailpassword user, we can always allow them to reset their password. - return doUpdatePasswordAndVerifyEmailAndTryLinkIfNotPrimary(new recipeUserId_1.default(userIdForWhomTokenWasGenerated)); + return doUpdatePasswordAndVerifyEmailAndTryLinkIfNotPrimary( + new recipeUserId_1.default(userIdForWhomTokenWasGenerated) + ); } // If the user is a primary user resetting the password of an emailpassword user linked to it // we need to check for account takeover risk (similar to what we do when generating the token) // We check if there is any login method in which the input email is verified. // If that is the case, then it's proven that the user owns the email and we can // trust linking of the email password account. - let emailVerified = existingUser.loginMethods.find((lm) => { - return lm.hasSameEmailAs(emailForWhomTokenWasGenerated) && lm.verified; - }) !== undefined; + let emailVerified = + existingUser.loginMethods.find((lm) => { + return lm.hasSameEmailAs(emailForWhomTokenWasGenerated) && lm.verified; + }) !== undefined; // finally, we check if the primary user has any other email / phone number // associated with this account - and if it does, then it means that // there is a risk of account takeover, so we do not allow the token to be generated - let hasOtherEmailOrPhone = existingUser.loginMethods.find((lm) => { - // we do the extra undefined check below cause - // hasSameEmailAs returns false if the lm.email is undefined, and - // we want to check that the email is different as opposed to email - // not existing in lm. - return ((lm.email !== undefined && !lm.hasSameEmailAs(emailForWhomTokenWasGenerated)) || - lm.phoneNumber !== undefined); - }) !== undefined; + let hasOtherEmailOrPhone = + existingUser.loginMethods.find((lm) => { + // we do the extra undefined check below cause + // hasSameEmailAs returns false if the lm.email is undefined, and + // we want to check that the email is different as opposed to email + // not existing in lm. + return ( + (lm.email !== undefined && !lm.hasSameEmailAs(emailForWhomTokenWasGenerated)) || + lm.phoneNumber !== undefined + ); + }) !== undefined; if (!emailVerified && hasOtherEmailOrPhone) { // We can return an invalid token error, because in this case the token should not have been created // whenever they try to re-create it they'll see the appropriate error message @@ -413,7 +485,9 @@ function getAPIImplementation() { }; } // since this doesn't result in linking and there is no risk of account takeover, we can allow the password reset to proceed - return doUpdatePasswordAndVerifyEmailAndTryLinkIfNotPrimary(new recipeUserId_1.default(userIdForWhomTokenWasGenerated)); + return doUpdatePasswordAndVerifyEmailAndTryLinkIfNotPrimary( + new recipeUserId_1.default(userIdForWhomTokenWasGenerated) + ); } // this means that the existingUser is primary but does not have an emailpassword user associated // with it. It could now mean that no emailpassword user exists, or it could mean that @@ -441,13 +515,15 @@ function getAPIImplementation() { return { status: "RESET_PASSWORD_INVALID_TOKEN_ERROR", }; - } - else { + } else { // we mark the email as verified because password reset also requires // access to the email to work.. This has a good side effect that // any other login method with the same email in existingAccount will also get marked // as verified. - await markEmailAsVerified(createUserResponse.user.loginMethods[0].recipeUserId, tokenConsumptionResponse.email); + await markEmailAsVerified( + createUserResponse.user.loginMethods[0].recipeUserId, + tokenConsumptionResponse.email + ); const updatedUser = await (0, __1.getUser)(createUserResponse.user.id, userContext); if (updatedUser === undefined) { throw new Error("Should never happen - user deleted after during password reset"); @@ -479,14 +555,26 @@ function getAPIImplementation() { }; } }, - signInPOST: async function ({ formFields, tenantId, session, shouldTryLinkingWithSessionUser, options, userContext, }) { + signInPOST: async function ({ + formFields, + tenantId, + session, + shouldTryLinkingWithSessionUser, + options, + userContext, + }) { const errorCodeMap = { - SIGN_IN_NOT_ALLOWED: "Cannot sign in due to security reasons. Please try resetting your password, use a different login method or contact support. (ERR_CODE_008)", + SIGN_IN_NOT_ALLOWED: + "Cannot sign in due to security reasons. Please try resetting your password, use a different login method or contact support. (ERR_CODE_008)", LINKING_TO_SESSION_USER_FAILED: { - EMAIL_VERIFICATION_REQUIRED: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_009)", - RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_010)", - ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_011)", - SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_012)", + EMAIL_VERIFICATION_REQUIRED: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_009)", + RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_010)", + ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_011)", + SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_012)", }, }; const emailAsUnknown = formFields.filter((f) => f.id === "email")[0].value; @@ -495,15 +583,21 @@ function getAPIImplementation() { // check for type is done in a parent function but they are kept // here to be on the safe side. if (typeof emailAsUnknown !== "string") - throw new Error("Should never come here since we already check that the email value is a string in validateFormFieldsOrThrowError"); + throw new Error( + "Should never come here since we already check that the email value is a string in validateFormFieldsOrThrowError" + ); if (typeof passwordAsUnknown !== "string") - throw new Error("Should never come here since we already check that the password value is a string in validateFormFieldsOrThrowError"); + throw new Error( + "Should never come here since we already check that the password value is a string in validateFormFieldsOrThrowError" + ); let email = emailAsUnknown; let password = passwordAsUnknown; const recipeId = "emailpassword"; const checkCredentialsOnTenant = async (tenantId) => { - return ((await options.recipeImplementation.verifyCredentials({ email, password, tenantId, userContext })) - .status === "OK"); + return ( + (await options.recipeImplementation.verifyCredentials({ email, password, tenantId, userContext })) + .status === "OK" + ); }; if ((0, utils_2.isFakeEmail)(email) && session === undefined) { // Fake emails cannot be used as a first factor @@ -511,14 +605,16 @@ function getAPIImplementation() { status: "WRONG_CREDENTIALS_ERROR", }; } - const authenticatingUser = await authUtils_1.AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired({ - accountInfo: { email }, - userContext, - recipeId, - session, - tenantId, - checkCredentialsOnTenant, - }); + const authenticatingUser = await authUtils_1.AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired( + { + accountInfo: { email }, + userContext, + recipeId, + session, + tenantId, + checkCredentialsOnTenant, + } + ); const isVerified = authenticatingUser !== undefined && authenticatingUser.loginMethod.verified; // We check this before preAuthChecks, because that function assumes that if isSignUp is false, // then authenticatingUser is defined. While it wouldn't technically cause any problems with @@ -536,7 +632,8 @@ function getAPIImplementation() { }, factorIds: ["emailpassword"], isSignUp: false, - authenticatingUser: authenticatingUser === null || authenticatingUser === void 0 ? void 0 : authenticatingUser.user, + authenticatingUser: + authenticatingUser === null || authenticatingUser === void 0 ? void 0 : authenticatingUser.user, isVerified, signInVerifiesLoginMethod: false, skipSessionUserUpdateInCore: false, @@ -549,7 +646,11 @@ function getAPIImplementation() { throw new Error("This should never happen: pre-auth checks should not fail for sign in"); } if (preAuthChecks.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(preAuthChecks, errorCodeMap, "SIGN_IN_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + preAuthChecks, + errorCodeMap, + "SIGN_IN_NOT_ALLOWED" + ); } if ((0, utils_2.isFakeEmail)(email) && preAuthChecks.isFirstFactor) { // Fake emails cannot be used as a first factor @@ -569,7 +670,11 @@ function getAPIImplementation() { return signInResponse; } if (signInResponse.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(signInResponse, errorCodeMap, "SIGN_IN_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + signInResponse, + errorCodeMap, + "SIGN_IN_NOT_ALLOWED" + ); } const postAuthChecks = await authUtils_1.AuthUtils.postAuthChecks({ authenticatedUser: signInResponse.user, @@ -583,7 +688,11 @@ function getAPIImplementation() { userContext, }); if (postAuthChecks.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(postAuthChecks, errorCodeMap, "SIGN_IN_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + postAuthChecks, + errorCodeMap, + "SIGN_IN_NOT_ALLOWED" + ); } return { status: "OK", @@ -591,14 +700,26 @@ function getAPIImplementation() { user: postAuthChecks.user, }; }, - signUpPOST: async function ({ formFields, tenantId, session, shouldTryLinkingWithSessionUser, options, userContext, }) { + signUpPOST: async function ({ + formFields, + tenantId, + session, + shouldTryLinkingWithSessionUser, + options, + userContext, + }) { const errorCodeMap = { - SIGN_UP_NOT_ALLOWED: "Cannot sign up due to security reasons. Please try logging in, use a different login method or contact support. (ERR_CODE_007)", + SIGN_UP_NOT_ALLOWED: + "Cannot sign up due to security reasons. Please try logging in, use a different login method or contact support. (ERR_CODE_007)", LINKING_TO_SESSION_USER_FAILED: { - EMAIL_VERIFICATION_REQUIRED: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_013)", - RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_014)", - ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_015)", - SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_016)", + EMAIL_VERIFICATION_REQUIRED: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_013)", + RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_014)", + ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_015)", + SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_016)", }, }; const emailAsUnknown = formFields.filter((f) => f.id === "email")[0].value; @@ -607,9 +728,13 @@ function getAPIImplementation() { // check for type is done in a parent function but they are kept // here to be on the safe side. if (typeof emailAsUnknown !== "string") - throw new Error("Should never come here since we already check that the email value is a string in validateFormFieldsOrThrowError"); + throw new Error( + "Should never come here since we already check that the email value is a string in validateFormFieldsOrThrowError" + ); if (typeof passwordAsUnknown !== "string") - throw new Error("Should never come here since we already check that the password value is a string in validateFormFieldsOrThrowError"); + throw new Error( + "Should never come here since we already check that the password value is a string in validateFormFieldsOrThrowError" + ); let email = emailAsUnknown; let password = passwordAsUnknown; const preAuthCheckRes = await authUtils_1.AuthUtils.preAuthChecks({ @@ -629,22 +754,32 @@ function getAPIImplementation() { shouldTryLinkingWithSessionUser, }); if (preAuthCheckRes.status === "SIGN_UP_NOT_ALLOWED") { - const conflictingUsers = await recipe_1.default.getInstance().recipeInterfaceImpl.listUsersByAccountInfo({ - tenantId, - accountInfo: { - email, - }, - doUnionOfAccountInfo: false, - userContext, - }); - if (conflictingUsers.some((u) => u.loginMethods.some((lm) => lm.recipeId === "emailpassword" && lm.hasSameEmailAs(email)))) { + const conflictingUsers = await recipe_1.default + .getInstance() + .recipeInterfaceImpl.listUsersByAccountInfo({ + tenantId, + accountInfo: { + email, + }, + doUnionOfAccountInfo: false, + userContext, + }); + if ( + conflictingUsers.some((u) => + u.loginMethods.some((lm) => lm.recipeId === "emailpassword" && lm.hasSameEmailAs(email)) + ) + ) { return { status: "EMAIL_ALREADY_EXISTS_ERROR", }; } } if (preAuthCheckRes.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(preAuthCheckRes, errorCodeMap, "SIGN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + preAuthCheckRes, + errorCodeMap, + "SIGN_UP_NOT_ALLOWED" + ); } if ((0, utils_2.isFakeEmail)(email) && preAuthCheckRes.isFirstFactor) { // Fake emails cannot be used as a first factor @@ -664,7 +799,11 @@ function getAPIImplementation() { return signUpResponse; } if (signUpResponse.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(signUpResponse, errorCodeMap, "SIGN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + signUpResponse, + errorCodeMap, + "SIGN_UP_NOT_ALLOWED" + ); } const postAuthChecks = await authUtils_1.AuthUtils.postAuthChecks({ authenticatedUser: signUpResponse.user, @@ -681,7 +820,11 @@ function getAPIImplementation() { // It should never actually come here, but we do it cause of consistency. // If it does come here (in case there is a bug), it would make this func throw // anyway, cause there is no SIGN_IN_NOT_ALLOWED in the errorCodeMap. - authUtils_1.AuthUtils.getErrorStatusResponseWithReason(postAuthChecks, errorCodeMap, "SIGN_UP_NOT_ALLOWED"); + authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + postAuthChecks, + errorCodeMap, + "SIGN_UP_NOT_ALLOWED" + ); throw new Error("This should never happen"); } return { diff --git a/lib/build/recipe/emailpassword/api/passwordReset.d.ts b/lib/build/recipe/emailpassword/api/passwordReset.d.ts index 3a2304943..08aef7f99 100644 --- a/lib/build/recipe/emailpassword/api/passwordReset.d.ts +++ b/lib/build/recipe/emailpassword/api/passwordReset.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function passwordReset(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function passwordReset( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/emailpassword/api/passwordReset.js b/lib/build/recipe/emailpassword/api/passwordReset.js index e1238257b..f54c1c5ac 100644 --- a/lib/build/recipe/emailpassword/api/passwordReset.js +++ b/lib/build/recipe/emailpassword/api/passwordReset.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = passwordReset; const utils_1 = require("../../../utils"); @@ -31,7 +33,12 @@ async function passwordReset(apiImplementation, tenantId, options, userContext) // - we want to throw this error before consuming the token, so that the user can try again // - there is a case in the api impl where we create a new user, and we want to assign // a password that meets the password policy. - let formFields = await (0, utils_2.validateFormFieldsOrThrowError)(options.config.resetPasswordUsingTokenFeature.formFieldsForPasswordResetForm, requestBody.formFields, tenantId, userContext); + let formFields = await (0, utils_2.validateFormFieldsOrThrowError)( + options.config.resetPasswordUsingTokenFeature.formFieldsForPasswordResetForm, + requestBody.formFields, + tenantId, + userContext + ); let token = requestBody.token; if (token === undefined) { throw new error_1.default({ @@ -66,10 +73,13 @@ async function passwordReset(apiImplementation, tenantId, options, userContext) message: "Error in input formFields", }); } - (0, utils_1.send200Response)(options.res, result.status === "OK" - ? { - status: "OK", - } - : result); + (0, utils_1.send200Response)( + options.res, + result.status === "OK" + ? { + status: "OK", + } + : result + ); return true; } diff --git a/lib/build/recipe/emailpassword/api/signin.d.ts b/lib/build/recipe/emailpassword/api/signin.d.ts index 178b76b67..4a712efbe 100644 --- a/lib/build/recipe/emailpassword/api/signin.d.ts +++ b/lib/build/recipe/emailpassword/api/signin.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function signInAPI(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function signInAPI( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/emailpassword/api/signin.js b/lib/build/recipe/emailpassword/api/signin.js index 6ef3fc878..bdd9a5798 100644 --- a/lib/build/recipe/emailpassword/api/signin.js +++ b/lib/build/recipe/emailpassword/api/signin.js @@ -25,9 +25,22 @@ async function signInAPI(apiImplementation, tenantId, options, userContext) { } const body = await options.req.getJSONBody(); // step 1 - let formFields = await (0, utils_2.validateFormFieldsOrThrowError)(options.config.signInFeature.formFields, body.formFields, tenantId, userContext); - const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)(options.req, body); - const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded(options.req, options.res, shouldTryLinkingWithSessionUser, userContext); + let formFields = await (0, utils_2.validateFormFieldsOrThrowError)( + options.config.signInFeature.formFields, + body.formFields, + tenantId, + userContext + ); + const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)( + options.req, + body + ); + const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded( + options.req, + options.res, + shouldTryLinkingWithSessionUser, + userContext + ); if (session !== undefined) { tenantId = session.getTenantId(); } @@ -40,9 +53,14 @@ async function signInAPI(apiImplementation, tenantId, options, userContext) { userContext, }); if (result.status === "OK") { - (0, utils_1.send200Response)(options.res, Object.assign({ status: "OK" }, (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext))); - } - else { + (0, utils_1.send200Response)( + options.res, + Object.assign( + { status: "OK" }, + (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext) + ) + ); + } else { (0, utils_1.send200Response)(options.res, result); } return true; diff --git a/lib/build/recipe/emailpassword/api/signup.d.ts b/lib/build/recipe/emailpassword/api/signup.d.ts index 7306003af..1487513c1 100644 --- a/lib/build/recipe/emailpassword/api/signup.d.ts +++ b/lib/build/recipe/emailpassword/api/signup.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function signUpAPI(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function signUpAPI( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/emailpassword/api/signup.js b/lib/build/recipe/emailpassword/api/signup.js index c0632e2db..32d877548 100644 --- a/lib/build/recipe/emailpassword/api/signup.js +++ b/lib/build/recipe/emailpassword/api/signup.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = signUpAPI; const utils_1 = require("../../../utils"); @@ -29,9 +31,22 @@ async function signUpAPI(apiImplementation, tenantId, options, userContext) { } const requestBody = await options.req.getJSONBody(); // step 1 - let formFields = await (0, utils_2.validateFormFieldsOrThrowError)(options.config.signUpFeature.formFields, requestBody.formFields, tenantId, userContext); - const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)(options.req, requestBody); - const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded(options.req, options.res, shouldTryLinkingWithSessionUser, userContext); + let formFields = await (0, utils_2.validateFormFieldsOrThrowError)( + options.config.signUpFeature.formFields, + requestBody.formFields, + tenantId, + userContext + ); + const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)( + options.req, + requestBody + ); + const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded( + options.req, + options.res, + shouldTryLinkingWithSessionUser, + userContext + ); if (session !== undefined) { tenantId = session.getTenantId(); } @@ -44,12 +59,16 @@ async function signUpAPI(apiImplementation, tenantId, options, userContext) { userContext: userContext, }); if (result.status === "OK") { - (0, utils_1.send200Response)(options.res, Object.assign({ status: "OK" }, (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext))); - } - else if (result.status === "GENERAL_ERROR") { + (0, utils_1.send200Response)( + options.res, + Object.assign( + { status: "OK" }, + (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext) + ) + ); + } else if (result.status === "GENERAL_ERROR") { (0, utils_1.send200Response)(options.res, result); - } - else if (result.status === "EMAIL_ALREADY_EXISTS_ERROR") { + } else if (result.status === "EMAIL_ALREADY_EXISTS_ERROR") { throw new error_1.default({ type: error_1.default.FIELD_ERROR, payload: [ @@ -60,8 +79,7 @@ async function signUpAPI(apiImplementation, tenantId, options, userContext) { ], message: "Error in input formFields", }); - } - else { + } else { (0, utils_1.send200Response)(options.res, result); } return true; diff --git a/lib/build/recipe/emailpassword/api/utils.d.ts b/lib/build/recipe/emailpassword/api/utils.d.ts index bfba7a7e6..0f67df755 100644 --- a/lib/build/recipe/emailpassword/api/utils.d.ts +++ b/lib/build/recipe/emailpassword/api/utils.d.ts @@ -1,7 +1,14 @@ // @ts-nocheck import { NormalisedFormField } from "../types"; import { UserContext } from "../../../types"; -export declare function validateFormFieldsOrThrowError(configFormFields: NormalisedFormField[], formFieldsRaw: any, tenantId: string, userContext: UserContext): Promise<{ - id: string; - value: unknown; -}[]>; +export declare function validateFormFieldsOrThrowError( + configFormFields: NormalisedFormField[], + formFieldsRaw: any, + tenantId: string, + userContext: UserContext +): Promise< + { + id: string; + value: unknown; + }[] +>; diff --git a/lib/build/recipe/emailpassword/api/utils.js b/lib/build/recipe/emailpassword/api/utils.js index 0b8f3b610..24e57b752 100644 --- a/lib/build/recipe/emailpassword/api/utils.js +++ b/lib/build/recipe/emailpassword/api/utils.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateFormFieldsOrThrowError = validateFormFieldsOrThrowError; const error_1 = __importDefault(require("../error")); @@ -33,7 +35,9 @@ async function validateFormFieldsOrThrowError(configFormFields, formFieldsRaw, t // we trim the email: https://github.com/supertokens/supertokens-core/issues/99 formFields = formFields.map((field) => { if (field.id === constants_1.FORM_FIELD_EMAIL_ID) { - return Object.assign(Object.assign({}, field), { value: typeof field.value === "string" ? field.value.trim() : field.value }); + return Object.assign(Object.assign({}, field), { + value: typeof field.value === "string" ? field.value.trim() : field.value, + }); } return field; }); @@ -62,7 +66,8 @@ async function validateFormOrThrowError(inputs, configFormFields, tenantId, user const input = inputs.find((input) => input.id === formField.id); // Add the not optional error if input is not passed // and the field is not optional. - const isValidInput = !!input && + const isValidInput = + !!input && ((typeof input.value === "string" ? input.value.length > 0 : input.value !== null && typeof input.value !== "undefined") || diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.d.ts b/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.d.ts index 30d5ecabf..7184fcbbd 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.d.ts +++ b/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.d.ts @@ -2,11 +2,14 @@ import { TypeEmailPasswordEmailDeliveryInput } from "../../../types"; import { NormalisedAppinfo, UserContext } from "../../../../../types"; import { EmailDeliveryInterface } from "../../../../../ingredients/emaildelivery/types"; -export default class BackwardCompatibilityService implements EmailDeliveryInterface { +export default class BackwardCompatibilityService + implements EmailDeliveryInterface { private isInServerlessEnv; private appInfo; constructor(appInfo: NormalisedAppinfo, isInServerlessEnv: boolean); - sendEmail: (input: TypeEmailPasswordEmailDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendEmail: ( + input: TypeEmailPasswordEmailDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.js b/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.js index d7f998fab..456506358 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.js +++ b/lib/build/recipe/emailpassword/emaildelivery/services/backwardCompatibility/index.js @@ -9,14 +9,20 @@ class BackwardCompatibilityService { // will get reset by the getUserById call above. try { if (!this.isInServerlessEnv) { - (0, passwordResetFunctions_1.createAndSendEmailUsingSupertokensService)(this.appInfo, input.user, input.passwordResetLink).catch((_) => { }); - } - else { + (0, passwordResetFunctions_1.createAndSendEmailUsingSupertokensService)( + this.appInfo, + input.user, + input.passwordResetLink + ).catch((_) => {}); + } else { // see https://github.com/supertokens/supertokens-node/pull/135 - await (0, passwordResetFunctions_1.createAndSendEmailUsingSupertokensService)(this.appInfo, input.user, input.passwordResetLink); + await (0, passwordResetFunctions_1.createAndSendEmailUsingSupertokensService)( + this.appInfo, + input.user, + input.passwordResetLink + ); } - } - catch (_) { } + } catch (_) {} }; this.isInServerlessEnv = isInServerlessEnv; this.appInfo = appInfo; diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/index.js b/lib/build/recipe/emailpassword/emaildelivery/services/index.js index d648973c6..91700aeaf 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/index.js +++ b/lib/build/recipe/emailpassword/emaildelivery/services/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SMTPService = void 0; const smtp_1 = __importDefault(require("./smtp")); diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.d.ts b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.d.ts index ea7f79b14..357c2f852 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.d.ts +++ b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.d.ts @@ -6,7 +6,9 @@ import { UserContext } from "../../../../../types"; export default class SMTPService implements EmailDeliveryInterface { serviceImpl: ServiceInterface; constructor(config: TypeInput); - sendEmail: (input: TypeEmailPasswordEmailDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendEmail: ( + input: TypeEmailPasswordEmailDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.js b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.js index 76335ab95..e6bf36f54 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.js +++ b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const nodemailer_1 = require("nodemailer"); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); @@ -10,7 +12,9 @@ class SMTPService { constructor(config) { this.sendEmail = async (input) => { let content = await this.serviceImpl.getContent(input); - await this.serviceImpl.sendRawEmail(Object.assign(Object.assign({}, content), { userContext: input.userContext })); + await this.serviceImpl.sendRawEmail( + Object.assign(Object.assign({}, content), { userContext: input.userContext }) + ); }; const transporter = (0, nodemailer_1.createTransport)({ host: config.smtpSettings.host, @@ -21,7 +25,9 @@ class SMTPService { }, secure: config.smtpSettings.secure, }); - let builder = new supertokens_js_override_1.default((0, serviceImplementation_1.getServiceImplementation)(transporter, config.smtpSettings.from)); + let builder = new supertokens_js_override_1.default( + (0, serviceImplementation_1.getServiceImplementation)(transporter, config.smtpSettings.from) + ); if (config.override !== undefined) { builder = builder.override(config.override); } diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.d.ts b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.d.ts index f54789fa9..34240509a 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.d.ts +++ b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.d.ts @@ -1,5 +1,7 @@ // @ts-nocheck import { TypeEmailPasswordPasswordResetEmailDeliveryInput } from "../../../types"; import { GetContentResult } from "../../../../../ingredients/emaildelivery/services/smtp"; -export default function getPasswordResetEmailContent(input: TypeEmailPasswordPasswordResetEmailDeliveryInput): GetContentResult; +export default function getPasswordResetEmailContent( + input: TypeEmailPasswordPasswordResetEmailDeliveryInput +): GetContentResult; export declare function getPasswordResetEmailHTML(appName: string, email: string, resetLink: string): string; diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js index 164945268..678c78872 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js +++ b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/passwordReset.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getPasswordResetEmailContent; exports.getPasswordResetEmailHTML = getPasswordResetEmailHTML; diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.d.ts b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.d.ts index 917f30d7d..95fdbda32 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.d.ts +++ b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.d.ts @@ -2,7 +2,10 @@ import { TypeEmailPasswordEmailDeliveryInput } from "../../../../types"; import { Transporter } from "nodemailer"; import { ServiceInterface } from "../../../../../../ingredients/emaildelivery/services/smtp"; -export declare function getServiceImplementation(transporter: Transporter, from: { - name: string; - email: string; -}): ServiceInterface; +export declare function getServiceImplementation( + transporter: Transporter, + from: { + name: string; + email: string; + } +): ServiceInterface; diff --git a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.js b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.js index b95dfe4a8..4a35ca732 100644 --- a/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.js +++ b/lib/build/recipe/emailpassword/emaildelivery/services/smtp/serviceImplementation/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getServiceImplementation = getServiceImplementation; const passwordReset_1 = __importDefault(require("../passwordReset")); @@ -29,8 +31,7 @@ function getServiceImplementation(transporter, from) { subject: input.subject, html: input.body, }); - } - else { + } else { await transporter.sendMail({ from: `${from.name} <${from.email}>`, to: input.toEmail, diff --git a/lib/build/recipe/emailpassword/error.d.ts b/lib/build/recipe/emailpassword/error.d.ts index e72600d1d..d4dc2cf9b 100644 --- a/lib/build/recipe/emailpassword/error.d.ts +++ b/lib/build/recipe/emailpassword/error.d.ts @@ -2,15 +2,19 @@ import STError from "../../error"; export default class SessionError extends STError { static FIELD_ERROR: "FIELD_ERROR"; - constructor(options: { - type: "FIELD_ERROR"; - payload: { - id: string; - error: string; - }[]; - message: string; - } | { - type: "BAD_INPUT_ERROR"; - message: string; - }); + constructor( + options: + | { + type: "FIELD_ERROR"; + payload: { + id: string; + error: string; + }[]; + message: string; + } + | { + type: "BAD_INPUT_ERROR"; + message: string; + } + ); } diff --git a/lib/build/recipe/emailpassword/error.js b/lib/build/recipe/emailpassword/error.js index 8166026f3..62b0605c0 100644 --- a/lib/build/recipe/emailpassword/error.js +++ b/lib/build/recipe/emailpassword/error.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); class SessionError extends error_1.default { diff --git a/lib/build/recipe/emailpassword/index.d.ts b/lib/build/recipe/emailpassword/index.d.ts index 05910e54f..42b4a07db 100644 --- a/lib/build/recipe/emailpassword/index.d.ts +++ b/lib/build/recipe/emailpassword/index.d.ts @@ -8,41 +8,92 @@ import { User } from "../../types"; export default class Wrapper { static init: typeof Recipe.init; static Error: typeof SuperTokensError; - static signUp(tenantId: string, email: string, password: string, session?: undefined, userContext?: Record): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "EMAIL_ALREADY_EXISTS_ERROR"; - }>; - static signUp(tenantId: string, email: string, password: string, session: SessionContainerInterface, userContext?: Record): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "EMAIL_ALREADY_EXISTS_ERROR"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; - static signIn(tenantId: string, email: string, password: string, session?: undefined, userContext?: Record): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "WRONG_CREDENTIALS_ERROR"; - }>; - static signIn(tenantId: string, email: string, password: string, session: SessionContainerInterface, userContext?: Record): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "WRONG_CREDENTIALS_ERROR"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; - static verifyCredentials(tenantId: string, email: string, password: string, userContext?: Record): Promise<{ + static signUp( + tenantId: string, + email: string, + password: string, + session?: undefined, + userContext?: Record + ): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_ALREADY_EXISTS_ERROR"; + } + >; + static signUp( + tenantId: string, + email: string, + password: string, + session: SessionContainerInterface, + userContext?: Record + ): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_ALREADY_EXISTS_ERROR"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; + static signIn( + tenantId: string, + email: string, + password: string, + session?: undefined, + userContext?: Record + ): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "WRONG_CREDENTIALS_ERROR"; + } + >; + static signIn( + tenantId: string, + email: string, + password: string, + session: SessionContainerInterface, + userContext?: Record + ): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "WRONG_CREDENTIALS_ERROR"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; + static verifyCredentials( + tenantId: string, + email: string, + password: string, + userContext?: Record + ): Promise<{ status: "OK" | "WRONG_CREDENTIALS_ERROR"; }>; /** @@ -56,25 +107,48 @@ export default class Wrapper { * * And we want to allow primaryUserId being passed in. */ - static createResetPasswordToken(tenantId: string, userId: string, email: string, userContext?: Record): Promise<{ - status: "OK"; - token: string; - } | { - status: "UNKNOWN_USER_ID_ERROR"; - }>; - static resetPasswordUsingToken(tenantId: string, token: string, newPassword: string, userContext?: Record): Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR" | "RESET_PASSWORD_INVALID_TOKEN_ERROR"; - } | { - status: "PASSWORD_POLICY_VIOLATED_ERROR"; - failureReason: string; - }>; - static consumePasswordResetToken(tenantId: string, token: string, userContext?: Record): Promise<{ - status: "OK"; - email: string; - userId: string; - } | { - status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; - }>; + static createResetPasswordToken( + tenantId: string, + userId: string, + email: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + token: string; + } + | { + status: "UNKNOWN_USER_ID_ERROR"; + } + >; + static resetPasswordUsingToken( + tenantId: string, + token: string, + newPassword: string, + userContext?: Record + ): Promise< + | { + status: "OK" | "UNKNOWN_USER_ID_ERROR" | "RESET_PASSWORD_INVALID_TOKEN_ERROR"; + } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } + >; + static consumePasswordResetToken( + tenantId: string, + token: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + email: string; + userId: string; + } + | { + status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; + } + >; static updateEmailOrPassword(input: { recipeUserId: RecipeUserId; email?: string; @@ -82,27 +156,46 @@ export default class Wrapper { userContext?: Record; applyPasswordPolicy?: boolean; tenantIdForPasswordPolicy?: string; - }): Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; - } | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; - reason: string; - } | { - status: "PASSWORD_POLICY_VIOLATED_ERROR"; - failureReason: string; - }>; - static createResetPasswordLink(tenantId: string, userId: string, email: string, userContext?: Record): Promise<{ - status: "OK"; - link: string; - } | { - status: "UNKNOWN_USER_ID_ERROR"; - }>; - static sendResetPasswordEmail(tenantId: string, userId: string, email: string, userContext?: Record): Promise<{ + }): Promise< + | { + status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } + >; + static createResetPasswordLink( + tenantId: string, + userId: string, + email: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + link: string; + } + | { + status: "UNKNOWN_USER_ID_ERROR"; + } + >; + static sendResetPasswordEmail( + tenantId: string, + userId: string, + email: string, + userContext?: Record + ): Promise<{ status: "OK" | "UNKNOWN_USER_ID_ERROR"; }>; - static sendEmail(input: TypeEmailPasswordEmailDeliveryInput & { - userContext?: Record; - }): Promise; + static sendEmail( + input: TypeEmailPasswordEmailDeliveryInput & { + userContext?: Record; + } + ): Promise; } export declare let init: typeof Recipe.init; export declare let Error: typeof SuperTokensError; diff --git a/lib/build/recipe/emailpassword/index.js b/lib/build/recipe/emailpassword/index.js index 40077b9bb..9d87ff175 100644 --- a/lib/build/recipe/emailpassword/index.js +++ b/lib/build/recipe/emailpassword/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.sendEmail = exports.sendResetPasswordEmail = exports.createResetPasswordLink = exports.updateEmailOrPassword = exports.consumePasswordResetToken = exports.resetPasswordUsingToken = exports.createResetPasswordToken = exports.verifyCredentials = exports.signIn = exports.signUp = exports.Error = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); @@ -110,7 +112,15 @@ class Wrapper { }); } static updateEmailOrPassword(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.updateEmailOrPassword(Object.assign(Object.assign({}, input), { userContext: (0, utils_2.getUserContext)(input.userContext), tenantIdForPasswordPolicy: input.tenantIdForPasswordPolicy === undefined ? constants_1.DEFAULT_TENANT_ID : input.tenantIdForPasswordPolicy })); + return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.updateEmailOrPassword( + Object.assign(Object.assign({}, input), { + userContext: (0, utils_2.getUserContext)(input.userContext), + tenantIdForPasswordPolicy: + input.tenantIdForPasswordPolicy === undefined + ? constants_1.DEFAULT_TENANT_ID + : input.tenantIdForPasswordPolicy, + }) + ); } static async createResetPasswordLink(tenantId, userId, email, userContext) { const ctx = (0, utils_2.getUserContext)(userContext); @@ -160,7 +170,12 @@ class Wrapper { } static async sendEmail(input) { let recipeInstance = recipe_1.default.getInstanceOrThrowError(); - return await recipeInstance.emailDelivery.ingredientInterfaceImpl.sendEmail(Object.assign(Object.assign({}, input), { tenantId: input.tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : input.tenantId, userContext: (0, utils_2.getUserContext)(input.userContext) })); + return await recipeInstance.emailDelivery.ingredientInterfaceImpl.sendEmail( + Object.assign(Object.assign({}, input), { + tenantId: input.tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : input.tenantId, + userContext: (0, utils_2.getUserContext)(input.userContext), + }) + ); } } Wrapper.init = recipe_1.default.init; diff --git a/lib/build/recipe/emailpassword/passwordResetFunctions.d.ts b/lib/build/recipe/emailpassword/passwordResetFunctions.d.ts index 5638c375e..e7ed30fe1 100644 --- a/lib/build/recipe/emailpassword/passwordResetFunctions.d.ts +++ b/lib/build/recipe/emailpassword/passwordResetFunctions.d.ts @@ -1,6 +1,10 @@ // @ts-nocheck import { NormalisedAppinfo } from "../../types"; -export declare function createAndSendEmailUsingSupertokensService(appInfo: NormalisedAppinfo, user: { - id: string; - email: string; -}, passwordResetURLWithToken: string): Promise; +export declare function createAndSendEmailUsingSupertokensService( + appInfo: NormalisedAppinfo, + user: { + id: string; + email: string; + }, + passwordResetURLWithToken: string +): Promise; diff --git a/lib/build/recipe/emailpassword/passwordResetFunctions.js b/lib/build/recipe/emailpassword/passwordResetFunctions.js index fd39f18be..183421a1e 100644 --- a/lib/build/recipe/emailpassword/passwordResetFunctions.js +++ b/lib/build/recipe/emailpassword/passwordResetFunctions.js @@ -21,15 +21,20 @@ async function createAndSendEmailUsingSupertokensService(appInfo, user, password if ((0, utils_1.isTestEnv)()) { return; } - await (0, utils_1.postWithFetch)("https://api.supertokens.io/0/st/auth/password/reset", { - "api-version": "0", - "content-type": "application/json; charset=utf-8", - }, { - email: user.email, - appName: appInfo.appName, - passwordResetURL: passwordResetURLWithToken, - }, { - successLog: `Password reset email sent to ${user.email}`, - errorLogHeader: "Error sending password reset email", - }); + await (0, utils_1.postWithFetch)( + "https://api.supertokens.io/0/st/auth/password/reset", + { + "api-version": "0", + "content-type": "application/json; charset=utf-8", + }, + { + email: user.email, + appName: appInfo.appName, + passwordResetURL: passwordResetURLWithToken, + }, + { + successLog: `Password reset email sent to ${user.email}`, + errorLogHeader: "Error sending password reset email", + } + ); } diff --git a/lib/build/recipe/emailpassword/recipe.d.ts b/lib/build/recipe/emailpassword/recipe.d.ts index 8966bde7a..fad20ce0f 100644 --- a/lib/build/recipe/emailpassword/recipe.d.ts +++ b/lib/build/recipe/emailpassword/recipe.d.ts @@ -15,14 +15,28 @@ export default class Recipe extends RecipeModule { apiImpl: APIInterface; isInServerlessEnv: boolean; emailDelivery: EmailDeliveryIngredient; - constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config: TypeInput | undefined, ingredients: { - emailDelivery: EmailDeliveryIngredient | undefined; - }); + constructor( + recipeId: string, + appInfo: NormalisedAppinfo, + isInServerlessEnv: boolean, + config: TypeInput | undefined, + ingredients: { + emailDelivery: EmailDeliveryIngredient | undefined; + } + ); static getInstanceOrThrowError(): Recipe; static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, tenantId: string, req: BaseRequest, res: BaseResponse, _path: NormalisedURLPath, _method: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + tenantId: string, + req: BaseRequest, + res: BaseResponse, + _path: NormalisedURLPath, + _method: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: STError, _request: BaseRequest, response: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; diff --git a/lib/build/recipe/emailpassword/recipe.js b/lib/build/recipe/emailpassword/recipe.js index 914e99003..20d5ddf8b 100644 --- a/lib/build/recipe/emailpassword/recipe.js +++ b/lib/build/recipe/emailpassword/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipeModule_1 = __importDefault(require("../../recipeModule")); const error_1 = __importDefault(require("./error")); @@ -58,7 +60,9 @@ class Recipe extends recipeModule_1.default { }, { method: "post", - pathWithoutApiBasePath: new normalisedURLPath_1.default(constants_1.GENERATE_PASSWORD_RESET_TOKEN_API), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + constants_1.GENERATE_PASSWORD_RESET_TOKEN_API + ), id: constants_1.GENERATE_PASSWORD_RESET_TOKEN_API, disabled: this.apiImpl.generatePasswordResetTokenPOST === undefined, }, @@ -95,17 +99,13 @@ class Recipe extends recipeModule_1.default { }; if (id === constants_1.SIGN_UP_API) { return await (0, signup_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.SIGN_IN_API) { + } else if (id === constants_1.SIGN_IN_API) { return await (0, signin_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.GENERATE_PASSWORD_RESET_TOKEN_API) { + } else if (id === constants_1.GENERATE_PASSWORD_RESET_TOKEN_API) { return await (0, generatePasswordResetToken_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.PASSWORD_RESET_API) { + } else if (id === constants_1.PASSWORD_RESET_API) { return await (0, passwordReset_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.SIGNUP_EMAIL_EXISTS_API || id === constants_1.SIGNUP_EMAIL_EXISTS_API_OLD) { + } else if (id === constants_1.SIGNUP_EMAIL_EXISTS_API || id === constants_1.SIGNUP_EMAIL_EXISTS_API_OLD) { return await (0, emailExists_1.default)(this.apiImpl, tenantId, options, userContext); } return false; @@ -117,12 +117,10 @@ class Recipe extends recipeModule_1.default { status: "FIELD_ERROR", formFields: err.payload, }); - } - else { + } else { throw err; } - } - else { + } else { throw err; } }; @@ -136,7 +134,12 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_1.validateAndNormaliseUserInput)(this, appInfo, config); { const getEmailPasswordConfig = () => this.config; - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), getEmailPasswordConfig)); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + getEmailPasswordConfig + ) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -188,7 +191,9 @@ class Recipe extends recipeModule_1.default { return a.timeJoined - b.timeJoined; }); // Then we take the ones that belong to this recipe - const recipeLoginMethodsOrderedByTimeJoinedOldestFirst = orderedLoginMethodsByTimeJoinedOldestFirst.filter((lm) => lm.recipeId === Recipe.RECIPE_ID); + const recipeLoginMethodsOrderedByTimeJoinedOldestFirst = orderedLoginMethodsByTimeJoinedOldestFirst.filter( + (lm) => lm.recipeId === Recipe.RECIPE_ID + ); let result; if (recipeLoginMethodsOrderedByTimeJoinedOldestFirst.length !== 0) { // If there are login methods belonging to this recipe, the factor is set up @@ -215,16 +220,18 @@ class Recipe extends recipeModule_1.default { .map((lm) => lm.email), ]; // We handle moving the session email to the top of the list later - } - else { + } else { // This factor hasn't been set up, we list all emails belonging to the user - if (orderedLoginMethodsByTimeJoinedOldestFirst.some((lm) => lm.email !== undefined && !(0, utils_3.isFakeEmail)(lm.email))) { + if ( + orderedLoginMethodsByTimeJoinedOldestFirst.some( + (lm) => lm.email !== undefined && !(0, utils_3.isFakeEmail)(lm.email) + ) + ) { // If there is at least one real email address linked to the user, we only suggest real addresses result = orderedLoginMethodsByTimeJoinedOldestFirst .filter((lm) => lm.email !== undefined && !(0, utils_3.isFakeEmail)(lm.email)) .map((lm) => lm.email); - } - else { + } else { // Else we use the fake ones result = orderedLoginMethodsByTimeJoinedOldestFirst .filter((lm) => lm.email !== undefined && (0, utils_3.isFakeEmail)(lm.email)) @@ -274,12 +281,21 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : []), { - emailDelivery: undefined, - }); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ), + { + emailDelivery: undefined, + } + ); return Recipe.instance; - } - else { + } else { throw new Error("Emailpassword recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/emailpassword/recipeImplementation.d.ts b/lib/build/recipe/emailpassword/recipeImplementation.d.ts index 3d70a735b..cfb8e6ad0 100644 --- a/lib/build/recipe/emailpassword/recipeImplementation.d.ts +++ b/lib/build/recipe/emailpassword/recipeImplementation.d.ts @@ -1,4 +1,7 @@ // @ts-nocheck import { RecipeInterface, TypeNormalisedInput } from "./types"; import { Querier } from "../../querier"; -export default function getRecipeInterface(querier: Querier, getEmailPasswordConfig: () => TypeNormalisedInput): RecipeInterface; +export default function getRecipeInterface( + querier: Querier, + getEmailPasswordConfig: () => TypeNormalisedInput +): RecipeInterface; diff --git a/lib/build/recipe/emailpassword/recipeImplementation.js b/lib/build/recipe/emailpassword/recipeImplementation.js index 9e5936d45..f951eed4a 100644 --- a/lib/build/recipe/emailpassword/recipeImplementation.js +++ b/lib/build/recipe/emailpassword/recipeImplementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const recipe_1 = __importDefault(require("../accountlinking/recipe")); @@ -26,14 +28,16 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { return response; } let updatedUser = response.user; - const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo({ - tenantId, - inputUser: response.user, - recipeUserId: response.recipeUserId, - session, - shouldTryLinkingWithSessionUser, - userContext, - }); + const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo( + { + tenantId, + inputUser: response.user, + recipeUserId: response.recipeUserId, + session, + shouldTryLinkingWithSessionUser, + userContext, + } + ); if (linkResult.status != "OK") { return linkResult; } @@ -45,10 +49,16 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { }; }, createNewRecipeUser: async function (input) { - const resp = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : input.tenantId}/recipe/signup`), { - email: input.email, - password: input.password, - }, input.userContext); + const resp = await querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${input.tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : input.tenantId}/recipe/signup` + ), + { + email: input.email, + password: input.password, + }, + input.userContext + ); if (resp.status === "OK") { return { status: "OK", @@ -63,7 +73,9 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { signIn: async function ({ email, password, tenantId, session, shouldTryLinkingWithSessionUser, userContext }) { const response = await this.verifyCredentials({ email, password, tenantId, userContext }); if (response.status === "OK") { - const loginMethod = response.user.loginMethods.find((lm) => lm.recipeUserId.getAsString() === response.recipeUserId.getAsString()); + const loginMethod = response.user.loginMethods.find( + (lm) => lm.recipeUserId.getAsString() === response.recipeUserId.getAsString() + ); if (!loginMethod.verified) { await recipe_1.default.getInstance().verifyEmailForRecipeUserIfLinkedAccountsAreVerified({ user: response.user, @@ -81,16 +93,18 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { // point of view who is calling the sign up recipe function. // We do this so that we get the updated user (in case the above // function updated the verification status) and can return that - response.user = (await (0, __1.getUser)(response.recipeUserId.getAsString(), userContext)); + response.user = await (0, __1.getUser)(response.recipeUserId.getAsString(), userContext); } - const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo({ - tenantId, - inputUser: response.user, - recipeUserId: response.recipeUserId, - session, - shouldTryLinkingWithSessionUser, - userContext, - }); + const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo( + { + tenantId, + inputUser: response.user, + recipeUserId: response.recipeUserId, + session, + shouldTryLinkingWithSessionUser, + userContext, + } + ); if (linkResult.status === "LINKING_TO_SESSION_USER_FAILED") { return linkResult; } @@ -98,11 +112,17 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { } return response; }, - verifyCredentials: async function ({ email, password, tenantId, userContext, }) { - const response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId}/recipe/signin`), { - email, - password, - }, userContext); + verifyCredentials: async function ({ email, password, tenantId, userContext }) { + const response = await querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId}/recipe/signin` + ), + { + email, + password, + }, + userContext + ); if (response.status === "OK") { return { status: "OK", @@ -114,18 +134,34 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { status: "WRONG_CREDENTIALS_ERROR", }; }, - createResetPasswordToken: async function ({ userId, email, tenantId, userContext, }) { + createResetPasswordToken: async function ({ userId, email, tenantId, userContext }) { // the input user ID can be a recipe or a primary user ID. - return await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId}/recipe/user/password/reset/token`), { - userId, - email, - }, userContext); + return await querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${ + tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId + }/recipe/user/password/reset/token` + ), + { + userId, + email, + }, + userContext + ); }, - consumePasswordResetToken: async function ({ token, tenantId, userContext, }) { - return await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId}/recipe/user/password/reset/token/consume`), { - method: "token", - token, - }, userContext); + consumePasswordResetToken: async function ({ token, tenantId, userContext }) { + return await querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${ + tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId + }/recipe/user/password/reset/token/consume` + ), + { + method: "token", + token, + }, + userContext + ); }, updateEmailOrPassword: async function (input) { const accountLinking = recipe_1.default.getInstance(); @@ -153,9 +189,10 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { if (!isEmailChangeAllowed.allowed) { return { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", - reason: isEmailChangeAllowed.reason === "ACCOUNT_TAKEOVER_RISK" - ? "New email cannot be applied to existing account because of account takeover risks." - : "New email cannot be applied to existing account because of there is another primary user with the same email address.", + reason: + isEmailChangeAllowed.reason === "ACCOUNT_TAKEOVER_RISK" + ? "New email cannot be applied to existing account because of account takeover risks." + : "New email cannot be applied to existing account because of there is another primary user with the same email address.", }; } } @@ -163,7 +200,11 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { let formFields = getEmailPasswordConfig().signUpFeature.formFields; if (input.password !== undefined) { const passwordField = formFields.filter((el) => el.id === constants_1.FORM_FIELD_PASSWORD_ID)[0]; - const error = await passwordField.validate(input.password, input.tenantIdForPasswordPolicy, input.userContext); + const error = await passwordField.validate( + input.password, + input.tenantIdForPasswordPolicy, + input.userContext + ); if (error !== undefined) { return { status: "PASSWORD_POLICY_VIOLATED_ERROR", @@ -178,11 +219,16 @@ function getRecipeInterface(querier, getEmailPasswordConfig) { // really up to the developer to decide what should be the pre condition for // a change in email. The check for email verification should actually go in // an update email API (post login update). - let response = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/user`), { - recipeUserId: input.recipeUserId.getAsString(), - email: input.email, - password: input.password, - }, {}, input.userContext); + let response = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/user`), + { + recipeUserId: input.recipeUserId.getAsString(), + email: input.email, + password: input.password, + }, + {}, + input.userContext + ); if (response.status === "OK") { const user = await (0, __1.getUser)(input.recipeUserId.getAsString(), input.userContext); if (user === undefined) { diff --git a/lib/build/recipe/emailpassword/types.d.ts b/lib/build/recipe/emailpassword/types.d.ts index 0ef1f85d2..1b853e05a 100644 --- a/lib/build/recipe/emailpassword/types.d.ts +++ b/lib/build/recipe/emailpassword/types.d.ts @@ -2,17 +2,25 @@ import type { BaseRequest, BaseResponse } from "../../framework"; import OverrideableBuilder from "supertokens-js-override"; import { SessionContainerInterface } from "../session/types"; -import { TypeInput as EmailDeliveryTypeInput, TypeInputWithService as EmailDeliveryTypeInputWithService } from "../../ingredients/emaildelivery/types"; +import { + TypeInput as EmailDeliveryTypeInput, + TypeInputWithService as EmailDeliveryTypeInputWithService, +} from "../../ingredients/emaildelivery/types"; import EmailDeliveryIngredient from "../../ingredients/emaildelivery"; import { GeneralErrorResponse, NormalisedAppinfo, User, UserContext } from "../../types"; import RecipeUserId from "../../recipeUserId"; export type TypeNormalisedInput = { signUpFeature: TypeNormalisedInputSignUp; signInFeature: TypeNormalisedInputSignIn; - getEmailDeliveryConfig: (isInServerlessEnv: boolean) => EmailDeliveryTypeInputWithService; + getEmailDeliveryConfig: ( + isInServerlessEnv: boolean + ) => EmailDeliveryTypeInputWithService; resetPasswordUsingTokenFeature: TypeNormalisedInputResetPasswordUsingTokenFeature; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -47,7 +55,10 @@ export type TypeInput = { signUpFeature?: TypeInputSignUp; emailDelivery?: EmailDeliveryTypeInput; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -59,28 +70,39 @@ export type RecipeInterface = { shouldTryLinkingWithSessionUser: boolean | undefined; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "EMAIL_ALREADY_EXISTS_ERROR"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_ALREADY_EXISTS_ERROR"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; createNewRecipeUser(input: { email: string; password: string; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "EMAIL_ALREADY_EXISTS_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_ALREADY_EXISTS_ERROR"; + } + >; signIn(input: { email: string; password: string; @@ -88,28 +110,39 @@ export type RecipeInterface = { shouldTryLinkingWithSessionUser: boolean | undefined; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "WRONG_CREDENTIALS_ERROR"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "WRONG_CREDENTIALS_ERROR"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; verifyCredentials(input: { email: string; password: string; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "WRONG_CREDENTIALS_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "WRONG_CREDENTIALS_ERROR"; + } + >; /** * We pass in the email as well to this function cause the input userId * may not be associated with an emailpassword account. In this case, we @@ -120,23 +153,29 @@ export type RecipeInterface = { email: string; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - token: string; - } | { - status: "UNKNOWN_USER_ID_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + token: string; + } + | { + status: "UNKNOWN_USER_ID_ERROR"; + } + >; consumePasswordResetToken(input: { token: string; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - email: string; - userId: string; - } | { - status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + email: string; + userId: string; + } + | { + status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; + } + >; updateEmailOrPassword(input: { recipeUserId: RecipeUserId; email?: string; @@ -144,15 +183,19 @@ export type RecipeInterface = { userContext: UserContext; applyPasswordPolicy?: boolean; tenantIdForPasswordPolicy: string; - }): Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; - } | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; - reason: string; - } | { - status: "PASSWORD_POLICY_VIOLATED_ERROR"; - failureReason: string; - }>; + }): Promise< + | { + status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR"; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } + >; }; export type APIOptions = { recipeImplementation: RecipeInterface; @@ -165,88 +208,120 @@ export type APIOptions = { emailDelivery: EmailDeliveryIngredient; }; export type APIInterface = { - emailExistsGET: undefined | ((input: { - email: string; - tenantId: string; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - exists: boolean; - } | GeneralErrorResponse>); - generatePasswordResetTokenPOST: undefined | ((input: { - formFields: { - id: string; - value: unknown; - }[]; - tenantId: string; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - } | { - status: "PASSWORD_RESET_NOT_ALLOWED"; - reason: string; - } | GeneralErrorResponse>); - passwordResetPOST: undefined | ((input: { - formFields: { - id: string; - value: unknown; - }[]; - token: string; - tenantId: string; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - email: string; - user: User; - } | { - status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; - } | { - status: "PASSWORD_POLICY_VIOLATED_ERROR"; - failureReason: string; - } | GeneralErrorResponse>); - signInPOST: undefined | ((input: { - formFields: { - id: string; - value: unknown; - }[]; - tenantId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - user: User; - session: SessionContainerInterface; - } | { - status: "SIGN_IN_NOT_ALLOWED"; - reason: string; - } | { - status: "WRONG_CREDENTIALS_ERROR"; - } | GeneralErrorResponse>); - signUpPOST: undefined | ((input: { - formFields: { - id: string; - value: unknown; - }[]; - tenantId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - user: User; - session: SessionContainerInterface; - } | { - status: "SIGN_UP_NOT_ALLOWED"; - reason: string; - } | { - status: "EMAIL_ALREADY_EXISTS_ERROR"; - } | GeneralErrorResponse>); + emailExistsGET: + | undefined + | ((input: { + email: string; + tenantId: string; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + exists: boolean; + } + | GeneralErrorResponse + >); + generatePasswordResetTokenPOST: + | undefined + | ((input: { + formFields: { + id: string; + value: unknown; + }[]; + tenantId: string; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + } + | { + status: "PASSWORD_RESET_NOT_ALLOWED"; + reason: string; + } + | GeneralErrorResponse + >); + passwordResetPOST: + | undefined + | ((input: { + formFields: { + id: string; + value: unknown; + }[]; + token: string; + tenantId: string; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + email: string; + user: User; + } + | { + status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"; + } + | { + status: "PASSWORD_POLICY_VIOLATED_ERROR"; + failureReason: string; + } + | GeneralErrorResponse + >); + signInPOST: + | undefined + | ((input: { + formFields: { + id: string; + value: unknown; + }[]; + tenantId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + user: User; + session: SessionContainerInterface; + } + | { + status: "SIGN_IN_NOT_ALLOWED"; + reason: string; + } + | { + status: "WRONG_CREDENTIALS_ERROR"; + } + | GeneralErrorResponse + >); + signUpPOST: + | undefined + | ((input: { + formFields: { + id: string; + value: unknown; + }[]; + tenantId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + user: User; + session: SessionContainerInterface; + } + | { + status: "SIGN_UP_NOT_ALLOWED"; + reason: string; + } + | { + status: "EMAIL_ALREADY_EXISTS_ERROR"; + } + | GeneralErrorResponse + >); }; export type TypeEmailPasswordPasswordResetEmailDeliveryInput = { type: "PASSWORD_RESET"; diff --git a/lib/build/recipe/emailpassword/utils.d.ts b/lib/build/recipe/emailpassword/utils.d.ts index b9aa6f378..a62eb7fe7 100644 --- a/lib/build/recipe/emailpassword/utils.d.ts +++ b/lib/build/recipe/emailpassword/utils.d.ts @@ -3,10 +3,25 @@ import Recipe from "./recipe"; import { TypeInput, TypeNormalisedInput, NormalisedFormField, TypeInputFormField } from "./types"; import { NormalisedAppinfo, UserContext } from "../../types"; import { BaseRequest } from "../../framework"; -export declare function validateAndNormaliseUserInput(recipeInstance: Recipe, appInfo: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + recipeInstance: Recipe, + appInfo: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; export declare function normaliseSignUpFormFields(formFields?: TypeInputFormField[]): NormalisedFormField[]; -export declare function defaultPasswordValidator(value: any): Promise<"Development bug: Please make sure the password field yields a string" | "Password must contain at least 8 characters, including a number" | "Password's length must be lesser than 100 characters" | "Password must contain at least one alphabet" | "Password must contain at least one number" | undefined>; -export declare function defaultEmailValidator(value: any): Promise<"Development bug: Please make sure the email field yields a string" | "Email is invalid" | undefined>; +export declare function defaultPasswordValidator( + value: any +): Promise< + | "Development bug: Please make sure the password field yields a string" + | "Password must contain at least 8 characters, including a number" + | "Password's length must be lesser than 100 characters" + | "Password must contain at least one alphabet" + | "Password must contain at least one number" + | undefined +>; +export declare function defaultEmailValidator( + value: any +): Promise<"Development bug: Please make sure the email field yields a string" | "Email is invalid" | undefined>; export declare function getPasswordResetLink(input: { appInfo: NormalisedAppinfo; token: string; diff --git a/lib/build/recipe/emailpassword/utils.js b/lib/build/recipe/emailpassword/utils.js index afb216652..70ecf4ba3 100644 --- a/lib/build/recipe/emailpassword/utils.js +++ b/lib/build/recipe/emailpassword/utils.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; exports.normaliseSignUpFormFields = normaliseSignUpFormFields; @@ -25,13 +27,26 @@ exports.getPasswordResetLink = getPasswordResetLink; const constants_1 = require("./constants"); const backwardCompatibility_1 = __importDefault(require("./emaildelivery/services/backwardCompatibility")); function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { - let signUpFeature = validateAndNormaliseSignupConfig(recipeInstance, appInfo, config === undefined ? undefined : config.signUpFeature); + let signUpFeature = validateAndNormaliseSignupConfig( + recipeInstance, + appInfo, + config === undefined ? undefined : config.signUpFeature + ); let signInFeature = validateAndNormaliseSignInConfig(recipeInstance, appInfo, signUpFeature); let resetPasswordUsingTokenFeature = validateAndNormaliseResetPasswordUsingTokenConfig(signUpFeature); - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); function getEmailDeliveryConfig(isInServerlessEnv) { var _a; - let emailService = (_a = config === null || config === void 0 ? void 0 : config.emailDelivery) === null || _a === void 0 ? void 0 : _a.service; + let emailService = + (_a = config === null || config === void 0 ? void 0 : config.emailDelivery) === null || _a === void 0 + ? void 0 + : _a.service; /** * If the user has not passed even that config, we use the default * createAndSendCustomEmail implementation which calls our supertokens API @@ -39,7 +54,7 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { if (emailService === undefined) { emailService = new backwardCompatibility_1.default(appInfo, isInServerlessEnv); } - return Object.assign(Object.assign({}, config === null || config === void 0 ? void 0 : config.emailDelivery), { + return Object.assign(Object.assign({}, config === null || config === void 0 ? void 0 : config.emailDelivery), { /** * if we do * let emailDelivery = { @@ -51,7 +66,8 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { * it it again get set to undefined, so we * set service at the end */ - service: emailService }); + service: emailService, + }); } return { signUpFeature, @@ -65,21 +81,21 @@ function validateAndNormaliseResetPasswordUsingTokenConfig(signUpConfig) { let formFieldsForPasswordResetForm = signUpConfig.formFields .filter((filter) => filter.id === constants_1.FORM_FIELD_PASSWORD_ID) .map((field) => { - return { - id: field.id, - validate: field.validate, - optional: false, - }; - }); + return { + id: field.id, + validate: field.validate, + optional: false, + }; + }); let formFieldsForGenerateTokenForm = signUpConfig.formFields .filter((filter) => filter.id === constants_1.FORM_FIELD_EMAIL_ID) .map((field) => { - return { - id: field.id, - validate: field.validate, - optional: false, - }; - }); + return { + id: field.id, + validate: field.validate, + optional: false, + }; + }); return { formFieldsForPasswordResetForm, formFieldsForGenerateTokenForm, @@ -87,15 +103,18 @@ function validateAndNormaliseResetPasswordUsingTokenConfig(signUpConfig) { } function normaliseSignInFormFields(formFields) { return formFields - .filter((filter) => filter.id === constants_1.FORM_FIELD_EMAIL_ID || filter.id === constants_1.FORM_FIELD_PASSWORD_ID) + .filter( + (filter) => + filter.id === constants_1.FORM_FIELD_EMAIL_ID || filter.id === constants_1.FORM_FIELD_PASSWORD_ID + ) .map((field) => { - return { - id: field.id, - // see issue: https://github.com/supertokens/supertokens-node/issues/36 - validate: field.id === constants_1.FORM_FIELD_EMAIL_ID ? field.validate : defaultValidator, - optional: false, - }; - }); + return { + id: field.id, + // see issue: https://github.com/supertokens/supertokens-node/issues/36 + validate: field.id === constants_1.FORM_FIELD_EMAIL_ID ? field.validate : defaultValidator, + optional: false, + }; + }); } function validateAndNormaliseSignInConfig(_, __, signUpConfig) { let formFields = normaliseSignInFormFields(signUpConfig.formFields); @@ -113,15 +132,13 @@ function normaliseSignUpFormFields(formFields) { validate: field.validate === undefined ? defaultPasswordValidator : field.validate, optional: false, }); - } - else if (field.id === constants_1.FORM_FIELD_EMAIL_ID) { + } else if (field.id === constants_1.FORM_FIELD_EMAIL_ID) { normalisedFormFields.push({ id: field.id, validate: field.validate === undefined ? defaultEmailValidator : field.validate, optional: false, }); - } - else { + } else { normalisedFormFields.push({ id: field.id, validate: field.validate === undefined ? defaultValidator : field.validate, @@ -185,21 +202,27 @@ async function defaultEmailValidator(value) { if (typeof value !== "string") { return "Development bug: Please make sure the email field yields a string"; } - if (value.match(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/) === null) { + if ( + value.match( + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + ) === null + ) { return "Email is invalid"; } return undefined; } function getPasswordResetLink(input) { - return (input.appInfo - .getOrigin({ - request: input.request, - userContext: input.userContext, - }) - .getAsStringDangerous() + + return ( + input.appInfo + .getOrigin({ + request: input.request, + userContext: input.userContext, + }) + .getAsStringDangerous() + input.appInfo.websiteBasePath.getAsStringDangerous() + "/reset-password?token=" + input.token + "&tenantId=" + - input.tenantId); + input.tenantId + ); } diff --git a/lib/build/recipe/emailverification/api/emailVerify.d.ts b/lib/build/recipe/emailverification/api/emailVerify.d.ts index 7025fa039..1f7b416c8 100644 --- a/lib/build/recipe/emailverification/api/emailVerify.d.ts +++ b/lib/build/recipe/emailverification/api/emailVerify.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function emailVerify(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function emailVerify( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/emailverification/api/emailVerify.js b/lib/build/recipe/emailverification/api/emailVerify.js index 1504f4ccc..80e678119 100644 --- a/lib/build/recipe/emailverification/api/emailVerify.js +++ b/lib/build/recipe/emailverification/api/emailVerify.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = emailVerify; const utils_1 = require("../../../utils"); @@ -42,7 +44,12 @@ async function emailVerify(apiImplementation, tenantId, options, userContext) { message: "The email verification token must be a string", }); } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [], sessionRequired: false }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [], sessionRequired: false }, + userContext + ); let response = await apiImplementation.verifyEmailPOST({ token, tenantId, @@ -55,16 +62,19 @@ async function emailVerify(apiImplementation, tenantId, options, userContext) { // automatically added to the response by the createNewSession function call // inside the verifyEmailPOST function. result = { status: "OK" }; - } - else { + } else { result = response; } - } - else { + } else { if (apiImplementation.isEmailVerifiedGET === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [] }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [] }, + userContext + ); result = await apiImplementation.isEmailVerifiedGET({ options, session, diff --git a/lib/build/recipe/emailverification/api/generateEmailVerifyToken.d.ts b/lib/build/recipe/emailverification/api/generateEmailVerifyToken.d.ts index 8ec37da34..487897d0e 100644 --- a/lib/build/recipe/emailverification/api/generateEmailVerifyToken.d.ts +++ b/lib/build/recipe/emailverification/api/generateEmailVerifyToken.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function generateEmailVerifyToken(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function generateEmailVerifyToken( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/emailverification/api/generateEmailVerifyToken.js b/lib/build/recipe/emailverification/api/generateEmailVerifyToken.js index ad0b547fb..0f7d1bdea 100644 --- a/lib/build/recipe/emailverification/api/generateEmailVerifyToken.js +++ b/lib/build/recipe/emailverification/api/generateEmailVerifyToken.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = generateEmailVerifyToken; const utils_1 = require("../../../utils"); @@ -25,7 +27,12 @@ async function generateEmailVerifyToken(apiImplementation, options, userContext) if (apiImplementation.generateEmailVerifyTokenPOST === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [] }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [] }, + userContext + ); const result = await apiImplementation.generateEmailVerifyTokenPOST({ options, session: session, diff --git a/lib/build/recipe/emailverification/api/implementation.js b/lib/build/recipe/emailverification/api/implementation.js index 6be544cf3..a4493686c 100644 --- a/lib/build/recipe/emailverification/api/implementation.js +++ b/lib/build/recipe/emailverification/api/implementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIInterface; const logger_1 = require("../../../logger"); @@ -22,13 +24,15 @@ function getAPIInterface() { return verifyTokenResponse; } // status: "OK" - let newSession = await recipe_1.default.getInstanceOrThrowError().updateSessionIfRequiredPostEmailVerification({ - req: options.req, - res: options.res, - session, - recipeUserIdWhoseEmailGotVerified: verifyTokenResponse.user.recipeUserId, - userContext, - }); + let newSession = await recipe_1.default + .getInstanceOrThrowError() + .updateSessionIfRequiredPostEmailVerification({ + req: options.req, + res: options.res, + session, + recipeUserIdWhoseEmailGotVerified: verifyTokenResponse.user.recipeUserId, + userContext, + }); return { status: "OK", user: verifyTokenResponse.user, @@ -37,7 +41,9 @@ function getAPIInterface() { }, isEmailVerifiedGET: async function ({ userContext, session, options }) { // In this API, we will check if the session's recipe user id's email is verified or not. - const emailInfo = await recipe_1.default.getInstanceOrThrowError().getEmailForRecipeUserId(undefined, session.getRecipeUserId(userContext), userContext); + const emailInfo = await recipe_1.default + .getInstanceOrThrowError() + .getEmailForRecipeUserId(undefined, session.getRecipeUserId(userContext), userContext); if (emailInfo.status === "OK") { const isVerified = await options.recipeImplementation.isEmailVerified({ recipeUserId: session.getRecipeUserId(userContext), @@ -50,35 +56,34 @@ function getAPIInterface() { // whilst the first browser is polling this API - in this case, // we want to have the same effect to the session as if the // email was opened on the original browser itself. - let newSession = await recipe_1.default.getInstanceOrThrowError().updateSessionIfRequiredPostEmailVerification({ - req: options.req, - res: options.res, - session, - recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), - userContext, - }); + let newSession = await recipe_1.default + .getInstanceOrThrowError() + .updateSessionIfRequiredPostEmailVerification({ + req: options.req, + res: options.res, + session, + recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), + userContext, + }); return { status: "OK", isVerified: true, newSession, }; - } - else { + } else { await session.setClaimValue(emailVerificationClaim_1.EmailVerificationClaim, false, userContext); return { status: "OK", isVerified: false, }; } - } - else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { + } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { // We consider people without email addresses as validated return { status: "OK", isVerified: true, }; - } - else { + } else { // this means that the user ID is not known to supertokens. This could // happen if the current session's user ID is not an auth user, // or if it belong to a recipe user ID that got deleted. Either way, @@ -92,26 +97,31 @@ function getAPIInterface() { generateEmailVerifyTokenPOST: async function ({ options, userContext, session }) { // In this API, we generate the email verification token for session's recipe user ID. const tenantId = session.getTenantId(); - const emailInfo = await recipe_1.default.getInstanceOrThrowError().getEmailForRecipeUserId(undefined, session.getRecipeUserId(userContext), userContext); + const emailInfo = await recipe_1.default + .getInstanceOrThrowError() + .getEmailForRecipeUserId(undefined, session.getRecipeUserId(userContext), userContext); if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { - (0, logger_1.logDebugMessage)(`Email verification email not sent to user ${session - .getRecipeUserId(userContext) - .getAsString()} because it doesn't have an email address.`); + (0, logger_1.logDebugMessage)( + `Email verification email not sent to user ${session + .getRecipeUserId(userContext) + .getAsString()} because it doesn't have an email address.` + ); // this can happen if the user ID was found, but it has no email. In this // case, we treat it as a success case. - let newSession = await recipe_1.default.getInstanceOrThrowError().updateSessionIfRequiredPostEmailVerification({ - req: options.req, - res: options.res, - session, - recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), - userContext, - }); + let newSession = await recipe_1.default + .getInstanceOrThrowError() + .updateSessionIfRequiredPostEmailVerification({ + req: options.req, + res: options.res, + session, + recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), + userContext, + }); return { status: "EMAIL_ALREADY_VERIFIED_ERROR", newSession, }; - } - else if (emailInfo.status === "OK") { + } else if (emailInfo.status === "OK") { let response = await options.recipeImplementation.createEmailVerificationToken({ recipeUserId: session.getRecipeUserId(userContext), email: emailInfo.email, @@ -121,16 +131,20 @@ function getAPIInterface() { // In case the email is already verified, we do the same thing // as what happens in the verifyEmailPOST API post email verification (cause maybe the session is outdated). if (response.status === "EMAIL_ALREADY_VERIFIED_ERROR") { - (0, logger_1.logDebugMessage)(`Email verification email not sent to user ${session - .getRecipeUserId(userContext) - .getAsString()} because it is already verified.`); - let newSession = await recipe_1.default.getInstanceOrThrowError().updateSessionIfRequiredPostEmailVerification({ - req: options.req, - res: options.res, - session, - recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), - userContext, - }); + (0, logger_1.logDebugMessage)( + `Email verification email not sent to user ${session + .getRecipeUserId(userContext) + .getAsString()} because it is already verified.` + ); + let newSession = await recipe_1.default + .getInstanceOrThrowError() + .updateSessionIfRequiredPostEmailVerification({ + req: options.req, + res: options.res, + session, + recipeUserIdWhoseEmailGotVerified: session.getRecipeUserId(userContext), + userContext, + }); return { status: "EMAIL_ALREADY_VERIFIED_ERROR", newSession, @@ -164,13 +178,14 @@ function getAPIInterface() { return { status: "OK", }; - } - else { + } else { // this means that the user ID is not known to supertokens. This could // happen if the current session's user ID is not an auth user, // or if it belong to a recipe user ID that got deleted. Either way, // we logout the user. - (0, logger_1.logDebugMessage)("generateEmailVerifyTokenPOST: Returning UNAUTHORISED because the user id provided is unknown"); + (0, logger_1.logDebugMessage)( + "generateEmailVerifyTokenPOST: Returning UNAUTHORISED because the user id provided is unknown" + ); throw new error_1.default({ type: error_1.default.UNAUTHORISED, message: "Unknown User ID provided" }); } }, diff --git a/lib/build/recipe/emailverification/emailVerificationClaim.js b/lib/build/recipe/emailverification/emailVerificationClaim.js index af2b89ddd..092eddd10 100644 --- a/lib/build/recipe/emailverification/emailVerificationClaim.js +++ b/lib/build/recipe/emailverification/emailVerificationClaim.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EmailVerificationClaim = exports.EmailVerificationClaimClass = void 0; const recipe_1 = __importDefault(require("./recipe")); @@ -22,35 +24,38 @@ class EmailVerificationClaimClass extends claims_1.BooleanClaim { email: emailInfo.email, userContext, }); - } - else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { + } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { // We consider people without email addresses as validated return true; - } - else { + } else { throw new Error("UNKNOWN_USER_ID"); } }, }); - this.validators = Object.assign(Object.assign({}, this.validators), { isVerified: (refetchTimeOnFalseInSeconds = 10, maxAgeInSeconds) => (Object.assign(Object.assign({}, this.validators.hasValue(true, maxAgeInSeconds)), { shouldRefetch: (payload, userContext) => { - const value = this.getValueFromPayload(payload, userContext); - if (value === undefined) { - return true; - } - const currentTime = Date.now(); - const lastRefetchTime = this.getLastRefetchTime(payload, userContext); - if (maxAgeInSeconds !== undefined) { - if (lastRefetchTime < currentTime - maxAgeInSeconds * 1000) { + this.validators = Object.assign(Object.assign({}, this.validators), { + isVerified: (refetchTimeOnFalseInSeconds = 10, maxAgeInSeconds) => + Object.assign(Object.assign({}, this.validators.hasValue(true, maxAgeInSeconds)), { + shouldRefetch: (payload, userContext) => { + const value = this.getValueFromPayload(payload, userContext); + if (value === undefined) { return true; } - } - if (value === false) { - if (lastRefetchTime < currentTime - refetchTimeOnFalseInSeconds * 1000) { - return true; + const currentTime = Date.now(); + const lastRefetchTime = this.getLastRefetchTime(payload, userContext); + if (maxAgeInSeconds !== undefined) { + if (lastRefetchTime < currentTime - maxAgeInSeconds * 1000) { + return true; + } } - } - return false; - } })) }); + if (value === false) { + if (lastRefetchTime < currentTime - refetchTimeOnFalseInSeconds * 1000) { + return true; + } + } + return false; + }, + }), + }); } } exports.EmailVerificationClaimClass = EmailVerificationClaimClass; diff --git a/lib/build/recipe/emailverification/emailVerificationFunctions.d.ts b/lib/build/recipe/emailverification/emailVerificationFunctions.d.ts index 8128246cb..2eb1c0427 100644 --- a/lib/build/recipe/emailverification/emailVerificationFunctions.d.ts +++ b/lib/build/recipe/emailverification/emailVerificationFunctions.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { UserEmailInfo } from "./types"; import { NormalisedAppinfo } from "../../types"; -export declare function createAndSendEmailUsingSupertokensService(appInfo: NormalisedAppinfo, user: UserEmailInfo, emailVerifyURLWithToken: string): Promise; +export declare function createAndSendEmailUsingSupertokensService( + appInfo: NormalisedAppinfo, + user: UserEmailInfo, + emailVerifyURLWithToken: string +): Promise; diff --git a/lib/build/recipe/emailverification/emailVerificationFunctions.js b/lib/build/recipe/emailverification/emailVerificationFunctions.js index 7faaa088a..ebeef238c 100644 --- a/lib/build/recipe/emailverification/emailVerificationFunctions.js +++ b/lib/build/recipe/emailverification/emailVerificationFunctions.js @@ -20,15 +20,20 @@ async function createAndSendEmailUsingSupertokensService(appInfo, user, emailVer if ((0, utils_1.isTestEnv)()) { return; } - await (0, utils_1.postWithFetch)("https://api.supertokens.io/0/st/auth/email/verify", { - "api-version": "0", - "content-type": "application/json; charset=utf-8", - }, { - email: user.email, - appName: appInfo.appName, - emailVerifyURL: emailVerifyURLWithToken, - }, { - successLog: `Email sent to ${user.email}`, - errorLogHeader: "Error sending verification email", - }); + await (0, utils_1.postWithFetch)( + "https://api.supertokens.io/0/st/auth/email/verify", + { + "api-version": "0", + "content-type": "application/json; charset=utf-8", + }, + { + email: user.email, + appName: appInfo.appName, + emailVerifyURL: emailVerifyURLWithToken, + }, + { + successLog: `Email sent to ${user.email}`, + errorLogHeader: "Error sending verification email", + } + ); } diff --git a/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.d.ts b/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.d.ts index f95580eb6..d5c7479ac 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.d.ts +++ b/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.d.ts @@ -2,11 +2,14 @@ import { TypeEmailVerificationEmailDeliveryInput } from "../../../types"; import { NormalisedAppinfo, UserContext } from "../../../../../types"; import { EmailDeliveryInterface } from "../../../../../ingredients/emaildelivery/types"; -export default class BackwardCompatibilityService implements EmailDeliveryInterface { +export default class BackwardCompatibilityService + implements EmailDeliveryInterface { private appInfo; private isInServerlessEnv; constructor(appInfo: NormalisedAppinfo, isInServerlessEnv: boolean); - sendEmail: (input: TypeEmailVerificationEmailDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendEmail: ( + input: TypeEmailVerificationEmailDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.js b/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.js index d35eb395f..f904e8e5f 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.js +++ b/lib/build/recipe/emailverification/emaildelivery/services/backwardCompatibility/index.js @@ -6,14 +6,20 @@ class BackwardCompatibilityService { this.sendEmail = async (input) => { try { if (!this.isInServerlessEnv) { - (0, emailVerificationFunctions_1.createAndSendEmailUsingSupertokensService)(this.appInfo, input.user, input.emailVerifyLink).catch((_) => { }); - } - else { + (0, emailVerificationFunctions_1.createAndSendEmailUsingSupertokensService)( + this.appInfo, + input.user, + input.emailVerifyLink + ).catch((_) => {}); + } else { // see https://github.com/supertokens/supertokens-node/pull/135 - await (0, emailVerificationFunctions_1.createAndSendEmailUsingSupertokensService)(this.appInfo, input.user, input.emailVerifyLink); + await (0, emailVerificationFunctions_1.createAndSendEmailUsingSupertokensService)( + this.appInfo, + input.user, + input.emailVerifyLink + ); } - } - catch (_) { } + } catch (_) {} }; this.appInfo = appInfo; this.isInServerlessEnv = isInServerlessEnv; diff --git a/lib/build/recipe/emailverification/emaildelivery/services/index.js b/lib/build/recipe/emailverification/emaildelivery/services/index.js index d648973c6..91700aeaf 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/index.js +++ b/lib/build/recipe/emailverification/emaildelivery/services/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SMTPService = void 0; const smtp_1 = __importDefault(require("./smtp")); diff --git a/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js b/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js index bcf722365..9cd5eaa46 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js +++ b/lib/build/recipe/emailverification/emaildelivery/services/smtp/emailVerify.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getEmailVerifyEmailContent; exports.getEmailVerifyEmailHTML = getEmailVerifyEmailHTML; diff --git a/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.d.ts b/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.d.ts index 7693cfff6..cca4977ab 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.d.ts +++ b/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.d.ts @@ -6,7 +6,9 @@ import { UserContext } from "../../../../../types"; export default class SMTPService implements EmailDeliveryInterface { serviceImpl: ServiceInterface; constructor(config: TypeInput); - sendEmail: (input: TypeEmailVerificationEmailDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendEmail: ( + input: TypeEmailVerificationEmailDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.js b/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.js index 76335ab95..e6bf36f54 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.js +++ b/lib/build/recipe/emailverification/emaildelivery/services/smtp/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const nodemailer_1 = require("nodemailer"); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); @@ -10,7 +12,9 @@ class SMTPService { constructor(config) { this.sendEmail = async (input) => { let content = await this.serviceImpl.getContent(input); - await this.serviceImpl.sendRawEmail(Object.assign(Object.assign({}, content), { userContext: input.userContext })); + await this.serviceImpl.sendRawEmail( + Object.assign(Object.assign({}, content), { userContext: input.userContext }) + ); }; const transporter = (0, nodemailer_1.createTransport)({ host: config.smtpSettings.host, @@ -21,7 +25,9 @@ class SMTPService { }, secure: config.smtpSettings.secure, }); - let builder = new supertokens_js_override_1.default((0, serviceImplementation_1.getServiceImplementation)(transporter, config.smtpSettings.from)); + let builder = new supertokens_js_override_1.default( + (0, serviceImplementation_1.getServiceImplementation)(transporter, config.smtpSettings.from) + ); if (config.override !== undefined) { builder = builder.override(config.override); } diff --git a/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.d.ts b/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.d.ts index d072890a9..3f668725f 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.d.ts +++ b/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.d.ts @@ -2,7 +2,10 @@ import { TypeEmailVerificationEmailDeliveryInput } from "../../../types"; import { Transporter } from "nodemailer"; import { ServiceInterface } from "../../../../../ingredients/emaildelivery/services/smtp"; -export declare function getServiceImplementation(transporter: Transporter, from: { - name: string; - email: string; -}): ServiceInterface; +export declare function getServiceImplementation( + transporter: Transporter, + from: { + name: string; + email: string; + } +): ServiceInterface; diff --git a/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.js b/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.js index 82b6d18f5..ad2ddc44f 100644 --- a/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.js +++ b/lib/build/recipe/emailverification/emaildelivery/services/smtp/serviceImplementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getServiceImplementation = getServiceImplementation; const emailVerify_1 = __importDefault(require("./emailVerify")); @@ -29,8 +31,7 @@ function getServiceImplementation(transporter, from) { subject: input.subject, html: input.body, }); - } - else { + } else { await transporter.sendMail({ from: `${from.name} <${from.email}>`, to: input.toEmail, diff --git a/lib/build/recipe/emailverification/error.d.ts b/lib/build/recipe/emailverification/error.d.ts index d6412505c..486758b61 100644 --- a/lib/build/recipe/emailverification/error.d.ts +++ b/lib/build/recipe/emailverification/error.d.ts @@ -1,8 +1,5 @@ // @ts-nocheck import STError from "../../error"; export default class SessionError extends STError { - constructor(options: { - type: "BAD_INPUT_ERROR"; - message: string; - }); + constructor(options: { type: "BAD_INPUT_ERROR"; message: string }); } diff --git a/lib/build/recipe/emailverification/error.js b/lib/build/recipe/emailverification/error.js index 4f3bedcb7..b0baf2c94 100644 --- a/lib/build/recipe/emailverification/error.js +++ b/lib/build/recipe/emailverification/error.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); class SessionError extends error_1.default { diff --git a/lib/build/recipe/emailverification/index.d.ts b/lib/build/recipe/emailverification/index.d.ts index 8f90db852..d502537b3 100644 --- a/lib/build/recipe/emailverification/index.d.ts +++ b/lib/build/recipe/emailverification/index.d.ts @@ -1,45 +1,99 @@ // @ts-nocheck import Recipe from "./recipe"; import SuperTokensError from "./error"; -import { RecipeInterface, APIOptions, APIInterface, UserEmailInfo, TypeEmailVerificationEmailDeliveryInput } from "./types"; +import { + RecipeInterface, + APIOptions, + APIInterface, + UserEmailInfo, + TypeEmailVerificationEmailDeliveryInput, +} from "./types"; import RecipeUserId from "../../recipeUserId"; export default class Wrapper { static init: typeof Recipe.init; static Error: typeof SuperTokensError; static EmailVerificationClaim: import("./emailVerificationClaim").EmailVerificationClaimClass; - static createEmailVerificationToken(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record): Promise<{ - status: "OK"; - token: string; - } | { - status: "EMAIL_ALREADY_VERIFIED_ERROR"; - }>; - static createEmailVerificationLink(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record): Promise<{ - status: "OK"; - link: string; - } | { - status: "EMAIL_ALREADY_VERIFIED_ERROR"; - }>; - static sendEmailVerificationEmail(tenantId: string, userId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record): Promise<{ - status: "OK"; - } | { - status: "EMAIL_ALREADY_VERIFIED_ERROR"; - }>; - static verifyEmailUsingToken(tenantId: string, token: string, attemptAccountLinking?: boolean, userContext?: Record): Promise<{ - status: "OK"; - user: UserEmailInfo; - } | { - status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR"; - }>; - static isEmailVerified(recipeUserId: RecipeUserId, email?: string, userContext?: Record): Promise; - static revokeEmailVerificationTokens(tenantId: string, recipeUserId: RecipeUserId, email?: string, userContext?: Record): Promise<{ + static createEmailVerificationToken( + tenantId: string, + recipeUserId: RecipeUserId, + email?: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + token: string; + } + | { + status: "EMAIL_ALREADY_VERIFIED_ERROR"; + } + >; + static createEmailVerificationLink( + tenantId: string, + recipeUserId: RecipeUserId, + email?: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + link: string; + } + | { + status: "EMAIL_ALREADY_VERIFIED_ERROR"; + } + >; + static sendEmailVerificationEmail( + tenantId: string, + userId: string, + recipeUserId: RecipeUserId, + email?: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + } + | { + status: "EMAIL_ALREADY_VERIFIED_ERROR"; + } + >; + static verifyEmailUsingToken( + tenantId: string, + token: string, + attemptAccountLinking?: boolean, + userContext?: Record + ): Promise< + | { + status: "OK"; + user: UserEmailInfo; + } + | { + status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR"; + } + >; + static isEmailVerified( + recipeUserId: RecipeUserId, + email?: string, + userContext?: Record + ): Promise; + static revokeEmailVerificationTokens( + tenantId: string, + recipeUserId: RecipeUserId, + email?: string, + userContext?: Record + ): Promise<{ status: string; }>; - static unverifyEmail(recipeUserId: RecipeUserId, email?: string, userContext?: Record): Promise<{ + static unverifyEmail( + recipeUserId: RecipeUserId, + email?: string, + userContext?: Record + ): Promise<{ status: string; }>; - static sendEmail(input: TypeEmailVerificationEmailDeliveryInput & { - userContext?: Record; - }): Promise; + static sendEmail( + input: TypeEmailVerificationEmailDeliveryInput & { + userContext?: Record; + } + ): Promise; } export declare let init: typeof Recipe.init; export declare let Error: typeof SuperTokensError; diff --git a/lib/build/recipe/emailverification/index.js b/lib/build/recipe/emailverification/index.js index 20182bc30..3b9bd8589 100644 --- a/lib/build/recipe/emailverification/index.js +++ b/lib/build/recipe/emailverification/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EmailVerificationClaim = exports.sendEmail = exports.unverifyEmail = exports.revokeEmailVerificationTokens = exports.isEmailVerified = exports.verifyEmailUsingToken = exports.sendEmailVerificationEmail = exports.createEmailVerificationLink = exports.createEmailVerificationToken = exports.Error = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); @@ -32,13 +34,11 @@ class Wrapper { const emailInfo = await recipeInstance.getEmailForRecipeUserId(undefined, recipeUserId, ctx); if (emailInfo.status === "OK") { email = emailInfo.email; - } - else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { + } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { return { status: "EMAIL_ALREADY_VERIFIED_ERROR", }; - } - else { + } else { throw new global.Error("Unknown User ID provided without email"); } } @@ -53,7 +53,12 @@ class Wrapper { const ctx = (0, utils_2.getUserContext)(userContext); const recipeInstance = recipe_1.default.getInstanceOrThrowError(); const appInfo = recipeInstance.getAppInfo(); - let emailVerificationToken = await (0, exports.createEmailVerificationToken)(tenantId, recipeUserId, email, ctx); + let emailVerificationToken = await (0, exports.createEmailVerificationToken)( + tenantId, + recipeUserId, + email, + ctx + ); if (emailVerificationToken.status === "EMAIL_ALREADY_VERIFIED_ERROR") { return { status: "EMAIL_ALREADY_VERIFIED_ERROR", @@ -77,13 +82,11 @@ class Wrapper { const emailInfo = await recipeInstance.getEmailForRecipeUserId(undefined, recipeUserId, ctx); if (emailInfo.status === "OK") { email = emailInfo.email; - } - else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { + } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { return { status: "EMAIL_ALREADY_VERIFIED_ERROR", }; - } - else { + } else { throw new global.Error("Unknown User ID provided without email"); } } @@ -123,11 +126,9 @@ class Wrapper { const emailInfo = await recipeInstance.getEmailForRecipeUserId(undefined, recipeUserId, ctx); if (emailInfo.status === "OK") { email = emailInfo.email; - } - else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { + } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { return true; - } - else { + } else { throw new global.Error("Unknown User ID provided without email"); } } @@ -147,16 +148,14 @@ class Wrapper { const emailInfo = await recipeInstance.getEmailForRecipeUserId(undefined, recipeUserId, ctx); if (emailInfo.status === "OK") { email = emailInfo.email; - } - else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { + } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { // This only happens for phone based passwordless users (or if the user added a custom getEmailForUserId) // We can return OK here, since there is no way to create an email verification token // if getEmailForUserId returns EMAIL_DOES_NOT_EXIST_ERROR. return { status: "OK", }; - } - else { + } else { throw new global.Error("Unknown User ID provided without email"); } } @@ -174,14 +173,12 @@ class Wrapper { const emailInfo = await recipeInstance.getEmailForRecipeUserId(undefined, recipeUserId, ctx); if (emailInfo.status === "OK") { email = emailInfo.email; - } - else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { + } else if (emailInfo.status === "EMAIL_DOES_NOT_EXIST_ERROR") { // Here we are returning OK since that's how it used to work, but a later call to isVerified will still return true return { status: "OK", }; - } - else { + } else { throw new global.Error("Unknown User ID provided without email"); } } @@ -193,7 +190,9 @@ class Wrapper { } static async sendEmail(input) { let recipeInstance = recipe_1.default.getInstanceOrThrowError(); - return await recipeInstance.emailDelivery.ingredientInterfaceImpl.sendEmail(Object.assign(Object.assign({}, input), { userContext: (0, utils_2.getUserContext)(input.userContext) })); + return await recipeInstance.emailDelivery.ingredientInterfaceImpl.sendEmail( + Object.assign(Object.assign({}, input), { userContext: (0, utils_2.getUserContext)(input.userContext) }) + ); } } Wrapper.init = recipe_1.default.init; @@ -211,4 +210,9 @@ exports.revokeEmailVerificationTokens = Wrapper.revokeEmailVerificationTokens; exports.unverifyEmail = Wrapper.unverifyEmail; exports.sendEmail = Wrapper.sendEmail; var emailVerificationClaim_2 = require("./emailVerificationClaim"); -Object.defineProperty(exports, "EmailVerificationClaim", { enumerable: true, get: function () { return emailVerificationClaim_2.EmailVerificationClaim; } }); +Object.defineProperty(exports, "EmailVerificationClaim", { + enumerable: true, + get: function () { + return emailVerificationClaim_2.EmailVerificationClaim; + }, +}); diff --git a/lib/build/recipe/emailverification/recipe.d.ts b/lib/build/recipe/emailverification/recipe.d.ts index 1b76f7d6b..6841e9797 100644 --- a/lib/build/recipe/emailverification/recipe.d.ts +++ b/lib/build/recipe/emailverification/recipe.d.ts @@ -17,15 +17,29 @@ export default class Recipe extends RecipeModule { apiImpl: APIInterface; isInServerlessEnv: boolean; emailDelivery: EmailDeliveryIngredient; - constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config: TypeInput, ingredients: { - emailDelivery: EmailDeliveryIngredient | undefined; - }); + constructor( + recipeId: string, + appInfo: NormalisedAppinfo, + isInServerlessEnv: boolean, + config: TypeInput, + ingredients: { + emailDelivery: EmailDeliveryIngredient | undefined; + } + ); static getInstanceOrThrowError(): Recipe; static getInstance(): Recipe | undefined; static init(config: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, tenantId: string, req: BaseRequest, res: BaseResponse, _: NormalisedURLPath, __: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + tenantId: string, + req: BaseRequest, + res: BaseResponse, + _: NormalisedURLPath, + __: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: STError, _: BaseRequest, __: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; diff --git a/lib/build/recipe/emailverification/recipe.js b/lib/build/recipe/emailverification/recipe.js index 4eded7c98..f5bf1be12 100644 --- a/lib/build/recipe/emailverification/recipe.js +++ b/lib/build/recipe/emailverification/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipeModule_1 = __importDefault(require("../../recipeModule")); const error_1 = __importDefault(require("./error")); @@ -45,7 +47,9 @@ class Recipe extends recipeModule_1.default { return [ { method: "post", - pathWithoutApiBasePath: new normalisedURLPath_1.default(constants_1.GENERATE_EMAIL_VERIFY_TOKEN_API), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + constants_1.GENERATE_EMAIL_VERIFY_TOKEN_API + ), id: constants_1.GENERATE_EMAIL_VERIFY_TOKEN_API, disabled: this.apiImpl.generateEmailVerifyTokenPOST === undefined, }, @@ -76,8 +80,7 @@ class Recipe extends recipeModule_1.default { }; if (id === constants_1.GENERATE_EMAIL_VERIFY_TOKEN_API) { return await (0, generateEmailVerifyToken_1.default)(this.apiImpl, options, userContext); - } - else { + } else { return await (0, emailVerify_1.default)(this.apiImpl, tenantId, options, userContext); } }; @@ -113,8 +116,7 @@ class Recipe extends recipeModule_1.default { email: currLM.email, status: "OK", }; - } - else { + } else { return { status: "EMAIL_DOES_NOT_EXIST_ERROR", }; @@ -147,7 +149,10 @@ class Recipe extends recipeModule_1.default { return primaryUser === null || primaryUser === void 0 ? void 0 : primaryUser.id; }; this.updateSessionIfRequiredPostEmailVerification = async (input) => { - let primaryUserId = await this.getPrimaryUserIdForRecipeUser(input.recipeUserIdWhoseEmailGotVerified, input.userContext); + let primaryUserId = await this.getPrimaryUserIdForRecipeUser( + input.recipeUserIdWhoseEmailGotVerified, + input.userContext + ); // if a session exists in the API, then we can update the session // claim related to email verification if (input.session !== undefined) { @@ -163,14 +168,20 @@ class Recipe extends recipeModule_1.default { // --> (Case 4) This is post login account linking, in which the account that got verified // got linked to ANOTHER primary account (user ID of account has changed to a different user ID != session.getUserId, but // we should ignore this since it will result in the user's session changing.) - if (input.session.getRecipeUserId(input.userContext).getAsString() === - input.recipeUserIdWhoseEmailGotVerified.getAsString()) { - (0, logger_1.logDebugMessage)("updateSessionIfRequiredPostEmailVerification the session belongs to the verified user"); + if ( + input.session.getRecipeUserId(input.userContext).getAsString() === + input.recipeUserIdWhoseEmailGotVerified.getAsString() + ) { + (0, logger_1.logDebugMessage)( + "updateSessionIfRequiredPostEmailVerification the session belongs to the verified user" + ); // this means that the session's login method's account is the // one that just got verified and that we are NOT doing post login // account linking. So this is only for (Case 1) and (Case 2) if (input.session.getUserId() === primaryUserId) { - (0, logger_1.logDebugMessage)("updateSessionIfRequiredPostEmailVerification the session userId matches the primary user id, so we are only refreshing the claim"); + (0, logger_1.logDebugMessage)( + "updateSessionIfRequiredPostEmailVerification the session userId matches the primary user id, so we are only refreshing the claim" + ); // if the session's primary user ID is equal to the // primary user ID that the account was linked to, then // this means that the new account became a primary user (Case 1) @@ -181,9 +192,11 @@ class Recipe extends recipeModule_1.default { try { // EmailVerificationClaim will be based on the recipeUserId // and not the primary user ID. - await input.session.fetchAndSetClaim(emailVerificationClaim_1.EmailVerificationClaim, input.userContext); - } - catch (err) { + await input.session.fetchAndSetClaim( + emailVerificationClaim_1.EmailVerificationClaim, + input.userContext + ); + } catch (err) { // This should never happen, since we've just set the status above. if (err.message === "UNKNOWN_USER_ID") { throw new error_2.default({ @@ -194,9 +207,10 @@ class Recipe extends recipeModule_1.default { throw err; } return; - } - else { - (0, logger_1.logDebugMessage)("updateSessionIfRequiredPostEmailVerification the session user id doesn't match the primary user id, so we are revoking all sessions and creating a new one"); + } else { + (0, logger_1.logDebugMessage)( + "updateSessionIfRequiredPostEmailVerification the session user id doesn't match the primary user id, so we are revoking all sessions and creating a new one" + ); // if the session's primary user ID is NOT equal to the // primary user ID that the account that it was linked to, then // this means that the new account got linked to another primary user (Case 2) @@ -204,13 +218,27 @@ class Recipe extends recipeModule_1.default { // a new session // Revoke all session belonging to session.getRecipeUserId() // We do not really need to do this, but we do it anyway.. no harm. - await session_1.default.revokeAllSessionsForUser(input.recipeUserIdWhoseEmailGotVerified.getAsString(), false, undefined, input.userContext); + await session_1.default.revokeAllSessionsForUser( + input.recipeUserIdWhoseEmailGotVerified.getAsString(), + false, + undefined, + input.userContext + ); // create a new session and return that.. - return await session_1.default.createNewSession(input.req, input.res, input.session.getTenantId(), input.session.getRecipeUserId(input.userContext), {}, {}, input.userContext); + return await session_1.default.createNewSession( + input.req, + input.res, + input.session.getTenantId(), + input.session.getRecipeUserId(input.userContext), + {}, + {}, + input.userContext + ); } - } - else { - (0, logger_1.logDebugMessage)("updateSessionIfRequiredPostEmailVerification the verified user doesn't match the session"); + } else { + (0, logger_1.logDebugMessage)( + "updateSessionIfRequiredPostEmailVerification the verified user doesn't match the session" + ); // this means that the session's login method's account was NOT the // one that just got verified and that we ARE doing post login // account linking. So this is only for (Case 3) and (Case 4) @@ -220,8 +248,7 @@ class Recipe extends recipeModule_1.default { // linked user's account). return undefined; } - } - else { + } else { (0, logger_1.logDebugMessage)("updateSessionIfRequiredPostEmailVerification got no session"); // the session is updated when the is email verification GET API is called // so we don't do anything in this API. @@ -231,7 +258,12 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_1.validateAndNormaliseUserInput)(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.getEmailForRecipeUserId)); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + this.getEmailForRecipeUserId + ) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -259,19 +291,36 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : []), { - emailDelivery: undefined, - }); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ), + { + emailDelivery: undefined, + } + ); postSuperTokensInitCallbacks_1.PostSuperTokensInitCallbacks.addPostInitCallback(() => { - recipe_1.default.getInstanceOrThrowError().addClaimFromOtherRecipe(emailVerificationClaim_1.EmailVerificationClaim); + recipe_1.default + .getInstanceOrThrowError() + .addClaimFromOtherRecipe(emailVerificationClaim_1.EmailVerificationClaim); if (config.mode === "REQUIRED") { - recipe_1.default.getInstanceOrThrowError().addClaimValidatorFromOtherRecipe(emailVerificationClaim_1.EmailVerificationClaim.validators.isVerified()); + recipe_1.default + .getInstanceOrThrowError() + .addClaimValidatorFromOtherRecipe( + emailVerificationClaim_1.EmailVerificationClaim.validators.isVerified() + ); } }); return Recipe.instance; - } - else { - throw new Error("Emailverification recipe has already been initialised. Please check your code for bugs."); + } else { + throw new Error( + "Emailverification recipe has already been initialised. Please check your code for bugs." + ); } }; } diff --git a/lib/build/recipe/emailverification/recipeImplementation.d.ts b/lib/build/recipe/emailverification/recipeImplementation.d.ts index 57ed3970a..625b1087e 100644 --- a/lib/build/recipe/emailverification/recipeImplementation.d.ts +++ b/lib/build/recipe/emailverification/recipeImplementation.d.ts @@ -2,4 +2,7 @@ import { RecipeInterface } from "./"; import { Querier } from "../../querier"; import { GetEmailForRecipeUserIdFunc } from "./types"; -export default function getRecipeInterface(querier: Querier, getEmailForRecipeUserId: GetEmailForRecipeUserIdFunc): RecipeInterface; +export default function getRecipeInterface( + querier: Querier, + getEmailForRecipeUserId: GetEmailForRecipeUserIdFunc +): RecipeInterface; diff --git a/lib/build/recipe/emailverification/recipeImplementation.js b/lib/build/recipe/emailverification/recipeImplementation.js index 302f53790..099fbc6e8 100644 --- a/lib/build/recipe/emailverification/recipeImplementation.js +++ b/lib/build/recipe/emailverification/recipeImplementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -9,28 +11,35 @@ const recipeUserId_1 = __importDefault(require("../../recipeUserId")); const __1 = require("../.."); function getRecipeInterface(querier, getEmailForRecipeUserId) { return { - createEmailVerificationToken: async function ({ recipeUserId, email, tenantId, userContext, }) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId}/recipe/user/email/verify/token`), { - userId: recipeUserId.getAsString(), - email, - }, userContext); + createEmailVerificationToken: async function ({ recipeUserId, email, tenantId, userContext }) { + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${tenantId}/recipe/user/email/verify/token`), + { + userId: recipeUserId.getAsString(), + email, + }, + userContext + ); if (response.status === "OK") { return { status: "OK", token: response.token, }; - } - else { + } else { return { status: "EMAIL_ALREADY_VERIFIED_ERROR", }; } }, - verifyEmailUsingToken: async function ({ token, attemptAccountLinking, tenantId, userContext, }) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId}/recipe/user/email/verify`), { - method: "token", - token, - }, userContext); + verifyEmailUsingToken: async function ({ token, attemptAccountLinking, tenantId, userContext }) { + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${tenantId}/recipe/user/email/verify`), + { + method: "token", + token, + }, + userContext + ); if (response.status === "OK") { const recipeUserId = new recipeUserId_1.default(response.userId); if (attemptAccountLinking) { @@ -62,32 +71,43 @@ function getRecipeInterface(querier, getEmailForRecipeUserId) { email: response.email, }, }; - } - else { + } else { return { status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR", }; } }, - isEmailVerified: async function ({ recipeUserId, email, userContext, }) { - let response = await querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/user/email/verify"), { - userId: recipeUserId.getAsString(), - email, - }, userContext); + isEmailVerified: async function ({ recipeUserId, email, userContext }) { + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/user/email/verify"), + { + userId: recipeUserId.getAsString(), + email, + }, + userContext + ); return response.isVerified; }, revokeEmailVerificationTokens: async function (input) { - await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/user/email/verify/token/remove`), { - userId: input.recipeUserId.getAsString(), - email: input.email, - }, input.userContext); + await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/user/email/verify/token/remove`), + { + userId: input.recipeUserId.getAsString(), + email: input.email, + }, + input.userContext + ); return { status: "OK" }; }, unverifyEmail: async function (input) { - await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/user/email/verify/remove"), { - userId: input.recipeUserId.getAsString(), - email: input.email, - }, input.userContext); + await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/user/email/verify/remove"), + { + userId: input.recipeUserId.getAsString(), + email: input.email, + }, + input.userContext + ); return { status: "OK" }; }, }; diff --git a/lib/build/recipe/emailverification/types.d.ts b/lib/build/recipe/emailverification/types.d.ts index 59652970c..f0d492f34 100644 --- a/lib/build/recipe/emailverification/types.d.ts +++ b/lib/build/recipe/emailverification/types.d.ts @@ -1,7 +1,10 @@ // @ts-nocheck import type { BaseRequest, BaseResponse } from "../../framework"; import OverrideableBuilder from "supertokens-js-override"; -import { TypeInput as EmailDeliveryTypeInput, TypeInputWithService as EmailDeliveryTypeInputWithService } from "../../ingredients/emaildelivery/types"; +import { + TypeInput as EmailDeliveryTypeInput, + TypeInputWithService as EmailDeliveryTypeInputWithService, +} from "../../ingredients/emaildelivery/types"; import EmailDeliveryIngredient from "../../ingredients/emaildelivery"; import { GeneralErrorResponse, NormalisedAppinfo, UserContext } from "../../types"; import { SessionContainerInterface } from "../session/types"; @@ -10,28 +13,48 @@ import { User } from "../../types"; export type TypeInput = { mode: "REQUIRED" | "OPTIONAL"; emailDelivery?: EmailDeliveryTypeInput; - getEmailForRecipeUserId?: (recipeUserId: RecipeUserId, userContext: UserContext) => Promise<{ - status: "OK"; - email: string; - } | { - status: "EMAIL_DOES_NOT_EXIST_ERROR" | "UNKNOWN_USER_ID_ERROR"; - }>; + getEmailForRecipeUserId?: ( + recipeUserId: RecipeUserId, + userContext: UserContext + ) => Promise< + | { + status: "OK"; + email: string; + } + | { + status: "EMAIL_DOES_NOT_EXIST_ERROR" | "UNKNOWN_USER_ID_ERROR"; + } + >; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { mode: "REQUIRED" | "OPTIONAL"; - getEmailDeliveryConfig: (isInServerlessEnv: boolean) => EmailDeliveryTypeInputWithService; - getEmailForRecipeUserId?: (recipeUserId: RecipeUserId, userContext: UserContext) => Promise<{ - status: "OK"; - email: string; - } | { - status: "EMAIL_DOES_NOT_EXIST_ERROR" | "UNKNOWN_USER_ID_ERROR"; - }>; + getEmailDeliveryConfig: ( + isInServerlessEnv: boolean + ) => EmailDeliveryTypeInputWithService; + getEmailForRecipeUserId?: ( + recipeUserId: RecipeUserId, + userContext: UserContext + ) => Promise< + | { + status: "OK"; + email: string; + } + | { + status: "EMAIL_DOES_NOT_EXIST_ERROR" | "UNKNOWN_USER_ID_ERROR"; + } + >; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -45,28 +68,30 @@ export type RecipeInterface = { email: string; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - token: string; - } | { - status: "EMAIL_ALREADY_VERIFIED_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + token: string; + } + | { + status: "EMAIL_ALREADY_VERIFIED_ERROR"; + } + >; verifyEmailUsingToken(input: { token: string; attemptAccountLinking: boolean; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - user: UserEmailInfo; - } | { - status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR"; - }>; - isEmailVerified(input: { - recipeUserId: RecipeUserId; - email: string; - userContext: UserContext; - }): Promise; + }): Promise< + | { + status: "OK"; + user: UserEmailInfo; + } + | { + status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR"; + } + >; + isEmailVerified(input: { recipeUserId: RecipeUserId; email: string; userContext: UserContext }): Promise; revokeEmailVerificationTokens(input: { recipeUserId: RecipeUserId; email: string; @@ -94,38 +119,55 @@ export type APIOptions = { emailDelivery: EmailDeliveryIngredient; }; export type APIInterface = { - verifyEmailPOST: undefined | ((input: { - token: string; - tenantId: string; - options: APIOptions; - userContext: UserContext; - session: SessionContainerInterface | undefined; - }) => Promise<{ - status: "OK"; - user: UserEmailInfo; - newSession?: SessionContainerInterface; - } | { - status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR"; - } | GeneralErrorResponse>); - isEmailVerifiedGET: undefined | ((input: { - options: APIOptions; - userContext: UserContext; - session: SessionContainerInterface; - }) => Promise<{ - status: "OK"; - isVerified: boolean; - newSession?: SessionContainerInterface; - } | GeneralErrorResponse>); - generateEmailVerifyTokenPOST: undefined | ((input: { - options: APIOptions; - userContext: UserContext; - session: SessionContainerInterface; - }) => Promise<{ - status: "OK"; - } | { - status: "EMAIL_ALREADY_VERIFIED_ERROR"; - newSession?: SessionContainerInterface; - } | GeneralErrorResponse>); + verifyEmailPOST: + | undefined + | ((input: { + token: string; + tenantId: string; + options: APIOptions; + userContext: UserContext; + session: SessionContainerInterface | undefined; + }) => Promise< + | { + status: "OK"; + user: UserEmailInfo; + newSession?: SessionContainerInterface; + } + | { + status: "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR"; + } + | GeneralErrorResponse + >); + isEmailVerifiedGET: + | undefined + | ((input: { + options: APIOptions; + userContext: UserContext; + session: SessionContainerInterface; + }) => Promise< + | { + status: "OK"; + isVerified: boolean; + newSession?: SessionContainerInterface; + } + | GeneralErrorResponse + >); + generateEmailVerifyTokenPOST: + | undefined + | ((input: { + options: APIOptions; + userContext: UserContext; + session: SessionContainerInterface; + }) => Promise< + | { + status: "OK"; + } + | { + status: "EMAIL_ALREADY_VERIFIED_ERROR"; + newSession?: SessionContainerInterface; + } + | GeneralErrorResponse + >); }; export type TypeEmailVerificationEmailDeliveryInput = { type: "EMAIL_VERIFICATION"; @@ -137,9 +179,16 @@ export type TypeEmailVerificationEmailDeliveryInput = { emailVerifyLink: string; tenantId: string; }; -export type GetEmailForRecipeUserIdFunc = (user: User | undefined, recipeUserId: RecipeUserId, userContext: UserContext) => Promise<{ - status: "OK"; - email: string; -} | { - status: "EMAIL_DOES_NOT_EXIST_ERROR" | "UNKNOWN_USER_ID_ERROR"; -}>; +export type GetEmailForRecipeUserIdFunc = ( + user: User | undefined, + recipeUserId: RecipeUserId, + userContext: UserContext +) => Promise< + | { + status: "OK"; + email: string; + } + | { + status: "EMAIL_DOES_NOT_EXIST_ERROR" | "UNKNOWN_USER_ID_ERROR"; + } +>; diff --git a/lib/build/recipe/emailverification/utils.d.ts b/lib/build/recipe/emailverification/utils.d.ts index fdfc82551..60043dc8a 100644 --- a/lib/build/recipe/emailverification/utils.d.ts +++ b/lib/build/recipe/emailverification/utils.d.ts @@ -3,7 +3,11 @@ import Recipe from "./recipe"; import { TypeInput, TypeNormalisedInput } from "./types"; import { NormalisedAppinfo, UserContext } from "../../types"; import { BaseRequest } from "../../framework"; -export declare function validateAndNormaliseUserInput(_: Recipe, appInfo: NormalisedAppinfo, config: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + _: Recipe, + appInfo: NormalisedAppinfo, + config: TypeInput +): TypeNormalisedInput; export declare function getEmailVerifyLink(input: { appInfo: NormalisedAppinfo; token: string; diff --git a/lib/build/recipe/emailverification/utils.js b/lib/build/recipe/emailverification/utils.js index d5c398ddf..989ed2440 100644 --- a/lib/build/recipe/emailverification/utils.js +++ b/lib/build/recipe/emailverification/utils.js @@ -13,15 +13,23 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; exports.getEmailVerifyLink = getEmailVerifyLink; const backwardCompatibility_1 = __importDefault(require("./emaildelivery/services/backwardCompatibility")); function validateAndNormaliseUserInput(_, appInfo, config) { - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config.override + ); function getEmailDeliveryConfig(isInServerlessEnv) { var _a; let emailService = (_a = config.emailDelivery) === null || _a === void 0 ? void 0 : _a.service; @@ -33,7 +41,7 @@ function validateAndNormaliseUserInput(_, appInfo, config) { if (emailService === undefined) { emailService = new backwardCompatibility_1.default(appInfo, isInServerlessEnv); } - return Object.assign(Object.assign({}, config.emailDelivery), { + return Object.assign(Object.assign({}, config.emailDelivery), { /** * if we do * let emailDelivery = { @@ -45,7 +53,8 @@ function validateAndNormaliseUserInput(_, appInfo, config) { * it it again get set to undefined, so we * set service at the end */ - service: emailService }); + service: emailService, + }); } return { mode: config.mode, @@ -55,16 +64,18 @@ function validateAndNormaliseUserInput(_, appInfo, config) { }; } function getEmailVerifyLink(input) { - return (input.appInfo - .getOrigin({ - request: input.request, - userContext: input.userContext, - }) - .getAsStringDangerous() + + return ( + input.appInfo + .getOrigin({ + request: input.request, + userContext: input.userContext, + }) + .getAsStringDangerous() + input.appInfo.websiteBasePath.getAsStringDangerous() + "/verify-email" + "?token=" + input.token + "&tenantId=" + - input.tenantId); + input.tenantId + ); } diff --git a/lib/build/recipe/jwt/api/getJWKS.d.ts b/lib/build/recipe/jwt/api/getJWKS.d.ts index b1fd38fd9..92997a1a4 100644 --- a/lib/build/recipe/jwt/api/getJWKS.d.ts +++ b/lib/build/recipe/jwt/api/getJWKS.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { UserContext } from "../../../types"; import { APIInterface, APIOptions } from "../types"; -export default function getJWKS(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function getJWKS( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/jwt/api/getJWKS.js b/lib/build/recipe/jwt/api/getJWKS.js index 5fdc20af7..0e14b1caf 100644 --- a/lib/build/recipe/jwt/api/getJWKS.js +++ b/lib/build/recipe/jwt/api/getJWKS.js @@ -26,8 +26,7 @@ async function getJWKS(apiImplementation, options, userContext) { }); if ("status" in result && result.status === "GENERAL_ERROR") { (0, utils_1.send200Response)(options.res, result); - } - else { + } else { options.res.setHeader("Access-Control-Allow-Origin", "*", false); (0, utils_1.send200Response)(options.res, result); } diff --git a/lib/build/recipe/jwt/api/implementation.js b/lib/build/recipe/jwt/api/implementation.js index ccbc24ceb..12eb0b023 100644 --- a/lib/build/recipe/jwt/api/implementation.js +++ b/lib/build/recipe/jwt/api/implementation.js @@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIImplementation; function getAPIImplementation() { return { - getJWKSGET: async function ({ options, userContext, }) { + getJWKSGET: async function ({ options, userContext }) { const resp = await options.recipeImplementation.getJWKS({ userContext }); if (resp.validityInSeconds !== undefined) { options.res.setHeader("Cache-Control", `max-age=${resp.validityInSeconds}, must-revalidate`, false); diff --git a/lib/build/recipe/jwt/index.d.ts b/lib/build/recipe/jwt/index.d.ts index 7a90d0e50..b5cc590ce 100644 --- a/lib/build/recipe/jwt/index.d.ts +++ b/lib/build/recipe/jwt/index.d.ts @@ -3,13 +3,23 @@ import Recipe from "./recipe"; import { APIInterface, RecipeInterface, APIOptions, JsonWebKey } from "./types"; export default class Wrapper { static init: typeof Recipe.init; - static createJWT(payload: any, validitySeconds?: number, useStaticSigningKey?: boolean, userContext?: Record): Promise<{ - status: "OK"; - jwt: string; - } | { - status: "UNSUPPORTED_ALGORITHM_ERROR"; - }>; - static getJWKS(userContext?: Record): Promise<{ + static createJWT( + payload: any, + validitySeconds?: number, + useStaticSigningKey?: boolean, + userContext?: Record + ): Promise< + | { + status: "OK"; + jwt: string; + } + | { + status: "UNSUPPORTED_ALGORITHM_ERROR"; + } + >; + static getJWKS( + userContext?: Record + ): Promise<{ keys: JsonWebKey[]; validityInSeconds?: number; }>; diff --git a/lib/build/recipe/jwt/index.js b/lib/build/recipe/jwt/index.js index fa956270c..2b086d35c 100644 --- a/lib/build/recipe/jwt/index.js +++ b/lib/build/recipe/jwt/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getJWKS = exports.createJWT = exports.init = void 0; const utils_1 = require("../../utils"); diff --git a/lib/build/recipe/jwt/recipe.d.ts b/lib/build/recipe/jwt/recipe.d.ts index 7d221b1a2..0f0a948c3 100644 --- a/lib/build/recipe/jwt/recipe.d.ts +++ b/lib/build/recipe/jwt/recipe.d.ts @@ -17,7 +17,15 @@ export default class Recipe extends RecipeModule { static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled(): APIHandled[]; - handleAPIRequest: (_id: string, _tenantId: string | undefined, req: BaseRequest, res: BaseResponse, _path: normalisedURLPath, _method: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + _id: string, + _tenantId: string | undefined, + req: BaseRequest, + res: BaseResponse, + _path: normalisedURLPath, + _method: HTTPMethod, + userContext: UserContext + ) => Promise; handleError(error: error, _: BaseRequest, __: BaseResponse, _userContext: UserContext): Promise; getAllCORSHeaders(): string[]; isErrorFromThisRecipe(err: any): err is error; diff --git a/lib/build/recipe/jwt/recipe.js b/lib/build/recipe/jwt/recipe.js index 429da73fd..6a76c9483 100644 --- a/lib/build/recipe/jwt/recipe.js +++ b/lib/build/recipe/jwt/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -45,7 +47,13 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_2.validateAndNormaliseUserInput)(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.config, appInfo)); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + this.config, + appInfo + ) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -63,10 +71,18 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_1.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_1.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return Recipe.instance; - } - else { + } else { throw new Error("JWT recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/jwt/recipeImplementation.d.ts b/lib/build/recipe/jwt/recipeImplementation.d.ts index 55dd3d95e..5109fbcb1 100644 --- a/lib/build/recipe/jwt/recipeImplementation.d.ts +++ b/lib/build/recipe/jwt/recipeImplementation.d.ts @@ -2,4 +2,8 @@ import { Querier } from "../../querier"; import { NormalisedAppinfo } from "../../types"; import { RecipeInterface, TypeNormalisedInput } from "./types"; -export default function getRecipeInterface(querier: Querier, config: TypeNormalisedInput, appInfo: NormalisedAppinfo): RecipeInterface; +export default function getRecipeInterface( + querier: Querier, + config: TypeNormalisedInput, + appInfo: NormalisedAppinfo +): RecipeInterface; diff --git a/lib/build/recipe/jwt/recipeImplementation.js b/lib/build/recipe/jwt/recipeImplementation.js index b55594812..c2056d974 100644 --- a/lib/build/recipe/jwt/recipeImplementation.js +++ b/lib/build/recipe/jwt/recipeImplementation.js @@ -13,41 +13,51 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); const defaultJWKSMaxAge = 60; // This corresponds to the dynamicSigningKeyOverlapMS in the core function getRecipeInterface(querier, config, appInfo) { return { - createJWT: async function ({ payload, validitySeconds, useStaticSigningKey, userContext, }) { + createJWT: async function ({ payload, validitySeconds, useStaticSigningKey, userContext }) { if (validitySeconds === undefined) { // If the user does not provide a validity to this function and the config validity is also undefined, use 100 years (in seconds) validitySeconds = config.jwtValiditySeconds; } - let response = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/jwt"), { - payload: payload !== null && payload !== void 0 ? payload : {}, - validity: validitySeconds, - useStaticSigningKey: useStaticSigningKey !== false, - algorithm: "RS256", - jwksDomain: appInfo.apiDomain.getAsStringDangerous(), - }, userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/jwt"), + { + payload: payload !== null && payload !== void 0 ? payload : {}, + validity: validitySeconds, + useStaticSigningKey: useStaticSigningKey !== false, + algorithm: "RS256", + jwksDomain: appInfo.apiDomain.getAsStringDangerous(), + }, + userContext + ); if (response.status === "OK") { return { status: "OK", jwt: response.jwt, }; - } - else { + } else { return { status: "UNSUPPORTED_ALGORITHM_ERROR", }; } }, getJWKS: async function ({ userContext }) { - const { body, headers } = await querier.sendGetRequestWithResponseHeaders(new normalisedURLPath_1.default("/.well-known/jwks.json"), {}, undefined, userContext); + const { body, headers } = await querier.sendGetRequestWithResponseHeaders( + new normalisedURLPath_1.default("/.well-known/jwks.json"), + {}, + undefined, + userContext + ); let validityInSeconds = defaultJWKSMaxAge; const cacheControl = headers.get("Cache-Control"); if (cacheControl) { diff --git a/lib/build/recipe/jwt/types.d.ts b/lib/build/recipe/jwt/types.d.ts index 043bc8dfb..db2027589 100644 --- a/lib/build/recipe/jwt/types.d.ts +++ b/lib/build/recipe/jwt/types.d.ts @@ -13,14 +13,20 @@ export type JsonWebKey = { export type TypeInput = { jwtValiditySeconds?: number; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { jwtValiditySeconds: number; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -38,12 +44,15 @@ export type RecipeInterface = { validitySeconds?: number; useStaticSigningKey?: boolean; userContext: UserContext; - }): Promise<{ - status: "OK"; - jwt: string; - } | { - status: "UNSUPPORTED_ALGORITHM_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + jwt: string; + } + | { + status: "UNSUPPORTED_ALGORITHM_ERROR"; + } + >; getJWKS(input: { userContext: UserContext; }): Promise<{ @@ -52,10 +61,15 @@ export type RecipeInterface = { }>; }; export type APIInterface = { - getJWKSGET: undefined | ((input: { - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - keys: JsonWebKey[]; - } | GeneralErrorResponse>); + getJWKSGET: + | undefined + | ((input: { + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + keys: JsonWebKey[]; + } + | GeneralErrorResponse + >); }; diff --git a/lib/build/recipe/jwt/utils.d.ts b/lib/build/recipe/jwt/utils.d.ts index 133d4840f..4025b1b44 100644 --- a/lib/build/recipe/jwt/utils.d.ts +++ b/lib/build/recipe/jwt/utils.d.ts @@ -2,4 +2,8 @@ import { NormalisedAppinfo } from "../../types"; import Recipe from "./recipe"; import { TypeInput, TypeNormalisedInput } from "./types"; -export declare function validateAndNormaliseUserInput(_: Recipe, __: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + _: Recipe, + __: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; diff --git a/lib/build/recipe/jwt/utils.js b/lib/build/recipe/jwt/utils.js index 5a9f692d5..6e66017a3 100644 --- a/lib/build/recipe/jwt/utils.js +++ b/lib/build/recipe/jwt/utils.js @@ -17,9 +17,18 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; function validateAndNormaliseUserInput(_, __, config) { var _a; - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { - jwtValiditySeconds: (_a = config === null || config === void 0 ? void 0 : config.jwtValiditySeconds) !== null && _a !== void 0 ? _a : 3153600000, + jwtValiditySeconds: + (_a = config === null || config === void 0 ? void 0 : config.jwtValiditySeconds) !== null && _a !== void 0 + ? _a + : 3153600000, override, }; } diff --git a/lib/build/recipe/multifactorauth/api/implementation.js b/lib/build/recipe/multifactorauth/api/implementation.js index ddc0dd268..b8d98d5d5 100644 --- a/lib/build/recipe/multifactorauth/api/implementation.js +++ b/lib/build/recipe/multifactorauth/api/implementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIInterface; const multiFactorAuthClaim_1 = require("../multiFactorAuthClaim"); @@ -64,19 +66,29 @@ function getAPIInterface() { userContext, }); factorsAllowedToSetup.push(id); - } - catch (err) { + } catch (err) { if (!(error_1.default.isErrorFromSuperTokens(err) && err.type === error_1.default.INVALID_CLAIMS)) { throw err; } // ignore claims error and not add to the list of factors allowed to be set up } } - const nextSetOfUnsatisfiedFactors = multiFactorAuthClaim_1.MultiFactorAuthClaim.getNextSetOfUnsatisfiedFactors(mfaInfo.completedFactors, mfaInfo.mfaRequirementsForAuth); - let getEmailsForFactorsResult = options.recipeInstance.getEmailsForFactors(sessionUser, session.getRecipeUserId(userContext)); - let getPhoneNumbersForFactorsResult = options.recipeInstance.getPhoneNumbersForFactors(sessionUser, session.getRecipeUserId(userContext)); - if (getEmailsForFactorsResult.status === "UNKNOWN_SESSION_RECIPE_USER_ID" || - getPhoneNumbersForFactorsResult.status === "UNKNOWN_SESSION_RECIPE_USER_ID") { + const nextSetOfUnsatisfiedFactors = multiFactorAuthClaim_1.MultiFactorAuthClaim.getNextSetOfUnsatisfiedFactors( + mfaInfo.completedFactors, + mfaInfo.mfaRequirementsForAuth + ); + let getEmailsForFactorsResult = options.recipeInstance.getEmailsForFactors( + sessionUser, + session.getRecipeUserId(userContext) + ); + let getPhoneNumbersForFactorsResult = options.recipeInstance.getPhoneNumbersForFactors( + sessionUser, + session.getRecipeUserId(userContext) + ); + if ( + getEmailsForFactorsResult.status === "UNKNOWN_SESSION_RECIPE_USER_ID" || + getPhoneNumbersForFactorsResult.status === "UNKNOWN_SESSION_RECIPE_USER_ID" + ) { throw new error_1.default({ type: "UNAUTHORISED", message: "User no longer associated with the session", @@ -88,9 +100,15 @@ function getAPIInterface() { // where user has already setup a factor and not completed it, none of the factors will be allowed to // be setup, and that that will result in an empty next array. However, we want to show the factor // that the user has already setup in that case. - const next = nextSetOfUnsatisfiedFactors.factorIds.filter((factorId) => factorsAllowedToSetup.includes(factorId) || factorsSetUpForUser.includes(factorId)); + const next = nextSetOfUnsatisfiedFactors.factorIds.filter( + (factorId) => factorsAllowedToSetup.includes(factorId) || factorsSetUpForUser.includes(factorId) + ); if (next.length === 0 && nextSetOfUnsatisfiedFactors.factorIds.length !== 0) { - throw new Error(`The user is required to complete secondary factors they are not allowed to (${nextSetOfUnsatisfiedFactors.factorIds.join(", ")}), likely because of configuration issues.`); + throw new Error( + `The user is required to complete secondary factors they are not allowed to (${nextSetOfUnsatisfiedFactors.factorIds.join( + ", " + )}), likely because of configuration issues.` + ); } return { status: "OK", diff --git a/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.d.ts b/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.d.ts index 9e9fa464c..081461387 100644 --- a/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.d.ts +++ b/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function resyncSessionAndFetchMFAInfo(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function resyncSessionAndFetchMFAInfo( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.js b/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.js index 53f5b9234..594f2ac70 100644 --- a/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.js +++ b/lib/build/recipe/multifactorauth/api/resyncSessionAndFetchMFAInfo.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = resyncSessionAndFetchMFAInfo; const utils_1 = require("../../../utils"); @@ -24,7 +26,12 @@ async function resyncSessionAndFetchMFAInfo(apiImplementation, options, userCont if (apiImplementation.resyncSessionAndFetchMFAInfoPUT === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [], sessionRequired: true }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [], sessionRequired: true }, + userContext + ); let response = await apiImplementation.resyncSessionAndFetchMFAInfoPUT({ options, session, diff --git a/lib/build/recipe/multifactorauth/index.d.ts b/lib/build/recipe/multifactorauth/index.d.ts index e10dd4799..b62940921 100644 --- a/lib/build/recipe/multifactorauth/index.d.ts +++ b/lib/build/recipe/multifactorauth/index.d.ts @@ -16,13 +16,32 @@ export default class Wrapper { THIRDPARTY: string; TOTP: string; }; - static assertAllowedToSetupFactorElseThrowInvalidClaimError(session: SessionContainerInterface, factorId: string, userContext?: Record): Promise; - static getMFARequirementsForAuth(session: SessionContainerInterface, userContext?: Record): Promise; - static markFactorAsCompleteInSession(session: SessionContainerInterface, factorId: string, userContext?: Record): Promise; + static assertAllowedToSetupFactorElseThrowInvalidClaimError( + session: SessionContainerInterface, + factorId: string, + userContext?: Record + ): Promise; + static getMFARequirementsForAuth( + session: SessionContainerInterface, + userContext?: Record + ): Promise; + static markFactorAsCompleteInSession( + session: SessionContainerInterface, + factorId: string, + userContext?: Record + ): Promise; static getFactorsSetupForUser(userId: string, userContext?: Record): Promise; static getRequiredSecondaryFactorsForUser(userId: string, userContext?: Record): Promise; - static addToRequiredSecondaryFactorsForUser(userId: string, factorId: string, userContext?: Record): Promise; - static removeFromRequiredSecondaryFactorsForUser(userId: string, factorId: string, userContext?: Record): Promise; + static addToRequiredSecondaryFactorsForUser( + userId: string, + factorId: string, + userContext?: Record + ): Promise; + static removeFromRequiredSecondaryFactorsForUser( + userId: string, + factorId: string, + userContext?: Record + ): Promise; } export declare let init: typeof Recipe.init; export declare let assertAllowedToSetupFactorElseThrowInvalidClaimError: typeof Wrapper.assertAllowedToSetupFactorElseThrowInvalidClaimError; diff --git a/lib/build/recipe/multifactorauth/index.js b/lib/build/recipe/multifactorauth/index.js index 3dbf1d2d1..c2fbc0843 100644 --- a/lib/build/recipe/multifactorauth/index.js +++ b/lib/build/recipe/multifactorauth/index.js @@ -13,19 +13,31 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FactorIds = exports.MultiFactorAuthClaim = exports.removeFromRequiredSecondaryFactorsForUser = exports.addToRequiredSecondaryFactorsForUser = exports.getMFARequirementsForAuth = exports.getRequiredSecondaryFactorsForUser = exports.getFactorsSetupForUser = exports.markFactorAsCompleteInSession = exports.assertAllowedToSetupFactorElseThrowInvalidClaimError = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); const multiFactorAuthClaim_1 = require("./multiFactorAuthClaim"); -Object.defineProperty(exports, "MultiFactorAuthClaim", { enumerable: true, get: function () { return multiFactorAuthClaim_1.MultiFactorAuthClaim; } }); +Object.defineProperty(exports, "MultiFactorAuthClaim", { + enumerable: true, + get: function () { + return multiFactorAuthClaim_1.MultiFactorAuthClaim; + }, +}); const __1 = require("../.."); const utils_1 = require("../../utils"); const utils_2 = require("./utils"); const types_1 = require("./types"); -Object.defineProperty(exports, "FactorIds", { enumerable: true, get: function () { return types_1.FactorIds; } }); +Object.defineProperty(exports, "FactorIds", { + enumerable: true, + get: function () { + return types_1.FactorIds; + }, +}); class Wrapper { static async assertAllowedToSetupFactorElseThrowInvalidClaimError(session, factorId, userContext) { let ctx = (0, utils_1.getUserContext)(userContext); @@ -34,17 +46,19 @@ class Wrapper { userContext: ctx, }); const factorsSetUpForUser = await Wrapper.getFactorsSetupForUser(session.getUserId(), ctx); - await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.assertAllowedToSetupFactorElseThrowInvalidClaimError({ - session, - factorId, - get factorsSetUpForUser() { - return Promise.resolve(factorsSetUpForUser); - }, - get mfaRequirementsForAuth() { - return Promise.resolve(mfaInfo.mfaRequirementsForAuth); - }, - userContext: ctx, - }); + await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.assertAllowedToSetupFactorElseThrowInvalidClaimError({ + session, + factorId, + get factorsSetUpForUser() { + return Promise.resolve(factorsSetUpForUser); + }, + get mfaRequirementsForAuth() { + return Promise.resolve(mfaInfo.mfaRequirementsForAuth); + }, + userContext: ctx, + }); } static async getMFARequirementsForAuth(session, userContext) { let ctx = (0, utils_1.getUserContext)(userContext); @@ -98,7 +112,8 @@ Wrapper.MultiFactorAuthClaim = multiFactorAuthClaim_1.MultiFactorAuthClaim; Wrapper.FactorIds = types_1.FactorIds; exports.default = Wrapper; exports.init = Wrapper.init; -exports.assertAllowedToSetupFactorElseThrowInvalidClaimError = Wrapper.assertAllowedToSetupFactorElseThrowInvalidClaimError; +exports.assertAllowedToSetupFactorElseThrowInvalidClaimError = + Wrapper.assertAllowedToSetupFactorElseThrowInvalidClaimError; exports.markFactorAsCompleteInSession = Wrapper.markFactorAsCompleteInSession; exports.getFactorsSetupForUser = Wrapper.getFactorsSetupForUser; exports.getRequiredSecondaryFactorsForUser = Wrapper.getRequiredSecondaryFactorsForUser; diff --git a/lib/build/recipe/multifactorauth/multiFactorAuthClaim.d.ts b/lib/build/recipe/multifactorauth/multiFactorAuthClaim.d.ts index ff964c9f0..07976ada7 100644 --- a/lib/build/recipe/multifactorauth/multiFactorAuthClaim.d.ts +++ b/lib/build/recipe/multifactorauth/multiFactorAuthClaim.d.ts @@ -14,26 +14,50 @@ export declare class MultiFactorAuthClaimClass extends SessionClaim SessionClaimValidator; hasCompletedRequirementList(requirementList: MFARequirementList, id?: string): SessionClaimValidator; }; - getNextSetOfUnsatisfiedFactors(completedFactors: MFAClaimValue["c"], requirementList: MFARequirementList): { + getNextSetOfUnsatisfiedFactors( + completedFactors: MFAClaimValue["c"], + requirementList: MFARequirementList + ): { factorIds: string[]; type: "string" | "oneOf" | "allOfInAnyOrder"; }; - fetchValue: (_userId: string, recipeUserId: RecipeUserId, tenantId: string, currentPayload: JSONObject | undefined, userContext: UserContext) => Promise<{ + fetchValue: ( + _userId: string, + recipeUserId: RecipeUserId, + tenantId: string, + currentPayload: JSONObject | undefined, + userContext: UserContext + ) => Promise<{ c: Record; v: boolean; }>; - addToPayload_internal: (payload: JSONObject, value: MFAClaimValue) => { - [x: string]: string | number | boolean | JSONObject | import("../../types").JSONArray | { - c: { - [x: string]: number | undefined; - }; - v: boolean; - } | null | undefined; + addToPayload_internal: ( + payload: JSONObject, + value: MFAClaimValue + ) => { + [x: string]: + | string + | number + | boolean + | JSONObject + | import("../../types").JSONArray + | { + c: { + [x: string]: number | undefined; + }; + v: boolean; + } + | null + | undefined; }; - removeFromPayload: (payload: JSONObject) => { + removeFromPayload: ( + payload: JSONObject + ) => { [x: string]: import("../../types").JSONValue; }; - removeFromPayloadByMerge_internal: (payload: JSONObject) => { + removeFromPayloadByMerge_internal: ( + payload: JSONObject + ) => { [x: string]: import("../../types").JSONValue; }; getValueFromPayload: (payload: JSONObject) => MFAClaimValue; diff --git a/lib/build/recipe/multifactorauth/multiFactorAuthClaim.js b/lib/build/recipe/multifactorauth/multiFactorAuthClaim.js index 0237d438f..0fb1b6eab 100644 --- a/lib/build/recipe/multifactorauth/multiFactorAuthClaim.js +++ b/lib/build/recipe/multifactorauth/multiFactorAuthClaim.js @@ -38,10 +38,15 @@ class MultiFactorAuthClaimClass extends claims_1.SessionClaim { }; this.addToPayload_internal = (payload, value) => { const prevValue = payload[this.key]; - return Object.assign(Object.assign({}, payload), { [this.key]: { - c: Object.assign(Object.assign({}, prevValue === null || prevValue === void 0 ? void 0 : prevValue.c), value.c), + return Object.assign(Object.assign({}, payload), { + [this.key]: { + c: Object.assign( + Object.assign({}, prevValue === null || prevValue === void 0 ? void 0 : prevValue.c), + value.c + ), v: value.v, - } }); + }, + }); }; this.removeFromPayload = (payload) => { const retVal = Object.assign({}, payload); @@ -70,11 +75,12 @@ class MultiFactorAuthClaimClass extends claims_1.SessionClaim { const { v } = claimVal; return { isValid: v, - reason: v === false - ? { - message: "MFA requirement for auth is not satisfied", - } - : undefined, + reason: + v === false + ? { + message: "MFA requirement for auth is not satisfied", + } + : undefined, }; }, }), @@ -96,7 +102,10 @@ class MultiFactorAuthClaimClass extends claims_1.SessionClaim { throw new Error("This should never happen, claim value not present in payload"); } const { c: completedFactors } = claimVal; - const nextSetOfUnsatisfiedFactors = this.getNextSetOfUnsatisfiedFactors(completedFactors, requirementList); + const nextSetOfUnsatisfiedFactors = this.getNextSetOfUnsatisfiedFactors( + completedFactors, + requirementList + ); if (nextSetOfUnsatisfiedFactors.factorIds.length === 0) { // No item in the requirementList is left unsatisfied, hence is Valid return { @@ -107,28 +116,29 @@ class MultiFactorAuthClaimClass extends claims_1.SessionClaim { return { isValid: false, reason: { - message: "Factor validation failed: " + + message: + "Factor validation failed: " + nextSetOfUnsatisfiedFactors.factorIds[0] + " not completed", factorId: nextSetOfUnsatisfiedFactors.factorIds[0], }, }; - } - else if (nextSetOfUnsatisfiedFactors.type === "oneOf") { + } else if (nextSetOfUnsatisfiedFactors.type === "oneOf") { return { isValid: false, reason: { - message: "None of these factors are complete in the session: " + + message: + "None of these factors are complete in the session: " + nextSetOfUnsatisfiedFactors.factorIds.join(", "), oneOf: nextSetOfUnsatisfiedFactors.factorIds, }, }; - } - else { + } else { return { isValid: false, reason: { - message: "Some of the factors are not complete in the session: " + + message: + "Some of the factors are not complete in the session: " + nextSetOfUnsatisfiedFactors.factorIds.join(", "), allOfInAnyOrder: nextSetOfUnsatisfiedFactors.factorIds, }, @@ -153,8 +163,7 @@ class MultiFactorAuthClaimClass extends claims_1.SessionClaim { type = "string"; nextFactors.add(req); } - } - else if ("oneOf" in req) { + } else if ("oneOf" in req) { let satisfied = false; for (const factorId of req.oneOf) { if (completedFactors[factorId] !== undefined) { @@ -167,8 +176,7 @@ class MultiFactorAuthClaimClass extends claims_1.SessionClaim { nextFactors.add(factorId); } } - } - else if ("allOfInAnyOrder" in req) { + } else if ("allOfInAnyOrder" in req) { for (const factorId of req.allOfInAnyOrder) { type = "allOfInAnyOrder"; if (completedFactors[factorId] === undefined) { diff --git a/lib/build/recipe/multifactorauth/recipe.d.ts b/lib/build/recipe/multifactorauth/recipe.d.ts index 1f40a800a..b8661a8a7 100644 --- a/lib/build/recipe/multifactorauth/recipe.d.ts +++ b/lib/build/recipe/multifactorauth/recipe.d.ts @@ -4,7 +4,16 @@ import NormalisedURLPath from "../../normalisedURLPath"; import RecipeModule from "../../recipeModule"; import STError from "../../error"; import { APIHandled, HTTPMethod, NormalisedAppinfo, RecipeListFunction, UserContext } from "../../types"; -import { APIInterface, GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc, GetEmailsForFactorFromOtherRecipesFunc, GetFactorsSetupForUserFromOtherRecipesFunc, GetPhoneNumbersForFactorsFromOtherRecipesFunc, RecipeInterface, TypeInput, TypeNormalisedInput } from "./types"; +import { + APIInterface, + GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc, + GetEmailsForFactorFromOtherRecipesFunc, + GetFactorsSetupForUserFromOtherRecipesFunc, + GetPhoneNumbersForFactorsFromOtherRecipesFunc, + RecipeInterface, + TypeInput, + TypeNormalisedInput, +} from "./types"; import { User } from "../../user"; import RecipeUserId from "../../recipeUserId"; import { Querier } from "../../querier"; @@ -28,25 +37,45 @@ export default class Recipe extends RecipeModule { static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, _tenantId: string, req: BaseRequest, res: BaseResponse, _: NormalisedURLPath, __: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + _tenantId: string, + req: BaseRequest, + res: BaseResponse, + _: NormalisedURLPath, + __: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: STError, _: BaseRequest, __: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; - addFuncToGetAllAvailableSecondaryFactorIdsFromOtherRecipes: (f: GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc) => void; + addFuncToGetAllAvailableSecondaryFactorIdsFromOtherRecipes: ( + f: GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc + ) => void; getAllAvailableSecondaryFactorIds: (tenantConfig: TenantConfig) => string[]; addFuncToGetFactorsSetupForUserFromOtherRecipes: (func: GetFactorsSetupForUserFromOtherRecipesFunc) => void; addFuncToGetEmailsForFactorFromOtherRecipes: (func: GetEmailsForFactorFromOtherRecipesFunc) => void; - getEmailsForFactors: (user: User, sessionRecipeUserId: RecipeUserId) => { - status: "OK"; - factorIdToEmailsMap: Record; - } | { - status: "UNKNOWN_SESSION_RECIPE_USER_ID"; - }; + getEmailsForFactors: ( + user: User, + sessionRecipeUserId: RecipeUserId + ) => + | { + status: "OK"; + factorIdToEmailsMap: Record; + } + | { + status: "UNKNOWN_SESSION_RECIPE_USER_ID"; + }; addFuncToGetPhoneNumbersForFactorsFromOtherRecipes: (func: GetPhoneNumbersForFactorsFromOtherRecipesFunc) => void; - getPhoneNumbersForFactors: (user: User, sessionRecipeUserId: RecipeUserId) => { - status: "OK"; - factorIdToPhoneNumberMap: Record; - } | { - status: "UNKNOWN_SESSION_RECIPE_USER_ID"; - }; + getPhoneNumbersForFactors: ( + user: User, + sessionRecipeUserId: RecipeUserId + ) => + | { + status: "OK"; + factorIdToPhoneNumberMap: Record; + } + | { + status: "UNKNOWN_SESSION_RECIPE_USER_ID"; + }; } diff --git a/lib/build/recipe/multifactorauth/recipe.js b/lib/build/recipe/multifactorauth/recipe.js index c071e3992..444652fef 100644 --- a/lib/build/recipe/multifactorauth/recipe.js +++ b/lib/build/recipe/multifactorauth/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -46,7 +48,9 @@ class Recipe extends recipeModule_1.default { return [ { method: "put", - pathWithoutApiBasePath: new normalisedURLPath_1.default(constants_1.RESYNC_SESSION_AND_FETCH_MFA_INFO), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + constants_1.RESYNC_SESSION_AND_FETCH_MFA_INFO + ), id: constants_1.RESYNC_SESSION_AND_FETCH_MFA_INFO, disabled: this.apiImpl.resyncSessionAndFetchMFAInfoPUT === undefined, }, @@ -109,7 +113,10 @@ class Recipe extends recipeModule_1.default { status: "UNKNOWN_SESSION_RECIPE_USER_ID", }; } - result.factorIdToEmailsMap = Object.assign(Object.assign({}, result.factorIdToEmailsMap), funcResult.factorIdToEmailsMap); + result.factorIdToEmailsMap = Object.assign( + Object.assign({}, result.factorIdToEmailsMap), + funcResult.factorIdToEmailsMap + ); } return result; }; @@ -128,7 +135,10 @@ class Recipe extends recipeModule_1.default { status: "UNKNOWN_SESSION_RECIPE_USER_ID", }; } - result.factorIdToPhoneNumberMap = Object.assign(Object.assign({}, result.factorIdToPhoneNumberMap), funcResult.factorIdToPhoneNumberMap); + result.factorIdToPhoneNumberMap = Object.assign( + Object.assign({}, result.factorIdToPhoneNumberMap), + funcResult.factorIdToPhoneNumberMap + ); } return result; }; @@ -138,7 +148,11 @@ class Recipe extends recipeModule_1.default { let originalImpl = (0, recipeImplementation_1.default)(this); let builder = new supertokens_js_override_1.default(originalImpl); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); - if (((_a = config === null || config === void 0 ? void 0 : config.override) === null || _a === void 0 ? void 0 : _a.functions) !== undefined) { + if ( + ((_a = config === null || config === void 0 ? void 0 : config.override) === null || _a === void 0 + ? void 0 + : _a.functions) !== undefined + ) { this.isGetMfaRequirementsForAuthOverridden = true; // assuming that's what most people will override } } @@ -154,7 +168,11 @@ class Recipe extends recipeModule_1.default { // We don't add MultiFactorAuthClaim as a global claim because the values are populated // on factor setup / completion any way (in the sign in / up APIs). // SessionRecipe.getInstanceOrThrowError().addClaimFromOtherRecipe(MultiFactorAuthClaim); - recipe_1.default.getInstanceOrThrowError().addClaimValidatorFromOtherRecipe(multiFactorAuthClaim_1.MultiFactorAuthClaim.validators.hasCompletedMFARequirementsForAuth()); + recipe_1.default + .getInstanceOrThrowError() + .addClaimValidatorFromOtherRecipe( + multiFactorAuthClaim_1.MultiFactorAuthClaim.validators.hasCompletedMFARequirementsForAuth() + ); }); this.querier = querier_1.Querier.getNewInstanceOrThrowError(recipeId); } @@ -170,11 +188,21 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return Recipe.instance; - } - else { - throw new Error("MultiFactorAuth recipe has already been initialised. Please check your code for bugs."); + } else { + throw new Error( + "MultiFactorAuth recipe has already been initialised. Please check your code for bugs." + ); } }; } diff --git a/lib/build/recipe/multifactorauth/recipeImplementation.js b/lib/build/recipe/multifactorauth/recipeImplementation.js index e64ac0d26..d4db1be38 100644 --- a/lib/build/recipe/multifactorauth/recipeImplementation.js +++ b/lib/build/recipe/multifactorauth/recipeImplementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const usermetadata_1 = __importDefault(require("../usermetadata")); @@ -44,7 +46,10 @@ function getRecipeInterface(recipeInstance) { } return factorIds; }, - getMFARequirementsForAuth: async function ({ requiredSecondaryFactorsForUser, requiredSecondaryFactorsForTenant, }) { + getMFARequirementsForAuth: async function ({ + requiredSecondaryFactorsForUser, + requiredSecondaryFactorsForTenant, + }) { // default requirements for Auth is the union of required factors for user and tenant // https://github.com/supertokens/supertokens-core/issues/554#issuecomment-1752852720 const allFactors = new Set(); @@ -79,32 +84,57 @@ function getRecipeInterface(recipeInstance) { throw new Error("should never happen"); } if (claimVal.v) { - (0, logger_1.logDebugMessage)(`assertAllowedToSetupFactorElseThrowInvalidClaimError ${input.factorId}: true because the session already satisfied auth reqs`); + (0, logger_1.logDebugMessage)( + `assertAllowedToSetupFactorElseThrowInvalidClaimError ${input.factorId}: true because the session already satisfied auth reqs` + ); return { isValid: true }; } - const setOfUnsatisfiedFactors = multiFactorAuthClaim_1.MultiFactorAuthClaim.getNextSetOfUnsatisfiedFactors(claimVal.c, await input.mfaRequirementsForAuth); + const setOfUnsatisfiedFactors = multiFactorAuthClaim_1.MultiFactorAuthClaim.getNextSetOfUnsatisfiedFactors( + claimVal.c, + await input.mfaRequirementsForAuth + ); const factorsSetUpForUserRes = await input.factorsSetUpForUser; if (setOfUnsatisfiedFactors.factorIds.some((id) => factorsSetUpForUserRes.includes(id))) { - (0, logger_1.logDebugMessage)(`assertAllowedToSetupFactorElseThrowInvalidClaimError ${input.factorId}: false because there are items already set up in the next set of unsatisfied factors: ${setOfUnsatisfiedFactors.factorIds.join(", ")}`); + (0, logger_1.logDebugMessage)( + `assertAllowedToSetupFactorElseThrowInvalidClaimError ${ + input.factorId + }: false because there are items already set up in the next set of unsatisfied factors: ${setOfUnsatisfiedFactors.factorIds.join( + ", " + )}` + ); return { isValid: false, reason: "Completed factors in the session does not satisfy the MFA requirements for auth", }; } - if (setOfUnsatisfiedFactors.factorIds.length > 0 && - !setOfUnsatisfiedFactors.factorIds.includes(input.factorId)) { + if ( + setOfUnsatisfiedFactors.factorIds.length > 0 && + !setOfUnsatisfiedFactors.factorIds.includes(input.factorId) + ) { // It can be a security issue if we don't do this check // Consider this case: // Requirements: [{oneOf: ["totp", "otp-email"]}, "otp-phone"] (this is what I call the lower sms costs case) // The user has setup otp-phone previously, but no totp or email // During sign-in, they'd be allowed to add a new phone number, then set up TOTP and complete sign-in, completely bypassing the old phone number. - (0, logger_1.logDebugMessage)(`assertAllowedToSetupFactorElseThrowInvalidClaimError ${input.factorId}: false because user is trying to set up factor that is not in the next set of unsatisfied factors: ${setOfUnsatisfiedFactors.factorIds.join(", ")}`); + (0, logger_1.logDebugMessage)( + `assertAllowedToSetupFactorElseThrowInvalidClaimError ${ + input.factorId + }: false because user is trying to set up factor that is not in the next set of unsatisfied factors: ${setOfUnsatisfiedFactors.factorIds.join( + ", " + )}` + ); return { isValid: false, reason: "Not allowed to setup factor that is not in the next set of unsatisfied factors", }; } - (0, logger_1.logDebugMessage)(`assertAllowedToSetupFactorElseThrowInvalidClaimError ${input.factorId}: true because the next set of unsatisfied factors is ${setOfUnsatisfiedFactors.factorIds.length === 0 ? "empty" : "cannot be completed otherwise"}`); + (0, logger_1.logDebugMessage)( + `assertAllowedToSetupFactorElseThrowInvalidClaimError ${ + input.factorId + }: true because the next set of unsatisfied factors is ${ + setOfUnsatisfiedFactors.factorIds.length === 0 ? "empty" : "cannot be completed otherwise" + }` + ); return { isValid: true }; }, }; @@ -120,31 +150,55 @@ function getRecipeInterface(recipeInstance) { getRequiredSecondaryFactorsForUser: async function ({ userId, userContext }) { var _a, _b; const metadata = await usermetadata_1.default.getUserMetadata(userId, userContext); - return (_b = (_a = metadata.metadata._supertokens) === null || _a === void 0 ? void 0 : _a.requiredSecondaryFactors) !== null && _b !== void 0 ? _b : []; + return (_b = + (_a = metadata.metadata._supertokens) === null || _a === void 0 + ? void 0 + : _a.requiredSecondaryFactors) !== null && _b !== void 0 + ? _b + : []; }, addToRequiredSecondaryFactorsForUser: async function ({ userId, factorId, userContext }) { var _a, _b; const metadata = await usermetadata_1.default.getUserMetadata(userId, userContext); - const factorIds = (_b = (_a = metadata.metadata._supertokens) === null || _a === void 0 ? void 0 : _a.requiredSecondaryFactors) !== null && _b !== void 0 ? _b : []; + const factorIds = + (_b = + (_a = metadata.metadata._supertokens) === null || _a === void 0 + ? void 0 + : _a.requiredSecondaryFactors) !== null && _b !== void 0 + ? _b + : []; if (factorIds.includes(factorId)) { return; } factorIds.push(factorId); - const metadataUpdate = Object.assign(Object.assign({}, metadata.metadata), { _supertokens: Object.assign(Object.assign({}, metadata.metadata._supertokens), { requiredSecondaryFactors: factorIds }) }); + const metadataUpdate = Object.assign(Object.assign({}, metadata.metadata), { + _supertokens: Object.assign(Object.assign({}, metadata.metadata._supertokens), { + requiredSecondaryFactors: factorIds, + }), + }); await usermetadata_1.default.updateUserMetadata(userId, metadataUpdate, userContext); }, removeFromRequiredSecondaryFactorsForUser: async function ({ userId, factorId, userContext }) { var _a, _b; const metadata = await usermetadata_1.default.getUserMetadata(userId, userContext); - if (((_a = metadata.metadata._supertokens) === null || _a === void 0 ? void 0 : _a.requiredSecondaryFactors) === undefined) { + if ( + ((_a = metadata.metadata._supertokens) === null || _a === void 0 + ? void 0 + : _a.requiredSecondaryFactors) === undefined + ) { return; } - let factorIds = (_b = metadata.metadata._supertokens.requiredSecondaryFactors) !== null && _b !== void 0 ? _b : []; + let factorIds = + (_b = metadata.metadata._supertokens.requiredSecondaryFactors) !== null && _b !== void 0 ? _b : []; if (!factorIds.includes(factorId)) { return; } factorIds = factorIds.filter((id) => id !== factorId); - const metadataUpdate = Object.assign(Object.assign({}, metadata.metadata), { _supertokens: Object.assign(Object.assign({}, metadata.metadata._supertokens), { requiredSecondaryFactors: factorIds }) }); + const metadataUpdate = Object.assign(Object.assign({}, metadata.metadata), { + _supertokens: Object.assign(Object.assign({}, metadata.metadata._supertokens), { + requiredSecondaryFactors: factorIds, + }), + }); await usermetadata_1.default.updateUserMetadata(userId, metadataUpdate, userContext); }, }; diff --git a/lib/build/recipe/multifactorauth/types.d.ts b/lib/build/recipe/multifactorauth/types.d.ts index 9b77ea0c7..d29042556 100644 --- a/lib/build/recipe/multifactorauth/types.d.ts +++ b/lib/build/recipe/multifactorauth/types.d.ts @@ -8,11 +8,15 @@ import { SessionContainerInterface } from "../session/types"; import Recipe from "./recipe"; import { TenantConfig } from "../multitenancy/types"; import RecipeUserId from "../../recipeUserId"; -export type MFARequirementList = ({ - oneOf: string[]; -} | { - allOfInAnyOrder: string[]; -} | string)[]; +export type MFARequirementList = ( + | { + oneOf: string[]; + } + | { + allOfInAnyOrder: string[]; + } + | string +)[]; export type MFAClaimValue = { c: Record; v: boolean; @@ -20,14 +24,20 @@ export type MFAClaimValue = { export type TypeInput = { firstFactors?: string[]; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { firstFactors?: string[]; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -54,14 +64,8 @@ export type RecipeInterface = { factorId: string; userContext: UserContext; }) => Promise; - getFactorsSetupForUser: (input: { - user: User; - userContext: UserContext; - }) => Promise; - getRequiredSecondaryFactorsForUser: (input: { - userId: string; - userContext: UserContext; - }) => Promise; + getFactorsSetupForUser: (input: { user: User; userContext: UserContext }) => Promise; + getRequiredSecondaryFactorsForUser: (input: { userId: string; userContext: UserContext }) => Promise; addToRequiredSecondaryFactorsForUser: (input: { userId: string; factorId: string; @@ -83,35 +87,50 @@ export type APIOptions = { res: BaseResponse; }; export type APIInterface = { - resyncSessionAndFetchMFAInfoPUT: undefined | ((input: { - options: APIOptions; - session: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - factors: { - next: string[]; - alreadySetup: string[]; - allowedToSetup: string[]; - }; - emails: Record; - phoneNumbers: Record; - } | GeneralErrorResponse>); + resyncSessionAndFetchMFAInfoPUT: + | undefined + | ((input: { + options: APIOptions; + session: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + factors: { + next: string[]; + alreadySetup: string[]; + allowedToSetup: string[]; + }; + emails: Record; + phoneNumbers: Record; + } + | GeneralErrorResponse + >); }; export type GetFactorsSetupForUserFromOtherRecipesFunc = (user: User, userContext: UserContext) => Promise; export type GetAllAvailableSecondaryFactorIdsFromOtherRecipesFunc = (tenantConfig: TenantConfig) => string[]; -export type GetEmailsForFactorFromOtherRecipesFunc = (user: User, sessionRecipeUserId: RecipeUserId) => { - status: "OK"; - factorIdToEmailsMap: Record; -} | { - status: "UNKNOWN_SESSION_RECIPE_USER_ID"; -}; -export type GetPhoneNumbersForFactorsFromOtherRecipesFunc = (user: User, sessionRecipeUserId: RecipeUserId) => { - status: "OK"; - factorIdToPhoneNumberMap: Record; -} | { - status: "UNKNOWN_SESSION_RECIPE_USER_ID"; -}; +export type GetEmailsForFactorFromOtherRecipesFunc = ( + user: User, + sessionRecipeUserId: RecipeUserId +) => + | { + status: "OK"; + factorIdToEmailsMap: Record; + } + | { + status: "UNKNOWN_SESSION_RECIPE_USER_ID"; + }; +export type GetPhoneNumbersForFactorsFromOtherRecipesFunc = ( + user: User, + sessionRecipeUserId: RecipeUserId +) => + | { + status: "OK"; + factorIdToPhoneNumberMap: Record; + } + | { + status: "UNKNOWN_SESSION_RECIPE_USER_ID"; + }; export declare const FactorIds: { EMAILPASSWORD: string; OTP_EMAIL: string; diff --git a/lib/build/recipe/multifactorauth/utils.d.ts b/lib/build/recipe/multifactorauth/utils.d.ts index 62de22b62..97f09f4e9 100644 --- a/lib/build/recipe/multifactorauth/utils.d.ts +++ b/lib/build/recipe/multifactorauth/utils.d.ts @@ -4,16 +4,21 @@ import { UserContext } from "../../types"; import { SessionContainerInterface } from "../session/types"; import { RecipeUserId } from "../.."; export declare function validateAndNormaliseUserInput(config?: TypeInput): TypeNormalisedInput; -export declare const updateAndGetMFARelatedInfoInSession: (input: ({ - sessionRecipeUserId: RecipeUserId; - tenantId: string; - accessTokenPayload: any; -} | { - session: SessionContainerInterface; -}) & { - updatedFactorId?: string; - userContext: UserContext; -}) => Promise<{ +export declare const updateAndGetMFARelatedInfoInSession: ( + input: ( + | { + sessionRecipeUserId: RecipeUserId; + tenantId: string; + accessTokenPayload: any; + } + | { + session: SessionContainerInterface; + } + ) & { + updatedFactorId?: string; + userContext: UserContext; + } +) => Promise<{ completedFactors: MFAClaimValue["c"]; mfaRequirementsForAuth: MFARequirementList; isMFARequirementsForAuthSatisfied: boolean; diff --git a/lib/build/recipe/multifactorauth/utils.js b/lib/build/recipe/multifactorauth/utils.js index 0a65409af..9586be8fe 100644 --- a/lib/build/recipe/multifactorauth/utils.js +++ b/lib/build/recipe/multifactorauth/utils.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.updateAndGetMFARelatedInfoInSession = void 0; exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; @@ -28,10 +30,19 @@ const error_1 = __importDefault(require("../session/error")); const types_1 = require("./types"); const utils_1 = require("../multitenancy/utils"); function validateAndNormaliseUserInput(config) { - if ((config === null || config === void 0 ? void 0 : config.firstFactors) !== undefined && (config === null || config === void 0 ? void 0 : config.firstFactors.length) === 0) { + if ( + (config === null || config === void 0 ? void 0 : config.firstFactors) !== undefined && + (config === null || config === void 0 ? void 0 : config.firstFactors.length) === 0 + ) { throw new Error("'firstFactors' can be either undefined or a non-empty array"); } - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { firstFactors: config === null || config === void 0 ? void 0 : config.firstFactors, override, @@ -48,8 +59,7 @@ const updateAndGetMFARelatedInfoInSession = async function (input) { tenantId = input.session.getTenantId(input.userContext); accessTokenPayload = input.session.getAccessTokenPayload(input.userContext); sessionHandle = input.session.getHandle(input.userContext); - } - else { + } else { sessionRecipeUserId = input.sessionRecipeUserId; tenantId = input.tenantId; accessTokenPayload = input.accessTokenPayload; @@ -66,8 +76,7 @@ const updateAndGetMFARelatedInfoInSession = async function (input) { }, v: true, // updated later in the function }; - } - else { + } else { updatedClaimVal = true; mfaClaimValue.c[input.updatedFactorId] = Math.floor(Date.now() / 1000); } @@ -95,32 +104,36 @@ const updateAndGetMFARelatedInfoInSession = async function (input) { for (const lM of sessionUser.loginMethods) { if (lM.recipeUserId.getAsString() === sessionRecipeUserId.getAsString()) { if (lM.recipeId === "emailpassword") { - let validRes = await (0, utils_1.isValidFirstFactor)(tenantId, types_1.FactorIds.EMAILPASSWORD, input.userContext); + let validRes = await (0, utils_1.isValidFirstFactor)( + tenantId, + types_1.FactorIds.EMAILPASSWORD, + input.userContext + ); if (validRes.status === "TENANT_NOT_FOUND_ERROR") { throw new error_1.default({ type: error_1.default.UNAUTHORISED, message: "Tenant not found", }); - } - else if (validRes.status === "OK") { + } else if (validRes.status === "OK") { computedFirstFactorIdForSession = types_1.FactorIds.EMAILPASSWORD; break; } - } - else if (lM.recipeId === "thirdparty") { - let validRes = await (0, utils_1.isValidFirstFactor)(tenantId, types_1.FactorIds.THIRDPARTY, input.userContext); + } else if (lM.recipeId === "thirdparty") { + let validRes = await (0, utils_1.isValidFirstFactor)( + tenantId, + types_1.FactorIds.THIRDPARTY, + input.userContext + ); if (validRes.status === "TENANT_NOT_FOUND_ERROR") { throw new error_1.default({ type: error_1.default.UNAUTHORISED, message: "Tenant not found", }); - } - else if (validRes.status === "OK") { + } else if (validRes.status === "OK") { computedFirstFactorIdForSession = types_1.FactorIds.THIRDPARTY; break; } - } - else { + } else { let factorsToCheck = []; if (lM.email !== undefined) { factorsToCheck.push(types_1.FactorIds.LINK_EMAIL); @@ -137,8 +150,7 @@ const updateAndGetMFARelatedInfoInSession = async function (input) { type: error_1.default.UNAUTHORISED, message: "Tenant not found", }); - } - else if (validRes.status === "OK") { + } else if (validRes.status === "OK") { computedFirstFactorIdForSession = factorId; break; } @@ -180,55 +192,68 @@ const updateAndGetMFARelatedInfoInSession = async function (input) { }); return userProm; } - const mfaRequirementsForAuth = await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.getMFARequirementsForAuth({ - accessTokenPayload, - tenantId, - get user() { - return userGetter(); - }, - get factorsSetUpForUser() { - return userGetter().then((user) => recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.getFactorsSetupForUser({ - user, - userContext: input.userContext, - })); - }, - get requiredSecondaryFactorsForUser() { - return userGetter().then((sessionUser) => { - if (sessionUser === undefined) { - throw new error_1.default({ - type: error_1.default.UNAUTHORISED, - message: "Session user not found", - }); - } - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.getRequiredSecondaryFactorsForUser({ - userId: sessionUser.id, - userContext: input.userContext, + const mfaRequirementsForAuth = await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.getMFARequirementsForAuth({ + accessTokenPayload, + tenantId, + get user() { + return userGetter(); + }, + get factorsSetUpForUser() { + return userGetter().then((user) => + recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.getFactorsSetupForUser({ + user, + userContext: input.userContext, + }) + ); + }, + get requiredSecondaryFactorsForUser() { + return userGetter().then((sessionUser) => { + if (sessionUser === undefined) { + throw new error_1.default({ + type: error_1.default.UNAUTHORISED, + message: "Session user not found", + }); + } + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.getRequiredSecondaryFactorsForUser({ + userId: sessionUser.id, + userContext: input.userContext, + }); }); - }); - }, - get requiredSecondaryFactorsForTenant() { - return multitenancy_1.default.getTenant(tenantId, input.userContext).then((tenantInfo) => { - var _a; - if (tenantInfo === undefined) { - throw new error_1.default({ - type: error_1.default.UNAUTHORISED, - message: "Tenant not found", - }); - } - return (_a = tenantInfo.requiredSecondaryFactors) !== null && _a !== void 0 ? _a : []; - }); - }, - completedFactors, - userContext: input.userContext, - }); - const areAuthReqsComplete = multiFactorAuthClaim_1.MultiFactorAuthClaim.getNextSetOfUnsatisfiedFactors(completedFactors, mfaRequirementsForAuth).factorIds - .length === 0; + }, + get requiredSecondaryFactorsForTenant() { + return multitenancy_1.default.getTenant(tenantId, input.userContext).then((tenantInfo) => { + var _a; + if (tenantInfo === undefined) { + throw new error_1.default({ + type: error_1.default.UNAUTHORISED, + message: "Tenant not found", + }); + } + return (_a = tenantInfo.requiredSecondaryFactors) !== null && _a !== void 0 ? _a : []; + }); + }, + completedFactors, + userContext: input.userContext, + }); + const areAuthReqsComplete = + multiFactorAuthClaim_1.MultiFactorAuthClaim.getNextSetOfUnsatisfiedFactors( + completedFactors, + mfaRequirementsForAuth + ).factorIds.length === 0; if (mfaClaimValue.v !== areAuthReqsComplete) { updatedClaimVal = true; mfaClaimValue.v = areAuthReqsComplete; } if ("session" in input && updatedClaimVal) { - await input.session.setClaimValue(multiFactorAuthClaim_1.MultiFactorAuthClaim, mfaClaimValue, input.userContext); + await input.session.setClaimValue( + multiFactorAuthClaim_1.MultiFactorAuthClaim, + mfaClaimValue, + input.userContext + ); } return { completedFactors, diff --git a/lib/build/recipe/multitenancy/allowedDomainsClaim.js b/lib/build/recipe/multitenancy/allowedDomainsClaim.js index e3f9f25c1..d679919b5 100644 --- a/lib/build/recipe/multitenancy/allowedDomainsClaim.js +++ b/lib/build/recipe/multitenancy/allowedDomainsClaim.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AllowedDomainsClaim = exports.AllowedDomainsClaimClass = void 0; const claims_1 = require("../session/claims"); diff --git a/lib/build/recipe/multitenancy/api/implementation.js b/lib/build/recipe/multitenancy/api/implementation.js index b715a946f..e352c8bca 100644 --- a/lib/build/recipe/multitenancy/api/implementation.js +++ b/lib/build/recipe/multitenancy/api/implementation.js @@ -16,11 +16,20 @@ function getAPIInterface() { } const providerInputsFromStatic = options.staticThirdPartyProviders; const providerConfigsFromCore = tenantConfigRes.thirdParty.providers; - const mergedProviders = (0, configUtils_1.mergeProvidersFromCoreAndStatic)(providerConfigsFromCore, providerInputsFromStatic, tenantId === constants_1.DEFAULT_TENANT_ID); + const mergedProviders = (0, configUtils_1.mergeProvidersFromCoreAndStatic)( + providerConfigsFromCore, + providerInputsFromStatic, + tenantId === constants_1.DEFAULT_TENANT_ID + ); const finalProviderList = []; for (const providerInput of mergedProviders) { try { - const providerInstance = await (0, configUtils_1.findAndCreateProviderInstance)(mergedProviders, providerInput.config.thirdPartyId, clientType, userContext); + const providerInstance = await (0, configUtils_1.findAndCreateProviderInstance)( + mergedProviders, + providerInput.config.thirdPartyId, + clientType, + userContext + ); if (providerInstance === undefined) { throw new Error("should never come here"); // because creating instance from the merged provider list itself } @@ -28,8 +37,7 @@ function getAPIInterface() { id: providerInstance.id, name: providerInstance.config.name, }); - } - catch (err) { + } catch (err) { if (err.type === "CLIENT_TYPE_NOT_FOUND_ERROR") { continue; } @@ -39,11 +47,9 @@ function getAPIInterface() { let firstFactors; if (tenantConfigRes.firstFactors !== undefined) { firstFactors = tenantConfigRes.firstFactors; // highest priority, config from core - } - else if (options.staticFirstFactors !== undefined) { + } else if (options.staticFirstFactors !== undefined) { firstFactors = options.staticFirstFactors; // next priority, static config - } - else { + } else { // Fallback to all available factors (de-duplicated) firstFactors = Array.from(new Set(options.allAvailableFirstFactors)); } @@ -72,7 +78,8 @@ function getAPIInterface() { providers: finalProviderList, }, passwordless: { - enabled: validFirstFactors.includes("otp-email") || + enabled: + validFirstFactors.includes("otp-email") || validFirstFactors.includes("otp-phone") || validFirstFactors.includes("link-email") || validFirstFactors.includes("link-phone"), diff --git a/lib/build/recipe/multitenancy/api/loginMethods.d.ts b/lib/build/recipe/multitenancy/api/loginMethods.d.ts index a6f390bb6..c497a7557 100644 --- a/lib/build/recipe/multitenancy/api/loginMethods.d.ts +++ b/lib/build/recipe/multitenancy/api/loginMethods.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function loginMethodsAPI(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function loginMethodsAPI( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/multitenancy/error.d.ts b/lib/build/recipe/multitenancy/error.d.ts index d6412505c..486758b61 100644 --- a/lib/build/recipe/multitenancy/error.d.ts +++ b/lib/build/recipe/multitenancy/error.d.ts @@ -1,8 +1,5 @@ // @ts-nocheck import STError from "../../error"; export default class SessionError extends STError { - constructor(options: { - type: "BAD_INPUT_ERROR"; - message: string; - }); + constructor(options: { type: "BAD_INPUT_ERROR"; message: string }); } diff --git a/lib/build/recipe/multitenancy/error.js b/lib/build/recipe/multitenancy/error.js index a0e8daf7f..c6c1f6ccc 100644 --- a/lib/build/recipe/multitenancy/error.js +++ b/lib/build/recipe/multitenancy/error.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); class SessionError extends error_1.default { diff --git a/lib/build/recipe/multitenancy/index.d.ts b/lib/build/recipe/multitenancy/index.d.ts index 543dd643c..6aef31375 100644 --- a/lib/build/recipe/multitenancy/index.d.ts +++ b/lib/build/recipe/multitenancy/index.d.ts @@ -6,47 +6,87 @@ import { AllowedDomainsClaim } from "./allowedDomainsClaim"; import RecipeUserId from "../../recipeUserId"; export default class Wrapper { static init: typeof Recipe.init; - static createOrUpdateTenant(tenantId: string, config?: { - firstFactors?: string[] | null; - requiredSecondaryFactors?: string[] | null; - coreConfig?: { - [key: string]: any; - }; - }, userContext?: Record): Promise<{ + static createOrUpdateTenant( + tenantId: string, + config?: { + firstFactors?: string[] | null; + requiredSecondaryFactors?: string[] | null; + coreConfig?: { + [key: string]: any; + }; + }, + userContext?: Record + ): Promise<{ status: "OK"; createdNew: boolean; }>; - static deleteTenant(tenantId: string, userContext?: Record): Promise<{ + static deleteTenant( + tenantId: string, + userContext?: Record + ): Promise<{ status: "OK"; didExist: boolean; }>; - static getTenant(tenantId: string, userContext?: Record): Promise<({ - status: "OK"; - } & TenantConfig) | undefined>; - static listAllTenants(userContext?: Record): Promise<{ + static getTenant( + tenantId: string, + userContext?: Record + ): Promise< + | ({ + status: "OK"; + } & TenantConfig) + | undefined + >; + static listAllTenants( + userContext?: Record + ): Promise<{ status: "OK"; tenants: ({ tenantId: string; } & TenantConfig)[]; }>; - static createOrUpdateThirdPartyConfig(tenantId: string, config: ProviderConfig, skipValidation?: boolean, userContext?: Record): Promise<{ + static createOrUpdateThirdPartyConfig( + tenantId: string, + config: ProviderConfig, + skipValidation?: boolean, + userContext?: Record + ): Promise<{ status: "OK"; createdNew: boolean; }>; - static deleteThirdPartyConfig(tenantId: string, thirdPartyId: string, userContext?: Record): Promise<{ + static deleteThirdPartyConfig( + tenantId: string, + thirdPartyId: string, + userContext?: Record + ): Promise<{ status: "OK"; didConfigExist: boolean; }>; - static associateUserToTenant(tenantId: string, recipeUserId: RecipeUserId, userContext?: Record): Promise<{ - status: "OK"; - wasAlreadyAssociated: boolean; - } | { - status: "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR"; - } | { - status: "ASSOCIATION_NOT_ALLOWED_ERROR"; - reason: string; - }>; - static disassociateUserFromTenant(tenantId: string, recipeUserId: RecipeUserId, userContext?: Record): Promise<{ + static associateUserToTenant( + tenantId: string, + recipeUserId: RecipeUserId, + userContext?: Record + ): Promise< + | { + status: "OK"; + wasAlreadyAssociated: boolean; + } + | { + status: + | "UNKNOWN_USER_ID_ERROR" + | "EMAIL_ALREADY_EXISTS_ERROR" + | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" + | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR"; + } + | { + status: "ASSOCIATION_NOT_ALLOWED_ERROR"; + reason: string; + } + >; + static disassociateUserFromTenant( + tenantId: string, + recipeUserId: RecipeUserId, + userContext?: Record + ): Promise<{ status: "OK"; wasAssociated: boolean; }>; diff --git a/lib/build/recipe/multitenancy/index.js b/lib/build/recipe/multitenancy/index.js index a1aee70b2..225ef101e 100644 --- a/lib/build/recipe/multitenancy/index.js +++ b/lib/build/recipe/multitenancy/index.js @@ -13,14 +13,21 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AllowedDomainsClaim = exports.disassociateUserFromTenant = exports.associateUserToTenant = exports.deleteThirdPartyConfig = exports.createOrUpdateThirdPartyConfig = exports.listAllTenants = exports.getTenant = exports.deleteTenant = exports.createOrUpdateTenant = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); const allowedDomainsClaim_1 = require("./allowedDomainsClaim"); -Object.defineProperty(exports, "AllowedDomainsClaim", { enumerable: true, get: function () { return allowedDomainsClaim_1.AllowedDomainsClaim; } }); +Object.defineProperty(exports, "AllowedDomainsClaim", { + enumerable: true, + get: function () { + return allowedDomainsClaim_1.AllowedDomainsClaim; + }, +}); const utils_1 = require("../../utils"); class Wrapper { static async createOrUpdateTenant(tenantId, config, userContext) { diff --git a/lib/build/recipe/multitenancy/recipe.d.ts b/lib/build/recipe/multitenancy/recipe.d.ts index de80cb133..0de41b877 100644 --- a/lib/build/recipe/multitenancy/recipe.d.ts +++ b/lib/build/recipe/multitenancy/recipe.d.ts @@ -23,7 +23,15 @@ export default class Recipe extends RecipeModule { static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, tenantId: string, req: BaseRequest, res: BaseResponse, _: NormalisedURLPath, __: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + tenantId: string, + req: BaseRequest, + res: BaseResponse, + _: NormalisedURLPath, + __: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: STError, _: BaseRequest, __: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; diff --git a/lib/build/recipe/multitenancy/recipe.js b/lib/build/recipe/multitenancy/recipe.js index 8266a991f..529ec4cca 100644 --- a/lib/build/recipe/multitenancy/recipe.js +++ b/lib/build/recipe/multitenancy/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -77,7 +79,9 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_1.validateAndNormaliseUserInput)(config); this.isInServerlessEnv = isInServerlessEnv; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId))); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId)) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -98,20 +102,29 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); if (Recipe.instance.getAllowedDomainsForTenantId !== undefined) { postSuperTokensInitCallbacks_1.PostSuperTokensInitCallbacks.addPostInitCallback(() => { try { - recipe_1.default.getInstanceOrThrowError().addClaimFromOtherRecipe(allowedDomainsClaim_1.AllowedDomainsClaim); - } - catch (_a) { + recipe_1.default + .getInstanceOrThrowError() + .addClaimFromOtherRecipe(allowedDomainsClaim_1.AllowedDomainsClaim); + } catch (_a) { // Skip adding claims if session recipe is not initialised } }); } return Recipe.instance; - } - else { + } else { throw new Error("Multitenancy recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/multitenancy/recipeImplementation.js b/lib/build/recipe/multitenancy/recipeImplementation.js index 0b23e1914..c84a6f268 100644 --- a/lib/build/recipe/multitenancy/recipeImplementation.js +++ b/lib/build/recipe/multitenancy/recipeImplementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -12,49 +14,103 @@ function getRecipeInterface(querier) { return tenantIdFromFrontend; }, createOrUpdateTenant: async function ({ tenantId, config, userContext }) { - let response = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/multitenancy/tenant/v2`), Object.assign({ tenantId }, config), {}, userContext); + let response = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/multitenancy/tenant/v2`), + Object.assign({ tenantId }, config), + {}, + userContext + ); return response; }, deleteTenant: async function ({ tenantId, userContext }) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/multitenancy/tenant/remove`), { - tenantId, - }, userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/multitenancy/tenant/remove`), + { + tenantId, + }, + userContext + ); return response; }, getTenant: async function ({ tenantId, userContext }) { - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/multitenancy/tenant/v2`), {}, userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default( + `/${ + tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId + }/recipe/multitenancy/tenant/v2` + ), + {}, + userContext + ); if (response.status === "TENANT_NOT_FOUND_ERROR") { return undefined; } return response; }, listAllTenants: async function ({ userContext }) { - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`/recipe/multitenancy/tenant/list/v2`), {}, userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default(`/recipe/multitenancy/tenant/list/v2`), + {}, + userContext + ); return response; }, createOrUpdateThirdPartyConfig: async function ({ tenantId, config, skipValidation, userContext }) { - let response = await querier.sendPutRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/multitenancy/config/thirdparty`), { - config, - skipValidation, - }, {}, userContext); + let response = await querier.sendPutRequest( + new normalisedURLPath_1.default( + `/${ + tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId + }/recipe/multitenancy/config/thirdparty` + ), + { + config, + skipValidation, + }, + {}, + userContext + ); return response; }, deleteThirdPartyConfig: async function ({ tenantId, thirdPartyId, userContext }) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/multitenancy/config/thirdparty/remove`), { - thirdPartyId, - }, userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${ + tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId + }/recipe/multitenancy/config/thirdparty/remove` + ), + { + thirdPartyId, + }, + userContext + ); return response; }, associateUserToTenant: async function ({ tenantId, recipeUserId, userContext }) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/multitenancy/tenant/user`), { - recipeUserId: recipeUserId.getAsString(), - }, userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${ + tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId + }/recipe/multitenancy/tenant/user` + ), + { + recipeUserId: recipeUserId.getAsString(), + }, + userContext + ); return response; }, disassociateUserFromTenant: async function ({ tenantId, recipeUserId, userContext }) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/multitenancy/tenant/user/remove`), { - recipeUserId: recipeUserId.getAsString(), - }, userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${ + tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId + }/recipe/multitenancy/tenant/user/remove` + ), + { + recipeUserId: recipeUserId.getAsString(), + }, + userContext + ); return response; }, }; diff --git a/lib/build/recipe/multitenancy/types.d.ts b/lib/build/recipe/multitenancy/types.d.ts index d389413ab..2b680d396 100644 --- a/lib/build/recipe/multitenancy/types.d.ts +++ b/lib/build/recipe/multitenancy/types.d.ts @@ -7,14 +7,20 @@ import RecipeUserId from "../../recipeUserId"; export type TypeInput = { getAllowedDomainsForTenantId?: (tenantId: string, userContext: UserContext) => Promise; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { getAllowedDomainsForTenantId?: (tenantId: string, userContext: UserContext) => Promise; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -29,10 +35,7 @@ export type TenantConfig = { }; }; export type RecipeInterface = { - getTenantId: (input: { - tenantIdFromFrontend: string; - userContext: UserContext; - }) => Promise; + getTenantId: (input: { tenantIdFromFrontend: string; userContext: UserContext }) => Promise; createOrUpdateTenant: (input: { tenantId: string; config?: { @@ -57,9 +60,12 @@ export type RecipeInterface = { getTenant: (input: { tenantId: string; userContext: UserContext; - }) => Promise<({ - status: "OK"; - } & TenantConfig) | undefined>; + }) => Promise< + | ({ + status: "OK"; + } & TenantConfig) + | undefined + >; listAllTenants: (input: { userContext: UserContext; }) => Promise<{ @@ -89,15 +95,23 @@ export type RecipeInterface = { tenantId: string; recipeUserId: RecipeUserId; userContext: UserContext; - }) => Promise<{ - status: "OK"; - wasAlreadyAssociated: boolean; - } | { - status: "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR"; - } | { - status: "ASSOCIATION_NOT_ALLOWED_ERROR"; - reason: string; - }>; + }) => Promise< + | { + status: "OK"; + wasAlreadyAssociated: boolean; + } + | { + status: + | "UNKNOWN_USER_ID_ERROR" + | "EMAIL_ALREADY_EXISTS_ERROR" + | "PHONE_NUMBER_ALREADY_EXISTS_ERROR" + | "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR"; + } + | { + status: "ASSOCIATION_NOT_ALLOWED_ERROR"; + reason: string; + } + >; disassociateUserFromTenant: (input: { tenantId: string; recipeUserId: RecipeUserId; @@ -124,21 +138,24 @@ export type APIInterface = { clientType?: string; options: APIOptions; userContext: UserContext; - }) => Promise<{ - status: "OK"; - emailPassword: { - enabled: boolean; - }; - thirdParty: { - enabled: boolean; - providers: { - id: string; - name?: string; - }[]; - }; - passwordless: { - enabled: boolean; - }; - firstFactors: string[]; - } | GeneralErrorResponse>; + }) => Promise< + | { + status: "OK"; + emailPassword: { + enabled: boolean; + }; + thirdParty: { + enabled: boolean; + providers: { + id: string; + name?: string; + }[]; + }; + passwordless: { + enabled: boolean; + }; + firstFactors: string[]; + } + | GeneralErrorResponse + >; }; diff --git a/lib/build/recipe/multitenancy/utils.d.ts b/lib/build/recipe/multitenancy/utils.d.ts index 7190e47b9..3bc6e2abc 100644 --- a/lib/build/recipe/multitenancy/utils.d.ts +++ b/lib/build/recipe/multitenancy/utils.d.ts @@ -2,14 +2,26 @@ import { TypeInput, TypeNormalisedInput, TenantConfig } from "./types"; import { UserContext } from "../../types"; export declare function validateAndNormaliseUserInput(config?: TypeInput): TypeNormalisedInput; -export declare const isValidFirstFactor: (tenantId: string, factorId: string, userContext: UserContext) => Promise<{ - status: "OK"; -} | { - status: "INVALID_FIRST_FACTOR_ERROR"; -} | { - status: "TENANT_NOT_FOUND_ERROR"; -}>; -export declare function isFactorConfiguredForTenant({ allAvailableFirstFactors, firstFactors, factorId, }: { +export declare const isValidFirstFactor: ( + tenantId: string, + factorId: string, + userContext: UserContext +) => Promise< + | { + status: "OK"; + } + | { + status: "INVALID_FIRST_FACTOR_ERROR"; + } + | { + status: "TENANT_NOT_FOUND_ERROR"; + } +>; +export declare function isFactorConfiguredForTenant({ + allAvailableFirstFactors, + firstFactors, + factorId, +}: { tenantConfig: TenantConfig; allAvailableFirstFactors: string[]; firstFactors: string[]; diff --git a/lib/build/recipe/multitenancy/utils.js b/lib/build/recipe/multitenancy/utils.js index ad2f08b52..5bb70e415 100644 --- a/lib/build/recipe/multitenancy/utils.js +++ b/lib/build/recipe/multitenancy/utils.js @@ -13,20 +13,22 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __rest = (this && this.__rest) || function (s, e) { - var t = {}; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __rest = + (this && this.__rest) || + function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; + } + return t; + }; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isValidFirstFactor = void 0; exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; @@ -35,9 +37,16 @@ const recipe_1 = __importDefault(require("./recipe")); const logger_1 = require("../../logger"); const types_1 = require("../multifactorauth/types"); function validateAndNormaliseUserInput(config) { - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { - getAllowedDomainsForTenantId: config === null || config === void 0 ? void 0 : config.getAllowedDomainsForTenantId, + getAllowedDomainsForTenantId: + config === null || config === void 0 ? void 0 : config.getAllowedDomainsForTenantId, override, }; } @@ -53,21 +62,29 @@ const isValidFirstFactor = async function (tenantId, factorId, userContext) { status: "TENANT_NOT_FOUND_ERROR", }; } - const { status: _ } = tenantInfo, tenantConfig = __rest(tenantInfo, ["status"]); + const { status: _ } = tenantInfo, + tenantConfig = __rest(tenantInfo, ["status"]); const firstFactorsFromMFA = mtRecipe.staticFirstFactors; - (0, logger_1.logDebugMessage)(`isValidFirstFactor got ${(_a = tenantConfig.firstFactors) === null || _a === void 0 ? void 0 : _a.join(", ")} from tenant config`); + (0, logger_1.logDebugMessage)( + `isValidFirstFactor got ${ + (_a = tenantConfig.firstFactors) === null || _a === void 0 ? void 0 : _a.join(", ") + } from tenant config` + ); (0, logger_1.logDebugMessage)(`isValidFirstFactor got ${firstFactorsFromMFA} from MFA`); // first factors configured in core is prioritised over the ones configured statically - let configuredFirstFactors = tenantConfig.firstFactors !== undefined ? tenantConfig.firstFactors : firstFactorsFromMFA; + let configuredFirstFactors = + tenantConfig.firstFactors !== undefined ? tenantConfig.firstFactors : firstFactorsFromMFA; if (configuredFirstFactors === undefined) { configuredFirstFactors = mtRecipe.allAvailableFirstFactors; } - if (isFactorConfiguredForTenant({ - tenantConfig, - allAvailableFirstFactors: mtRecipe.allAvailableFirstFactors, - firstFactors: configuredFirstFactors, - factorId, - })) { + if ( + isFactorConfiguredForTenant({ + tenantConfig, + allAvailableFirstFactors: mtRecipe.allAvailableFirstFactors, + firstFactors: configuredFirstFactors, + factorId, + }) + ) { return { status: "OK", }; @@ -77,11 +94,14 @@ const isValidFirstFactor = async function (tenantId, factorId, userContext) { }; }; exports.isValidFirstFactor = isValidFirstFactor; -function isFactorConfiguredForTenant({ allAvailableFirstFactors, firstFactors, factorId, }) { +function isFactorConfiguredForTenant({ allAvailableFirstFactors, firstFactors, factorId }) { // Here we filter the array so that we only have: // 1. Factors that other recipes have marked as available // 2. Custom factors (not in the built-in FactorIds list) - let configuredFirstFactors = firstFactors.filter((factorId) => allAvailableFirstFactors.includes(factorId) || !Object.values(types_1.FactorIds).includes(factorId)); + let configuredFirstFactors = firstFactors.filter( + (factorId) => + allAvailableFirstFactors.includes(factorId) || !Object.values(types_1.FactorIds).includes(factorId) + ); // Filter based on enabled recipes in the core is no more required // if (tenantConfig.emailPassword.enabled === false) { // configuredFirstFactors = configuredFirstFactors.filter( diff --git a/lib/build/recipe/oauth2provider/OAuth2Client.d.ts b/lib/build/recipe/oauth2provider/OAuth2Client.d.ts index b34a58256..8d5ab3324 100644 --- a/lib/build/recipe/oauth2provider/OAuth2Client.d.ts +++ b/lib/build/recipe/oauth2provider/OAuth2Client.d.ts @@ -138,6 +138,34 @@ export declare class OAuth2Client { metadata: Record; /** This flag is set to true if refresh tokens are updated upon use */ enableRefreshTokenRotation: boolean; - constructor({ clientId, clientSecret, clientName, scope, redirectUris, postLogoutRedirectUris, authorizationCodeGrantAccessTokenLifespan, authorizationCodeGrantIdTokenLifespan, authorizationCodeGrantRefreshTokenLifespan, clientCredentialsGrantAccessTokenLifespan, implicitGrantAccessTokenLifespan, implicitGrantIdTokenLifespan, refreshTokenGrantAccessTokenLifespan, refreshTokenGrantIdTokenLifespan, refreshTokenGrantRefreshTokenLifespan, tokenEndpointAuthMethod, clientUri, audience, grantTypes, responseTypes, logoUri, policyUri, tosUri, createdAt, updatedAt, metadata, enableRefreshTokenRotation, }: OAuth2ClientOptions); + constructor({ + clientId, + clientSecret, + clientName, + scope, + redirectUris, + postLogoutRedirectUris, + authorizationCodeGrantAccessTokenLifespan, + authorizationCodeGrantIdTokenLifespan, + authorizationCodeGrantRefreshTokenLifespan, + clientCredentialsGrantAccessTokenLifespan, + implicitGrantAccessTokenLifespan, + implicitGrantIdTokenLifespan, + refreshTokenGrantAccessTokenLifespan, + refreshTokenGrantIdTokenLifespan, + refreshTokenGrantRefreshTokenLifespan, + tokenEndpointAuthMethod, + clientUri, + audience, + grantTypes, + responseTypes, + logoUri, + policyUri, + tosUri, + createdAt, + updatedAt, + metadata, + enableRefreshTokenRotation, + }: OAuth2ClientOptions); static fromAPIResponse(response: any): OAuth2Client; } diff --git a/lib/build/recipe/oauth2provider/OAuth2Client.js b/lib/build/recipe/oauth2provider/OAuth2Client.js index 64b0b97ee..741b6790f 100644 --- a/lib/build/recipe/oauth2provider/OAuth2Client.js +++ b/lib/build/recipe/oauth2provider/OAuth2Client.js @@ -17,7 +17,35 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.OAuth2Client = void 0; const utils_1 = require("../../utils"); class OAuth2Client { - constructor({ clientId, clientSecret, clientName, scope, redirectUris = null, postLogoutRedirectUris, authorizationCodeGrantAccessTokenLifespan = null, authorizationCodeGrantIdTokenLifespan = null, authorizationCodeGrantRefreshTokenLifespan = null, clientCredentialsGrantAccessTokenLifespan = null, implicitGrantAccessTokenLifespan = null, implicitGrantIdTokenLifespan = null, refreshTokenGrantAccessTokenLifespan = null, refreshTokenGrantIdTokenLifespan = null, refreshTokenGrantRefreshTokenLifespan = null, tokenEndpointAuthMethod, clientUri = "", audience = [], grantTypes = null, responseTypes = null, logoUri = "", policyUri = "", tosUri = "", createdAt, updatedAt, metadata = {}, enableRefreshTokenRotation = false, }) { + constructor({ + clientId, + clientSecret, + clientName, + scope, + redirectUris = null, + postLogoutRedirectUris, + authorizationCodeGrantAccessTokenLifespan = null, + authorizationCodeGrantIdTokenLifespan = null, + authorizationCodeGrantRefreshTokenLifespan = null, + clientCredentialsGrantAccessTokenLifespan = null, + implicitGrantAccessTokenLifespan = null, + implicitGrantIdTokenLifespan = null, + refreshTokenGrantAccessTokenLifespan = null, + refreshTokenGrantIdTokenLifespan = null, + refreshTokenGrantRefreshTokenLifespan = null, + tokenEndpointAuthMethod, + clientUri = "", + audience = [], + grantTypes = null, + responseTypes = null, + logoUri = "", + policyUri = "", + tosUri = "", + createdAt, + updatedAt, + metadata = {}, + enableRefreshTokenRotation = false, + }) { /** * Metadata - JSON object */ diff --git a/lib/build/recipe/oauth2provider/api/auth.d.ts b/lib/build/recipe/oauth2provider/api/auth.d.ts index bd8b4a391..059876918 100644 --- a/lib/build/recipe/oauth2provider/api/auth.d.ts +++ b/lib/build/recipe/oauth2provider/api/auth.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function authGET(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function authGET( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/auth.js b/lib/build/recipe/oauth2provider/api/auth.js index 5d4632226..1f45d2ae2 100644 --- a/lib/build/recipe/oauth2provider/api/auth.js +++ b/lib/build/recipe/oauth2provider/api/auth.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = authGET; const utils_1 = require("../../../utils"); @@ -34,13 +36,11 @@ async function authGET(apiImplementation, options, userContext) { try { session = await session_1.default.getSession(options.req, options.res, { sessionRequired: false }, userContext); shouldTryRefresh = false; - } - catch (error) { + } catch (error) { session = undefined; if (error_1.default.isErrorFromSuperTokens(error) && error.type === error_1.default.TRY_REFRESH_TOKEN) { shouldTryRefresh = true; - } - else { + } else { // This should generally not happen, but we can handle this as if the session is not present, // because then we redirect to the frontend, which should handle the validation error shouldTryRefresh = false; @@ -59,18 +59,25 @@ async function authGET(apiImplementation, options, userContext) { const cookieStr = set_cookie_parser_1.default.splitCookiesString(response.cookies); const cookies = set_cookie_parser_1.default.parse(cookieStr); for (const cookie of cookies) { - options.res.setCookie(cookie.name, cookie.value, cookie.domain, !!cookie.secure, !!cookie.httpOnly, new Date(cookie.expires).getTime(), cookie.path || "/", cookie.sameSite); + options.res.setCookie( + cookie.name, + cookie.value, + cookie.domain, + !!cookie.secure, + !!cookie.httpOnly, + new Date(cookie.expires).getTime(), + cookie.path || "/", + cookie.sameSite + ); } } options.res.original.redirect(response.redirectTo); - } - else if ("statusCode" in response) { + } else if ("statusCode" in response) { (0, utils_1.sendNon200Response)(options.res, (_a = response.statusCode) !== null && _a !== void 0 ? _a : 400, { error: response.error, error_description: response.errorDescription, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, response); } return true; diff --git a/lib/build/recipe/oauth2provider/api/endSession.d.ts b/lib/build/recipe/oauth2provider/api/endSession.d.ts index 0f161e541..1f454cbd0 100644 --- a/lib/build/recipe/oauth2provider/api/endSession.d.ts +++ b/lib/build/recipe/oauth2provider/api/endSession.d.ts @@ -1,5 +1,13 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export declare function endSessionGET(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; -export declare function endSessionPOST(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export declare function endSessionGET( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; +export declare function endSessionPOST( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/endSession.js b/lib/build/recipe/oauth2provider/api/endSession.js index e45f4cc74..a31e329d5 100644 --- a/lib/build/recipe/oauth2provider/api/endSession.js +++ b/lib/build/recipe/oauth2provider/api/endSession.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.endSessionGET = endSessionGET; exports.endSessionPOST = endSessionPOST; @@ -30,7 +32,12 @@ async function endSessionGET(apiImplementation, options, userContext) { const origURL = options.req.getOriginalURL(); const splitURL = origURL.split("?"); const params = new URLSearchParams(splitURL[1]); - return endSessionCommon(Object.fromEntries(params.entries()), apiImplementation.endSessionGET, options, userContext); + return endSessionCommon( + Object.fromEntries(params.entries()), + apiImplementation.endSessionGET, + options, + userContext + ); } async function endSessionPOST(apiImplementation, options, userContext) { if (apiImplementation.endSessionPOST === undefined) { @@ -48,15 +55,13 @@ async function endSessionCommon(params, apiImplementation, options, userContext) try { session = await session_1.default.getSession(options.req, options.res, { sessionRequired: false }, userContext); shouldTryRefresh = false; - } - catch (error) { + } catch (error) { // We can handle this as if the session is not present, because then we redirect to the frontend, // which should handle the validation error session = undefined; if (error_1.default.isErrorFromSuperTokens(error) && error.type === error_2.default.TRY_REFRESH_TOKEN) { shouldTryRefresh = true; - } - else { + } else { shouldTryRefresh = false; } } @@ -69,14 +74,12 @@ async function endSessionCommon(params, apiImplementation, options, userContext) }); if ("redirectTo" in response) { options.res.original.redirect(response.redirectTo); - } - else if ("error" in response) { + } else if ("error" in response) { (0, utils_1.sendNon200Response)(options.res, (_a = response.statusCode) !== null && _a !== void 0 ? _a : 400, { error: response.error, error_description: response.errorDescription, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, response); } return true; diff --git a/lib/build/recipe/oauth2provider/api/implementation.js b/lib/build/recipe/oauth2provider/api/implementation.js index 858c27890..89de95c3d 100644 --- a/lib/build/recipe/oauth2provider/api/implementation.js +++ b/lib/build/recipe/oauth2provider/api/implementation.js @@ -110,16 +110,14 @@ function getAPIImplementation() { authorizationHeader: input.authorizationHeader, userContext: input.userContext, }); - } - else if ("clientId" in input && input.clientId !== undefined) { + } else if ("clientId" in input && input.clientId !== undefined) { return input.options.recipeImplementation.revokeToken({ token: input.token, clientId: input.clientId, clientSecret: input.clientSecret, userContext: input.userContext, }); - } - else { + } else { throw new Error(`Either of 'authorizationHeader' or 'clientId' must be provided`); } }, diff --git a/lib/build/recipe/oauth2provider/api/introspectToken.d.ts b/lib/build/recipe/oauth2provider/api/introspectToken.d.ts index 135880d83..3d2972c0d 100644 --- a/lib/build/recipe/oauth2provider/api/introspectToken.d.ts +++ b/lib/build/recipe/oauth2provider/api/introspectToken.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function introspectTokenPOST(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function introspectTokenPOST( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/login.d.ts b/lib/build/recipe/oauth2provider/api/login.d.ts index 1a1417232..6f4253cef 100644 --- a/lib/build/recipe/oauth2provider/api/login.d.ts +++ b/lib/build/recipe/oauth2provider/api/login.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function login(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function login( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/login.js b/lib/build/recipe/oauth2provider/api/login.js index 661e96415..f67decc1f 100644 --- a/lib/build/recipe/oauth2provider/api/login.js +++ b/lib/build/recipe/oauth2provider/api/login.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = login; const set_cookie_parser_1 = __importDefault(require("set-cookie-parser")); @@ -32,19 +34,20 @@ async function login(apiImplementation, options, userContext) { try { session = await session_1.default.getSession(options.req, options.res, { sessionRequired: false }, userContext); shouldTryRefresh = false; - } - catch (error) { + } catch (error) { // We can handle this as if the session is not present, because then we redirect to the frontend, // which should handle the validation error session = undefined; if (error_1.default.isErrorFromSuperTokens(error) && error.type === error_2.default.TRY_REFRESH_TOKEN) { shouldTryRefresh = true; - } - else { + } else { shouldTryRefresh = false; } } - const loginChallenge = (_a = options.req.getKeyValueFromQuery("login_challenge")) !== null && _a !== void 0 ? _a : options.req.getKeyValueFromQuery("loginChallenge"); + const loginChallenge = + (_a = options.req.getKeyValueFromQuery("login_challenge")) !== null && _a !== void 0 + ? _a + : options.req.getKeyValueFromQuery("loginChallenge"); if (loginChallenge === undefined) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, @@ -63,14 +66,22 @@ async function login(apiImplementation, options, userContext) { const cookieStr = set_cookie_parser_1.default.splitCookiesString(response.cookies); const cookies = set_cookie_parser_1.default.parse(cookieStr); for (const cookie of cookies) { - options.res.setCookie(cookie.name, cookie.value, cookie.domain, !!cookie.secure, !!cookie.httpOnly, new Date(cookie.expires).getTime(), cookie.path || "/", cookie.sameSite); + options.res.setCookie( + cookie.name, + cookie.value, + cookie.domain, + !!cookie.secure, + !!cookie.httpOnly, + new Date(cookie.expires).getTime(), + cookie.path || "/", + cookie.sameSite + ); } } (0, utils_1.send200Response)(options.res, { frontendRedirectTo: response.frontendRedirectTo, }); - } - else if ("statusCode" in response) { + } else if ("statusCode" in response) { // We want to avoid returning a 401 to the frontend, as it may trigger a refresh loop if (response.statusCode === 401) { response.statusCode = 400; @@ -79,8 +90,7 @@ async function login(apiImplementation, options, userContext) { error: response.error, error_description: response.errorDescription, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, response); } return true; diff --git a/lib/build/recipe/oauth2provider/api/loginInfo.d.ts b/lib/build/recipe/oauth2provider/api/loginInfo.d.ts index e9817552e..536858263 100644 --- a/lib/build/recipe/oauth2provider/api/loginInfo.d.ts +++ b/lib/build/recipe/oauth2provider/api/loginInfo.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function loginInfoGET(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function loginInfoGET( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/loginInfo.js b/lib/build/recipe/oauth2provider/api/loginInfo.js index 2c8df8913..69b27aca5 100644 --- a/lib/build/recipe/oauth2provider/api/loginInfo.js +++ b/lib/build/recipe/oauth2provider/api/loginInfo.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = loginInfoGET; const utils_1 = require("../../../utils"); @@ -25,7 +27,10 @@ async function loginInfoGET(apiImplementation, options, userContext) { if (apiImplementation.loginInfoGET === undefined) { return false; } - const loginChallenge = (_a = options.req.getKeyValueFromQuery("login_challenge")) !== null && _a !== void 0 ? _a : options.req.getKeyValueFromQuery("loginChallenge"); + const loginChallenge = + (_a = options.req.getKeyValueFromQuery("login_challenge")) !== null && _a !== void 0 + ? _a + : options.req.getKeyValueFromQuery("loginChallenge"); if (loginChallenge === undefined) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, @@ -46,8 +51,7 @@ async function loginInfoGET(apiImplementation, options, userContext) { error: response.error, error_description: response.errorDescription, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, response); } return true; diff --git a/lib/build/recipe/oauth2provider/api/logout.d.ts b/lib/build/recipe/oauth2provider/api/logout.d.ts index e53197994..339a73e77 100644 --- a/lib/build/recipe/oauth2provider/api/logout.d.ts +++ b/lib/build/recipe/oauth2provider/api/logout.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export declare function logoutPOST(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export declare function logoutPOST( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/logout.js b/lib/build/recipe/oauth2provider/api/logout.js index 9141d8f9b..a7fcc83ac 100644 --- a/lib/build/recipe/oauth2provider/api/logout.js +++ b/lib/build/recipe/oauth2provider/api/logout.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.logoutPOST = logoutPOST; const utils_1 = require("../../../utils"); @@ -29,8 +31,7 @@ async function logoutPOST(apiImplementation, options, userContext) { let session; try { session = await session_1.default.getSession(options.req, options.res, { sessionRequired: false }, userContext); - } - catch (_b) { + } catch (_b) { session = undefined; } const body = await options.req.getBodyAsJSONOrFormData(); @@ -48,8 +49,7 @@ async function logoutPOST(apiImplementation, options, userContext) { }); if ("status" in response && response.status === "OK") { (0, utils_1.send200Response)(options.res, response); - } - else if ("statusCode" in response) { + } else if ("statusCode" in response) { // We want to avoid returning a 401 to the frontend, as it may trigger a refresh loop if (response.statusCode === 401) { response.statusCode = 400; @@ -58,8 +58,7 @@ async function logoutPOST(apiImplementation, options, userContext) { error: response.error, error_description: response.errorDescription, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, response); } return true; diff --git a/lib/build/recipe/oauth2provider/api/revokeToken.d.ts b/lib/build/recipe/oauth2provider/api/revokeToken.d.ts index d79a68c45..902e734d5 100644 --- a/lib/build/recipe/oauth2provider/api/revokeToken.d.ts +++ b/lib/build/recipe/oauth2provider/api/revokeToken.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function revokeTokenPOST(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function revokeTokenPOST( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/revokeToken.js b/lib/build/recipe/oauth2provider/api/revokeToken.js index 20037a66c..6428730b9 100644 --- a/lib/build/recipe/oauth2provider/api/revokeToken.js +++ b/lib/build/recipe/oauth2provider/api/revokeToken.js @@ -28,7 +28,11 @@ async function revokeTokenPOST(apiImplementation, options, userContext) { } const authorizationHeader = options.req.getHeaderValue("authorization"); if (authorizationHeader !== undefined && (body.client_id !== undefined || body.client_secret !== undefined)) { - (0, utils_1.sendNon200ResponseWithMessage)(options.res, "Only one of authorization header or client_id and client_secret can be provided", 400); + (0, utils_1.sendNon200ResponseWithMessage)( + options.res, + "Only one of authorization header or client_id and client_secret can be provided", + 400 + ); return true; } let response = await apiImplementation.revokeTokenPOST({ @@ -45,8 +49,7 @@ async function revokeTokenPOST(apiImplementation, options, userContext) { error: response.error, error_description: response.errorDescription, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, response); } return true; diff --git a/lib/build/recipe/oauth2provider/api/token.d.ts b/lib/build/recipe/oauth2provider/api/token.d.ts index 68d95e24e..c697b7744 100644 --- a/lib/build/recipe/oauth2provider/api/token.d.ts +++ b/lib/build/recipe/oauth2provider/api/token.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function tokenPOST(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function tokenPOST( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/token.js b/lib/build/recipe/oauth2provider/api/token.js index 2fd7fbcb7..0c228f289 100644 --- a/lib/build/recipe/oauth2provider/api/token.js +++ b/lib/build/recipe/oauth2provider/api/token.js @@ -34,8 +34,7 @@ async function tokenPOST(apiImplementation, options, userContext) { error: response.error, error_description: response.errorDescription, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, response); } return true; diff --git a/lib/build/recipe/oauth2provider/api/userInfo.d.ts b/lib/build/recipe/oauth2provider/api/userInfo.d.ts index 92f0a98be..d0b8cdf4e 100644 --- a/lib/build/recipe/oauth2provider/api/userInfo.d.ts +++ b/lib/build/recipe/oauth2provider/api/userInfo.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function userInfoGET(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function userInfoGET( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/oauth2provider/api/userInfo.js b/lib/build/recipe/oauth2provider/api/userInfo.js index 2fb1fd43b..f75970fd0 100644 --- a/lib/build/recipe/oauth2provider/api/userInfo.js +++ b/lib/build/recipe/oauth2provider/api/userInfo.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = userInfoGET; const recipe_1 = __importDefault(require("../recipe")); @@ -33,22 +35,25 @@ async function userInfoGET(apiImplementation, tenantId, options, userContext) { const accessToken = authHeader.replace(/^Bearer /, "").trim(); let accessTokenPayload; try { - const { payload, } = await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.validateOAuth2AccessToken({ + const { + payload, + } = await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.validateOAuth2AccessToken({ token: accessToken, userContext, }); accessTokenPayload = payload; - } - catch (error) { + } catch (error) { options.res.setHeader("WWW-Authenticate", 'Bearer error="invalid_token"', false); options.res.setHeader("Access-Control-Expose-Headers", "WWW-Authenticate", true); (0, utils_1.sendNon200ResponseWithMessage)(options.res, "Invalid or expired OAuth2 access token", 401); return true; } - if (accessTokenPayload === null || + if ( + accessTokenPayload === null || typeof accessTokenPayload !== "object" || typeof accessTokenPayload.sub !== "string" || - !Array.isArray(accessTokenPayload.scp)) { + !Array.isArray(accessTokenPayload.scp) + ) { options.res.setHeader("WWW-Authenticate", 'Bearer error="invalid_token"', false); options.res.setHeader("Access-Control-Expose-Headers", "WWW-Authenticate", true); (0, utils_1.sendNon200ResponseWithMessage)(options.res, "Malformed access token payload", 401); @@ -59,7 +64,11 @@ async function userInfoGET(apiImplementation, tenantId, options, userContext) { if (user === undefined) { options.res.setHeader("WWW-Authenticate", 'Bearer error="invalid_token"', false); options.res.setHeader("Access-Control-Expose-Headers", "WWW-Authenticate", true); - (0, utils_1.sendNon200ResponseWithMessage)(options.res, "Couldn't find any user associated with the access token", 401); + (0, utils_1.sendNon200ResponseWithMessage)( + options.res, + "Couldn't find any user associated with the access token", + 401 + ); return true; } const response = await apiImplementation.userInfoGET({ diff --git a/lib/build/recipe/oauth2provider/api/utils.d.ts b/lib/build/recipe/oauth2provider/api/utils.d.ts index acc1c2a03..1bf243b1a 100644 --- a/lib/build/recipe/oauth2provider/api/utils.d.ts +++ b/lib/build/recipe/oauth2provider/api/utils.d.ts @@ -2,7 +2,15 @@ import { UserContext } from "../../../types"; import { SessionContainerInterface } from "../../session/types"; import { ErrorOAuth2, RecipeInterface } from "../types"; -export declare function loginGET({ recipeImplementation, loginChallenge, shouldTryRefresh, session, cookies, isDirectCall, userContext, }: { +export declare function loginGET({ + recipeImplementation, + loginChallenge, + shouldTryRefresh, + session, + cookies, + isDirectCall, + userContext, +}: { recipeImplementation: RecipeInterface; loginChallenge: string; session?: SessionContainerInterface; @@ -10,16 +18,27 @@ export declare function loginGET({ recipeImplementation, loginChallenge, shouldT cookies?: string; userContext: UserContext; isDirectCall: boolean; -}): Promise; -export declare function handleLoginInternalRedirects({ response, recipeImplementation, session, shouldTryRefresh, cookie, userContext, }: { +}): Promise< + | ErrorOAuth2 + | { + status: string; + redirectTo: string; + cookies: string | undefined; + } + | { + redirectTo: string; + cookies: string | undefined; + status?: undefined; + } +>; +export declare function handleLoginInternalRedirects({ + response, + recipeImplementation, + session, + shouldTryRefresh, + cookie, + userContext, +}: { response: { redirectTo: string; cookies?: string; @@ -29,17 +48,28 @@ export declare function handleLoginInternalRedirects({ response, recipeImplement shouldTryRefresh: boolean; cookie?: string; userContext: UserContext; -}): Promise<{ - redirectTo: string; - cookies?: string; -} | ErrorOAuth2>; -export declare function handleLogoutInternalRedirects({ response, recipeImplementation, session, userContext, }: { +}): Promise< + | { + redirectTo: string; + cookies?: string; + } + | ErrorOAuth2 +>; +export declare function handleLogoutInternalRedirects({ + response, + recipeImplementation, + session, + userContext, +}: { response: { redirectTo: string; }; recipeImplementation: RecipeInterface; session?: SessionContainerInterface; userContext: UserContext; -}): Promise<{ - redirectTo: string; -} | ErrorOAuth2>; +}): Promise< + | { + redirectTo: string; + } + | ErrorOAuth2 +>; diff --git a/lib/build/recipe/oauth2provider/api/utils.js b/lib/build/recipe/oauth2provider/api/utils.js index e02679926..e89095fde 100644 --- a/lib/build/recipe/oauth2provider/api/utils.js +++ b/lib/build/recipe/oauth2provider/api/utils.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.loginGET = loginGET; exports.handleLoginInternalRedirects = handleLoginInternalRedirects; @@ -13,7 +15,15 @@ const constants_2 = require("../constants"); const set_cookie_parser_1 = __importDefault(require("set-cookie-parser")); // API implementation for the loginGET function. // Extracted for use in both apiImplementation and handleInternalRedirects. -async function loginGET({ recipeImplementation, loginChallenge, shouldTryRefresh, session, cookies, isDirectCall, userContext, }) { +async function loginGET({ + recipeImplementation, + loginChallenge, + shouldTryRefresh, + session, + cookies, + isDirectCall, + userContext, +}) { var _a, _b; const loginRequest = await recipeImplementation.getLoginRequest({ challenge: loginChallenge, @@ -22,12 +32,20 @@ async function loginGET({ recipeImplementation, loginChallenge, shouldTryRefresh if (loginRequest.status === "ERROR") { return loginRequest; } - const sessionInfo = session !== undefined ? await (0, session_1.getSessionInformation)(session === null || session === void 0 ? void 0 : session.getHandle()) : undefined; + const sessionInfo = + session !== undefined + ? await (0, session_1.getSessionInformation)( + session === null || session === void 0 ? void 0 : session.getHandle() + ) + : undefined; if (!sessionInfo) { session = undefined; } const incomingAuthUrlQueryParams = new URLSearchParams(loginRequest.requestUrl.split("?")[1]); - const promptParam = (_a = incomingAuthUrlQueryParams.get("prompt")) !== null && _a !== void 0 ? _a : incomingAuthUrlQueryParams.get("st_prompt"); + const promptParam = + (_a = incomingAuthUrlQueryParams.get("prompt")) !== null && _a !== void 0 + ? _a + : incomingAuthUrlQueryParams.get("st_prompt"); const maxAgeParam = incomingAuthUrlQueryParams.get("max_age"); if (maxAgeParam !== null) { try { @@ -56,8 +74,7 @@ async function loginGET({ recipeImplementation, loginChallenge, shouldTryRefresh }); return { status: "REDIRECT", redirectTo: reject.redirectTo, cookies }; } - } - catch (_c) { + } catch (_c) { const reject = await recipeImplementation.rejectLoginRequest({ challenge: loginChallenge, error: { @@ -71,13 +88,15 @@ async function loginGET({ recipeImplementation, loginChallenge, shouldTryRefresh } } const tenantIdParam = incomingAuthUrlQueryParams.get("tenant_id"); - if (session && + if ( + session && (["", undefined].includes(loginRequest.subject) || session.getUserId() === loginRequest.subject) && (["", null].includes(tenantIdParam) || session.getTenantId() === tenantIdParam) && (promptParam !== "login" || isDirectCall) && (maxAgeParam === null || (maxAgeParam === "0" && isDirectCall) || - Number.parseInt(maxAgeParam) * 1000 > Date.now() - sessionInfo.timeCreated)) { + Number.parseInt(maxAgeParam) * 1000 > Date.now() - sessionInfo.timeCreated) + ) { const accept = await recipeImplementation.acceptLoginRequest({ challenge: loginChallenge, subject: session.getUserId(), @@ -102,7 +121,8 @@ async function loginGET({ recipeImplementation, loginChallenge, shouldTryRefresh error: { status: "ERROR", error: "login_required", - errorDescription: "The Authorization Server requires End-User authentication. Prompt 'none' was requested, but no existing or expired login session was found.", + errorDescription: + "The Authorization Server requires End-User authentication. Prompt 'none' was requested, but no existing or expired login session was found.", }, userContext, }); @@ -114,7 +134,8 @@ async function loginGET({ recipeImplementation, loginChallenge, shouldTryRefresh type: "login", loginChallenge, forceFreshAuth: session !== undefined || promptParam === "login", - tenantId: tenantIdParam !== null && tenantIdParam !== void 0 ? tenantIdParam : constants_1.DEFAULT_TENANT_ID, + tenantId: + tenantIdParam !== null && tenantIdParam !== void 0 ? tenantIdParam : constants_1.DEFAULT_TENANT_ID, hint: (_b = loginRequest.oidcContext) === null || _b === void 0 ? void 0 : _b.login_hint, userContext, }), @@ -133,8 +154,7 @@ function getMergedCookies({ origCookies = "", newCookies }) { for (const { name, value, expires } of setCookies) { if (expires && new Date(expires) < new Date()) { delete cookieMap[name]; - } - else { + } else { cookieMap[name] = value; } } @@ -164,7 +184,14 @@ function isLogoutInternalRedirect(redirectTo) { // In the OAuth2 flow, we do several internal redirects. These redirects don't require a frontend-to-api-server round trip. // If an internal redirect is identified, it's handled directly by this function. // Currently, we only need to handle redirects to /oauth/login and /oauth/auth endpoints in the login flow. -async function handleLoginInternalRedirects({ response, recipeImplementation, session, shouldTryRefresh, cookie = "", userContext, }) { +async function handleLoginInternalRedirects({ + response, + recipeImplementation, + session, + shouldTryRefresh, + cookie = "", + userContext, +}) { var _a; if (!isLoginInternalRedirect(response.redirectTo)) { return response; @@ -178,7 +205,8 @@ async function handleLoginInternalRedirects({ response, recipeImplementation, se const queryString = response.redirectTo.split("?")[1]; const params = new URLSearchParams(queryString); if (response.redirectTo.includes(constants_2.LOGIN_PATH)) { - const loginChallenge = (_a = params.get("login_challenge")) !== null && _a !== void 0 ? _a : params.get("loginChallenge"); + const loginChallenge = + (_a = params.get("login_challenge")) !== null && _a !== void 0 ? _a : params.get("loginChallenge"); if (!loginChallenge) { throw new Error(`Expected loginChallenge in ${response.redirectTo}`); } @@ -198,8 +226,7 @@ async function handleLoginInternalRedirects({ response, recipeImplementation, se redirectTo: loginRes.redirectTo, cookies: mergeSetCookieHeaders(loginRes.cookies, response.cookies), }; - } - else if (response.redirectTo.includes(constants_2.AUTH_PATH)) { + } else if (response.redirectTo.includes(constants_2.AUTH_PATH)) { const authRes = await recipeImplementation.authorization({ params: Object.fromEntries(params.entries()), cookies: cookie, @@ -213,8 +240,7 @@ async function handleLoginInternalRedirects({ response, recipeImplementation, se redirectTo: authRes.redirectTo, cookies: mergeSetCookieHeaders(authRes.cookies, response.cookies), }; - } - else { + } else { throw new Error(`Unexpected internal redirect ${response.redirectTo}`); } redirectCount++; @@ -224,7 +250,7 @@ async function handleLoginInternalRedirects({ response, recipeImplementation, se // In the OAuth2 flow, we do several internal redirects. These redirects don't require a frontend-to-api-server round trip. // If an internal redirect is identified, it's handled directly by this function. // Currently, we only need to handle redirects to /oauth/end_session endpoint in the logout flow. -async function handleLogoutInternalRedirects({ response, recipeImplementation, session, userContext, }) { +async function handleLogoutInternalRedirects({ response, recipeImplementation, session, userContext }) { if (!isLogoutInternalRedirect(response.redirectTo)) { return response; } @@ -249,8 +275,7 @@ async function handleLogoutInternalRedirects({ response, recipeImplementation, s return endSessionRes; } response = endSessionRes; - } - else { + } else { throw new Error(`Unexpected internal redirect ${response.redirectTo}`); } redirectCount++; diff --git a/lib/build/recipe/oauth2provider/index.d.ts b/lib/build/recipe/oauth2provider/index.d.ts index e81b9b6c5..2df42517f 100644 --- a/lib/build/recipe/oauth2provider/index.d.ts +++ b/lib/build/recipe/oauth2provider/index.d.ts @@ -1,67 +1,134 @@ // @ts-nocheck import Recipe from "./recipe"; -import { APIInterface, RecipeInterface, APIOptions, CreateOAuth2ClientInput, UpdateOAuth2ClientInput, DeleteOAuth2ClientInput, GetOAuth2ClientsInput } from "./types"; +import { + APIInterface, + RecipeInterface, + APIOptions, + CreateOAuth2ClientInput, + UpdateOAuth2ClientInput, + DeleteOAuth2ClientInput, + GetOAuth2ClientsInput, +} from "./types"; export default class Wrapper { static init: typeof Recipe.init; - static getOAuth2Client(clientId: string, userContext?: Record): Promise<{ - status: "OK"; - client: import("./OAuth2Client").OAuth2Client; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - static getOAuth2Clients(input: GetOAuth2ClientsInput, userContext?: Record): Promise<{ - status: "OK"; - clients: Array; - nextPaginationToken?: string; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - static createOAuth2Client(input: CreateOAuth2ClientInput, userContext?: Record): Promise<{ - status: "OK"; - client: import("./OAuth2Client").OAuth2Client; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - static updateOAuth2Client(input: UpdateOAuth2ClientInput, userContext?: Record): Promise<{ - status: "OK"; - client: import("./OAuth2Client").OAuth2Client; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - static deleteOAuth2Client(input: DeleteOAuth2ClientInput, userContext?: Record): Promise<{ - status: "OK"; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - static validateOAuth2AccessToken(token: string, requirements?: { - clientId?: string; - scopes?: string[]; - audience?: string; - }, checkDatabase?: boolean, userContext?: Record): Promise<{ + static getOAuth2Client( + clientId: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + client: import("./OAuth2Client").OAuth2Client; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + static getOAuth2Clients( + input: GetOAuth2ClientsInput, + userContext?: Record + ): Promise< + | { + status: "OK"; + clients: Array; + nextPaginationToken?: string; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + static createOAuth2Client( + input: CreateOAuth2ClientInput, + userContext?: Record + ): Promise< + | { + status: "OK"; + client: import("./OAuth2Client").OAuth2Client; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + static updateOAuth2Client( + input: UpdateOAuth2ClientInput, + userContext?: Record + ): Promise< + | { + status: "OK"; + client: import("./OAuth2Client").OAuth2Client; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + static deleteOAuth2Client( + input: DeleteOAuth2ClientInput, + userContext?: Record + ): Promise< + | { + status: "OK"; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + static validateOAuth2AccessToken( + token: string, + requirements?: { + clientId?: string; + scopes?: string[]; + audience?: string; + }, + checkDatabase?: boolean, + userContext?: Record + ): Promise<{ status: "OK"; payload: import("../usermetadata").JSONObject; }>; - static createTokenForClientCredentials(clientId: string, clientSecret: string, scope?: string[], audience?: string, userContext?: Record): Promise; - static revokeToken(token: string, clientId: string, clientSecret?: string, userContext?: Record): Promise; - static revokeTokensByClientId(clientId: string, userContext?: Record): Promise<{ + static createTokenForClientCredentials( + clientId: string, + clientSecret: string, + scope?: string[], + audience?: string, + userContext?: Record + ): Promise; + static revokeToken( + token: string, + clientId: string, + clientSecret?: string, + userContext?: Record + ): Promise< + | import("./types").ErrorOAuth2 + | { + status: "OK"; + } + >; + static revokeTokensByClientId( + clientId: string, + userContext?: Record + ): Promise<{ status: "OK"; }>; - static revokeTokensBySessionHandle(sessionHandle: string, userContext?: Record): Promise<{ + static revokeTokensBySessionHandle( + sessionHandle: string, + userContext?: Record + ): Promise<{ status: "OK"; }>; - static validateOAuth2RefreshToken(token: string, scopes?: string[], userContext?: Record): Promise; + static validateOAuth2RefreshToken( + token: string, + scopes?: string[], + userContext?: Record + ): Promise; } export declare let init: typeof Recipe.init; export declare let getOAuth2Client: typeof Wrapper.getOAuth2Client; diff --git a/lib/build/recipe/oauth2provider/index.js b/lib/build/recipe/oauth2provider/index.js index c47012458..cd56b52c9 100644 --- a/lib/build/recipe/oauth2provider/index.js +++ b/lib/build/recipe/oauth2provider/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.revokeTokensBySessionHandle = exports.revokeTokensByClientId = exports.revokeToken = exports.createTokenForClientCredentials = exports.validateOAuth2RefreshToken = exports.validateOAuth2AccessToken = exports.deleteOAuth2Client = exports.updateOAuth2Client = exports.createOAuth2Client = exports.getOAuth2Clients = exports.getOAuth2Client = exports.init = void 0; const utils_1 = require("../../utils"); @@ -28,16 +30,32 @@ class Wrapper { }); } static async getOAuth2Clients(input, userContext) { - return await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.getOAuth2Clients(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) })); + return await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.getOAuth2Clients( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) }) + ); } static async createOAuth2Client(input, userContext) { - return await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createOAuth2Client(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) })); + return await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.createOAuth2Client( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) }) + ); } static async updateOAuth2Client(input, userContext) { - return await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.updateOAuth2Client(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) })); + return await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.updateOAuth2Client( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) }) + ); } static async deleteOAuth2Client(input, userContext) { - return await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.deleteOAuth2Client(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) })); + return await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.deleteOAuth2Client( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(userContext) }) + ); } static validateOAuth2AccessToken(token, requirements, checkDatabase, userContext) { return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.validateOAuth2AccessToken({ @@ -70,8 +88,7 @@ class Wrapper { const { tokenEndpointAuthMethod } = res.client; if (tokenEndpointAuthMethod === "none") { authorizationHeader = "Basic " + Buffer.from(clientId + ":").toString("base64"); - } - else if (tokenEndpointAuthMethod === "client_secret_basic") { + } else if (tokenEndpointAuthMethod === "client_secret_basic") { authorizationHeader = "Basic " + Buffer.from(clientId + ":" + clientSecret).toString("base64"); } if (authorizationHeader !== undefined) { diff --git a/lib/build/recipe/oauth2provider/recipe.d.ts b/lib/build/recipe/oauth2provider/recipe.d.ts index 31819ab29..6afd8ddcc 100644 --- a/lib/build/recipe/oauth2provider/recipe.d.ts +++ b/lib/build/recipe/oauth2provider/recipe.d.ts @@ -4,7 +4,15 @@ import type { BaseRequest, BaseResponse } from "../../framework"; import NormalisedURLPath from "../../normalisedURLPath"; import RecipeModule from "../../recipeModule"; import { APIHandled, HTTPMethod, JSONObject, NormalisedAppinfo, RecipeListFunction, UserContext } from "../../types"; -import { APIInterface, PayloadBuilderFunction, RecipeInterface, TypeInput, TypeNormalisedInput, UserInfo, UserInfoBuilderFunction } from "./types"; +import { + APIInterface, + PayloadBuilderFunction, + RecipeInterface, + TypeInput, + TypeNormalisedInput, + UserInfo, + UserInfoBuilderFunction, +} from "./types"; import { User } from "../../user"; export default class Recipe extends RecipeModule { static RECIPE_ID: "oauth2provider"; @@ -25,11 +33,35 @@ export default class Recipe extends RecipeModule { addAccessTokenBuilderFromOtherRecipe: (accessTokenBuilders: PayloadBuilderFunction) => void; addIdTokenBuilderFromOtherRecipe: (idTokenBuilder: PayloadBuilderFunction) => void; getAPIsHandled(): APIHandled[]; - handleAPIRequest: (id: string, tenantId: string, req: BaseRequest, res: BaseResponse, _path: NormalisedURLPath, method: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + tenantId: string, + req: BaseRequest, + res: BaseResponse, + _path: NormalisedURLPath, + method: HTTPMethod, + userContext: UserContext + ) => Promise; handleError(error: error, _: BaseRequest, __: BaseResponse, _userContext: UserContext): Promise; getAllCORSHeaders(): string[]; isErrorFromThisRecipe(err: any): err is error; - getDefaultAccessTokenPayload(user: User, scopes: string[], sessionHandle: string, userContext: UserContext): Promise; - getDefaultIdTokenPayload(user: User, scopes: string[], sessionHandle: string, userContext: UserContext): Promise; - getDefaultUserInfoPayload(user: User, accessTokenPayload: JSONObject, scopes: string[], tenantId: string, userContext: UserContext): Promise; + getDefaultAccessTokenPayload( + user: User, + scopes: string[], + sessionHandle: string, + userContext: UserContext + ): Promise; + getDefaultIdTokenPayload( + user: User, + scopes: string[], + sessionHandle: string, + userContext: UserContext + ): Promise; + getDefaultUserInfoPayload( + user: User, + accessTokenPayload: JSONObject, + scopes: string[], + tenantId: string, + userContext: UserContext + ): Promise; } diff --git a/lib/build/recipe/oauth2provider/recipe.js b/lib/build/recipe/oauth2provider/recipe.js index fe886b694..93d5b954e 100644 --- a/lib/build/recipe/oauth2provider/recipe.js +++ b/lib/build/recipe/oauth2provider/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -96,7 +98,16 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_1.validateAndNormaliseUserInput)(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.config, appInfo, this.getDefaultAccessTokenPayload.bind(this), this.getDefaultIdTokenPayload.bind(this), this.getDefaultUserInfoPayload.bind(this))); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + this.config, + appInfo, + this.getDefaultAccessTokenPayload.bind(this), + this.getDefaultIdTokenPayload.bind(this), + this.getDefaultUserInfoPayload.bind(this) + ) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -117,10 +128,18 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return Recipe.instance; - } - else { + } else { throw new Error("OAuth2Provider recipe has already been initialised. Please check your code for bugs."); } }; @@ -210,16 +229,22 @@ class Recipe extends recipeModule_1.default { let payload = {}; if (scopes.includes("email")) { payload.email = user === null || user === void 0 ? void 0 : user.emails[0]; - payload.email_verified = user.loginMethods.some((lm) => lm.hasSameEmailAs(user === null || user === void 0 ? void 0 : user.emails[0]) && lm.verified); + payload.email_verified = user.loginMethods.some( + (lm) => lm.hasSameEmailAs(user === null || user === void 0 ? void 0 : user.emails[0]) && lm.verified + ); payload.emails = user.emails; } if (scopes.includes("phoneNumber")) { payload.phoneNumber = user === null || user === void 0 ? void 0 : user.phoneNumbers[0]; - payload.phoneNumber_verified = user.loginMethods.some((lm) => lm.hasSamePhoneNumberAs(user === null || user === void 0 ? void 0 : user.phoneNumbers[0]) && lm.verified); + payload.phoneNumber_verified = user.loginMethods.some( + (lm) => + lm.hasSamePhoneNumberAs(user === null || user === void 0 ? void 0 : user.phoneNumbers[0]) && + lm.verified + ); payload.phoneNumbers = user.phoneNumbers; } for (const fn of this.accessTokenBuilders) { - payload = Object.assign(Object.assign({}, payload), (await fn(user, scopes, sessionHandle, userContext))); + payload = Object.assign(Object.assign({}, payload), await fn(user, scopes, sessionHandle, userContext)); } return payload; } @@ -227,16 +252,22 @@ class Recipe extends recipeModule_1.default { let payload = {}; if (scopes.includes("email")) { payload.email = user === null || user === void 0 ? void 0 : user.emails[0]; - payload.email_verified = user.loginMethods.some((lm) => lm.hasSameEmailAs(user === null || user === void 0 ? void 0 : user.emails[0]) && lm.verified); + payload.email_verified = user.loginMethods.some( + (lm) => lm.hasSameEmailAs(user === null || user === void 0 ? void 0 : user.emails[0]) && lm.verified + ); payload.emails = user.emails; } if (scopes.includes("phoneNumber")) { payload.phoneNumber = user === null || user === void 0 ? void 0 : user.phoneNumbers[0]; - payload.phoneNumber_verified = user.loginMethods.some((lm) => lm.hasSamePhoneNumberAs(user === null || user === void 0 ? void 0 : user.phoneNumbers[0]) && lm.verified); + payload.phoneNumber_verified = user.loginMethods.some( + (lm) => + lm.hasSamePhoneNumberAs(user === null || user === void 0 ? void 0 : user.phoneNumbers[0]) && + lm.verified + ); payload.phoneNumbers = user.phoneNumbers; } for (const fn of this.idTokenBuilders) { - payload = Object.assign(Object.assign({}, payload), (await fn(user, scopes, sessionHandle, userContext))); + payload = Object.assign(Object.assign({}, payload), await fn(user, scopes, sessionHandle, userContext)); } return payload; } @@ -247,16 +278,25 @@ class Recipe extends recipeModule_1.default { if (scopes.includes("email")) { // TODO: try and get the email based on the user id of the entire user object payload.email = user === null || user === void 0 ? void 0 : user.emails[0]; - payload.email_verified = user.loginMethods.some((lm) => lm.hasSameEmailAs(user === null || user === void 0 ? void 0 : user.emails[0]) && lm.verified); + payload.email_verified = user.loginMethods.some( + (lm) => lm.hasSameEmailAs(user === null || user === void 0 ? void 0 : user.emails[0]) && lm.verified + ); payload.emails = user.emails; } if (scopes.includes("phoneNumber")) { payload.phoneNumber = user === null || user === void 0 ? void 0 : user.phoneNumbers[0]; - payload.phoneNumber_verified = user.loginMethods.some((lm) => lm.hasSamePhoneNumberAs(user === null || user === void 0 ? void 0 : user.phoneNumbers[0]) && lm.verified); + payload.phoneNumber_verified = user.loginMethods.some( + (lm) => + lm.hasSamePhoneNumberAs(user === null || user === void 0 ? void 0 : user.phoneNumbers[0]) && + lm.verified + ); payload.phoneNumbers = user.phoneNumbers; } for (const fn of this.userInfoBuilders) { - payload = Object.assign(Object.assign({}, payload), (await fn(user, accessTokenPayload, scopes, tenantId, userContext))); + payload = Object.assign( + Object.assign({}, payload), + await fn(user, accessTokenPayload, scopes, tenantId, userContext) + ); } return payload; } diff --git a/lib/build/recipe/oauth2provider/recipeImplementation.d.ts b/lib/build/recipe/oauth2provider/recipeImplementation.d.ts index 571e44ab4..4ecaeef69 100644 --- a/lib/build/recipe/oauth2provider/recipeImplementation.d.ts +++ b/lib/build/recipe/oauth2provider/recipeImplementation.d.ts @@ -2,4 +2,11 @@ import { Querier } from "../../querier"; import { NormalisedAppinfo } from "../../types"; import { RecipeInterface, TypeNormalisedInput, PayloadBuilderFunction, UserInfoBuilderFunction } from "./types"; -export default function getRecipeInterface(querier: Querier, _config: TypeNormalisedInput, appInfo: NormalisedAppinfo, getDefaultAccessTokenPayload: PayloadBuilderFunction, getDefaultIdTokenPayload: PayloadBuilderFunction, getDefaultUserInfoPayload: UserInfoBuilderFunction): RecipeInterface; +export default function getRecipeInterface( + querier: Querier, + _config: TypeNormalisedInput, + appInfo: NormalisedAppinfo, + getDefaultAccessTokenPayload: PayloadBuilderFunction, + getDefaultIdTokenPayload: PayloadBuilderFunction, + getDefaultUserInfoPayload: UserInfoBuilderFunction +): RecipeInterface; diff --git a/lib/build/recipe/oauth2provider/recipeImplementation.js b/lib/build/recipe/oauth2provider/recipeImplementation.js index ca5adb88b..c776e4599 100644 --- a/lib/build/recipe/oauth2provider/recipeImplementation.js +++ b/lib/build/recipe/oauth2provider/recipeImplementation.js @@ -13,42 +13,63 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const jose = __importStar(require("jose")); @@ -61,7 +82,10 @@ const recipe_2 = __importDefault(require("../openid/recipe")); const constants_1 = require("../multitenancy/constants"); const utils_1 = require("../../utils"); function getUpdatedRedirectTo(appInfo, redirectTo) { - return redirectTo.replace("{apiDomain}", appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous()); + return redirectTo.replace( + "{apiDomain}", + appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous() + ); } function copyAndCleanRequestBodyInput(input) { let result = Object.assign({}, input); @@ -70,10 +94,21 @@ function copyAndCleanRequestBodyInput(input) { delete result.session; return result; } -function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayload, getDefaultIdTokenPayload, getDefaultUserInfoPayload) { +function getRecipeInterface( + querier, + _config, + appInfo, + getDefaultAccessTokenPayload, + getDefaultIdTokenPayload, + getDefaultUserInfoPayload +) { return { getLoginRequest: async function (input) { - const resp = await querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/oauth/auth/requests/login"), { loginChallenge: input.challenge }, input.userContext); + const resp = await querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/oauth/auth/requests/login"), + { loginChallenge: input.challenge }, + input.userContext + ); if (resp.status !== "OK") { return { status: "ERROR", @@ -96,34 +131,48 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl }; }, acceptLoginRequest: async function (input) { - const resp = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/login/accept`), { - acr: input.acr, - amr: input.amr, - context: input.context, - extendSessionLifespan: input.extendSessionLifespan, - identityProviderSessionId: input.identityProviderSessionId, - subject: input.subject, - }, { - loginChallenge: input.challenge, - }, input.userContext); + const resp = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/login/accept`), + { + acr: input.acr, + amr: input.amr, + context: input.context, + extendSessionLifespan: input.extendSessionLifespan, + identityProviderSessionId: input.identityProviderSessionId, + subject: input.subject, + }, + { + loginChallenge: input.challenge, + }, + input.userContext + ); return { redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo), }; }, rejectLoginRequest: async function (input) { - const resp = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/login/reject`), { - error: input.error.error, - errorDescription: input.error.errorDescription, - statusCode: input.error.statusCode, - }, { - login_challenge: input.challenge, - }, input.userContext); + const resp = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/login/reject`), + { + error: input.error.error, + errorDescription: input.error.errorDescription, + statusCode: input.error.statusCode, + }, + { + login_challenge: input.challenge, + }, + input.userContext + ); return { redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo), }; }, getConsentRequest: async function (input) { - const resp = await querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/oauth/auth/requests/consent"), { consentChallenge: input.challenge }, input.userContext); + const resp = await querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/oauth/auth/requests/consent"), + { consentChallenge: input.challenge }, + input.userContext + ); return { acr: resp.acr, amr: resp.amr, @@ -140,32 +189,42 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl }; }, acceptConsentRequest: async function (input) { - const resp = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/consent/accept`), { - context: input.context, - grantAccessTokenAudience: input.grantAccessTokenAudience, - grantScope: input.grantScope, - handledAt: input.handledAt, - iss: await recipe_2.default.getIssuer(input.userContext), - tId: input.tenantId, - rsub: input.rsub, - sessionHandle: input.sessionHandle, - initialAccessTokenPayload: input.initialAccessTokenPayload, - initialIdTokenPayload: input.initialIdTokenPayload, - }, { - consentChallenge: input.challenge, - }, input.userContext); + const resp = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/consent/accept`), + { + context: input.context, + grantAccessTokenAudience: input.grantAccessTokenAudience, + grantScope: input.grantScope, + handledAt: input.handledAt, + iss: await recipe_2.default.getIssuer(input.userContext), + tId: input.tenantId, + rsub: input.rsub, + sessionHandle: input.sessionHandle, + initialAccessTokenPayload: input.initialAccessTokenPayload, + initialIdTokenPayload: input.initialIdTokenPayload, + }, + { + consentChallenge: input.challenge, + }, + input.userContext + ); return { redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo), }; }, rejectConsentRequest: async function (input) { - const resp = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/consent/reject`), { - error: input.error.error, - errorDescription: input.error.errorDescription, - statusCode: input.error.statusCode, - }, { - consentChallenge: input.challenge, - }, input.userContext); + const resp = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/consent/reject`), + { + error: input.error.error, + errorDescription: input.error.errorDescription, + statusCode: input.error.statusCode, + }, + { + consentChallenge: input.challenge, + }, + input.userContext + ); return { redirectTo: getUpdatedRedirectTo(appInfo, resp.redirectTo), }; @@ -193,7 +252,11 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl sessionHandle: (_c = input.session) === null || _c === void 0 ? void 0 : _c.getHandle(), userContext: input.userContext, }); - const responseTypes = (_e = (_d = input.params.response_type) === null || _d === void 0 ? void 0 : _d.split(" ")) !== null && _e !== void 0 ? _e : []; + const responseTypes = + (_e = (_d = input.params.response_type) === null || _d === void 0 ? void 0 : _d.split(" ")) !== null && + _e !== void 0 + ? _e + : []; if (input.session !== undefined) { const clientInfo = await this.getOAuth2Client({ clientId: input.params.client_id, @@ -219,35 +282,41 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl } // These default to an empty objects, because we want to keep them as a required input // but they'll not be actually used in the flows where we are not building them. - const idToken = scopes.includes("openid") && (responseTypes.includes("id_token") || responseTypes.includes("code")) - ? await this.buildIdTokenPayload({ - user, - client, - sessionHandle: input.session.getHandle(), - scopes, - userContext: input.userContext, - }) - : {}; - const accessToken = responseTypes.includes("token") || responseTypes.includes("code") - ? await this.buildAccessTokenPayload({ - user, - client, - sessionHandle: input.session.getHandle(), - scopes, - userContext: input.userContext, - }) - : {}; + const idToken = + scopes.includes("openid") && (responseTypes.includes("id_token") || responseTypes.includes("code")) + ? await this.buildIdTokenPayload({ + user, + client, + sessionHandle: input.session.getHandle(), + scopes, + userContext: input.userContext, + }) + : {}; + const accessToken = + responseTypes.includes("token") || responseTypes.includes("code") + ? await this.buildAccessTokenPayload({ + user, + client, + sessionHandle: input.session.getHandle(), + scopes, + userContext: input.userContext, + }) + : {}; payloads = { idToken, accessToken, }; } - const resp = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/auth`), { - params: Object.assign(Object.assign({}, input.params), { scope: scopes.join(" ") }), - iss: await recipe_2.default.getIssuer(input.userContext), - cookies: input.cookies, - session: payloads, - }, input.userContext); + const resp = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/auth`), + { + params: Object.assign(Object.assign({}, input.params), { scope: scopes.join(" ") }), + iss: await recipe_2.default.getIssuer(input.userContext), + cookies: input.cookies, + session: payloads, + }, + input.userContext + ); if (resp.status === "CLIENT_NOT_FOUND_ERROR") { return { status: "ERROR", @@ -309,9 +378,12 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl }; } if (input.body.grant_type === "client_credentials") { - let clientId = input.authorizationHeader !== undefined - ? (0, utils_1.decodeBase64)(input.authorizationHeader.replace(/^Basic /, "").trim()).split(":")[0] - : input.body.client_id; + let clientId = + input.authorizationHeader !== undefined + ? (0, utils_1.decodeBase64)(input.authorizationHeader.replace(/^Basic /, "").trim()).split( + ":" + )[0] + : input.body.client_id; if (clientId === undefined) { return { status: "ERROR", @@ -320,7 +392,11 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl errorDescription: "client_id is required", }; } - const scopes = (_b = (_a = input.body.scope) === null || _a === void 0 ? void 0 : _a.split(" ")) !== null && _b !== void 0 ? _b : []; + const scopes = + (_b = (_a = input.body.scope) === null || _a === void 0 ? void 0 : _a.split(" ")) !== null && + _b !== void 0 + ? _b + : []; const clientInfo = await this.getOAuth2Client({ clientId, userContext: input.userContext, @@ -350,7 +426,11 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl }); } if (input.body.grant_type === "refresh_token") { - const scopes = (_d = (_c = input.body.scope) === null || _c === void 0 ? void 0 : _c.split(" ")) !== null && _d !== void 0 ? _d : []; + const scopes = + (_d = (_c = input.body.scope) === null || _c === void 0 ? void 0 : _c.split(" ")) !== null && + _d !== void 0 + ? _d + : []; const tokenInfo = await this.introspectToken({ token: input.body.refresh_token, scopes, @@ -399,7 +479,11 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl if (input.authorizationHeader) { body["authorizationHeader"] = input.authorizationHeader; } - const res = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/token`), body, input.userContext); + const res = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/token`), + body, + input.userContext + ); if (res.status === "CLIENT_NOT_FOUND_ERROR") { return { status: "ERROR", @@ -419,19 +503,23 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl return res; }, getOAuth2Clients: async function (input) { - let response = await querier.sendGetRequestWithResponseHeaders(new normalisedURLPath_1.default(`/recipe/oauth/clients/list`), { - pageSize: input.pageSize, - clientName: input.clientName, - pageToken: input.paginationToken, - }, {}, input.userContext); + let response = await querier.sendGetRequestWithResponseHeaders( + new normalisedURLPath_1.default(`/recipe/oauth/clients/list`), + { + pageSize: input.pageSize, + clientName: input.clientName, + pageToken: input.paginationToken, + }, + {}, + input.userContext + ); if (response.body.status === "OK") { return { status: "OK", clients: response.body.clients.map((client) => OAuth2Client_1.OAuth2Client.fromAPIResponse(client)), nextPaginationToken: response.body.nextPaginationToken, }; - } - else { + } else { return { status: "ERROR", error: response.body.error, @@ -440,21 +528,24 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl } }, getOAuth2Client: async function (input) { - let response = await querier.sendGetRequestWithResponseHeaders(new normalisedURLPath_1.default(`/recipe/oauth/clients`), { clientId: input.clientId }, {}, input.userContext); + let response = await querier.sendGetRequestWithResponseHeaders( + new normalisedURLPath_1.default(`/recipe/oauth/clients`), + { clientId: input.clientId }, + {}, + input.userContext + ); if (response.body.status === "OK") { return { status: "OK", client: OAuth2Client_1.OAuth2Client.fromAPIResponse(response.body), }; - } - else if (response.body.status === "CLIENT_NOT_FOUND_ERROR") { + } else if (response.body.status === "CLIENT_NOT_FOUND_ERROR") { return { status: "ERROR", error: "invalid_request", errorDescription: "The provided client_id is not valid or unknown", }; - } - else { + } else { return { status: "ERROR", error: response.body.error, @@ -463,14 +554,17 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl } }, createOAuth2Client: async function (input) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/clients`), copyAndCleanRequestBodyInput(input), input.userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/clients`), + copyAndCleanRequestBodyInput(input), + input.userContext + ); if (response.status === "OK") { return { status: "OK", client: OAuth2Client_1.OAuth2Client.fromAPIResponse(response), }; - } - else { + } else { return { status: "ERROR", error: response.error, @@ -479,14 +573,18 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl } }, updateOAuth2Client: async function (input) { - let response = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/oauth/clients`), copyAndCleanRequestBodyInput(input), { clientId: input.clientId }, input.userContext); + let response = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/oauth/clients`), + copyAndCleanRequestBodyInput(input), + { clientId: input.clientId }, + input.userContext + ); if (response.status === "OK") { return { status: "OK", client: OAuth2Client_1.OAuth2Client.fromAPIResponse(response), }; - } - else { + } else { return { status: "ERROR", error: response.error, @@ -495,11 +593,14 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl } }, deleteOAuth2Client: async function (input) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/clients/remove`), { clientId: input.clientId }, input.userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/clients/remove`), + { clientId: input.clientId }, + input.userContext + ); if (response.status === "OK") { return { status: "OK" }; - } - else { + } else { return { status: "ERROR", error: response.error, @@ -544,39 +645,55 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl queryParams.set("forceFreshAuth", "true"); } return `${websiteDomain}${websiteBasePath}?${queryParams.toString()}`; - } - else if (input.type === "try-refresh") { + } else if (input.type === "try-refresh") { return `${websiteDomain}${websiteBasePath}/try-refresh?loginChallenge=${input.loginChallenge}`; - } - else if (input.type === "post-logout-fallback") { + } else if (input.type === "post-logout-fallback") { return `${websiteDomain}${websiteBasePath}`; - } - else if (input.type === "logout-confirmation") { + } else if (input.type === "logout-confirmation") { return `${websiteDomain}${websiteBasePath}/oauth/logout?logoutChallenge=${input.logoutChallenge}`; } throw new Error("This should never happen: invalid type passed to getFrontendRedirectionURL"); }, validateOAuth2AccessToken: async function (input) { var _a, _b, _c; - const payload = (await jose.jwtVerify(input.token, (0, combinedRemoteJWKSet_1.getCombinedJWKS)(recipe_1.default.getInstanceOrThrowError().config))).payload; + const payload = ( + await jose.jwtVerify( + input.token, + (0, combinedRemoteJWKSet_1.getCombinedJWKS)(recipe_1.default.getInstanceOrThrowError().config) + ) + ).payload; if (payload.stt !== 1) { throw new Error("Wrong token type"); } - if (((_a = input.requirements) === null || _a === void 0 ? void 0 : _a.clientId) !== undefined && payload.client_id !== input.requirements.clientId) { - throw new Error(`The token doesn't belong to the specified client (${input.requirements.clientId} !== ${payload.client_id})`); - } - if (((_b = input.requirements) === null || _b === void 0 ? void 0 : _b.scopes) !== undefined && - input.requirements.scopes.some((scope) => !payload.scp.includes(scope))) { + if ( + ((_a = input.requirements) === null || _a === void 0 ? void 0 : _a.clientId) !== undefined && + payload.client_id !== input.requirements.clientId + ) { + throw new Error( + `The token doesn't belong to the specified client (${input.requirements.clientId} !== ${payload.client_id})` + ); + } + if ( + ((_b = input.requirements) === null || _b === void 0 ? void 0 : _b.scopes) !== undefined && + input.requirements.scopes.some((scope) => !payload.scp.includes(scope)) + ) { throw new Error("The token is missing some required scopes"); } const aud = payload.aud instanceof Array ? payload.aud : [payload.aud]; - if (((_c = input.requirements) === null || _c === void 0 ? void 0 : _c.audience) !== undefined && !aud.includes(input.requirements.audience)) { + if ( + ((_c = input.requirements) === null || _c === void 0 ? void 0 : _c.audience) !== undefined && + !aud.includes(input.requirements.audience) + ) { throw new Error("The token doesn't belong to the specified audience"); } if (input.checkDatabase) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/introspect`), { - token: input.token, - }, input.userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/introspect`), + { + token: input.token, + }, + input.userContext + ); if (response.active !== true) { throw new Error("The token is expired, invalid or has been revoked"); } @@ -589,8 +706,7 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl }; if ("authorizationHeader" in input && input.authorizationHeader !== undefined) { requestBody.authorizationHeader = input.authorizationHeader; - } - else { + } else { if ("clientId" in input && input.clientId !== undefined) { requestBody.client_id = input.clientId; } @@ -598,7 +714,11 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl requestBody.client_secret = input.clientSecret; } } - const res = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/token/revoke`), requestBody, input.userContext); + const res = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/token/revoke`), + requestBody, + input.userContext + ); if (res.status !== "OK") { return { status: "ERROR", @@ -610,11 +730,19 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl return { status: "OK" }; }, revokeTokensBySessionHandle: async function (input) { - await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/session/revoke`), { sessionHandle: input.sessionHandle }, input.userContext); + await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/session/revoke`), + { sessionHandle: input.sessionHandle }, + input.userContext + ); return { status: "OK" }; }, revokeTokensByClientId: async function (input) { - await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/tokens/revoke`), { clientId: input.clientId }, input.userContext); + await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/tokens/revoke`), + { clientId: input.clientId }, + input.userContext + ); return { status: "OK" }; }, introspectToken: async function ({ token, scopes, userContext }) { @@ -630,17 +758,20 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl checkDatabase: false, userContext, }); - } - catch (error) { + } catch (error) { return { active: false }; } } // For tokens that passed local validation or if it's a refresh token, // validate the token with the database by calling the core introspection endpoint - const res = await querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/oauth/introspect`), { - token, - scope: scopes ? scopes.join(" ") : undefined, - }, userContext); + const res = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/oauth/introspect`), + { + token, + scope: scopes ? scopes.join(" ") : undefined, + }, + userContext + ); return res; }, endSession: async function (input) { @@ -656,13 +787,17 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl * CASE 3: `end_session` request with a `logout_verifier` (after accepting the logout request) * - Redirects to the `post_logout_redirect_uri` or the default logout fallback page. */ - const resp = await querier.sendGetRequest(new normalisedURLPath_1.default(`/recipe/oauth/sessions/logout`), { - clientId: input.params.client_id, - idTokenHint: input.params.id_token_hint, - postLogoutRedirectUri: input.params.post_logout_redirect_uri, - state: input.params.state, - logoutVerifier: input.params.logout_verifier, - }, input.userContext); + const resp = await querier.sendGetRequest( + new normalisedURLPath_1.default(`/recipe/oauth/sessions/logout`), + { + clientId: input.params.client_id, + idTokenHint: input.params.id_token_hint, + postLogoutRedirectUri: input.params.post_logout_redirect_uri, + state: input.params.state, + logoutVerifier: input.params.logout_verifier, + }, + input.userContext + ); if ("error" in resp) { return { status: "ERROR", @@ -685,8 +820,7 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl userContext: input.userContext, }), }; - } - else { + } else { // Accept the logout challenge immediately as there is no supertokens session const acceptLogoutResponse = await this.acceptLogoutRequest({ challenge: logoutChallenge, @@ -712,7 +846,12 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl return { redirectTo }; }, acceptLogoutRequest: async function (input) { - const resp = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/logout/accept`), { challenge: input.challenge }, {}, input.userContext); + const resp = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/logout/accept`), + { challenge: input.challenge }, + {}, + input.userContext + ); if (resp.status !== "OK") { return { status: "ERROR", @@ -733,7 +872,12 @@ function getRecipeInterface(querier, _config, appInfo, getDefaultAccessTokenPayl return { redirectTo }; }, rejectLogoutRequest: async function (input) { - const resp = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/logout/reject`), {}, { challenge: input.challenge }, input.userContext); + const resp = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/oauth/auth/requests/logout/reject`), + {}, + { challenge: input.challenge }, + input.userContext + ); if (resp.status != "OK") { throw new Error(resp.error); } diff --git a/lib/build/recipe/oauth2provider/types.d.ts b/lib/build/recipe/oauth2provider/types.d.ts index 6af202c5e..907750601 100644 --- a/lib/build/recipe/oauth2provider/types.d.ts +++ b/lib/build/recipe/oauth2provider/types.d.ts @@ -8,13 +8,19 @@ import { User } from "../../user"; import RecipeUserId from "../../recipeUserId"; export type TypeInput = { override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -82,30 +88,32 @@ export type UserInfo = { phoneNumber_verified?: boolean; [key: string]: JSONValue; }; -export type InstrospectTokenResponse = { - active: false; -} | ({ - active: true; -} & JSONObject); +export type InstrospectTokenResponse = + | { + active: false; + } + | ({ + active: true; + } & JSONObject); export type RecipeInterface = { authorization(input: { params: Record; cookies: string | undefined; session: SessionContainerInterface | undefined; userContext: UserContext; - }): Promise<{ - redirectTo: string; - cookies: string | undefined; - } | ErrorOAuth2>; + }): Promise< + | { + redirectTo: string; + cookies: string | undefined; + } + | ErrorOAuth2 + >; tokenExchange(input: { authorizationHeader?: string; body: Record; userContext: UserContext; }): Promise; - getConsentRequest(input: { - challenge: string; - userContext: UserContext; - }): Promise; + getConsentRequest(input: { challenge: string; userContext: UserContext }): Promise; acceptConsentRequest(input: { challenge: string; context?: any; @@ -131,9 +139,12 @@ export type RecipeInterface = { getLoginRequest(input: { challenge: string; userContext: UserContext; - }): Promise<(LoginRequest & { - status: "OK"; - }) | ErrorOAuth2>; + }): Promise< + | (LoginRequest & { + status: "OK"; + }) + | ErrorOAuth2 + >; acceptLoginRequest(input: { challenge: string; acr?: string; @@ -156,54 +167,77 @@ export type RecipeInterface = { getOAuth2Client(input: { clientId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - client: OAuth2Client; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - getOAuth2Clients(input: GetOAuth2ClientsInput & { - userContext: UserContext; - }): Promise<{ - status: "OK"; - clients: Array; - nextPaginationToken?: string; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - createOAuth2Client(input: CreateOAuth2ClientInput & { - userContext: UserContext; - }): Promise<{ - status: "OK"; - client: OAuth2Client; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - updateOAuth2Client(input: UpdateOAuth2ClientInput & { - userContext: UserContext; - }): Promise<{ - status: "OK"; - client: OAuth2Client; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; - deleteOAuth2Client(input: DeleteOAuth2ClientInput & { - userContext: UserContext; - }): Promise<{ - status: "OK"; - } | { - status: "ERROR"; - error: string; - errorDescription: string; - }>; + }): Promise< + | { + status: "OK"; + client: OAuth2Client; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + getOAuth2Clients( + input: GetOAuth2ClientsInput & { + userContext: UserContext; + } + ): Promise< + | { + status: "OK"; + clients: Array; + nextPaginationToken?: string; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + createOAuth2Client( + input: CreateOAuth2ClientInput & { + userContext: UserContext; + } + ): Promise< + | { + status: "OK"; + client: OAuth2Client; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + updateOAuth2Client( + input: UpdateOAuth2ClientInput & { + userContext: UserContext; + } + ): Promise< + | { + status: "OK"; + client: OAuth2Client; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; + deleteOAuth2Client( + input: DeleteOAuth2ClientInput & { + userContext: UserContext; + } + ): Promise< + | { + status: "OK"; + } + | { + status: "ERROR"; + error: string; + errorDescription: string; + } + >; validateOAuth2AccessToken(input: { token: string; requirements?: { @@ -245,36 +279,50 @@ export type RecipeInterface = { tenantId: string; userContext: UserContext; }): Promise; - getFrontendRedirectionURL(input: { - type: "login"; - loginChallenge: string; - tenantId: string; - forceFreshAuth: boolean; - hint: string | undefined; - userContext: UserContext; - } | { - type: "try-refresh"; - loginChallenge: string; - userContext: UserContext; - } | { - type: "logout-confirmation"; - logoutChallenge: string; - userContext: UserContext; - } | { - type: "post-logout-fallback"; - userContext: UserContext; - }): Promise; - revokeToken(input: { - token: string; - userContext: UserContext; - } & ({ - authorizationHeader: string; - } | { - clientId: string; - clientSecret?: string; - })): Promise<{ - status: "OK"; - } | ErrorOAuth2>; + getFrontendRedirectionURL( + input: + | { + type: "login"; + loginChallenge: string; + tenantId: string; + forceFreshAuth: boolean; + hint: string | undefined; + userContext: UserContext; + } + | { + type: "try-refresh"; + loginChallenge: string; + userContext: UserContext; + } + | { + type: "logout-confirmation"; + logoutChallenge: string; + userContext: UserContext; + } + | { + type: "post-logout-fallback"; + userContext: UserContext; + } + ): Promise; + revokeToken( + input: { + token: string; + userContext: UserContext; + } & ( + | { + authorizationHeader: string; + } + | { + clientId: string; + clientSecret?: string; + } + ) + ): Promise< + | { + status: "OK"; + } + | ErrorOAuth2 + >; revokeTokensByClientId(input: { clientId: string; userContext: UserContext; @@ -297,15 +345,21 @@ export type RecipeInterface = { session?: SessionContainerInterface; shouldTryRefresh: boolean; userContext: UserContext; - }): Promise<{ - redirectTo: string; - } | ErrorOAuth2>; + }): Promise< + | { + redirectTo: string; + } + | ErrorOAuth2 + >; acceptLogoutRequest(input: { challenge: string; userContext: UserContext; - }): Promise<{ - redirectTo: string; - } | ErrorOAuth2>; + }): Promise< + | { + redirectTo: string; + } + | ErrorOAuth2 + >; rejectLogoutRequest(input: { challenge: string; userContext: UserContext; @@ -314,94 +368,146 @@ export type RecipeInterface = { }>; }; export type APIInterface = { - loginGET: undefined | ((input: { - loginChallenge: string; - options: APIOptions; - session?: SessionContainerInterface; - shouldTryRefresh: boolean; - userContext: UserContext; - }) => Promise<{ - frontendRedirectTo: string; - cookies?: string; - } | ErrorOAuth2 | GeneralErrorResponse>); - authGET: undefined | ((input: { - params: any; - cookie: string | undefined; - session: SessionContainerInterface | undefined; - shouldTryRefresh: boolean; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - redirectTo: string; - cookies?: string; - } | ErrorOAuth2 | GeneralErrorResponse>); - tokenPOST: undefined | ((input: { - authorizationHeader?: string; - body: any; - options: APIOptions; - userContext: UserContext; - }) => Promise); - loginInfoGET: undefined | ((input: { - loginChallenge: string; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - info: LoginInfo; - } | ErrorOAuth2 | GeneralErrorResponse>); - userInfoGET: undefined | ((input: { - accessTokenPayload: JSONObject; - user: User; - scopes: string[]; - tenantId: string; - options: APIOptions; - userContext: UserContext; - }) => Promise); - revokeTokenPOST: undefined | ((input: { - token: string; - options: APIOptions; - userContext: UserContext; - } & ({ - authorizationHeader: string; - } | { - clientId: string; - clientSecret?: string; - })) => Promise<{ - status: "OK"; - } | ErrorOAuth2>); - introspectTokenPOST: undefined | ((input: { - token: string; - scopes?: string[]; - options: APIOptions; - userContext: UserContext; - }) => Promise); - endSessionGET: undefined | ((input: { - params: Record; - session?: SessionContainerInterface; - shouldTryRefresh: boolean; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - redirectTo: string; - } | ErrorOAuth2 | GeneralErrorResponse>); - endSessionPOST: undefined | ((input: { - params: Record; - session?: SessionContainerInterface; - shouldTryRefresh: boolean; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - redirectTo: string; - } | ErrorOAuth2 | GeneralErrorResponse>); - logoutPOST: undefined | ((input: { - logoutChallenge: string; - options: APIOptions; - session?: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - frontendRedirectTo: string; - } | ErrorOAuth2 | GeneralErrorResponse>); + loginGET: + | undefined + | ((input: { + loginChallenge: string; + options: APIOptions; + session?: SessionContainerInterface; + shouldTryRefresh: boolean; + userContext: UserContext; + }) => Promise< + | { + frontendRedirectTo: string; + cookies?: string; + } + | ErrorOAuth2 + | GeneralErrorResponse + >); + authGET: + | undefined + | ((input: { + params: any; + cookie: string | undefined; + session: SessionContainerInterface | undefined; + shouldTryRefresh: boolean; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + redirectTo: string; + cookies?: string; + } + | ErrorOAuth2 + | GeneralErrorResponse + >); + tokenPOST: + | undefined + | ((input: { + authorizationHeader?: string; + body: any; + options: APIOptions; + userContext: UserContext; + }) => Promise); + loginInfoGET: + | undefined + | ((input: { + loginChallenge: string; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + info: LoginInfo; + } + | ErrorOAuth2 + | GeneralErrorResponse + >); + userInfoGET: + | undefined + | ((input: { + accessTokenPayload: JSONObject; + user: User; + scopes: string[]; + tenantId: string; + options: APIOptions; + userContext: UserContext; + }) => Promise); + revokeTokenPOST: + | undefined + | (( + input: { + token: string; + options: APIOptions; + userContext: UserContext; + } & ( + | { + authorizationHeader: string; + } + | { + clientId: string; + clientSecret?: string; + } + ) + ) => Promise< + | { + status: "OK"; + } + | ErrorOAuth2 + >); + introspectTokenPOST: + | undefined + | ((input: { + token: string; + scopes?: string[]; + options: APIOptions; + userContext: UserContext; + }) => Promise); + endSessionGET: + | undefined + | ((input: { + params: Record; + session?: SessionContainerInterface; + shouldTryRefresh: boolean; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + redirectTo: string; + } + | ErrorOAuth2 + | GeneralErrorResponse + >); + endSessionPOST: + | undefined + | ((input: { + params: Record; + session?: SessionContainerInterface; + shouldTryRefresh: boolean; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + redirectTo: string; + } + | ErrorOAuth2 + | GeneralErrorResponse + >); + logoutPOST: + | undefined + | ((input: { + logoutChallenge: string; + options: APIOptions; + session?: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + frontendRedirectTo: string; + } + | ErrorOAuth2 + | GeneralErrorResponse + >); }; export type OAuth2ClientOptions = { clientId: string; @@ -447,7 +553,9 @@ export type GetOAuth2ClientsInput = { clientName?: string; }; export type CreateOAuth2ClientInput = Partial>; -export type UpdateOAuth2ClientInput = NonNullableProperties> & { +export type UpdateOAuth2ClientInput = NonNullableProperties< + Omit +> & { clientId: string; redirectUris?: string[] | null; grantTypes?: string[] | null; @@ -457,5 +565,16 @@ export type UpdateOAuth2ClientInput = NonNullableProperties Promise; -export type UserInfoBuilderFunction = (user: User, accessTokenPayload: JSONObject, scopes: string[], tenantId: string, userContext: UserContext) => Promise; +export type PayloadBuilderFunction = ( + user: User, + scopes: string[], + sessionHandle: string, + userContext: UserContext +) => Promise; +export type UserInfoBuilderFunction = ( + user: User, + accessTokenPayload: JSONObject, + scopes: string[], + tenantId: string, + userContext: UserContext +) => Promise; diff --git a/lib/build/recipe/oauth2provider/utils.d.ts b/lib/build/recipe/oauth2provider/utils.d.ts index 133d4840f..4025b1b44 100644 --- a/lib/build/recipe/oauth2provider/utils.d.ts +++ b/lib/build/recipe/oauth2provider/utils.d.ts @@ -2,4 +2,8 @@ import { NormalisedAppinfo } from "../../types"; import Recipe from "./recipe"; import { TypeInput, TypeNormalisedInput } from "./types"; -export declare function validateAndNormaliseUserInput(_: Recipe, __: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + _: Recipe, + __: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; diff --git a/lib/build/recipe/oauth2provider/utils.js b/lib/build/recipe/oauth2provider/utils.js index a6baa525b..f1892c87c 100644 --- a/lib/build/recipe/oauth2provider/utils.js +++ b/lib/build/recipe/oauth2provider/utils.js @@ -16,7 +16,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; function validateAndNormaliseUserInput(_, __, config) { - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { override, }; diff --git a/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.d.ts b/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.d.ts index 31f793b8c..45955e60f 100644 --- a/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.d.ts +++ b/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { UserContext } from "../../../types"; import { APIInterface, APIOptions } from "../types"; -export default function getOpenIdDiscoveryConfiguration(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function getOpenIdDiscoveryConfiguration( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.js b/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.js index c4d955cca..175eb33c8 100644 --- a/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.js +++ b/lib/build/recipe/openid/api/getOpenIdDiscoveryConfiguration.js @@ -25,8 +25,7 @@ async function getOpenIdDiscoveryConfiguration(apiImplementation, options, userC id_token_signing_alg_values_supported: result.id_token_signing_alg_values_supported, response_types_supported: result.response_types_supported, }); - } - else { + } else { (0, utils_1.send200Response)(options.res, result); } return true; diff --git a/lib/build/recipe/openid/index.d.ts b/lib/build/recipe/openid/index.d.ts index 7e921973b..84b55bd8c 100644 --- a/lib/build/recipe/openid/index.d.ts +++ b/lib/build/recipe/openid/index.d.ts @@ -2,7 +2,9 @@ import OpenIdRecipe from "./recipe"; export default class OpenIdRecipeWrapper { static init: typeof OpenIdRecipe.init; - static getOpenIdDiscoveryConfiguration(userContext?: Record): Promise<{ + static getOpenIdDiscoveryConfiguration( + userContext?: Record + ): Promise<{ status: "OK"; issuer: string; jwks_uri: string; diff --git a/lib/build/recipe/openid/index.js b/lib/build/recipe/openid/index.js index a2db963b5..bc8673582 100644 --- a/lib/build/recipe/openid/index.js +++ b/lib/build/recipe/openid/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getOpenIdDiscoveryConfiguration = exports.init = void 0; const utils_1 = require("../../utils"); diff --git a/lib/build/recipe/openid/recipe.d.ts b/lib/build/recipe/openid/recipe.d.ts index 49476b007..fd2505e28 100644 --- a/lib/build/recipe/openid/recipe.d.ts +++ b/lib/build/recipe/openid/recipe.d.ts @@ -17,7 +17,15 @@ export default class OpenIdRecipe extends RecipeModule { static reset(): void; static getIssuer(userContext: UserContext): Promise; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, _tenantId: string, req: BaseRequest, response: BaseResponse, _path: normalisedURLPath, _method: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + _tenantId: string, + req: BaseRequest, + response: BaseResponse, + _path: normalisedURLPath, + _method: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (error: STError) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; diff --git a/lib/build/recipe/openid/recipe.js b/lib/build/recipe/openid/recipe.js index 9d0b912b4..845b86706 100644 --- a/lib/build/recipe/openid/recipe.js +++ b/lib/build/recipe/openid/recipe.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * @@ -50,8 +52,7 @@ class OpenIdRecipe extends recipeModule_1.default { }; if (id === constants_1.GET_DISCOVERY_CONFIG_URL) { return await (0, getOpenIdDiscoveryConfiguration_1.default)(this.apiImpl, apiOptions, userContext); - } - else { + } else { return false; } }; @@ -79,10 +80,17 @@ class OpenIdRecipe extends recipeModule_1.default { static init(config) { return (appInfo, _isInServerlessEnv, plugins) => { if (OpenIdRecipe.instance === undefined) { - OpenIdRecipe.instance = new OpenIdRecipe(OpenIdRecipe.RECIPE_ID, appInfo, (0, utils_2.applyPlugins)(OpenIdRecipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + OpenIdRecipe.instance = new OpenIdRecipe( + OpenIdRecipe.RECIPE_ID, + appInfo, + (0, utils_2.applyPlugins)( + OpenIdRecipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return OpenIdRecipe.instance; - } - else { + } else { throw new Error("OpenId recipe has already been initialised. Please check your code for bugs."); } }; @@ -94,7 +102,9 @@ class OpenIdRecipe extends recipeModule_1.default { OpenIdRecipe.instance = undefined; } static async getIssuer(userContext) { - return (await this.getInstanceOrThrowError().recipeImplementation.getOpenIdDiscoveryConfiguration({ userContext })).issuer; + return ( + await this.getInstanceOrThrowError().recipeImplementation.getOpenIdDiscoveryConfiguration({ userContext }) + ).issuer; } } OpenIdRecipe.RECIPE_ID = "openid"; diff --git a/lib/build/recipe/openid/recipeImplementation.js b/lib/build/recipe/openid/recipeImplementation.js index 6f1fd775b..6af6994ec 100644 --- a/lib/build/recipe/openid/recipeImplementation.js +++ b/lib/build/recipe/openid/recipeImplementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const recipe_1 = __importDefault(require("../jwt/recipe")); @@ -12,8 +14,11 @@ function getRecipeInterface(appInfo) { return { getOpenIdDiscoveryConfiguration: async function () { let issuer = appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous(); - let jwks_uri = appInfo.apiDomain.getAsStringDangerous() + - appInfo.apiBasePath.appendPath(new normalisedURLPath_1.default(constants_1.GET_JWKS_API)).getAsStringDangerous(); + let jwks_uri = + appInfo.apiDomain.getAsStringDangerous() + + appInfo.apiBasePath + .appendPath(new normalisedURLPath_1.default(constants_1.GET_JWKS_API)) + .getAsStringDangerous(); const apiBasePath = appInfo.apiDomain.getAsStringDangerous() + appInfo.apiBasePath.getAsStringDangerous(); return { status: "OK", @@ -30,7 +35,7 @@ function getRecipeInterface(appInfo) { response_types_supported: ["code", "id_token", "id_token token"], }; }, - createJWT: async function ({ payload, validitySeconds, useStaticSigningKey, userContext, }) { + createJWT: async function ({ payload, validitySeconds, useStaticSigningKey, userContext }) { payload = payload === undefined || payload === null ? {} : payload; let issuer = (await this.getOpenIdDiscoveryConfiguration({ userContext })).issuer; return await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createJWT({ diff --git a/lib/build/recipe/openid/types.d.ts b/lib/build/recipe/openid/types.d.ts index 40698db1a..1a67be77b 100644 --- a/lib/build/recipe/openid/types.d.ts +++ b/lib/build/recipe/openid/types.d.ts @@ -4,13 +4,19 @@ import type { BaseRequest, BaseResponse } from "../../framework"; import { GeneralErrorResponse, UserContext } from "../../types"; export type TypeInput = { override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -22,23 +28,28 @@ export type APIOptions = { res: BaseResponse; }; export type APIInterface = { - getOpenIdDiscoveryConfigurationGET: undefined | ((input: { - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - issuer: string; - jwks_uri: string; - authorization_endpoint: string; - token_endpoint: string; - userinfo_endpoint: string; - revocation_endpoint: string; - token_introspection_endpoint: string; - end_session_endpoint: string; - subject_types_supported: string[]; - id_token_signing_alg_values_supported: string[]; - response_types_supported: string[]; - } | GeneralErrorResponse>); + getOpenIdDiscoveryConfigurationGET: + | undefined + | ((input: { + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + issuer: string; + jwks_uri: string; + authorization_endpoint: string; + token_endpoint: string; + userinfo_endpoint: string; + revocation_endpoint: string; + token_introspection_endpoint: string; + end_session_endpoint: string; + subject_types_supported: string[]; + id_token_signing_alg_values_supported: string[]; + response_types_supported: string[]; + } + | GeneralErrorResponse + >); }; export type RecipeInterface = { getOpenIdDiscoveryConfiguration(input: { @@ -62,10 +73,13 @@ export type RecipeInterface = { validitySeconds?: number; useStaticSigningKey?: boolean; userContext: UserContext; - }): Promise<{ - status: "OK"; - jwt: string; - } | { - status: "UNSUPPORTED_ALGORITHM_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + jwt: string; + } + | { + status: "UNSUPPORTED_ALGORITHM_ERROR"; + } + >; }; diff --git a/lib/build/recipe/openid/utils.js b/lib/build/recipe/openid/utils.js index 0fee66536..16363534f 100644 --- a/lib/build/recipe/openid/utils.js +++ b/lib/build/recipe/openid/utils.js @@ -2,7 +2,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; function validateAndNormaliseUserInput(config) { - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { override, }; diff --git a/lib/build/recipe/passwordless/api/consumeCode.d.ts b/lib/build/recipe/passwordless/api/consumeCode.d.ts index 95eaca99c..a07ff159f 100644 --- a/lib/build/recipe/passwordless/api/consumeCode.d.ts +++ b/lib/build/recipe/passwordless/api/consumeCode.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function consumeCode(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function consumeCode( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/passwordless/api/consumeCode.js b/lib/build/recipe/passwordless/api/consumeCode.js index efd8b99de..783f9c134 100644 --- a/lib/build/recipe/passwordless/api/consumeCode.js +++ b/lib/build/recipe/passwordless/api/consumeCode.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = consumeCode; const utils_1 = require("../../../utils"); @@ -49,40 +51,52 @@ async function consumeCode(apiImplementation, tenantId, options, userContext) { message: "Please provide both deviceId and userInputCode", }); } - } - else if (linkCode === undefined) { + } else if (linkCode === undefined) { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, message: "Please provide one of (linkCode) or (deviceId+userInputCode) and not both", }); } - const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)(options.req, body); - const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded(options.req, options.res, shouldTryLinkingWithSessionUser, userContext); + const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)( + options.req, + body + ); + const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded( + options.req, + options.res, + shouldTryLinkingWithSessionUser, + userContext + ); if (session !== undefined) { tenantId = session.getTenantId(); } - let result = await apiImplementation.consumeCodePOST(deviceId !== undefined - ? { - deviceId, - userInputCode, - preAuthSessionId, - tenantId, - session, - shouldTryLinkingWithSessionUser, - options, - userContext, - } - : { - linkCode, - options, - preAuthSessionId, - tenantId, - session, - shouldTryLinkingWithSessionUser, - userContext, - }); + let result = await apiImplementation.consumeCodePOST( + deviceId !== undefined + ? { + deviceId, + userInputCode, + preAuthSessionId, + tenantId, + session, + shouldTryLinkingWithSessionUser, + options, + userContext, + } + : { + linkCode, + options, + preAuthSessionId, + tenantId, + session, + shouldTryLinkingWithSessionUser, + userContext, + } + ); if (result.status === "OK") { - result = Object.assign(Object.assign({}, result), (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext)); + result = Object.assign( + Object.assign({}, result), + (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext) + ); delete result.session; } (0, utils_1.send200Response)(options.res, result); diff --git a/lib/build/recipe/passwordless/api/createCode.d.ts b/lib/build/recipe/passwordless/api/createCode.d.ts index 593fdf54e..1d2619c75 100644 --- a/lib/build/recipe/passwordless/api/createCode.d.ts +++ b/lib/build/recipe/passwordless/api/createCode.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function createCode(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function createCode( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/passwordless/api/createCode.js b/lib/build/recipe/passwordless/api/createCode.js index 88cf8ca83..791d55810 100644 --- a/lib/build/recipe/passwordless/api/createCode.js +++ b/lib/build/recipe/passwordless/api/createCode.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = createCode; const utils_1 = require("../../../utils"); @@ -48,8 +50,10 @@ async function createCode(apiImplementation, tenantId, options, userContext) { }); } // normalise and validate format of input - if (email !== undefined && - (options.config.contactMethod === "EMAIL" || options.config.contactMethod === "EMAIL_OR_PHONE")) { + if ( + email !== undefined && + (options.config.contactMethod === "EMAIL" || options.config.contactMethod === "EMAIL_OR_PHONE") + ) { email = email.trim(); const validateError = await options.config.validateEmailAddress(email, tenantId); if (validateError !== undefined) { @@ -60,8 +64,10 @@ async function createCode(apiImplementation, tenantId, options, userContext) { return true; } } - if (phoneNumber !== undefined && - (options.config.contactMethod === "PHONE" || options.config.contactMethod === "EMAIL_OR_PHONE")) { + if ( + phoneNumber !== undefined && + (options.config.contactMethod === "PHONE" || options.config.contactMethod === "EMAIL_OR_PHONE") + ) { const validateError = await options.config.validatePhoneNumber(phoneNumber, tenantId); if (validateError !== undefined) { (0, utils_1.send200Response)(options.res, { @@ -75,19 +81,28 @@ async function createCode(apiImplementation, tenantId, options, userContext) { // this can come here if the user has provided their own impl of validatePhoneNumber and // the phone number is valid according to their impl, but not according to the libphonenumber-js lib. phoneNumber = phoneNumber.trim(); - } - else { + } else { phoneNumber = parsedPhoneNumber.format("E.164"); } } - const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)(options.req, body); - const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded(options.req, options.res, shouldTryLinkingWithSessionUser, userContext); + const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)( + options.req, + body + ); + const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded( + options.req, + options.res, + shouldTryLinkingWithSessionUser, + userContext + ); if (session !== undefined) { tenantId = session.getTenantId(); } - let result = await apiImplementation.createCodePOST(email !== undefined - ? { email, session, tenantId, shouldTryLinkingWithSessionUser, options, userContext } - : { phoneNumber: phoneNumber, session, tenantId, shouldTryLinkingWithSessionUser, options, userContext }); + let result = await apiImplementation.createCodePOST( + email !== undefined + ? { email, session, tenantId, shouldTryLinkingWithSessionUser, options, userContext } + : { phoneNumber: phoneNumber, session, tenantId, shouldTryLinkingWithSessionUser, options, userContext } + ); (0, utils_1.send200Response)(options.res, result); return true; } diff --git a/lib/build/recipe/passwordless/api/emailExists.d.ts b/lib/build/recipe/passwordless/api/emailExists.d.ts index 478175dec..2f55b6d3b 100644 --- a/lib/build/recipe/passwordless/api/emailExists.d.ts +++ b/lib/build/recipe/passwordless/api/emailExists.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function emailExists(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function emailExists( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/passwordless/api/emailExists.js b/lib/build/recipe/passwordless/api/emailExists.js index 34470ff4e..5aaa3710c 100644 --- a/lib/build/recipe/passwordless/api/emailExists.js +++ b/lib/build/recipe/passwordless/api/emailExists.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = emailExists; const utils_1 = require("../../../utils"); diff --git a/lib/build/recipe/passwordless/api/implementation.js b/lib/build/recipe/passwordless/api/implementation.js index fbba0b1c9..112b2f8b5 100644 --- a/lib/build/recipe/passwordless/api/implementation.js +++ b/lib/build/recipe/passwordless/api/implementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIImplementation; const logger_1 = require("../../../logger"); @@ -17,14 +19,19 @@ function getAPIImplementation() { consumeCodePOST: async function (input) { var _a, _b, _c; const errorCodeMap = { - SIGN_UP_NOT_ALLOWED: "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_002)", - SIGN_IN_NOT_ALLOWED: "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_003)", + SIGN_UP_NOT_ALLOWED: + "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_002)", + SIGN_IN_NOT_ALLOWED: + "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_003)", LINKING_TO_SESSION_USER_FAILED: { // We should never get an email verification error here, since pwless automatically marks the user // email as verified - RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_017)", - ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_018)", - SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_019)", + RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_017)", + ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_018)", + SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_019)", }, }; const deviceInfo = await input.options.recipeImplementation.listCodesByPreAuthSessionId({ @@ -38,42 +45,47 @@ function getAPIImplementation() { }; } const recipeId = "passwordless"; - const accountInfo = deviceInfo.phoneNumber !== undefined - ? { - phoneNumber: deviceInfo.phoneNumber, - } - : { - email: deviceInfo.email, - }; + const accountInfo = + deviceInfo.phoneNumber !== undefined + ? { + phoneNumber: deviceInfo.phoneNumber, + } + : { + email: deviceInfo.email, + }; let checkCredentialsResponseProm; let checkCredentials = async () => { if (checkCredentialsResponseProm === undefined) { - checkCredentialsResponseProm = input.options.recipeImplementation.checkCode("deviceId" in input - ? { - preAuthSessionId: input.preAuthSessionId, - deviceId: input.deviceId, - userInputCode: input.userInputCode, - tenantId: input.tenantId, - userContext: input.userContext, - } - : { - preAuthSessionId: input.preAuthSessionId, - linkCode: input.linkCode, - tenantId: input.tenantId, - userContext: input.userContext, - }); + checkCredentialsResponseProm = input.options.recipeImplementation.checkCode( + "deviceId" in input + ? { + preAuthSessionId: input.preAuthSessionId, + deviceId: input.deviceId, + userInputCode: input.userInputCode, + tenantId: input.tenantId, + userContext: input.userContext, + } + : { + preAuthSessionId: input.preAuthSessionId, + linkCode: input.linkCode, + tenantId: input.tenantId, + userContext: input.userContext, + } + ); } const checkCredentialsResponse = await checkCredentialsResponseProm; return checkCredentialsResponse.status === "OK"; }; - const authenticatingUser = await authUtils_1.AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired({ - accountInfo, - recipeId, - userContext: input.userContext, - session: input.session, - tenantId: input.tenantId, - checkCredentialsOnTenant: checkCredentials, - }); + const authenticatingUser = await authUtils_1.AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired( + { + accountInfo, + recipeId, + userContext: input.userContext, + session: input.session, + tenantId: input.tenantId, + checkCredentialsOnTenant: checkCredentials, + } + ); const emailVerificationInstance = recipe_2.default.getInstance(); // If we have a session and emailverification was initialized plus this code was sent to an email // then we check if we can/should verify this email address for the session user. @@ -81,9 +93,11 @@ function getAPIImplementation() { // and making a user primary if they are verified, but the verification process itself involves account linking. // If a valid code was submitted, we can take that as the session (and the session user) having access to the email // which means that we can verify their email address - if (accountInfo.email !== undefined && + if ( + accountInfo.email !== undefined && input.session !== undefined && - emailVerificationInstance !== undefined) { + emailVerificationInstance !== undefined + ) { // We first load the session user, so we can check if verification is required // We do this first, it is better for caching if we group the post calls together (verifyIng the code and the email address) const sessionUser = await (0, __1.getUser)(input.session.getUserId(), input.userContext); @@ -93,7 +107,9 @@ function getAPIImplementation() { message: "Session user not found", }); } - const loginMethod = sessionUser.loginMethods.find((lm) => lm.recipeUserId.getAsString() === input.session.getRecipeUserId().getAsString()); + const loginMethod = sessionUser.loginMethods.find( + (lm) => lm.recipeUserId.getAsString() === input.session.getRecipeUserId().getAsString() + ); if (loginMethod === undefined) { throw new error_1.default({ type: error_1.default.UNAUTHORISED, @@ -105,12 +121,14 @@ function getAPIImplementation() { if (loginMethod.hasSameEmailAs(accountInfo.email) && !loginMethod.verified) { // We first check that the submitted code is actually valid if (await checkCredentials()) { - const tokenResponse = await emailVerificationInstance.recipeInterfaceImpl.createEmailVerificationToken({ - tenantId: input.tenantId, - recipeUserId: loginMethod.recipeUserId, - email: accountInfo.email, - userContext: input.userContext, - }); + const tokenResponse = await emailVerificationInstance.recipeInterfaceImpl.createEmailVerificationToken( + { + tenantId: input.tenantId, + recipeUserId: loginMethod.recipeUserId, + email: accountInfo.email, + userContext: input.userContext, + } + ); if (tokenResponse.status === "OK") { await emailVerificationInstance.recipeInterfaceImpl.verifyEmailUsingToken({ tenantId: input.tenantId, @@ -128,16 +146,13 @@ function getAPIImplementation() { if (deviceInfo.email !== undefined) { if ("userInputCode" in input) { factorId = multifactorauth_1.FactorIds.OTP_EMAIL; - } - else { + } else { factorId = multifactorauth_1.FactorIds.LINK_EMAIL; } - } - else { + } else { if ("userInputCode" in input) { factorId = multifactorauth_1.FactorIds.OTP_PHONE; - } - else { + } else { factorId = multifactorauth_1.FactorIds.LINK_PHONE; } } @@ -149,9 +164,16 @@ function getAPIImplementation() { phoneNumber: deviceInfo.phoneNumber, }, factorIds: [factorId], - authenticatingUser: authenticatingUser === null || authenticatingUser === void 0 ? void 0 : authenticatingUser.user, + authenticatingUser: + authenticatingUser === null || authenticatingUser === void 0 ? void 0 : authenticatingUser.user, isSignUp, - isVerified: (_a = authenticatingUser === null || authenticatingUser === void 0 ? void 0 : authenticatingUser.loginMethod.verified) !== null && _a !== void 0 ? _a : true, + isVerified: + (_a = + authenticatingUser === null || authenticatingUser === void 0 + ? void 0 + : authenticatingUser.loginMethod.verified) !== null && _a !== void 0 + ? _a + : true, signInVerifiesLoginMethod: true, skipSessionUserUpdateInCore: false, tenantId: input.tenantId, @@ -162,7 +184,11 @@ function getAPIImplementation() { if (preAuthChecks.status !== "OK") { // On the frontend, this should show a UI of asking the user // to login using a different method. - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(preAuthChecks, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + preAuthChecks, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } if (checkCredentialsResponseProm !== undefined) { // We need to cast this because otherwise TS thinks that this is never updated for some reason. @@ -172,31 +198,39 @@ function getAPIImplementation() { return checkCredentialsResponse; } } - let response = await input.options.recipeImplementation.consumeCode("deviceId" in input - ? { - preAuthSessionId: input.preAuthSessionId, - deviceId: input.deviceId, - userInputCode: input.userInputCode, - session: input.session, - shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, - tenantId: input.tenantId, - userContext: input.userContext, - } - : { - preAuthSessionId: input.preAuthSessionId, - linkCode: input.linkCode, - session: input.session, - shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, - tenantId: input.tenantId, - userContext: input.userContext, - }); - if (response.status === "RESTART_FLOW_ERROR" || + let response = await input.options.recipeImplementation.consumeCode( + "deviceId" in input + ? { + preAuthSessionId: input.preAuthSessionId, + deviceId: input.deviceId, + userInputCode: input.userInputCode, + session: input.session, + shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, + tenantId: input.tenantId, + userContext: input.userContext, + } + : { + preAuthSessionId: input.preAuthSessionId, + linkCode: input.linkCode, + session: input.session, + shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, + tenantId: input.tenantId, + userContext: input.userContext, + } + ); + if ( + response.status === "RESTART_FLOW_ERROR" || response.status === "INCORRECT_USER_INPUT_CODE_ERROR" || - response.status === "EXPIRED_USER_INPUT_CODE_ERROR") { + response.status === "EXPIRED_USER_INPUT_CODE_ERROR" + ) { return response; } if (response.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(response, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + response, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } // Here we do these checks after sign in is done cause: // - We first want to check if the credentials are correct first or not @@ -208,7 +242,10 @@ function getAPIImplementation() { factorId, isSignUp, authenticatedUser: (_b = response.user) !== null && _b !== void 0 ? _b : authenticatingUser.user, - recipeUserId: (_c = response.recipeUserId) !== null && _c !== void 0 ? _c : authenticatingUser.loginMethod.recipeUserId, + recipeUserId: + (_c = response.recipeUserId) !== null && _c !== void 0 + ? _c + : authenticatingUser.loginMethod.recipeUserId, req: input.options.req, res: input.options.res, tenantId: input.tenantId, @@ -216,7 +253,11 @@ function getAPIImplementation() { session: input.session, }); if (postAuthChecks.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(postAuthChecks, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + postAuthChecks, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } return { status: "OK", @@ -228,9 +269,11 @@ function getAPIImplementation() { createCodePOST: async function (input) { var _a; const errorCodeMap = { - SIGN_UP_NOT_ALLOWED: "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_002)", + SIGN_UP_NOT_ALLOWED: + "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_002)", LINKING_TO_SESSION_USER_FAILED: { - SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_019)", + SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_019)", }, }; const accountInfo = {}; @@ -243,30 +286,42 @@ function getAPIImplementation() { // Here we use do not use the helper from AuthUtil to check if this is going to be a sign in or up, because: // 1. At this point we have no way to check credentials // 2. We do not want to associate the relevant recipe user with the current tenant (yet) - const userWithMatchingLoginMethod = await getPasswordlessUserByAccountInfo(Object.assign(Object.assign({}, input), { accountInfo })); + const userWithMatchingLoginMethod = await getPasswordlessUserByAccountInfo( + Object.assign(Object.assign({}, input), { accountInfo }) + ); let factorIds; if (input.session !== undefined) { if (accountInfo.email !== undefined) { factorIds = [multifactorauth_1.FactorIds.OTP_EMAIL]; - } - else { + } else { factorIds = [multifactorauth_1.FactorIds.OTP_PHONE]; } - } - else { + } else { factorIds = (0, utils_1.getEnabledPwlessFactors)(input.options.config); if (accountInfo.email !== undefined) { - factorIds = factorIds.filter((factor) => [multifactorauth_1.FactorIds.OTP_EMAIL, multifactorauth_1.FactorIds.LINK_EMAIL].includes(factor)); - } - else { - factorIds = factorIds.filter((factor) => [multifactorauth_1.FactorIds.OTP_PHONE, multifactorauth_1.FactorIds.LINK_PHONE].includes(factor)); + factorIds = factorIds.filter((factor) => + [multifactorauth_1.FactorIds.OTP_EMAIL, multifactorauth_1.FactorIds.LINK_EMAIL].includes(factor) + ); + } else { + factorIds = factorIds.filter((factor) => + [multifactorauth_1.FactorIds.OTP_PHONE, multifactorauth_1.FactorIds.LINK_PHONE].includes(factor) + ); } } const preAuthChecks = await authUtils_1.AuthUtils.preAuthChecks({ authenticatingAccountInfo: Object.assign(Object.assign({}, accountInfo), { recipeId: "passwordless" }), isSignUp: userWithMatchingLoginMethod === undefined, - authenticatingUser: userWithMatchingLoginMethod === null || userWithMatchingLoginMethod === void 0 ? void 0 : userWithMatchingLoginMethod.user, - isVerified: (_a = userWithMatchingLoginMethod === null || userWithMatchingLoginMethod === void 0 ? void 0 : userWithMatchingLoginMethod.loginMethod.verified) !== null && _a !== void 0 ? _a : true, + authenticatingUser: + userWithMatchingLoginMethod === null || userWithMatchingLoginMethod === void 0 + ? void 0 + : userWithMatchingLoginMethod.user, + isVerified: + (_a = + userWithMatchingLoginMethod === null || userWithMatchingLoginMethod === void 0 + ? void 0 + : userWithMatchingLoginMethod.loginMethod.verified) !== null && _a !== void 0 + ? _a + : true, signInVerifiesLoginMethod: true, skipSessionUserUpdateInCore: true, tenantId: input.tenantId, @@ -278,31 +333,49 @@ function getAPIImplementation() { if (preAuthChecks.status !== "OK") { // On the frontend, this should show a UI of asking the user // to login using a different method. - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(preAuthChecks, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + preAuthChecks, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } - let response = await input.options.recipeImplementation.createCode("email" in input - ? { - userContext: input.userContext, - email: input.email, - userInputCode: input.options.config.getCustomUserInputCode === undefined - ? undefined - : await input.options.config.getCustomUserInputCode(input.tenantId, input.userContext), - session: input.session, - shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, - tenantId: input.tenantId, - } - : { - userContext: input.userContext, - phoneNumber: input.phoneNumber, - userInputCode: input.options.config.getCustomUserInputCode === undefined - ? undefined - : await input.options.config.getCustomUserInputCode(input.tenantId, input.userContext), - session: input.session, - shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, - tenantId: input.tenantId, - }); + let response = await input.options.recipeImplementation.createCode( + "email" in input + ? { + userContext: input.userContext, + email: input.email, + userInputCode: + input.options.config.getCustomUserInputCode === undefined + ? undefined + : await input.options.config.getCustomUserInputCode( + input.tenantId, + input.userContext + ), + session: input.session, + shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, + tenantId: input.tenantId, + } + : { + userContext: input.userContext, + phoneNumber: input.phoneNumber, + userInputCode: + input.options.config.getCustomUserInputCode === undefined + ? undefined + : await input.options.config.getCustomUserInputCode( + input.tenantId, + input.userContext + ), + session: input.session, + shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, + tenantId: input.tenantId, + } + ); if (response.status !== "OK") { - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(response, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + response, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } // now we send the email / text message. let magicLink = undefined; @@ -310,29 +383,27 @@ function getAPIImplementation() { let flowType = input.options.config.flowType; if (preAuthChecks.validFactorIds.every((id) => id.startsWith("link"))) { flowType = "MAGIC_LINK"; - } - else if (preAuthChecks.validFactorIds.every((id) => id.startsWith("otp"))) { + } else if (preAuthChecks.validFactorIds.every((id) => id.startsWith("otp"))) { flowType = "USER_INPUT_CODE"; - } - else { + } else { flowType = "USER_INPUT_CODE_AND_MAGIC_LINK"; } if (flowType === "MAGIC_LINK" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") { magicLink = input.options.appInfo .getOrigin({ - request: input.options.req, - userContext: input.userContext, - }) + request: input.options.req, + userContext: input.userContext, + }) .getAsStringDangerous() + - input.options.appInfo.websiteBasePath.getAsStringDangerous() + - "/verify" + - "?preAuthSessionId=" + - response.preAuthSessionId + - "&tenantId=" + - input.tenantId + - "#" + - response.linkCode; + input.options.appInfo.websiteBasePath.getAsStringDangerous() + + "/verify" + + "?preAuthSessionId=" + + response.preAuthSessionId + + "&tenantId=" + + input.tenantId + + "#" + + response.linkCode; } if (flowType === "USER_INPUT_CODE" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") { userInputCode = response.userInputCode; @@ -340,8 +411,10 @@ function getAPIImplementation() { // we don't do something special for serverless env here // cause we want to wait for service's reply since it can show // a UI error message for if sending an SMS / email failed or not. - if (input.options.config.contactMethod === "PHONE" || - (input.options.config.contactMethod === "EMAIL_OR_PHONE" && "phoneNumber" in input)) { + if ( + input.options.config.contactMethod === "PHONE" || + (input.options.config.contactMethod === "EMAIL_OR_PHONE" && "phoneNumber" in input) + ) { (0, logger_1.logDebugMessage)(`Sending passwordless login SMS to ${input.phoneNumber}`); await input.options.smsDelivery.ingredientInterfaceImpl.sendSms({ type: "PASSWORDLESS_LOGIN", @@ -354,8 +427,7 @@ function getAPIImplementation() { tenantId: input.tenantId, userContext: input.userContext, }); - } - else { + } else { (0, logger_1.logDebugMessage)(`Sending passwordless login email to ${input.email}`); await input.options.emailDelivery.ingredientInterfaceImpl.sendEmail({ type: "PASSWORDLESS_LOGIN", @@ -385,17 +457,24 @@ function getAPIImplementation() { doUnionOfAccountInfo: false, userContext: input.userContext, }); - const userExists = users.some((u) => u.loginMethods.some((lm) => lm.recipeId === "passwordless" && lm.hasSameEmailAs(input.email))); + const userExists = users.some((u) => + u.loginMethods.some((lm) => lm.recipeId === "passwordless" && lm.hasSameEmailAs(input.email)) + ); return { exists: userExists, status: "OK", }; }, phoneNumberExistsGET: async function (input) { - let users = await (0, __1.listUsersByAccountInfo)(input.tenantId, { - phoneNumber: input.phoneNumber, - // tenantId: input.tenantId, - }, false, input.userContext); + let users = await (0, __1.listUsersByAccountInfo)( + input.tenantId, + { + phoneNumber: input.phoneNumber, + // tenantId: input.tenantId, + }, + false, + input.userContext + ); return { exists: users.length > 0, status: "OK", @@ -412,18 +491,31 @@ function getAPIImplementation() { status: "RESTART_FLOW_ERROR", }; } - if ((input.options.config.contactMethod === "PHONE" && deviceInfo.phoneNumber === undefined) || - (input.options.config.contactMethod === "EMAIL" && deviceInfo.email === undefined)) { + if ( + (input.options.config.contactMethod === "PHONE" && deviceInfo.phoneNumber === undefined) || + (input.options.config.contactMethod === "EMAIL" && deviceInfo.email === undefined) + ) { return { status: "RESTART_FLOW_ERROR", }; } - const userWithMatchingLoginMethod = await getPasswordlessUserByAccountInfo(Object.assign(Object.assign({}, input), { accountInfo: deviceInfo })); - const authTypeInfo = await authUtils_1.AuthUtils.checkAuthTypeAndLinkingStatus(input.session, input.shouldTryLinkingWithSessionUser, { - recipeId: "passwordless", - email: deviceInfo.email, - phoneNumber: deviceInfo.phoneNumber, - }, userWithMatchingLoginMethod === null || userWithMatchingLoginMethod === void 0 ? void 0 : userWithMatchingLoginMethod.user, true, input.userContext); + const userWithMatchingLoginMethod = await getPasswordlessUserByAccountInfo( + Object.assign(Object.assign({}, input), { accountInfo: deviceInfo }) + ); + const authTypeInfo = await authUtils_1.AuthUtils.checkAuthTypeAndLinkingStatus( + input.session, + input.shouldTryLinkingWithSessionUser, + { + recipeId: "passwordless", + email: deviceInfo.email, + phoneNumber: deviceInfo.phoneNumber, + }, + userWithMatchingLoginMethod === null || userWithMatchingLoginMethod === void 0 + ? void 0 + : userWithMatchingLoginMethod.user, + true, + input.userContext + ); if (authTypeInfo.status === "LINKING_TO_SESSION_USER_FAILED") { // This can happen in the following edge-cases: // 1. Either the session didn't exist during createCode or the app didn't want to link to the session user @@ -442,9 +534,10 @@ function getAPIImplementation() { let response = await input.options.recipeImplementation.createNewCodeForDevice({ userContext: input.userContext, deviceId: input.deviceId, - userInputCode: input.options.config.getCustomUserInputCode === undefined - ? undefined - : await input.options.config.getCustomUserInputCode(input.tenantId, input.userContext), + userInputCode: + input.options.config.getCustomUserInputCode === undefined + ? undefined + : await input.options.config.getCustomUserInputCode(input.tenantId, input.userContext), tenantId: input.tenantId, }); if (response.status === "USER_INPUT_CODE_ALREADY_USED_ERROR") { @@ -465,45 +558,46 @@ function getAPIImplementation() { if (!authTypeInfo.isFirstFactor) { if (deviceInfo.email !== undefined) { factorIds = [multifactorauth_1.FactorIds.OTP_EMAIL]; - } - else { + } else { factorIds = [multifactorauth_1.FactorIds.OTP_PHONE]; } // We do not do further filtering here, since we know the exact factor id and the fact that it was created // which means it was allowed and the user is allowed to re-send it. // We will execute all check when the code is consumed anyway. - } - else { + } else { factorIds = (0, utils_1.getEnabledPwlessFactors)(input.options.config); - factorIds = await authUtils_1.AuthUtils.filterOutInvalidFirstFactorsOrThrowIfAllAreInvalid(factorIds, input.tenantId, false, input.userContext); + factorIds = await authUtils_1.AuthUtils.filterOutInvalidFirstFactorsOrThrowIfAllAreInvalid( + factorIds, + input.tenantId, + false, + input.userContext + ); } // This is correct because in createCodePOST we only allow OTP_EMAIL let flowType = input.options.config.flowType; if (factorIds.every((id) => id.startsWith("link"))) { flowType = "MAGIC_LINK"; - } - else if (factorIds.every((id) => id.startsWith("otp"))) { + } else if (factorIds.every((id) => id.startsWith("otp"))) { flowType = "USER_INPUT_CODE"; - } - else { + } else { flowType = "USER_INPUT_CODE_AND_MAGIC_LINK"; } if (flowType === "MAGIC_LINK" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") { magicLink = input.options.appInfo .getOrigin({ - request: input.options.req, - userContext: input.userContext, - }) + request: input.options.req, + userContext: input.userContext, + }) .getAsStringDangerous() + - input.options.appInfo.websiteBasePath.getAsStringDangerous() + - "/verify" + - "?preAuthSessionId=" + - response.preAuthSessionId + - "&tenantId=" + - input.tenantId + - "#" + - response.linkCode; + input.options.appInfo.websiteBasePath.getAsStringDangerous() + + "/verify" + + "?preAuthSessionId=" + + response.preAuthSessionId + + "&tenantId=" + + input.tenantId + + "#" + + response.linkCode; } if (flowType === "USER_INPUT_CODE" || flowType === "USER_INPUT_CODE_AND_MAGIC_LINK") { userInputCode = response.userInputCode; @@ -511,9 +605,11 @@ function getAPIImplementation() { // we don't do something special for serverless env here // cause we want to wait for service's reply since it can show // a UI error message for if sending an SMS / email failed or not. - if (input.options.config.contactMethod === "PHONE" || + if ( + input.options.config.contactMethod === "PHONE" || (input.options.config.contactMethod === "EMAIL_OR_PHONE" && - deviceInfo.phoneNumber !== undefined)) { + deviceInfo.phoneNumber !== undefined) + ) { (0, logger_1.logDebugMessage)(`Sending passwordless login SMS to ${input.phoneNumber}`); await input.options.smsDelivery.ingredientInterfaceImpl.sendSms({ type: "PASSWORDLESS_LOGIN", @@ -526,8 +622,7 @@ function getAPIImplementation() { tenantId: input.tenantId, userContext: input.userContext, }); - } - else { + } else { (0, logger_1.logDebugMessage)(`Sending passwordless login email to ${input.email}`); await input.options.emailDelivery.ingredientInterfaceImpl.sendEmail({ type: "PASSWORDLESS_LOGIN", @@ -556,18 +651,29 @@ async function getPasswordlessUserByAccountInfo(input) { doUnionOfAccountInfo: false, userContext: input.userContext, }); - (0, logger_1.logDebugMessage)(`getPasswordlessUserByAccountInfo got ${existingUsers.length} from core resp ${JSON.stringify(input.accountInfo)}`); + (0, logger_1.logDebugMessage)( + `getPasswordlessUserByAccountInfo got ${existingUsers.length} from core resp ${JSON.stringify( + input.accountInfo + )}` + ); const usersWithMatchingLoginMethods = existingUsers .map((user) => ({ - user, - loginMethod: user.loginMethods.find((lm) => lm.recipeId === "passwordless" && - (lm.hasSameEmailAs(input.accountInfo.email) || - lm.hasSamePhoneNumberAs(input.accountInfo.phoneNumber))), - })) + user, + loginMethod: user.loginMethods.find( + (lm) => + lm.recipeId === "passwordless" && + (lm.hasSameEmailAs(input.accountInfo.email) || + lm.hasSamePhoneNumberAs(input.accountInfo.phoneNumber)) + ), + })) .filter(({ loginMethod }) => loginMethod !== undefined); - (0, logger_1.logDebugMessage)(`getPasswordlessUserByAccountInfo ${usersWithMatchingLoginMethods.length} has matching login methods`); + (0, logger_1.logDebugMessage)( + `getPasswordlessUserByAccountInfo ${usersWithMatchingLoginMethods.length} has matching login methods` + ); if (usersWithMatchingLoginMethods.length > 1) { - throw new Error("This should never happen: multiple users exist matching the accountInfo in passwordless createCode"); + throw new Error( + "This should never happen: multiple users exist matching the accountInfo in passwordless createCode" + ); } return usersWithMatchingLoginMethods[0]; } diff --git a/lib/build/recipe/passwordless/api/phoneNumberExists.d.ts b/lib/build/recipe/passwordless/api/phoneNumberExists.d.ts index 5ab652f23..9d545f9dc 100644 --- a/lib/build/recipe/passwordless/api/phoneNumberExists.d.ts +++ b/lib/build/recipe/passwordless/api/phoneNumberExists.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function phoneNumberExists(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function phoneNumberExists( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/passwordless/api/phoneNumberExists.js b/lib/build/recipe/passwordless/api/phoneNumberExists.js index 01de183dd..4a1ecc779 100644 --- a/lib/build/recipe/passwordless/api/phoneNumberExists.js +++ b/lib/build/recipe/passwordless/api/phoneNumberExists.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = phoneNumberExists; const utils_1 = require("../../../utils"); diff --git a/lib/build/recipe/passwordless/api/resendCode.d.ts b/lib/build/recipe/passwordless/api/resendCode.d.ts index 3453d3e1a..d6fd98191 100644 --- a/lib/build/recipe/passwordless/api/resendCode.d.ts +++ b/lib/build/recipe/passwordless/api/resendCode.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function resendCode(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function resendCode( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/passwordless/api/resendCode.js b/lib/build/recipe/passwordless/api/resendCode.js index 144c6169d..019213f41 100644 --- a/lib/build/recipe/passwordless/api/resendCode.js +++ b/lib/build/recipe/passwordless/api/resendCode.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = resendCode; const utils_1 = require("../../../utils"); @@ -40,8 +42,16 @@ async function resendCode(apiImplementation, tenantId, options, userContext) { message: "Please provide a deviceId", }); } - const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)(options.req, body); - const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded(options.req, options.res, shouldTryLinkingWithSessionUser, userContext); + const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)( + options.req, + body + ); + const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded( + options.req, + options.res, + shouldTryLinkingWithSessionUser, + userContext + ); let result = await apiImplementation.resendCodePOST({ deviceId, preAuthSessionId, diff --git a/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.d.ts b/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.d.ts index 0ea2b47d1..3c47b9d5a 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.d.ts +++ b/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.d.ts @@ -2,10 +2,13 @@ import { TypePasswordlessEmailDeliveryInput } from "../../../types"; import { EmailDeliveryInterface } from "../../../../../ingredients/emaildelivery/types"; import { NormalisedAppinfo, UserContext } from "../../../../../types"; -export default class BackwardCompatibilityService implements EmailDeliveryInterface { +export default class BackwardCompatibilityService + implements EmailDeliveryInterface { private appInfo; constructor(appInfo: NormalisedAppinfo); - sendEmail: (input: TypePasswordlessEmailDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendEmail: ( + input: TypePasswordlessEmailDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js b/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js index 1e9e4c6f4..7ca9d976e 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js +++ b/lib/build/recipe/passwordless/emaildelivery/services/backwardCompatibility/index.js @@ -5,20 +5,25 @@ async function createAndSendEmailUsingSupertokensService(input) { if ((0, utils_1.isTestEnv)()) { return; } - const result = await (0, utils_1.postWithFetch)("https://api.supertokens.io/0/st/auth/passwordless/login", { - "api-version": "0", - "content-type": "application/json; charset=utf-8", - }, { - email: input.email, - appName: input.appInfo.appName, - codeLifetime: input.codeLifetime, - urlWithLinkCode: input.urlWithLinkCode, - userInputCode: input.userInputCode, - // isFirstFactor: input.isFirstFactor, - }, { - successLog: `Email sent to ${input.email}`, - errorLogHeader: "Error sending passwordless login email", - }); + const result = await (0, utils_1.postWithFetch)( + "https://api.supertokens.io/0/st/auth/passwordless/login", + { + "api-version": "0", + "content-type": "application/json; charset=utf-8", + }, + { + email: input.email, + appName: input.appInfo.appName, + codeLifetime: input.codeLifetime, + urlWithLinkCode: input.urlWithLinkCode, + userInputCode: input.userInputCode, + // isFirstFactor: input.isFirstFactor, + }, + { + successLog: `Email sent to ${input.email}`, + errorLogHeader: "Error sending passwordless login email", + } + ); if ("error" in result) { throw result.error; } @@ -29,8 +34,7 @@ async function createAndSendEmailUsingSupertokensService(input) { * will be of type `{err: string}` */ throw new Error(result.resp.body.err); - } - else { + } else { throw new Error(`Request failed with status code ${result.resp.status}`); } } diff --git a/lib/build/recipe/passwordless/emaildelivery/services/index.js b/lib/build/recipe/passwordless/emaildelivery/services/index.js index 3e4b76c1d..7e07f6706 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/index.js +++ b/lib/build/recipe/passwordless/emaildelivery/services/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SMTPService = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. diff --git a/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.d.ts b/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.d.ts index 68fe55216..188d41809 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.d.ts +++ b/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.d.ts @@ -6,7 +6,9 @@ import { UserContext } from "../../../../../types"; export default class SMTPService implements EmailDeliveryInterface { serviceImpl: ServiceInterface; constructor(config: TypeInput); - sendEmail: (input: TypePasswordlessEmailDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendEmail: ( + input: TypePasswordlessEmailDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.js b/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.js index 76335ab95..e6bf36f54 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.js +++ b/lib/build/recipe/passwordless/emaildelivery/services/smtp/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const nodemailer_1 = require("nodemailer"); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); @@ -10,7 +12,9 @@ class SMTPService { constructor(config) { this.sendEmail = async (input) => { let content = await this.serviceImpl.getContent(input); - await this.serviceImpl.sendRawEmail(Object.assign(Object.assign({}, content), { userContext: input.userContext })); + await this.serviceImpl.sendRawEmail( + Object.assign(Object.assign({}, content), { userContext: input.userContext }) + ); }; const transporter = (0, nodemailer_1.createTransport)({ host: config.smtpSettings.host, @@ -21,7 +25,9 @@ class SMTPService { }, secure: config.smtpSettings.secure, }); - let builder = new supertokens_js_override_1.default((0, serviceImplementation_1.getServiceImplementation)(transporter, config.smtpSettings.from)); + let builder = new supertokens_js_override_1.default( + (0, serviceImplementation_1.getServiceImplementation)(transporter, config.smtpSettings.from) + ); if (config.override !== undefined) { builder = builder.override(config.override); } diff --git a/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.d.ts b/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.d.ts index d33aac81d..e3ae65d56 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.d.ts +++ b/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.d.ts @@ -2,4 +2,10 @@ import { TypePasswordlessEmailDeliveryInput } from "../../../types"; import { GetContentResult } from "../../../../../ingredients/emaildelivery/services/smtp"; export default function getPasswordlessLoginEmailContent(input: TypePasswordlessEmailDeliveryInput): GetContentResult; -export declare function getPasswordlessLoginEmailHTML(appName: string, email: string, codeLifetime: number, urlWithLinkCode?: string, userInputCode?: string): string; +export declare function getPasswordlessLoginEmailHTML( + appName: string, + email: string, + codeLifetime: number, + urlWithLinkCode?: string, + userInputCode?: string +): string; diff --git a/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js b/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js index 145925400..b5398319e 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js +++ b/lib/build/recipe/passwordless/emaildelivery/services/smtp/passwordlessLogin.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getPasswordlessLoginEmailContent; exports.getPasswordlessLoginEmailHTML = getPasswordlessLoginEmailHTML; @@ -10,7 +12,13 @@ const utils_1 = require("../../../../../utils"); function getPasswordlessLoginEmailContent(input) { let supertokens = supertokens_1.default.getInstanceOrThrowError(); let appName = supertokens.appInfo.appName; - let body = getPasswordlessLoginEmailHTML(appName, input.email, input.codeLifetime, input.urlWithLinkCode, input.userInputCode); + let body = getPasswordlessLoginEmailHTML( + appName, + input.email, + input.codeLifetime, + input.urlWithLinkCode, + input.userInputCode + ); return { body, toEmail: input.email, @@ -2844,13 +2852,29 @@ function getPasswordlessLoginOTPAndURLLinkBody(appName, email, codeLifetime, url } function getPasswordlessLoginEmailHTML(appName, email, codeLifetime, urlWithLinkCode, userInputCode) { if (urlWithLinkCode !== undefined && userInputCode !== undefined) { - return getPasswordlessLoginOTPAndURLLinkBody(appName, email, (0, utils_1.humaniseMilliseconds)(codeLifetime), urlWithLinkCode, userInputCode); + return getPasswordlessLoginOTPAndURLLinkBody( + appName, + email, + (0, utils_1.humaniseMilliseconds)(codeLifetime), + urlWithLinkCode, + userInputCode + ); } if (userInputCode !== undefined) { - return getPasswordlessLoginOTPBody(appName, email, (0, utils_1.humaniseMilliseconds)(codeLifetime), userInputCode); + return getPasswordlessLoginOTPBody( + appName, + email, + (0, utils_1.humaniseMilliseconds)(codeLifetime), + userInputCode + ); } if (urlWithLinkCode !== undefined) { - return getPasswordlessLoginURLLinkBody(appName, email, (0, utils_1.humaniseMilliseconds)(codeLifetime), urlWithLinkCode); + return getPasswordlessLoginURLLinkBody( + appName, + email, + (0, utils_1.humaniseMilliseconds)(codeLifetime), + urlWithLinkCode + ); } throw Error("this should never be thrown"); } diff --git a/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.d.ts b/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.d.ts index 894b09ef1..7a58ac4e4 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.d.ts +++ b/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.d.ts @@ -2,7 +2,10 @@ import { TypePasswordlessEmailDeliveryInput } from "../../../types"; import { Transporter } from "nodemailer"; import { ServiceInterface } from "../../../../../ingredients/emaildelivery/services/smtp"; -export declare function getServiceImplementation(transporter: Transporter, from: { - name: string; - email: string; -}): ServiceInterface; +export declare function getServiceImplementation( + transporter: Transporter, + from: { + name: string; + email: string; + } +): ServiceInterface; diff --git a/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.js b/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.js index d0856c68a..4e6c1ea38 100644 --- a/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.js +++ b/lib/build/recipe/passwordless/emaildelivery/services/smtp/serviceImplementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getServiceImplementation = getServiceImplementation; const passwordlessLogin_1 = __importDefault(require("./passwordlessLogin")); @@ -29,8 +31,7 @@ function getServiceImplementation(transporter, from) { subject: input.subject, html: input.body, }); - } - else { + } else { await transporter.sendMail({ from: `${from.name} <${from.email}>`, to: input.toEmail, diff --git a/lib/build/recipe/passwordless/error.d.ts b/lib/build/recipe/passwordless/error.d.ts index d6412505c..486758b61 100644 --- a/lib/build/recipe/passwordless/error.d.ts +++ b/lib/build/recipe/passwordless/error.d.ts @@ -1,8 +1,5 @@ // @ts-nocheck import STError from "../../error"; export default class SessionError extends STError { - constructor(options: { - type: "BAD_INPUT_ERROR"; - message: string; - }); + constructor(options: { type: "BAD_INPUT_ERROR"; message: string }); } diff --git a/lib/build/recipe/passwordless/error.js b/lib/build/recipe/passwordless/error.js index 3748d17e3..852278b6d 100644 --- a/lib/build/recipe/passwordless/error.js +++ b/lib/build/recipe/passwordless/error.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); class SessionError extends error_1.default { diff --git a/lib/build/recipe/passwordless/index.d.ts b/lib/build/recipe/passwordless/index.d.ts index 220cac810..e757af855 100644 --- a/lib/build/recipe/passwordless/index.d.ts +++ b/lib/build/recipe/passwordless/index.d.ts @@ -1,23 +1,34 @@ // @ts-nocheck import Recipe from "./recipe"; import SuperTokensError from "./error"; -import { RecipeInterface, APIOptions, APIInterface, TypePasswordlessEmailDeliveryInput, TypePasswordlessSmsDeliveryInput } from "./types"; +import { + RecipeInterface, + APIOptions, + APIInterface, + TypePasswordlessEmailDeliveryInput, + TypePasswordlessSmsDeliveryInput, +} from "./types"; import RecipeUserId from "../../recipeUserId"; import { SessionContainerInterface } from "../session/types"; import { User } from "../../types"; export default class Wrapper { static init: typeof Recipe.init; static Error: typeof SuperTokensError; - static createCode(input: ({ - email: string; - } | { - phoneNumber: string; - }) & { - tenantId: string; - userInputCode?: string; - session?: SessionContainerInterface; - userContext?: Record; - }): Promise<{ + static createCode( + input: ( + | { + email: string; + } + | { + phoneNumber: string; + } + ) & { + tenantId: string; + userInputCode?: string; + session?: SessionContainerInterface; + userContext?: Record; + } + ): Promise<{ status: "OK"; preAuthSessionId: string; codeId: string; @@ -32,89 +43,113 @@ export default class Wrapper { userInputCode?: string; tenantId: string; userContext?: Record; - }): Promise<{ - status: "OK"; - preAuthSessionId: string; - codeId: string; - deviceId: string; - userInputCode: string; - linkCode: string; - codeLifetime: number; - timeCreated: number; - } | { - status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + preAuthSessionId: string; + codeId: string; + deviceId: string; + userInputCode: string; + linkCode: string; + codeLifetime: number; + timeCreated: number; + } + | { + status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR"; + } + >; /** * 1. verifies the code * 2. creates the user if it doesn't exist * 3. tries to link it * 4. marks the email as verified */ - static consumeCode(input: { - preAuthSessionId: string; - userInputCode: string; - deviceId: string; - session?: undefined; - tenantId: string; - userContext?: Record; - } | { - preAuthSessionId: string; - linkCode: string; - session?: undefined; - tenantId: string; - userContext?: Record; - }): Promise<{ - status: "OK"; - consumedDevice: { - preAuthSessionId: string; - failedCodeInputAttemptCount: number; - email?: string; - phoneNumber?: string; - }; - createdNewRecipeUser: boolean; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; - failedCodeInputAttemptCount: number; - maximumCodeInputAttempts: number; - } | { - status: "RESTART_FLOW_ERROR"; - }>; - static consumeCode(input: { - preAuthSessionId: string; - userInputCode: string; - deviceId: string; - session: SessionContainerInterface; - tenantId: string; - userContext?: Record; - } | { - preAuthSessionId: string; - linkCode: string; - session: SessionContainerInterface; - tenantId: string; - userContext?: Record; - }): Promise<{ - status: "OK"; - consumedDevice: { - preAuthSessionId: string; - failedCodeInputAttemptCount: number; - email?: string; - phoneNumber?: string; - }; - createdNewRecipeUser: boolean; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; - failedCodeInputAttemptCount: number; - maximumCodeInputAttempts: number; - } | { - status: "RESTART_FLOW_ERROR"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + static consumeCode( + input: + | { + preAuthSessionId: string; + userInputCode: string; + deviceId: string; + session?: undefined; + tenantId: string; + userContext?: Record; + } + | { + preAuthSessionId: string; + linkCode: string; + session?: undefined; + tenantId: string; + userContext?: Record; + } + ): Promise< + | { + status: "OK"; + consumedDevice: { + preAuthSessionId: string; + failedCodeInputAttemptCount: number; + email?: string; + phoneNumber?: string; + }; + createdNewRecipeUser: boolean; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; + failedCodeInputAttemptCount: number; + maximumCodeInputAttempts: number; + } + | { + status: "RESTART_FLOW_ERROR"; + } + >; + static consumeCode( + input: + | { + preAuthSessionId: string; + userInputCode: string; + deviceId: string; + session: SessionContainerInterface; + tenantId: string; + userContext?: Record; + } + | { + preAuthSessionId: string; + linkCode: string; + session: SessionContainerInterface; + tenantId: string; + userContext?: Record; + } + ): Promise< + | { + status: "OK"; + consumedDevice: { + preAuthSessionId: string; + failedCodeInputAttemptCount: number; + email?: string; + phoneNumber?: string; + }; + createdNewRecipeUser: boolean; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; + failedCodeInputAttemptCount: number; + maximumCodeInputAttempts: number; + } + | { + status: "RESTART_FLOW_ERROR"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; /** * This function will only verify the code (not consume it), and: * NOT create a new user if it doesn't exist @@ -122,63 +157,86 @@ export default class Wrapper { * NOT do any linking * NOT delete the code unless it returned RESTART_FLOW_ERROR */ - static checkCode(input: { - preAuthSessionId: string; - userInputCode: string; - deviceId: string; - tenantId: string; - userContext?: Record; - } | { - preAuthSessionId: string; - linkCode: string; - tenantId: string; - userContext?: Record; - }): Promise<{ - status: "OK"; - consumedDevice: { - preAuthSessionId: string; - failedCodeInputAttemptCount: number; - email?: string; - phoneNumber?: string; - }; - } | { - status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; - failedCodeInputAttemptCount: number; - maximumCodeInputAttempts: number; - } | { - status: "RESTART_FLOW_ERROR"; - }>; + static checkCode( + input: + | { + preAuthSessionId: string; + userInputCode: string; + deviceId: string; + tenantId: string; + userContext?: Record; + } + | { + preAuthSessionId: string; + linkCode: string; + tenantId: string; + userContext?: Record; + } + ): Promise< + | { + status: "OK"; + consumedDevice: { + preAuthSessionId: string; + failedCodeInputAttemptCount: number; + email?: string; + phoneNumber?: string; + }; + } + | { + status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; + failedCodeInputAttemptCount: number; + maximumCodeInputAttempts: number; + } + | { + status: "RESTART_FLOW_ERROR"; + } + >; static updateUser(input: { recipeUserId: RecipeUserId; email?: string | null; phoneNumber?: string | null; userContext?: Record; - }): Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR"; - } | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR"; - reason: string; - }>; - static revokeAllCodes(input: { - email: string; - tenantId: string; - userContext?: Record; - } | { - phoneNumber: string; - tenantId: string; - userContext?: Record; - }): Promise<{ + }): Promise< + | { + status: + | "OK" + | "UNKNOWN_USER_ID_ERROR" + | "EMAIL_ALREADY_EXISTS_ERROR" + | "PHONE_NUMBER_ALREADY_EXISTS_ERROR"; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } + >; + static revokeAllCodes( + input: + | { + email: string; + tenantId: string; + userContext?: Record; + } + | { + phoneNumber: string; + tenantId: string; + userContext?: Record; + } + ): Promise<{ status: "OK"; }>; - static revokeCode(input: { - codeId: string; - tenantId: string; - userContext?: Record; - } | { - preAuthSessionId: string; - tenantId: string; - userContext?: Record; - }): Promise<{ + static revokeCode( + input: + | { + codeId: string; + tenantId: string; + userContext?: Record; + } + | { + preAuthSessionId: string; + tenantId: string; + userContext?: Record; + } + ): Promise<{ status: "OK"; }>; static listCodesByEmail(input: { @@ -201,37 +259,49 @@ export default class Wrapper { tenantId: string; userContext?: Record; }): Promise; - static createMagicLink(input: { - email: string; - tenantId: string; - userContext?: Record; - } | { - phoneNumber: string; - tenantId: string; - userContext?: Record; - }): Promise; - static signInUp(input: { - email: string; - tenantId: string; - session?: SessionContainerInterface; - userContext?: Record; - } | { - phoneNumber: string; - tenantId: string; - session?: SessionContainerInterface; - userContext?: Record; - }): Promise<{ + static createMagicLink( + input: + | { + email: string; + tenantId: string; + userContext?: Record; + } + | { + phoneNumber: string; + tenantId: string; + userContext?: Record; + } + ): Promise; + static signInUp( + input: + | { + email: string; + tenantId: string; + session?: SessionContainerInterface; + userContext?: Record; + } + | { + phoneNumber: string; + tenantId: string; + session?: SessionContainerInterface; + userContext?: Record; + } + ): Promise<{ status: string; createdNewRecipeUser: boolean; recipeUserId: RecipeUserId; user: User; }>; - static sendEmail(input: TypePasswordlessEmailDeliveryInput & { - userContext?: Record; - }): Promise; - static sendSms(input: TypePasswordlessSmsDeliveryInput & { - userContext?: Record; - }): Promise; + static sendEmail( + input: TypePasswordlessEmailDeliveryInput & { + userContext?: Record; + } + ): Promise; + static sendSms( + input: TypePasswordlessSmsDeliveryInput & { + userContext?: Record; + } + ): Promise; } export declare let init: typeof Recipe.init; export declare let Error: typeof SuperTokensError; diff --git a/lib/build/recipe/passwordless/index.js b/lib/build/recipe/passwordless/index.js index 05cbf2c6c..ed0ff33e6 100644 --- a/lib/build/recipe/passwordless/index.js +++ b/lib/build/recipe/passwordless/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.sendSms = exports.sendEmail = exports.checkCode = exports.signInUp = exports.createMagicLink = exports.revokeCode = exports.revokeAllCodes = exports.updateUser = exports.createNewCodeForDevice = exports.listCodesByPreAuthSessionId = exports.listCodesByPhoneNumber = exports.listCodesByEmail = exports.listCodesByDeviceId = exports.consumeCode = exports.createCode = exports.Error = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); @@ -24,13 +26,29 @@ const __1 = require("../.."); const utils_1 = require("../../utils"); class Wrapper { static createCode(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createCode(Object.assign(Object.assign({}, input), { session: input.session, shouldTryLinkingWithSessionUser: !!input.session, userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createCode( + Object.assign(Object.assign({}, input), { + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + userContext: (0, utils_1.getUserContext)(input.userContext), + }) + ); } static createNewCodeForDevice(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.createNewCodeForDevice(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.createNewCodeForDevice( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static consumeCode(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.consumeCode(Object.assign(Object.assign({}, input), { session: input.session, shouldTryLinkingWithSessionUser: !!input.session, userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.consumeCode( + Object.assign(Object.assign({}, input), { + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + userContext: (0, utils_1.getUserContext)(input.userContext), + }) + ); } /** * This function will only verify the code (not consume it), and: @@ -40,41 +58,90 @@ class Wrapper { * NOT delete the code unless it returned RESTART_FLOW_ERROR */ static checkCode(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.checkCode(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.checkCode( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static updateUser(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.updateUser(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.updateUser( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static revokeAllCodes(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.revokeAllCodes(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.revokeAllCodes( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static revokeCode(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.revokeCode(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.revokeCode( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static listCodesByEmail(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.listCodesByEmail(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.listCodesByEmail( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static listCodesByPhoneNumber(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.listCodesByPhoneNumber(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.listCodesByPhoneNumber( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static listCodesByDeviceId(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.listCodesByDeviceId(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.listCodesByDeviceId( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static listCodesByPreAuthSessionId(input) { - return recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.listCodesByPreAuthSessionId(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.listCodesByPreAuthSessionId( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static createMagicLink(input) { const ctx = (0, utils_1.getUserContext)(input.userContext); - return recipe_1.default.getInstanceOrThrowError().createMagicLink(Object.assign(Object.assign({}, input), { request: (0, __1.getRequestFromUserContext)(ctx), userContext: ctx })); + return recipe_1.default.getInstanceOrThrowError().createMagicLink( + Object.assign(Object.assign({}, input), { + request: (0, __1.getRequestFromUserContext)(ctx), + userContext: ctx, + }) + ); } static signInUp(input) { - return recipe_1.default.getInstanceOrThrowError().signInUp(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return recipe_1.default + .getInstanceOrThrowError() + .signInUp( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static async sendEmail(input) { - return await recipe_1.default.getInstanceOrThrowError().emailDelivery.ingredientInterfaceImpl.sendEmail(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return await recipe_1.default + .getInstanceOrThrowError() + .emailDelivery.ingredientInterfaceImpl.sendEmail( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } static async sendSms(input) { - return await recipe_1.default.getInstanceOrThrowError().smsDelivery.ingredientInterfaceImpl.sendSms(Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) })); + return await recipe_1.default + .getInstanceOrThrowError() + .smsDelivery.ingredientInterfaceImpl.sendSms( + Object.assign(Object.assign({}, input), { userContext: (0, utils_1.getUserContext)(input.userContext) }) + ); } } Wrapper.init = recipe_1.default.init; diff --git a/lib/build/recipe/passwordless/recipe.d.ts b/lib/build/recipe/passwordless/recipe.d.ts index 32bd23659..903121051 100644 --- a/lib/build/recipe/passwordless/recipe.d.ts +++ b/lib/build/recipe/passwordless/recipe.d.ts @@ -18,42 +18,64 @@ export default class Recipe extends RecipeModule { isInServerlessEnv: boolean; emailDelivery: EmailDeliveryIngredient; smsDelivery: SmsDeliveryIngredient; - constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config: TypeInput, ingredients: { - emailDelivery: EmailDeliveryIngredient | undefined; - smsDelivery: SmsDeliveryIngredient | undefined; - }); + constructor( + recipeId: string, + appInfo: NormalisedAppinfo, + isInServerlessEnv: boolean, + config: TypeInput, + ingredients: { + emailDelivery: EmailDeliveryIngredient | undefined; + smsDelivery: SmsDeliveryIngredient | undefined; + } + ); static getInstanceOrThrowError(): Recipe; static init(config: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, tenantId: string, req: BaseRequest, res: BaseResponse, _: NormalisedURLPath, __: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + tenantId: string, + req: BaseRequest, + res: BaseResponse, + _: NormalisedURLPath, + __: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: STError, _: BaseRequest, __: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; - createMagicLink: (input: { - email: string; - tenantId: string; - session?: SessionContainerInterface; - request: BaseRequest | undefined; - userContext: UserContext; - } | { - phoneNumber: string; - tenantId: string; - session?: SessionContainerInterface; - request: BaseRequest | undefined; - userContext: UserContext; - }) => Promise; - signInUp: (input: { - email: string; - tenantId: string; - session?: SessionContainerInterface; - userContext: UserContext; - } | { - phoneNumber: string; - tenantId: string; - session?: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ + createMagicLink: ( + input: + | { + email: string; + tenantId: string; + session?: SessionContainerInterface; + request: BaseRequest | undefined; + userContext: UserContext; + } + | { + phoneNumber: string; + tenantId: string; + session?: SessionContainerInterface; + request: BaseRequest | undefined; + userContext: UserContext; + } + ) => Promise; + signInUp: ( + input: + | { + email: string; + tenantId: string; + session?: SessionContainerInterface; + userContext: UserContext; + } + | { + phoneNumber: string; + tenantId: string; + session?: SessionContainerInterface; + userContext: UserContext; + } + ) => Promise<{ status: string; createdNewRecipeUser: boolean; recipeUserId: import("../..").RecipeUserId; diff --git a/lib/build/recipe/passwordless/recipe.js b/lib/build/recipe/passwordless/recipe.js index 76a4e303c..ea77f9394 100644 --- a/lib/build/recipe/passwordless/recipe.js +++ b/lib/build/recipe/passwordless/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipeModule_1 = __importDefault(require("../../recipeModule")); const error_1 = __importDefault(require("./error")); @@ -79,7 +81,9 @@ class Recipe extends recipeModule_1.default { id: constants_1.DOES_PHONE_NUMBER_EXIST_API_OLD, disabled: this.apiImpl.phoneNumberExistsGET === undefined, method: "get", - pathWithoutApiBasePath: new normalisedURLPath_1.default(constants_1.DOES_PHONE_NUMBER_EXIST_API_OLD), + pathWithoutApiBasePath: new normalisedURLPath_1.default( + constants_1.DOES_PHONE_NUMBER_EXIST_API_OLD + ), }, { id: constants_1.RESEND_CODE_API, @@ -103,17 +107,16 @@ class Recipe extends recipeModule_1.default { }; if (id === constants_1.CONSUME_CODE_API) { return await (0, consumeCode_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.CREATE_CODE_API) { + } else if (id === constants_1.CREATE_CODE_API) { return await (0, createCode_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.DOES_EMAIL_EXIST_API || id === constants_1.DOES_EMAIL_EXIST_API_OLD) { + } else if (id === constants_1.DOES_EMAIL_EXIST_API || id === constants_1.DOES_EMAIL_EXIST_API_OLD) { return await (0, emailExists_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.DOES_PHONE_NUMBER_EXIST_API || id === constants_1.DOES_PHONE_NUMBER_EXIST_API_OLD) { + } else if ( + id === constants_1.DOES_PHONE_NUMBER_EXIST_API || + id === constants_1.DOES_PHONE_NUMBER_EXIST_API_OLD + ) { return await (0, phoneNumberExists_1.default)(this.apiImpl, tenantId, options, userContext); - } - else { + } else { return await (0, resendCode_1.default)(this.apiImpl, tenantId, options, userContext); } }; @@ -128,36 +131,40 @@ class Recipe extends recipeModule_1.default { }; // helper functions below... this.createMagicLink = async (input) => { - let userInputCode = this.config.getCustomUserInputCode !== undefined - ? await this.config.getCustomUserInputCode(input.tenantId, input.userContext) - : undefined; - const codeInfo = await this.recipeInterfaceImpl.createCode("email" in input - ? { - email: input.email, - userInputCode, - session: input.session, - shouldTryLinkingWithSessionUser: !!input.session, - tenantId: input.tenantId, - userContext: input.userContext, - } - : { - phoneNumber: input.phoneNumber, - userInputCode, - session: input.session, - shouldTryLinkingWithSessionUser: !!input.session, - tenantId: input.tenantId, - userContext: input.userContext, - }); + let userInputCode = + this.config.getCustomUserInputCode !== undefined + ? await this.config.getCustomUserInputCode(input.tenantId, input.userContext) + : undefined; + const codeInfo = await this.recipeInterfaceImpl.createCode( + "email" in input + ? { + email: input.email, + userInputCode, + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + tenantId: input.tenantId, + userContext: input.userContext, + } + : { + phoneNumber: input.phoneNumber, + userInputCode, + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + tenantId: input.tenantId, + userContext: input.userContext, + } + ); if (codeInfo.status !== "OK") { throw new Error("Failed to create user. Please retry"); } const appInfo = this.getAppInfo(); - let magicLink = appInfo - .getOrigin({ - request: input.request, - userContext: input.userContext, - }) - .getAsStringDangerous() + + let magicLink = + appInfo + .getOrigin({ + request: input.request, + userContext: input.userContext, + }) + .getAsStringDangerous() + appInfo.websiteBasePath.getAsStringDangerous() + "/verify" + "?preAuthSessionId=" + @@ -169,42 +176,46 @@ class Recipe extends recipeModule_1.default { return magicLink; }; this.signInUp = async (input) => { - let codeInfo = await this.recipeInterfaceImpl.createCode("email" in input - ? { - email: input.email, - tenantId: input.tenantId, - session: input.session, - shouldTryLinkingWithSessionUser: !!input.session, - userContext: input.userContext, - } - : { - phoneNumber: input.phoneNumber, - tenantId: input.tenantId, - session: input.session, - shouldTryLinkingWithSessionUser: !!input.session, - userContext: input.userContext, - }); + let codeInfo = await this.recipeInterfaceImpl.createCode( + "email" in input + ? { + email: input.email, + tenantId: input.tenantId, + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + userContext: input.userContext, + } + : { + phoneNumber: input.phoneNumber, + tenantId: input.tenantId, + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + userContext: input.userContext, + } + ); if (codeInfo.status !== "OK") { throw new Error("Failed to create user. Please retry"); } - let consumeCodeResponse = await this.recipeInterfaceImpl.consumeCode(this.config.flowType === "MAGIC_LINK" - ? { - preAuthSessionId: codeInfo.preAuthSessionId, - linkCode: codeInfo.linkCode, - session: input.session, - shouldTryLinkingWithSessionUser: !!input.session, - tenantId: input.tenantId, - userContext: input.userContext, - } - : { - preAuthSessionId: codeInfo.preAuthSessionId, - deviceId: codeInfo.deviceId, - userInputCode: codeInfo.userInputCode, - session: input.session, - shouldTryLinkingWithSessionUser: !!input.session, - tenantId: input.tenantId, - userContext: input.userContext, - }); + let consumeCodeResponse = await this.recipeInterfaceImpl.consumeCode( + this.config.flowType === "MAGIC_LINK" + ? { + preAuthSessionId: codeInfo.preAuthSessionId, + linkCode: codeInfo.linkCode, + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + tenantId: input.tenantId, + userContext: input.userContext, + } + : { + preAuthSessionId: codeInfo.preAuthSessionId, + deviceId: codeInfo.deviceId, + userInputCode: codeInfo.userInputCode, + session: input.session, + shouldTryLinkingWithSessionUser: !!input.session, + tenantId: input.tenantId, + userContext: input.userContext, + } + ); if (consumeCodeResponse.status === "OK") { return { status: "OK", @@ -212,15 +223,16 @@ class Recipe extends recipeModule_1.default { recipeUserId: consumeCodeResponse.recipeUserId, user: consumeCodeResponse.user, }; - } - else { + } else { throw new Error("Failed to create user. Please retry"); } }; this.isInServerlessEnv = isInServerlessEnv; this.config = (0, utils_1.validateAndNormaliseUserInput)(this, appInfo, config); { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId))); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId)) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -262,12 +274,18 @@ class Recipe extends recipeModule_1.default { // so that the frontend asks the user to enter an email, // or uses the email of another login method. if (loginMethod.email !== undefined && !(0, utils_2.isFakeEmail)(loginMethod.email)) { - if (factorId === multifactorauth_1.FactorIds.OTP_EMAIL || factorId === multifactorauth_1.FactorIds.LINK_EMAIL) { + if ( + factorId === multifactorauth_1.FactorIds.OTP_EMAIL || + factorId === multifactorauth_1.FactorIds.LINK_EMAIL + ) { return true; } } if (loginMethod.phoneNumber !== undefined) { - if (factorId === multifactorauth_1.FactorIds.OTP_PHONE || factorId === multifactorauth_1.FactorIds.LINK_PHONE) { + if ( + factorId === multifactorauth_1.FactorIds.OTP_PHONE || + factorId === multifactorauth_1.FactorIds.LINK_PHONE + ) { return true; } } @@ -302,11 +320,15 @@ class Recipe extends recipeModule_1.default { // we want to ask the user to enter their email, or to use // another login method that has no fake email. if (orderedLoginMethodsByTimeJoinedOldestFirst[i].recipeId === Recipe.RECIPE_ID) { - if (orderedLoginMethodsByTimeJoinedOldestFirst[i].email !== undefined && - !(0, utils_2.isFakeEmail)(orderedLoginMethodsByTimeJoinedOldestFirst[i].email)) { + if ( + orderedLoginMethodsByTimeJoinedOldestFirst[i].email !== undefined && + !(0, utils_2.isFakeEmail)(orderedLoginMethodsByTimeJoinedOldestFirst[i].email) + ) { // loginmethods for passwordless are guaranteed to have unique emails // across all the loginmethods for a user. - nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined.push(orderedLoginMethodsByTimeJoinedOldestFirst[i].email); + nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined.push( + orderedLoginMethodsByTimeJoinedOldestFirst[i].email + ); } } } @@ -324,12 +346,17 @@ class Recipe extends recipeModule_1.default { // for setting or asking for the OTP for the same email // that the user used to login. let emailsResult = []; - if (sessionLoginMethod.email !== undefined && !(0, utils_2.isFakeEmail)(sessionLoginMethod.email)) { + if ( + sessionLoginMethod.email !== undefined && + !(0, utils_2.isFakeEmail)(sessionLoginMethod.email) + ) { emailsResult = [sessionLoginMethod.email]; } for (let i = 0; i < orderedLoginMethodsByTimeJoinedOldestFirst.length; i++) { - if (orderedLoginMethodsByTimeJoinedOldestFirst[i].email !== undefined && - !(0, utils_2.isFakeEmail)(orderedLoginMethodsByTimeJoinedOldestFirst[i].email)) { + if ( + orderedLoginMethodsByTimeJoinedOldestFirst[i].email !== undefined && + !(0, utils_2.isFakeEmail)(orderedLoginMethodsByTimeJoinedOldestFirst[i].email) + ) { // we have the if check below cause different loginMethods // across different recipes can have the same email. if (!emailsResult.includes(orderedLoginMethodsByTimeJoinedOldestFirst[i].email)) { @@ -348,17 +375,20 @@ class Recipe extends recipeModule_1.default { status: "OK", factorIdToEmailsMap, }; - } - else if (nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined.length === 1) { + } else if (nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined.length === 1) { // we return just this email and not others cause we want to // not create more loginMethods with passwordless for the user // object. let factorIdToEmailsMap = {}; if (allFactors.includes(multifactorauth_1.FactorIds.OTP_EMAIL)) { - factorIdToEmailsMap[multifactorauth_1.FactorIds.OTP_EMAIL] = nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined; + factorIdToEmailsMap[ + multifactorauth_1.FactorIds.OTP_EMAIL + ] = nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined; } if (allFactors.includes(multifactorauth_1.FactorIds.LINK_EMAIL)) { - factorIdToEmailsMap[multifactorauth_1.FactorIds.LINK_EMAIL] = nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined; + factorIdToEmailsMap[ + multifactorauth_1.FactorIds.LINK_EMAIL + ] = nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined; } return { status: "OK", @@ -370,8 +400,10 @@ class Recipe extends recipeModule_1.default { // if the session's email is in the list of // nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined (for better UX) let emailsResult = []; - if (sessionLoginMethod.email !== undefined && - nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined.includes(sessionLoginMethod.email)) { + if ( + sessionLoginMethod.email !== undefined && + nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined.includes(sessionLoginMethod.email) + ) { emailsResult = [sessionLoginMethod.email]; } for (let i = 0; i < nonFakeEmailsThatPasswordlessLoginMethodOrderedByTimeJoined.length; i++) { @@ -420,7 +452,9 @@ class Recipe extends recipeModule_1.default { if (orderedLoginMethodsByTimeJoinedOldestFirst[i].phoneNumber !== undefined) { // loginmethods for passwordless are guaranteed to have unique phone numbers // across all the loginmethods for a user. - phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined.push(orderedLoginMethodsByTimeJoinedOldestFirst[i].phoneNumber); + phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined.push( + orderedLoginMethodsByTimeJoinedOldestFirst[i].phoneNumber + ); } } } @@ -461,17 +495,20 @@ class Recipe extends recipeModule_1.default { status: "OK", factorIdToPhoneNumberMap, }; - } - else if (phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined.length === 1) { + } else if (phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined.length === 1) { // we return just this phone number and not others cause we want to // not create more loginMethods with passwordless for the user // object. let factorIdToPhoneNumberMap = {}; if (allFactors.includes(multifactorauth_1.FactorIds.OTP_PHONE)) { - factorIdToPhoneNumberMap[multifactorauth_1.FactorIds.OTP_PHONE] = phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined; + factorIdToPhoneNumberMap[ + multifactorauth_1.FactorIds.OTP_PHONE + ] = phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined; } if (allFactors.includes(multifactorauth_1.FactorIds.LINK_PHONE)) { - factorIdToPhoneNumberMap[multifactorauth_1.FactorIds.LINK_PHONE] = phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined; + factorIdToPhoneNumberMap[ + multifactorauth_1.FactorIds.LINK_PHONE + ] = phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined; } return { status: "OK", @@ -483,8 +520,12 @@ class Recipe extends recipeModule_1.default { // if the session's phone is in the list of // phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined (for better UX) let phonesResult = []; - if (sessionLoginMethod.phoneNumber !== undefined && - phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined.includes(sessionLoginMethod.phoneNumber)) { + if ( + sessionLoginMethod.phoneNumber !== undefined && + phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined.includes( + sessionLoginMethod.phoneNumber + ) + ) { phonesResult = [sessionLoginMethod.phoneNumber]; } for (let i = 0; i < phoneNumbersThatPasswordlessLoginMethodOrderedByTimeJoined.length; i++) { @@ -522,13 +563,22 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_3.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : []), { - emailDelivery: undefined, - smsDelivery: undefined, - }); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_3.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ), + { + emailDelivery: undefined, + smsDelivery: undefined, + } + ); return Recipe.instance; - } - else { + } else { throw new Error("Passwordless recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/passwordless/recipeImplementation.js b/lib/build/recipe/passwordless/recipeImplementation.js index c8246436e..4d9bb0fb2 100644 --- a/lib/build/recipe/passwordless/recipeImplementation.js +++ b/lib/build/recipe/passwordless/recipeImplementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const recipe_1 = __importDefault(require("../accountlinking/recipe")); @@ -25,7 +27,11 @@ function getRecipeInterface(querier) { } return { consumeCode: async function (input) { - const response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code/consume`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + const response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code/consume`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); if (response.status !== "OK") { return response; } @@ -34,23 +40,34 @@ function getRecipeInterface(querier) { response.recipeUserId = new recipeUserId_1.default(response.recipeUserId); // Attempt account linking (this is a sign up) let updatedUser = response.user; - const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo({ - tenantId: input.tenantId, - inputUser: response.user, - recipeUserId: response.recipeUserId, - session: input.session, - shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, - userContext: input.userContext, - }); + const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo( + { + tenantId: input.tenantId, + inputUser: response.user, + recipeUserId: response.recipeUserId, + session: input.session, + shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, + userContext: input.userContext, + } + ); if (linkResult.status !== "OK") { return linkResult; } updatedUser = linkResult.user; response.user = updatedUser; - return Object.assign(Object.assign({}, response), { consumedDevice: response.consumedDevice, createdNewRecipeUser: response.createdNewUser, user: response.user, recipeUserId: response.recipeUserId }); + return Object.assign(Object.assign({}, response), { + consumedDevice: response.consumedDevice, + createdNewRecipeUser: response.createdNewUser, + user: response.user, + recipeUserId: response.recipeUserId, + }); }, checkCode: async function (input) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code/check`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code/check`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); if (response.status !== "OK") { return response; } @@ -58,37 +75,69 @@ function getRecipeInterface(querier) { return response; }, createCode: async function (input) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return response; }, createNewCodeForDevice: async function (input) { - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return response; }, listCodesByDeviceId: async function (input) { - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return response.devices.length === 1 ? response.devices[0] : undefined; }, listCodesByEmail: async function (input) { - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return response.devices; }, listCodesByPhoneNumber: async function (input) { - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return response.devices; }, listCodesByPreAuthSessionId: async function (input) { - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return response.devices.length === 1 ? response.devices[0] : undefined; }, revokeAllCodes: async function (input) { - await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes/remove`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/codes/remove`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return { status: "OK", }; }, revokeCode: async function (input) { - await querier.sendPostRequest(new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code/remove`), copyAndRemoveUserContextAndTenantId(input), input.userContext); + await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${input.tenantId}/recipe/signinup/code/remove`), + copyAndRemoveUserContextAndTenantId(input), + input.userContext + ); return { status: "OK" }; }, updateUser: async function (input) { @@ -117,13 +166,19 @@ function getRecipeInterface(querier) { if (!isEmailChangeAllowed.allowed) { return { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", - reason: isEmailChangeAllowed.reason === "ACCOUNT_TAKEOVER_RISK" - ? "New email cannot be applied to existing account because of account takeover risks." - : "New email cannot be applied to existing account because of there is another primary user with the same email address.", + reason: + isEmailChangeAllowed.reason === "ACCOUNT_TAKEOVER_RISK" + ? "New email cannot be applied to existing account because of account takeover risks." + : "New email cannot be applied to existing account because of there is another primary user with the same email address.", }; } } - let response = await querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/user`), copyAndRemoveUserContextAndTenantId(input), {}, input.userContext); + let response = await querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/user`), + copyAndRemoveUserContextAndTenantId(input), + {}, + input.userContext + ); if (response.status !== "OK") { return response; } diff --git a/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.d.ts b/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.d.ts index edd8c7e51..a0e2dbe84 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.d.ts +++ b/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.d.ts @@ -4,7 +4,9 @@ import { SmsDeliveryInterface } from "../../../../../ingredients/smsdelivery/typ import { UserContext } from "../../../../../types"; export default class BackwardCompatibilityService implements SmsDeliveryInterface { constructor(); - sendSms: (input: TypePasswordlessSmsDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendSms: ( + input: TypePasswordlessSmsDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.js b/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.js index 267f48430..bca8dac47 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.js +++ b/lib/build/recipe/passwordless/smsdelivery/services/backwardCompatibility/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_1 = require("../../../../../ingredients/smsdelivery/services/supertokens"); const supertokens_2 = __importDefault(require("../../../../../supertokens")); @@ -9,23 +11,28 @@ const utils_1 = require("../../../../../utils"); async function createAndSendSmsUsingSupertokensService(input) { let supertokens = supertokens_2.default.getInstanceOrThrowError(); let appName = supertokens.appInfo.appName; - const result = await (0, utils_1.postWithFetch)(supertokens_1.SUPERTOKENS_SMS_SERVICE_URL, { - "api-version": "0", - "content-type": "application/json; charset=utf-8", - }, { - smsInput: { - appName, - type: "PASSWORDLESS_LOGIN", - phoneNumber: input.phoneNumber, - userInputCode: input.userInputCode, - urlWithLinkCode: input.urlWithLinkCode, - codeLifetime: input.codeLifetime, - // isFirstFactor: input.isFirstFactor, + const result = await (0, utils_1.postWithFetch)( + supertokens_1.SUPERTOKENS_SMS_SERVICE_URL, + { + "api-version": "0", + "content-type": "application/json; charset=utf-8", }, - }, { - successLog: `Passwordless login SMS sent to ${input.phoneNumber}`, - errorLogHeader: "Error sending passwordless login SMS", - }); + { + smsInput: { + appName, + type: "PASSWORDLESS_LOGIN", + phoneNumber: input.phoneNumber, + userInputCode: input.userInputCode, + urlWithLinkCode: input.urlWithLinkCode, + codeLifetime: input.codeLifetime, + // isFirstFactor: input.isFirstFactor, + }, + }, + { + successLog: `Passwordless login SMS sent to ${input.phoneNumber}`, + errorLogHeader: "Error sending passwordless login SMS", + } + ); if ("error" in result) { throw result.error; } @@ -37,12 +44,10 @@ async function createAndSendSmsUsingSupertokensService(input) { * will be of type `{err: string}` */ throw new Error(result.resp.body.err); - } - else { + } else { throw new Error(`Request failed with status code ${result.resp.status}`); } - } - else { + } else { /** * if we do console.log(`SMS content: ${input}`); * Output would be: @@ -68,7 +73,9 @@ async function createAndSendSmsUsingSupertokensService(input) { * "b": 2 * } */ - console.log("Free daily SMS quota reached. If you want to use SuperTokens to send SMS, please sign up on supertokens.com to get your SMS API key, else you can also define your own method by overriding the service. For now, we are logging it below:"); + console.log( + "Free daily SMS quota reached. If you want to use SuperTokens to send SMS, please sign up on supertokens.com to get your SMS API key, else you can also define your own method by overriding the service. For now, we are logging it below:" + ); console.log(`\nSMS content: ${JSON.stringify(input, null, 2)}`); } } diff --git a/lib/build/recipe/passwordless/smsdelivery/services/index.js b/lib/build/recipe/passwordless/smsdelivery/services/index.js index c4ba9a912..f85fb8900 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/index.js +++ b/lib/build/recipe/passwordless/smsdelivery/services/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SupertokensService = exports.TwilioService = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. diff --git a/lib/build/recipe/passwordless/smsdelivery/services/supertokens/index.js b/lib/build/recipe/passwordless/smsdelivery/services/supertokens/index.js index b2dc87b08..eb3d45066 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/supertokens/index.js +++ b/lib/build/recipe/passwordless/smsdelivery/services/supertokens/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * @@ -25,24 +27,29 @@ class SupertokensService { this.sendSms = async (input) => { let supertokens = supertokens_2.default.getInstanceOrThrowError(); let appName = supertokens.appInfo.appName; - const res = await (0, utils_1.postWithFetch)(supertokens_1.SUPERTOKENS_SMS_SERVICE_URL, { - "api-version": "0", - "content-type": "application/json; charset=utf-8", - }, { - apiKey: this.apiKey, - smsInput: { - type: input.type, - phoneNumber: input.phoneNumber, - userInputCode: input.userInputCode, - urlWithLinkCode: input.urlWithLinkCode, - codeLifetime: input.codeLifetime, - isFirstFactor: input.isFirstFactor, - appName, + const res = await (0, utils_1.postWithFetch)( + supertokens_1.SUPERTOKENS_SMS_SERVICE_URL, + { + "api-version": "0", + "content-type": "application/json; charset=utf-8", }, - }, { - successLog: `Passwordless login SMS sent to ${input.phoneNumber}`, - errorLogHeader: "Error sending SMS", - }); + { + apiKey: this.apiKey, + smsInput: { + type: input.type, + phoneNumber: input.phoneNumber, + userInputCode: input.userInputCode, + urlWithLinkCode: input.urlWithLinkCode, + codeLifetime: input.codeLifetime, + isFirstFactor: input.isFirstFactor, + appName, + }, + }, + { + successLog: `Passwordless login SMS sent to ${input.phoneNumber}`, + errorLogHeader: "Error sending SMS", + } + ); if ("error" in res) { throw res.error; } diff --git a/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.d.ts b/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.d.ts index 3f5458100..d5e84942d 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.d.ts +++ b/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.d.ts @@ -7,7 +7,9 @@ export default class TwilioService implements SmsDeliveryInterface; private config; constructor(config: TypeInput); - sendSms: (input: TypePasswordlessSmsDeliveryInput & { - userContext: UserContext; - }) => Promise; + sendSms: ( + input: TypePasswordlessSmsDeliveryInput & { + userContext: UserContext; + } + ) => Promise; } diff --git a/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.js b/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.js index 8ddf0b043..1f35417a3 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.js +++ b/lib/build/recipe/passwordless/smsdelivery/services/twilio/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * @@ -26,15 +28,30 @@ class TwilioService { this.sendSms = async (input) => { let content = await this.serviceImpl.getContent(input); if ("from" in this.config.twilioSettings) { - await this.serviceImpl.sendRawSms(Object.assign(Object.assign({}, content), { userContext: input.userContext, from: this.config.twilioSettings.from })); - } - else { - await this.serviceImpl.sendRawSms(Object.assign(Object.assign({}, content), { userContext: input.userContext, messagingServiceSid: this.config.twilioSettings.messagingServiceSid })); + await this.serviceImpl.sendRawSms( + Object.assign(Object.assign({}, content), { + userContext: input.userContext, + from: this.config.twilioSettings.from, + }) + ); + } else { + await this.serviceImpl.sendRawSms( + Object.assign(Object.assign({}, content), { + userContext: input.userContext, + messagingServiceSid: this.config.twilioSettings.messagingServiceSid, + }) + ); } }; this.config = (0, twilio_1.normaliseUserInputConfig)(config); - const twilioClient = (0, twilio_2.default)(config.twilioSettings.accountSid, config.twilioSettings.authToken, config.twilioSettings.opts); - let builder = new supertokens_js_override_1.default((0, serviceImplementation_1.getServiceImplementation)(twilioClient)); + const twilioClient = (0, twilio_2.default)( + config.twilioSettings.accountSid, + config.twilioSettings.authToken, + config.twilioSettings.opts + ); + let builder = new supertokens_js_override_1.default( + (0, serviceImplementation_1.getServiceImplementation)(twilioClient) + ); if (config.override !== undefined) { builder = builder.override(config.override); } diff --git a/lib/build/recipe/passwordless/smsdelivery/services/twilio/passwordlessLogin.js b/lib/build/recipe/passwordless/smsdelivery/services/twilio/passwordlessLogin.js index 6cdc7fc09..aa20b5f16 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/twilio/passwordlessLogin.js +++ b/lib/build/recipe/passwordless/smsdelivery/services/twilio/passwordlessLogin.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getPasswordlessLoginSmsContent; const utils_1 = require("../../../../../utils"); @@ -19,11 +21,9 @@ function getPasswordlessLoginSmsBody(appName, codeLifetime, urlWithLinkCode, use let message = ""; if (urlWithLinkCode !== undefined && userInputCode !== undefined) { message += `OTP to login is ${userInputCode} for ${appName}\n\nOR click ${urlWithLinkCode} to login.\n\n`; - } - else if (urlWithLinkCode !== undefined) { + } else if (urlWithLinkCode !== undefined) { message += `Click ${urlWithLinkCode} to login to ${appName}\n\n`; - } - else { + } else { message += `OTP to login is ${userInputCode} for ${appName}\n\n`; } const humanisedCodeLifetime = (0, utils_1.humaniseMilliseconds)(codeLifetime); diff --git a/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.d.ts b/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.d.ts index 7f73b5364..6aa22d4d2 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.d.ts +++ b/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.d.ts @@ -2,4 +2,6 @@ import { TypePasswordlessSmsDeliveryInput } from "../../../types"; import Twilio from "twilio/lib/rest/Twilio"; import { ServiceInterface } from "../../../../../ingredients/smsdelivery/services/twilio"; -export declare function getServiceImplementation(twilioClient: Twilio): ServiceInterface; +export declare function getServiceImplementation( + twilioClient: Twilio +): ServiceInterface; diff --git a/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.js b/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.js index 9f4720bba..f52406a18 100644 --- a/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.js +++ b/lib/build/recipe/passwordless/smsdelivery/services/twilio/serviceImplementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getServiceImplementation = getServiceImplementation; const passwordlessLogin_1 = __importDefault(require("./passwordlessLogin")); @@ -28,8 +30,7 @@ function getServiceImplementation(twilioClient) { body: input.body, from: input.from, }); - } - else { + } else { await twilioClient.messages.create({ to: input.toPhoneNumber, body: input.body, diff --git a/lib/build/recipe/passwordless/types.d.ts b/lib/build/recipe/passwordless/types.d.ts index 3a29f5ee6..90c6c6672 100644 --- a/lib/build/recipe/passwordless/types.d.ts +++ b/lib/build/recipe/passwordless/types.d.ts @@ -2,64 +2,101 @@ import type { BaseRequest, BaseResponse } from "../../framework"; import OverrideableBuilder from "supertokens-js-override"; import { SessionContainerInterface } from "../session/types"; -import { TypeInput as EmailDeliveryTypeInput, TypeInputWithService as EmailDeliveryTypeInputWithService } from "../../ingredients/emaildelivery/types"; +import { + TypeInput as EmailDeliveryTypeInput, + TypeInputWithService as EmailDeliveryTypeInputWithService, +} from "../../ingredients/emaildelivery/types"; import EmailDeliveryIngredient from "../../ingredients/emaildelivery"; -import { TypeInput as SmsDeliveryTypeInput, TypeInputWithService as SmsDeliveryTypeInputWithService } from "../../ingredients/smsdelivery/types"; +import { + TypeInput as SmsDeliveryTypeInput, + TypeInputWithService as SmsDeliveryTypeInputWithService, +} from "../../ingredients/smsdelivery/types"; import SmsDeliveryIngredient from "../../ingredients/smsdelivery"; import { GeneralErrorResponse, NormalisedAppinfo, User, UserContext } from "../../types"; import RecipeUserId from "../../recipeUserId"; -export type TypeInput = ({ - contactMethod: "PHONE"; - validatePhoneNumber?: (phoneNumber: string, tenantId: string) => Promise | string | undefined; -} | { - contactMethod: "EMAIL"; - validateEmailAddress?: (email: string, tenantId: string) => Promise | string | undefined; -} | { - contactMethod: "EMAIL_OR_PHONE"; - validateEmailAddress?: (email: string, tenantId: string) => Promise | string | undefined; - validatePhoneNumber?: (phoneNumber: string, tenantId: string) => Promise | string | undefined; -}) & { +export type TypeInput = ( + | { + contactMethod: "PHONE"; + validatePhoneNumber?: ( + phoneNumber: string, + tenantId: string + ) => Promise | string | undefined; + } + | { + contactMethod: "EMAIL"; + validateEmailAddress?: (email: string, tenantId: string) => Promise | string | undefined; + } + | { + contactMethod: "EMAIL_OR_PHONE"; + validateEmailAddress?: (email: string, tenantId: string) => Promise | string | undefined; + validatePhoneNumber?: ( + phoneNumber: string, + tenantId: string + ) => Promise | string | undefined; + } +) & { flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; emailDelivery?: EmailDeliveryTypeInput; smsDelivery?: SmsDeliveryTypeInput; getCustomUserInputCode?: (tenantId: string, userContext: UserContext) => Promise | string; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; -export type TypeNormalisedInput = ({ - contactMethod: "PHONE"; - validatePhoneNumber: (phoneNumber: string, tenantId: string) => Promise | string | undefined; -} | { - contactMethod: "EMAIL"; - validateEmailAddress: (email: string, tenantId: string) => Promise | string | undefined; -} | { - contactMethod: "EMAIL_OR_PHONE"; - validateEmailAddress: (email: string, tenantId: string) => Promise | string | undefined; - validatePhoneNumber: (phoneNumber: string, tenantId: string) => Promise | string | undefined; -}) & { +export type TypeNormalisedInput = ( + | { + contactMethod: "PHONE"; + validatePhoneNumber: ( + phoneNumber: string, + tenantId: string + ) => Promise | string | undefined; + } + | { + contactMethod: "EMAIL"; + validateEmailAddress: (email: string, tenantId: string) => Promise | string | undefined; + } + | { + contactMethod: "EMAIL_OR_PHONE"; + validateEmailAddress: (email: string, tenantId: string) => Promise | string | undefined; + validatePhoneNumber: ( + phoneNumber: string, + tenantId: string + ) => Promise | string | undefined; + } +) & { flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; getCustomUserInputCode?: (tenantId: string, userContext: UserContext) => Promise | string; getSmsDeliveryConfig: () => SmsDeliveryTypeInputWithService; getEmailDeliveryConfig: () => EmailDeliveryTypeInputWithService; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type RecipeInterface = { - createCode: (input: ({ - email: string; - } | { - phoneNumber: string; - }) & { - userInputCode?: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - tenantId: string; - userContext: UserContext; - }) => Promise<{ + createCode: ( + input: ( + | { + email: string; + } + | { + phoneNumber: string; + } + ) & { + userInputCode?: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + tenantId: string; + userContext: UserContext; + } + ) => Promise<{ status: "OK"; preAuthSessionId: string; codeId: string; @@ -74,118 +111,153 @@ export type RecipeInterface = { userInputCode?: string; tenantId: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - preAuthSessionId: string; - codeId: string; - deviceId: string; - userInputCode: string; - linkCode: string; - codeLifetime: number; - timeCreated: number; - } | { - status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR"; - }>; - consumeCode: (input: { - userInputCode: string; - deviceId: string; - preAuthSessionId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - tenantId: string; - userContext: UserContext; - } | { - linkCode: string; - preAuthSessionId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - tenantId: string; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - consumedDevice: { - preAuthSessionId: string; - failedCodeInputAttemptCount: number; - email?: string; - phoneNumber?: string; - }; - createdNewRecipeUser: boolean; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; - failedCodeInputAttemptCount: number; - maximumCodeInputAttempts: number; - } | { - status: "RESTART_FLOW_ERROR"; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; - checkCode: (input: { - userInputCode: string; - deviceId: string; - preAuthSessionId: string; - tenantId: string; - userContext: UserContext; - } | { - linkCode: string; - preAuthSessionId: string; - tenantId: string; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - consumedDevice: { - preAuthSessionId: string; - failedCodeInputAttemptCount: number; - email?: string; - phoneNumber?: string; - }; - } | { - status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; - failedCodeInputAttemptCount: number; - maximumCodeInputAttempts: number; - } | { - status: "RESTART_FLOW_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + preAuthSessionId: string; + codeId: string; + deviceId: string; + userInputCode: string; + linkCode: string; + codeLifetime: number; + timeCreated: number; + } + | { + status: "RESTART_FLOW_ERROR" | "USER_INPUT_CODE_ALREADY_USED_ERROR"; + } + >; + consumeCode: ( + input: + | { + userInputCode: string; + deviceId: string; + preAuthSessionId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + tenantId: string; + userContext: UserContext; + } + | { + linkCode: string; + preAuthSessionId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + tenantId: string; + userContext: UserContext; + } + ) => Promise< + | { + status: "OK"; + consumedDevice: { + preAuthSessionId: string; + failedCodeInputAttemptCount: number; + email?: string; + phoneNumber?: string; + }; + createdNewRecipeUser: boolean; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; + failedCodeInputAttemptCount: number; + maximumCodeInputAttempts: number; + } + | { + status: "RESTART_FLOW_ERROR"; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; + checkCode: ( + input: + | { + userInputCode: string; + deviceId: string; + preAuthSessionId: string; + tenantId: string; + userContext: UserContext; + } + | { + linkCode: string; + preAuthSessionId: string; + tenantId: string; + userContext: UserContext; + } + ) => Promise< + | { + status: "OK"; + consumedDevice: { + preAuthSessionId: string; + failedCodeInputAttemptCount: number; + email?: string; + phoneNumber?: string; + }; + } + | { + status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; + failedCodeInputAttemptCount: number; + maximumCodeInputAttempts: number; + } + | { + status: "RESTART_FLOW_ERROR"; + } + >; updateUser: (input: { recipeUserId: RecipeUserId; email?: string | null; phoneNumber?: string | null; userContext: UserContext; - }) => Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR" | "EMAIL_ALREADY_EXISTS_ERROR" | "PHONE_NUMBER_ALREADY_EXISTS_ERROR"; - } | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR"; - reason: string; - }>; - revokeAllCodes: (input: { - email: string; - tenantId: string; - userContext: UserContext; - } | { - phoneNumber: string; - tenantId: string; - userContext: UserContext; - }) => Promise<{ + }) => Promise< + | { + status: + | "OK" + | "UNKNOWN_USER_ID_ERROR" + | "EMAIL_ALREADY_EXISTS_ERROR" + | "PHONE_NUMBER_ALREADY_EXISTS_ERROR"; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR" | "PHONE_NUMBER_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } + >; + revokeAllCodes: ( + input: + | { + email: string; + tenantId: string; + userContext: UserContext; + } + | { + phoneNumber: string; + tenantId: string; + userContext: UserContext; + } + ) => Promise<{ status: "OK"; }>; - revokeCode: (input: { - codeId: string; - tenantId: string; - userContext: UserContext; - } | { - preAuthSessionId: string; - tenantId: string; - userContext: UserContext; - }) => Promise<{ + revokeCode: ( + input: + | { + codeId: string; + tenantId: string; + userContext: UserContext; + } + | { + preAuthSessionId: string; + tenantId: string; + userContext: UserContext; + } + ) => Promise<{ status: "OK"; }>; - listCodesByEmail: (input: { - email: string; - tenantId: string; - userContext: UserContext; - }) => Promise; + listCodesByEmail: (input: { email: string; tenantId: string; userContext: UserContext }) => Promise; listCodesByPhoneNumber: (input: { phoneNumber: string; tenantId: string; @@ -225,83 +297,114 @@ export type APIOptions = { smsDelivery: SmsDeliveryIngredient; }; export type APIInterface = { - createCodePOST?: (input: ({ - email: string; - } | { - phoneNumber: string; - }) & { - tenantId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - deviceId: string; - preAuthSessionId: string; - flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; - } | { - status: "SIGN_IN_UP_NOT_ALLOWED"; - reason: string; - } | GeneralErrorResponse>; - resendCodePOST?: (input: { - deviceId: string; - preAuthSessionId: string; - } & { - tenantId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - options: APIOptions; - userContext: UserContext; - }) => Promise; - consumeCodePOST?: (input: ({ - userInputCode: string; - deviceId: string; - preAuthSessionId: string; - } | { - linkCode: string; - preAuthSessionId: string; - }) & { - tenantId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - createdNewRecipeUser: boolean; - user: User; - session: SessionContainerInterface; - } | { - status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; - failedCodeInputAttemptCount: number; - maximumCodeInputAttempts: number; - } | { - status: "RESTART_FLOW_ERROR"; - } | { - status: "SIGN_IN_UP_NOT_ALLOWED"; - reason: string; - } | GeneralErrorResponse>; + createCodePOST?: ( + input: ( + | { + email: string; + } + | { + phoneNumber: string; + } + ) & { + tenantId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + options: APIOptions; + userContext: UserContext; + } + ) => Promise< + | { + status: "OK"; + deviceId: string; + preAuthSessionId: string; + flowType: "USER_INPUT_CODE" | "MAGIC_LINK" | "USER_INPUT_CODE_AND_MAGIC_LINK"; + } + | { + status: "SIGN_IN_UP_NOT_ALLOWED"; + reason: string; + } + | GeneralErrorResponse + >; + resendCodePOST?: ( + input: { + deviceId: string; + preAuthSessionId: string; + } & { + tenantId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + options: APIOptions; + userContext: UserContext; + } + ) => Promise< + | GeneralErrorResponse + | { + status: "RESTART_FLOW_ERROR" | "OK"; + } + >; + consumeCodePOST?: ( + input: ( + | { + userInputCode: string; + deviceId: string; + preAuthSessionId: string; + } + | { + linkCode: string; + preAuthSessionId: string; + } + ) & { + tenantId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + options: APIOptions; + userContext: UserContext; + } + ) => Promise< + | { + status: "OK"; + createdNewRecipeUser: boolean; + user: User; + session: SessionContainerInterface; + } + | { + status: "INCORRECT_USER_INPUT_CODE_ERROR" | "EXPIRED_USER_INPUT_CODE_ERROR"; + failedCodeInputAttemptCount: number; + maximumCodeInputAttempts: number; + } + | { + status: "RESTART_FLOW_ERROR"; + } + | { + status: "SIGN_IN_UP_NOT_ALLOWED"; + reason: string; + } + | GeneralErrorResponse + >; emailExistsGET?: (input: { email: string; tenantId: string; options: APIOptions; userContext: UserContext; - }) => Promise<{ - status: "OK"; - exists: boolean; - } | GeneralErrorResponse>; + }) => Promise< + | { + status: "OK"; + exists: boolean; + } + | GeneralErrorResponse + >; phoneNumberExistsGET?: (input: { phoneNumber: string; tenantId: string; options: APIOptions; userContext: UserContext; - }) => Promise<{ - status: "OK"; - exists: boolean; - } | GeneralErrorResponse>; + }) => Promise< + | { + status: "OK"; + exists: boolean; + } + | GeneralErrorResponse + >; }; export type TypePasswordlessEmailDeliveryInput = { type: "PASSWORDLESS_LOGIN"; diff --git a/lib/build/recipe/passwordless/utils.d.ts b/lib/build/recipe/passwordless/utils.d.ts index e72ef0708..8d1b4b9f2 100644 --- a/lib/build/recipe/passwordless/utils.d.ts +++ b/lib/build/recipe/passwordless/utils.d.ts @@ -2,7 +2,11 @@ import Recipe from "./recipe"; import { TypeInput, TypeNormalisedInput } from "./types"; import { NormalisedAppinfo } from "../../types"; -export declare function validateAndNormaliseUserInput(_: Recipe, appInfo: NormalisedAppinfo, config: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + _: Recipe, + appInfo: NormalisedAppinfo, + config: TypeInput +): TypeNormalisedInput; export declare function defaultValidatePhoneNumber(value: string): Promise | string | undefined; export declare function defaultValidateEmail(value: string): Promise | string | undefined; export declare function getEnabledPwlessFactors(config: TypeInput): string[]; diff --git a/lib/build/recipe/passwordless/utils.js b/lib/build/recipe/passwordless/utils.js index 7c5c833ad..6fb95062a 100644 --- a/lib/build/recipe/passwordless/utils.js +++ b/lib/build/recipe/passwordless/utils.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; exports.defaultValidatePhoneNumber = defaultValidatePhoneNumber; @@ -26,15 +28,23 @@ const backwardCompatibility_1 = __importDefault(require("./emaildelivery/service const backwardCompatibility_2 = __importDefault(require("./smsdelivery/services/backwardCompatibility")); const multifactorauth_1 = require("../multifactorauth"); function validateAndNormaliseUserInput(_, appInfo, config) { - if (config.contactMethod !== "PHONE" && + if ( + config.contactMethod !== "PHONE" && config.contactMethod !== "EMAIL" && - config.contactMethod !== "EMAIL_OR_PHONE") { + config.contactMethod !== "EMAIL_OR_PHONE" + ) { throw new Error('Please pass one of "PHONE", "EMAIL" or "EMAIL_OR_PHONE" as the contactMethod'); } if (config.flowType === undefined) { throw new Error("Please pass flowType argument in the config"); } - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config.override + ); function getEmailDeliveryConfig() { var _a; let emailService = (_a = config.emailDelivery) === null || _a === void 0 ? void 0 : _a.service; @@ -46,7 +56,7 @@ function validateAndNormaliseUserInput(_, appInfo, config) { if (emailService === undefined) { emailService = new backwardCompatibility_1.default(appInfo); } - let emailDelivery = Object.assign(Object.assign({}, config.emailDelivery), { + let emailDelivery = Object.assign(Object.assign({}, config.emailDelivery), { /** * if we do * let emailDelivery = { @@ -58,7 +68,8 @@ function validateAndNormaliseUserInput(_, appInfo, config) { * it it again get set to undefined, so we * set service at the end */ - service: emailService }); + service: emailService, + }); return emailDelivery; } function getSmsDeliveryConfig() { @@ -74,7 +85,7 @@ function validateAndNormaliseUserInput(_, appInfo, config) { if (smsService === undefined) { smsService = new backwardCompatibility_2.default(); } - let smsDelivery = Object.assign(Object.assign({}, config.smsDelivery), { + let smsDelivery = Object.assign(Object.assign({}, config.smsDelivery), { /** * if we do * let smsDelivery = { @@ -86,7 +97,8 @@ function validateAndNormaliseUserInput(_, appInfo, config) { * it it again get set to undefined, so we * set service at the end */ - service: smsService }); + service: smsService, + }); return smsDelivery; } if (config.contactMethod === "EMAIL") { @@ -96,30 +108,32 @@ function validateAndNormaliseUserInput(_, appInfo, config) { getSmsDeliveryConfig, flowType: config.flowType, contactMethod: "EMAIL", - validateEmailAddress: config.validateEmailAddress === undefined ? defaultValidateEmail : config.validateEmailAddress, + validateEmailAddress: + config.validateEmailAddress === undefined ? defaultValidateEmail : config.validateEmailAddress, getCustomUserInputCode: config.getCustomUserInputCode, }; - } - else if (config.contactMethod === "PHONE") { + } else if (config.contactMethod === "PHONE") { return { override, getEmailDeliveryConfig, getSmsDeliveryConfig, flowType: config.flowType, contactMethod: "PHONE", - validatePhoneNumber: config.validatePhoneNumber === undefined ? defaultValidatePhoneNumber : config.validatePhoneNumber, + validatePhoneNumber: + config.validatePhoneNumber === undefined ? defaultValidatePhoneNumber : config.validatePhoneNumber, getCustomUserInputCode: config.getCustomUserInputCode, }; - } - else { + } else { return { override, getEmailDeliveryConfig, getSmsDeliveryConfig, flowType: config.flowType, contactMethod: "EMAIL_OR_PHONE", - validateEmailAddress: config.validateEmailAddress === undefined ? defaultValidateEmail : config.validateEmailAddress, - validatePhoneNumber: config.validatePhoneNumber === undefined ? defaultValidatePhoneNumber : config.validatePhoneNumber, + validateEmailAddress: + config.validateEmailAddress === undefined ? defaultValidateEmail : config.validateEmailAddress, + validatePhoneNumber: + config.validatePhoneNumber === undefined ? defaultValidatePhoneNumber : config.validatePhoneNumber, getCustomUserInputCode: config.getCustomUserInputCode, }; } @@ -142,7 +156,11 @@ function defaultValidateEmail(value) { if (typeof value !== "string") { return "Development bug: Please make sure the email field is a string"; } - if (value.match(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/) === null) { + if ( + value.match( + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + ) === null + ) { return "Email is invalid"; } return undefined; @@ -152,34 +170,31 @@ function getEnabledPwlessFactors(config) { if (config.flowType === "MAGIC_LINK") { if (config.contactMethod === "EMAIL") { allFactors = [multifactorauth_1.FactorIds.LINK_EMAIL]; - } - else if (config.contactMethod === "PHONE") { + } else if (config.contactMethod === "PHONE") { allFactors = [multifactorauth_1.FactorIds.LINK_PHONE]; - } - else { + } else { allFactors = [multifactorauth_1.FactorIds.LINK_EMAIL, multifactorauth_1.FactorIds.LINK_PHONE]; } - } - else if (config.flowType === "USER_INPUT_CODE") { + } else if (config.flowType === "USER_INPUT_CODE") { if (config.contactMethod === "EMAIL") { allFactors = [multifactorauth_1.FactorIds.OTP_EMAIL]; - } - else if (config.contactMethod === "PHONE") { + } else if (config.contactMethod === "PHONE") { allFactors = [multifactorauth_1.FactorIds.OTP_PHONE]; - } - else { + } else { allFactors = [multifactorauth_1.FactorIds.OTP_EMAIL, multifactorauth_1.FactorIds.OTP_PHONE]; } - } - else { + } else { if (config.contactMethod === "EMAIL") { allFactors = [multifactorauth_1.FactorIds.OTP_EMAIL, multifactorauth_1.FactorIds.LINK_EMAIL]; - } - else if (config.contactMethod === "PHONE") { + } else if (config.contactMethod === "PHONE") { allFactors = [multifactorauth_1.FactorIds.OTP_PHONE, multifactorauth_1.FactorIds.LINK_PHONE]; - } - else { - allFactors = [multifactorauth_1.FactorIds.OTP_EMAIL, multifactorauth_1.FactorIds.OTP_PHONE, multifactorauth_1.FactorIds.LINK_EMAIL, multifactorauth_1.FactorIds.LINK_PHONE]; + } else { + allFactors = [ + multifactorauth_1.FactorIds.OTP_EMAIL, + multifactorauth_1.FactorIds.OTP_PHONE, + multifactorauth_1.FactorIds.LINK_EMAIL, + multifactorauth_1.FactorIds.LINK_PHONE, + ]; } } return allFactors; diff --git a/lib/build/recipe/session/accessToken.d.ts b/lib/build/recipe/session/accessToken.d.ts index 01a4ece91..8b0685ec8 100644 --- a/lib/build/recipe/session/accessToken.d.ts +++ b/lib/build/recipe/session/accessToken.d.ts @@ -2,7 +2,11 @@ import { ParsedJWTInfo } from "./jwt"; import * as jose from "jose"; import RecipeUserId from "../../recipeUserId"; -export declare function getInfoFromAccessToken(jwtInfo: ParsedJWTInfo, jwks: jose.JWTVerifyGetKey, doAntiCsrfCheck: boolean): Promise<{ +export declare function getInfoFromAccessToken( + jwtInfo: ParsedJWTInfo, + jwks: jose.JWTVerifyGetKey, + doAntiCsrfCheck: boolean +): Promise<{ sessionHandle: string; userId: string; recipeUserId: RecipeUserId; diff --git a/lib/build/recipe/session/accessToken.js b/lib/build/recipe/session/accessToken.js index c8a6e4b44..b2276385e 100644 --- a/lib/build/recipe/session/accessToken.js +++ b/lib/build/recipe/session/accessToken.js @@ -13,49 +13,95 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; }; - return ownKeys(o); + })(); +var __asyncValues = + (this && this.__asyncValues) || + function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], + i; + return m + ? m.call(o) + : ((o = typeof __values === "function" ? __values(o) : o[Symbol.iterator]()), + (i = {}), + verb("next"), + verb("throw"), + verb("return"), + (i[Symbol.asyncIterator] = function () { + return this; + }), + i); + function verb(n) { + i[n] = + o[n] && + function (v) { + return new Promise(function (resolve, reject) { + (v = o[n](v)), settle(resolve, reject, v.done, v.value); + }); + }; + } + function settle(resolve, reject, d, v) { + Promise.resolve(v).then(function (v) { + resolve({ value: v, done: d }); + }, reject); + } }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; }; -})(); -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.getInfoFromAccessToken = getInfoFromAccessToken; exports.validateAccessTokenStructure = validateAccessTokenStructure; @@ -74,42 +120,50 @@ async function getInfoFromAccessToken(jwtInfo, jwks, doAntiCsrfCheck) { let payload = undefined; try { payload = (await jose.jwtVerify(jwtInfo.rawTokenString, jwks)).payload; - } - catch (error) { + } catch (error) { // We only want to opt-into this for V2 access tokens - if (jwtInfo.version === 2 && (error === null || error === void 0 ? void 0 : error.code) === "ERR_JWKS_MULTIPLE_MATCHING_KEYS") { + if ( + jwtInfo.version === 2 && + (error === null || error === void 0 ? void 0 : error.code) === "ERR_JWKS_MULTIPLE_MATCHING_KEYS" + ) { processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.MULTI_JWKS_VALIDATION); try { // We are trying to validate the token with each key. // Since the kid is missing from v2 tokens, this basically means we try all keys present in the cache. - for (var _e = true, error_2 = __asyncValues(error), error_2_1; error_2_1 = await error_2.next(), _a = error_2_1.done, !_a; _e = true) { + for ( + var _e = true, error_2 = __asyncValues(error), error_2_1; + (error_2_1 = await error_2.next()), (_a = error_2_1.done), !_a; + _e = true + ) { _c = error_2_1.value; _e = false; const publicKey = _c; try { payload = (await jose.jwtVerify(jwtInfo.rawTokenString, publicKey)).payload; break; - } - catch (innerError) { - if ((innerError === null || innerError === void 0 ? void 0 : innerError.code) === "ERR_JWS_SIGNATURE_VERIFICATION_FAILED") { + } catch (innerError) { + if ( + (innerError === null || innerError === void 0 ? void 0 : innerError.code) === + "ERR_JWS_SIGNATURE_VERIFICATION_FAILED" + ) { continue; } throw innerError; } } - } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { + } catch (e_1_1) { + e_1 = { error: e_1_1 }; + } finally { try { if (!_e && !_a && (_b = error_2.return)) await _b.call(error_2); + } finally { + if (e_1) throw e_1.error; } - finally { if (e_1) throw e_1.error; } } if (payload === undefined) { throw new jose.errors.JWSSignatureVerificationFailed(); } - } - else { + } else { throw error; } } @@ -117,14 +171,16 @@ async function getInfoFromAccessToken(jwtInfo, jwks, doAntiCsrfCheck) { validateAccessTokenStructure(payload, jwtInfo.version); // We can mark these as defined (the ! after the calls), since validateAccessTokenPayload checks this let userId = jwtInfo.version === 2 ? sanitizeStringInput(payload.userId) : sanitizeStringInput(payload.sub); - let expiryTime = jwtInfo.version === 2 ? sanitizeNumberInput(payload.expiryTime) : sanitizeNumberInput(payload.exp) * 1000; - let timeCreated = jwtInfo.version === 2 - ? sanitizeNumberInput(payload.timeCreated) - : sanitizeNumberInput(payload.iat) * 1000; + let expiryTime = + jwtInfo.version === 2 ? sanitizeNumberInput(payload.expiryTime) : sanitizeNumberInput(payload.exp) * 1000; + let timeCreated = + jwtInfo.version === 2 ? sanitizeNumberInput(payload.timeCreated) : sanitizeNumberInput(payload.iat) * 1000; let userData = jwtInfo.version === 2 ? payload.userData : payload; let sessionHandle = sanitizeStringInput(payload.sessionHandle); // we use ?? below cause recipeUserId may be undefined for JWTs that are of an older version. - let recipeUserId = new recipeUserId_1.default((_d = sanitizeStringInput(payload.rsub)) !== null && _d !== void 0 ? _d : userId); + let recipeUserId = new recipeUserId_1.default( + (_d = sanitizeStringInput(payload.rsub)) !== null && _d !== void 0 ? _d : userId + ); let refreshTokenHash1 = sanitizeStringInput(payload.refreshTokenHash1); let parentRefreshTokenHash1 = sanitizeStringInput(payload.parentRefreshTokenHash1); let antiCsrfToken = sanitizeStringInput(payload.antiCsrfToken); @@ -150,10 +206,11 @@ async function getInfoFromAccessToken(jwtInfo, jwks, doAntiCsrfCheck) { recipeUserId, tenantId, }; - } - catch (err) { - (0, logger_1.logDebugMessage)("getInfoFromAccessToken: Returning TRY_REFRESH_TOKEN because access token validation failed - " + - err.message); + } catch (err) { + (0, logger_1.logDebugMessage)( + "getInfoFromAccessToken: Returning TRY_REFRESH_TOKEN because access token validation failed - " + + err.message + ); throw new error_1.default({ message: "Failed to verify access token", type: error_1.default.TRY_REFRESH_TOKEN, @@ -165,36 +222,40 @@ function validateAccessTokenStructure(payload, version) { throw Error("Wrong token type"); } if (version >= 5) { - if (typeof payload.sub !== "string" || + if ( + typeof payload.sub !== "string" || typeof payload.exp !== "number" || typeof payload.iat !== "number" || typeof payload.sessionHandle !== "string" || typeof payload.refreshTokenHash1 !== "string" || - typeof payload.rsub !== "string") { + typeof payload.rsub !== "string" + ) { (0, logger_1.logDebugMessage)("validateAccessTokenStructure: Access token is using version >= 4"); // The error message below will be logged by the error handler that translates this into a TRY_REFRESH_TOKEN_ERROR // it would come here if we change the structure of the JWT. throw Error("Access token does not contain all the information. Maybe the structure has changed?"); } - } - else if (version >= 4) { - if (typeof payload.sub !== "string" || + } else if (version >= 4) { + if ( + typeof payload.sub !== "string" || typeof payload.exp !== "number" || typeof payload.iat !== "number" || typeof payload.sessionHandle !== "string" || - typeof payload.refreshTokenHash1 !== "string") { + typeof payload.refreshTokenHash1 !== "string" + ) { (0, logger_1.logDebugMessage)("validateAccessTokenStructure: Access token is using version >= 4"); // The error message below will be logged by the error handler that translates this into a TRY_REFRESH_TOKEN_ERROR // it would come here if we change the structure of the JWT. throw Error("Access token does not contain all the information. Maybe the structure has changed?"); } - } - else if (version >= 3) { - if (typeof payload.sub !== "string" || + } else if (version >= 3) { + if ( + typeof payload.sub !== "string" || typeof payload.exp !== "number" || typeof payload.iat !== "number" || typeof payload.sessionHandle !== "string" || - typeof payload.refreshTokenHash1 !== "string") { + typeof payload.refreshTokenHash1 !== "string" + ) { (0, logger_1.logDebugMessage)("validateAccessTokenStructure: Access token is using version >= 3"); // The error message below will be logged by the error handler that translates this into a TRY_REFRESH_TOKEN_ERROR // it would come here if we change the structure of the JWT. @@ -205,13 +266,14 @@ function validateAccessTokenStructure(payload, version) { throw Error("Access token does not contain all the information. Maybe the structure has changed?"); } } - } - else if (typeof payload.sessionHandle !== "string" || + } else if ( + typeof payload.sessionHandle !== "string" || typeof payload.userId !== "string" || typeof payload.refreshTokenHash1 !== "string" || payload.userData === undefined || typeof payload.expiryTime !== "number" || - typeof payload.timeCreated !== "number") { + typeof payload.timeCreated !== "number" + ) { (0, logger_1.logDebugMessage)("validateAccessTokenStructure: Access token is using version < 3"); // The error message below will be logged by the error handler that translates this into a TRY_REFRESH_TOKEN_ERROR // it would come here if we change the structure of the JWT. @@ -228,8 +290,7 @@ function sanitizeStringInput(field) { try { let result = field.trim(); return result; - } - catch (err) { } + } catch (err) {} return undefined; } function sanitizeNumberInput(field) { diff --git a/lib/build/recipe/session/api/implementation.js b/lib/build/recipe/session/api/implementation.js index faae0f8cf..0afc6aa1a 100644 --- a/lib/build/recipe/session/api/implementation.js +++ b/lib/build/recipe/session/api/implementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIInterface; const utils_1 = require("../../../utils"); @@ -9,7 +11,7 @@ const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath" const sessionRequestFunctions_1 = require("../sessionRequestFunctions"); function getAPIInterface() { return { - refreshPOST: async function ({ options, userContext, }) { + refreshPOST: async function ({ options, userContext }) { return (0, sessionRequestFunctions_1.refreshSessionInRequest)({ req: options.req, res: options.res, @@ -18,7 +20,7 @@ function getAPIInterface() { recipeInterfaceImpl: options.recipeImplementation, }); }, - verifySession: async function ({ verifySessionOptions, options, userContext, }) { + verifySession: async function ({ verifySessionOptions, options, userContext }) { let method = (0, utils_1.normaliseHttpMethod)(options.req.getMethod()); if (method === "options" || method === "trace") { return undefined; @@ -33,8 +35,7 @@ function getAPIInterface() { config: options.config, recipeInterfaceImpl: options.recipeImplementation, }); - } - else { + } else { return (0, sessionRequestFunctions_1.getSessionFromRequest)({ req: options.req, res: options.res, @@ -45,7 +46,7 @@ function getAPIInterface() { }); } }, - signOutPOST: async function ({ session, userContext, }) { + signOutPOST: async function ({ session, userContext }) { await session.revokeSession(userContext); return { status: "OK", diff --git a/lib/build/recipe/session/api/refresh.d.ts b/lib/build/recipe/session/api/refresh.d.ts index 5fb27d06f..63910c21a 100644 --- a/lib/build/recipe/session/api/refresh.d.ts +++ b/lib/build/recipe/session/api/refresh.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function handleRefreshAPI(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function handleRefreshAPI( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/session/api/signout.d.ts b/lib/build/recipe/session/api/signout.d.ts index 128c06920..758ce9ed6 100644 --- a/lib/build/recipe/session/api/signout.d.ts +++ b/lib/build/recipe/session/api/signout.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function signOutAPI(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function signOutAPI( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/session/claimBaseClasses/booleanClaim.js b/lib/build/recipe/session/claimBaseClasses/booleanClaim.js index f3d21b4de..37e233d3f 100644 --- a/lib/build/recipe/session/claimBaseClasses/booleanClaim.js +++ b/lib/build/recipe/session/claimBaseClasses/booleanClaim.js @@ -5,7 +5,10 @@ const primitiveClaim_1 = require("./primitiveClaim"); class BooleanClaim extends primitiveClaim_1.PrimitiveClaim { constructor(conf) { super(conf); - this.validators = Object.assign(Object.assign({}, this.validators), { isTrue: (maxAge, id) => this.validators.hasValue(true, maxAge, id), isFalse: (maxAge, id) => this.validators.hasValue(false, maxAge, id) }); + this.validators = Object.assign(Object.assign({}, this.validators), { + isTrue: (maxAge, id) => this.validators.hasValue(true, maxAge, id), + isFalse: (maxAge, id) => this.validators.hasValue(false, maxAge, id), + }); } } exports.BooleanClaim = BooleanClaim; diff --git a/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.d.ts b/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.d.ts index c044c6ba9..8e95bd617 100644 --- a/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.d.ts +++ b/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.d.ts @@ -3,13 +3,15 @@ import RecipeUserId from "../../../recipeUserId"; import { JSONObject, JSONPrimitive, UserContext } from "../../../types"; import { SessionClaim, SessionClaimValidator } from "../types"; export declare class PrimitiveArrayClaim extends SessionClaim { - readonly fetchValue: (userId: string, recipeUserId: RecipeUserId, tenantId: string, currentPayload: JSONObject | undefined, userContext: UserContext) => Promise | T[] | undefined; + readonly fetchValue: ( + userId: string, + recipeUserId: RecipeUserId, + tenantId: string, + currentPayload: JSONObject | undefined, + userContext: UserContext + ) => Promise | T[] | undefined; readonly defaultMaxAgeInSeconds: number | undefined; - constructor(config: { - key: string; - fetchValue: SessionClaim["fetchValue"]; - defaultMaxAgeInSeconds?: number; - }); + constructor(config: { key: string; fetchValue: SessionClaim["fetchValue"]; defaultMaxAgeInSeconds?: number }); addToPayload_internal(payload: any, value: T[], _userContext: UserContext): any; removeFromPayloadByMerge_internal(payload: any, _userContext: UserContext): any; removeFromPayload(payload: any, _userContext: UserContext): any; diff --git a/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.js b/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.js index 67004373b..d057552b5 100644 --- a/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.js +++ b/lib/build/recipe/session/claimBaseClasses/primitiveArrayClaim.js @@ -10,7 +10,8 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return { claim: this, id: id !== null && id !== void 0 ? id : this.key, - shouldRefetch: (payload, ctx) => this.getValueFromPayload(payload, ctx) === undefined || + shouldRefetch: (payload, ctx) => + this.getValueFromPayload(payload, ctx) === undefined || // We know payload[this.id] is defined since the value is not undefined in this branch (maxAgeInSeconds !== undefined && payload[this.key].t < Date.now() - maxAgeInSeconds * 1000), validate: async (payload, ctx) => { @@ -18,7 +19,11 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { if (claimVal === undefined) { return { isValid: false, - reason: { message: "value does not exist", expectedToInclude: val, actualValue: claimVal }, + reason: { + message: "value does not exist", + expectedToInclude: val, + actualValue: claimVal, + }, }; } const ageInSeconds = (Date.now() - this.getLastRefetchTime(payload, ctx)) / 1000; @@ -46,7 +51,8 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return { claim: this, id: id !== null && id !== void 0 ? id : this.key, - shouldRefetch: (payload, ctx) => this.getValueFromPayload(payload, ctx) === undefined || + shouldRefetch: (payload, ctx) => + this.getValueFromPayload(payload, ctx) === undefined || // We know payload[this.id] is defined since the value is not undefined in this branch (maxAgeInSeconds !== undefined && payload[this.key].t < Date.now() - maxAgeInSeconds * 1000), validate: async (payload, ctx) => { @@ -86,7 +92,8 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return { claim: this, id: id !== null && id !== void 0 ? id : this.key, - shouldRefetch: (payload, ctx) => this.getValueFromPayload(payload, ctx) === undefined || + shouldRefetch: (payload, ctx) => + this.getValueFromPayload(payload, ctx) === undefined || // We know payload[this.id] is defined since the value is not undefined in this branch (maxAgeInSeconds !== undefined && payload[this.key].t < Date.now() - maxAgeInSeconds * 1000), validate: async (payload, ctx) => { @@ -94,7 +101,11 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { if (claimVal === undefined) { return { isValid: false, - reason: { message: "value does not exist", expectedToInclude: val, actualValue: claimVal }, + reason: { + message: "value does not exist", + expectedToInclude: val, + actualValue: claimVal, + }, }; } const ageInSeconds = (Date.now() - this.getLastRefetchTime(payload, ctx)) / 1000; @@ -113,9 +124,9 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return isValid ? { isValid } : { - isValid, - reason: { message: "wrong value", expectedToInclude: val, actualValue: claimVal }, - }; + isValid, + reason: { message: "wrong value", expectedToInclude: val, actualValue: claimVal }, + }; }, }; }, @@ -123,7 +134,8 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return { claim: this, id: id !== null && id !== void 0 ? id : this.key, - shouldRefetch: (payload, ctx) => this.getValueFromPayload(payload, ctx) === undefined || + shouldRefetch: (payload, ctx) => + this.getValueFromPayload(payload, ctx) === undefined || // We know payload[this.id] is defined since the value is not undefined in this branch (maxAgeInSeconds !== undefined && payload[this.key].t < Date.now() - maxAgeInSeconds * 1000), validate: async (payload, ctx) => { @@ -154,13 +166,13 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return isValid ? { isValid: isValid } : { - isValid, - reason: { - message: "wrong value", - expectedToIncludeAtLeastOneOf: val, - actualValue: claimVal, - }, - }; + isValid, + reason: { + message: "wrong value", + expectedToIncludeAtLeastOneOf: val, + actualValue: claimVal, + }, + }; }, }; }, @@ -168,7 +180,8 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return { claim: this, id: id !== null && id !== void 0 ? id : this.key, - shouldRefetch: (payload, ctx) => this.getValueFromPayload(payload, ctx) === undefined || + shouldRefetch: (payload, ctx) => + this.getValueFromPayload(payload, ctx) === undefined || // We know payload[this.id] is defined since the value is not undefined in this branch (maxAgeInSeconds !== undefined && payload[this.key].t < Date.now() - maxAgeInSeconds * 1000), validate: async (payload, ctx) => { @@ -199,9 +212,9 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { return isValid ? { isValid: isValid } : { - isValid, - reason: { message: "wrong value", expectedToNotInclude: val, actualValue: claimVal }, - }; + isValid, + reason: { message: "wrong value", expectedToNotInclude: val, actualValue: claimVal }, + }; }, }; }, @@ -210,10 +223,12 @@ class PrimitiveArrayClaim extends types_1.SessionClaim { this.defaultMaxAgeInSeconds = config.defaultMaxAgeInSeconds; } addToPayload_internal(payload, value, _userContext) { - return Object.assign(Object.assign({}, payload), { [this.key]: { + return Object.assign(Object.assign({}, payload), { + [this.key]: { v: value, t: Date.now(), - } }); + }, + }); } removeFromPayloadByMerge_internal(payload, _userContext) { const res = Object.assign(Object.assign({}, payload), { [this.key]: null }); diff --git a/lib/build/recipe/session/claimBaseClasses/primitiveClaim.d.ts b/lib/build/recipe/session/claimBaseClasses/primitiveClaim.d.ts index d8798483a..7ef6ebb7e 100644 --- a/lib/build/recipe/session/claimBaseClasses/primitiveClaim.d.ts +++ b/lib/build/recipe/session/claimBaseClasses/primitiveClaim.d.ts @@ -3,13 +3,15 @@ import RecipeUserId from "../../../recipeUserId"; import { JSONObject, JSONPrimitive, UserContext } from "../../../types"; import { SessionClaim, SessionClaimValidator } from "../types"; export declare class PrimitiveClaim extends SessionClaim { - readonly fetchValue: (userId: string, recipeUserId: RecipeUserId, tenantId: string, currentPayload: JSONObject | undefined, userContext: UserContext) => Promise | T | undefined; + readonly fetchValue: ( + userId: string, + recipeUserId: RecipeUserId, + tenantId: string, + currentPayload: JSONObject | undefined, + userContext: UserContext + ) => Promise | T | undefined; readonly defaultMaxAgeInSeconds: number | undefined; - constructor(config: { - key: string; - fetchValue: SessionClaim["fetchValue"]; - defaultMaxAgeInSeconds?: number; - }); + constructor(config: { key: string; fetchValue: SessionClaim["fetchValue"]; defaultMaxAgeInSeconds?: number }); addToPayload_internal(payload: any, value: T, _userContext: UserContext): any; removeFromPayloadByMerge_internal(payload: any, _userContext: UserContext): any; removeFromPayload(payload: any, _userContext: UserContext): any; diff --git a/lib/build/recipe/session/claimBaseClasses/primitiveClaim.js b/lib/build/recipe/session/claimBaseClasses/primitiveClaim.js index 35eee64fe..12407fabc 100644 --- a/lib/build/recipe/session/claimBaseClasses/primitiveClaim.js +++ b/lib/build/recipe/session/claimBaseClasses/primitiveClaim.js @@ -10,7 +10,8 @@ class PrimitiveClaim extends types_1.SessionClaim { return { claim: this, id: id !== null && id !== void 0 ? id : this.key, - shouldRefetch: (payload, ctx) => this.getValueFromPayload(payload, ctx) === undefined || + shouldRefetch: (payload, ctx) => + this.getValueFromPayload(payload, ctx) === undefined || (maxAgeInSeconds !== undefined && // We know payload[this.id] is defined since the value is not undefined in this branch payload[this.key].t < Date.now() - maxAgeInSeconds * 1000), validate: async (payload, ctx) => { @@ -47,10 +48,12 @@ class PrimitiveClaim extends types_1.SessionClaim { this.defaultMaxAgeInSeconds = config.defaultMaxAgeInSeconds; } addToPayload_internal(payload, value, _userContext) { - return Object.assign(Object.assign({}, payload), { [this.key]: { + return Object.assign(Object.assign({}, payload), { + [this.key]: { v: value, t: Date.now(), - } }); + }, + }); } removeFromPayloadByMerge_internal(payload, _userContext) { const res = Object.assign(Object.assign({}, payload), { [this.key]: null }); diff --git a/lib/build/recipe/session/claims.js b/lib/build/recipe/session/claims.js index 4a547fb2e..30fae1663 100644 --- a/lib/build/recipe/session/claims.js +++ b/lib/build/recipe/session/claims.js @@ -2,10 +2,30 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.BooleanClaim = exports.PrimitiveArrayClaim = exports.PrimitiveClaim = exports.SessionClaim = void 0; var types_1 = require("./types"); -Object.defineProperty(exports, "SessionClaim", { enumerable: true, get: function () { return types_1.SessionClaim; } }); +Object.defineProperty(exports, "SessionClaim", { + enumerable: true, + get: function () { + return types_1.SessionClaim; + }, +}); var primitiveClaim_1 = require("./claimBaseClasses/primitiveClaim"); -Object.defineProperty(exports, "PrimitiveClaim", { enumerable: true, get: function () { return primitiveClaim_1.PrimitiveClaim; } }); +Object.defineProperty(exports, "PrimitiveClaim", { + enumerable: true, + get: function () { + return primitiveClaim_1.PrimitiveClaim; + }, +}); var primitiveArrayClaim_1 = require("./claimBaseClasses/primitiveArrayClaim"); -Object.defineProperty(exports, "PrimitiveArrayClaim", { enumerable: true, get: function () { return primitiveArrayClaim_1.PrimitiveArrayClaim; } }); +Object.defineProperty(exports, "PrimitiveArrayClaim", { + enumerable: true, + get: function () { + return primitiveArrayClaim_1.PrimitiveArrayClaim; + }, +}); var booleanClaim_1 = require("./claimBaseClasses/booleanClaim"); -Object.defineProperty(exports, "BooleanClaim", { enumerable: true, get: function () { return booleanClaim_1.BooleanClaim; } }); +Object.defineProperty(exports, "BooleanClaim", { + enumerable: true, + get: function () { + return booleanClaim_1.BooleanClaim; + }, +}); diff --git a/lib/build/recipe/session/cookieAndHeaders.d.ts b/lib/build/recipe/session/cookieAndHeaders.d.ts index 7b7b7c512..dd036e7d3 100644 --- a/lib/build/recipe/session/cookieAndHeaders.d.ts +++ b/lib/build/recipe/session/cookieAndHeaders.d.ts @@ -2,15 +2,41 @@ import type { BaseRequest, BaseResponse } from "../../framework"; import { UserContext } from "../../types"; import { TokenTransferMethod, TokenType, TypeNormalisedInput } from "./types"; -export declare function clearSessionFromAllTokenTransferMethods(config: TypeNormalisedInput, res: BaseResponse, request: BaseRequest, userContext: UserContext): void; -export declare function clearSession(config: TypeNormalisedInput, res: BaseResponse, transferMethod: TokenTransferMethod, request: BaseRequest, userContext: UserContext): void; +export declare function clearSessionFromAllTokenTransferMethods( + config: TypeNormalisedInput, + res: BaseResponse, + request: BaseRequest, + userContext: UserContext +): void; +export declare function clearSession( + config: TypeNormalisedInput, + res: BaseResponse, + transferMethod: TokenTransferMethod, + request: BaseRequest, + userContext: UserContext +): void; export declare function getAntiCsrfTokenFromHeaders(req: BaseRequest): string | undefined; export declare function setAntiCsrfTokenInHeaders(res: BaseResponse, antiCsrfToken: string): void; export declare function buildFrontToken(userId: string, atExpiry: number, accessTokenPayload: any): string; export declare function setFrontTokenInHeaders(res: BaseResponse, frontToken: string): void; export declare function getCORSAllowedHeaders(): string[]; -export declare function getToken(config: TypeNormalisedInput, req: BaseRequest, tokenType: TokenType, transferMethod: TokenTransferMethod, userContext: UserContext): string | undefined; -export declare function setToken(config: TypeNormalisedInput, res: BaseResponse, tokenType: TokenType, value: string, expires: number, transferMethod: TokenTransferMethod, req: BaseRequest, userContext: UserContext): void; +export declare function getToken( + config: TypeNormalisedInput, + req: BaseRequest, + tokenType: TokenType, + transferMethod: TokenTransferMethod, + userContext: UserContext +): string | undefined; +export declare function setToken( + config: TypeNormalisedInput, + res: BaseResponse, + tokenType: TokenType, + value: string, + expires: number, + transferMethod: TokenTransferMethod, + req: BaseRequest, + userContext: UserContext +): void; export declare function setHeader(res: BaseResponse, name: string, value: string): void; /** * @@ -23,7 +49,16 @@ export declare function setHeader(res: BaseResponse, name: string, value: string * @param expires * @param path */ -export declare function setCookie(config: TypeNormalisedInput, res: BaseResponse, name: string, value: string, expires: number, pathType: "refreshTokenPath" | "accessTokenPath", req: BaseRequest | undefined, userContext: UserContext): void; +export declare function setCookie( + config: TypeNormalisedInput, + res: BaseResponse, + name: string, + value: string, + expires: number, + pathType: "refreshTokenPath" | "accessTokenPath", + req: BaseRequest | undefined, + userContext: UserContext +): void; export declare function getAuthModeFromHeader(req: BaseRequest): string | undefined; /** * This function addresses an edge case where changing the cookieDomain config on the server can @@ -37,10 +72,20 @@ export declare function getAuthModeFromHeader(req: BaseRequest): string | undefi * * This function checks for multiple cookies with the same name and clears the cookies for the older domain */ -export declare function clearSessionCookiesFromOlderCookieDomain({ req, res, config, userContext, }: { +export declare function clearSessionCookiesFromOlderCookieDomain({ + req, + res, + config, + userContext, +}: { req: BaseRequest; res: BaseResponse; config: TypeNormalisedInput; userContext: UserContext; }): void; -export declare function hasMultipleCookiesForTokenType(config: TypeNormalisedInput, req: BaseRequest, tokenType: TokenType, userContext: UserContext): boolean; +export declare function hasMultipleCookiesForTokenType( + config: TypeNormalisedInput, + req: BaseRequest, + tokenType: TokenType, + userContext: UserContext +): boolean; diff --git a/lib/build/recipe/session/cookieAndHeaders.js b/lib/build/recipe/session/cookieAndHeaders.js index e560beeda..8616a6b02 100644 --- a/lib/build/recipe/session/cookieAndHeaders.js +++ b/lib/build/recipe/session/cookieAndHeaders.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearSessionFromAllTokenTransferMethods = clearSessionFromAllTokenTransferMethods; exports.clearSession = clearSession; @@ -78,29 +80,40 @@ function setFrontTokenInHeaders(res, frontToken) { res.setHeader("Access-Control-Expose-Headers", constants_2.frontTokenHeaderKey, true); } function getCORSAllowedHeaders() { - return [constants_2.antiCsrfHeaderKey, constants_1.HEADER_RID, constants_2.authorizationHeaderKey, constants_2.authModeHeaderKey]; + return [ + constants_2.antiCsrfHeaderKey, + constants_1.HEADER_RID, + constants_2.authorizationHeaderKey, + constants_2.authModeHeaderKey, + ]; } function getToken(config, req, tokenType, transferMethod, userContext) { if (transferMethod === "cookie") { return req.getCookieValue(config.getCookieNameForTokenType(req, tokenType, userContext)); - } - else if (transferMethod === "header") { + } else if (transferMethod === "header") { const value = req.getHeaderValue(constants_2.authorizationHeaderKey); if (value === undefined || !value.startsWith("Bearer ")) { return undefined; } return value.replace(/^Bearer /, "").trim(); - } - else { + } else { throw new Error("Should never happen: Unknown transferMethod: " + transferMethod); } } function setToken(config, res, tokenType, value, expires, transferMethod, req, userContext) { (0, logger_1.logDebugMessage)(`setToken: Setting ${tokenType} token as ${transferMethod}`); if (transferMethod === "cookie") { - setCookie(config, res, config.getCookieNameForTokenType(req, tokenType, userContext), value, expires, tokenType === "refresh" ? "refreshTokenPath" : "accessTokenPath", req, userContext); - } - else if (transferMethod === "header") { + setCookie( + config, + res, + config.getCookieNameForTokenType(req, tokenType, userContext), + value, + expires, + tokenType === "refresh" ? "refreshTokenPath" : "accessTokenPath", + req, + userContext + ); + } else if (transferMethod === "header") { setHeader(res, config.getResponseHeaderNameForTokenType(req, tokenType, userContext), value); } } @@ -129,8 +142,7 @@ function setCookie(config, res, name, value, expires, pathType, req, userContext let path = ""; if (pathType === "refreshTokenPath") { path = config.refreshTokenPath.getAsStringDangerous(); - } - else if (pathType === "accessTokenPath") { + } else if (pathType === "accessTokenPath") { path = config.accessTokenPath.getAsStringDangerous() === "" ? "/" : config.accessTokenPath.getAsStringDangerous(); } @@ -139,7 +151,9 @@ function setCookie(config, res, name, value, expires, pathType, req, userContext } function getAuthModeFromHeader(req) { var _a; - return (_a = req.getHeaderValue(constants_2.authModeHeaderKey)) === null || _a === void 0 ? void 0 : _a.toLowerCase(); + return (_a = req.getHeaderValue(constants_2.authModeHeaderKey)) === null || _a === void 0 + ? void 0 + : _a.toLowerCase(); } /** * This function addresses an edge case where changing the cookieDomain config on the server can @@ -153,7 +167,7 @@ function getAuthModeFromHeader(req) { * * This function checks for multiple cookies with the same name and clears the cookies for the older domain */ -function clearSessionCookiesFromOlderCookieDomain({ req, res, config, userContext, }) { +function clearSessionCookiesFromOlderCookieDomain({ req, res, config, userContext }) { const allowedTransferMethod = config.getTokenTransferMethod({ req, forCreateNewSession: false, @@ -172,16 +186,30 @@ function clearSessionCookiesFromOlderCookieDomain({ req, res, config, userContex // Using the wrong cookie can cause an infinite refresh loop. To avoid this, // we throw a 500 error asking the user to set 'olderCookieDomain'. if (config.olderCookieDomain === undefined) { - throw new Error(`The request contains multiple session cookies. This may happen if you've changed the 'cookieDomain' value in your configuration. To clear tokens from the previous domain, set 'olderCookieDomain' in your config.`); + throw new Error( + `The request contains multiple session cookies. This may happen if you've changed the 'cookieDomain' value in your configuration. To clear tokens from the previous domain, set 'olderCookieDomain' in your config.` + ); } - (0, logger_1.logDebugMessage)(`clearSessionCookiesFromOlderCookieDomain: Clearing duplicate ${token} cookie with domain ${config.olderCookieDomain}`); - setToken(Object.assign(Object.assign({}, config), { cookieDomain: config.olderCookieDomain }), res, token, "", 0, "cookie", req, userContext); + (0, logger_1.logDebugMessage)( + `clearSessionCookiesFromOlderCookieDomain: Clearing duplicate ${token} cookie with domain ${config.olderCookieDomain}` + ); + setToken( + Object.assign(Object.assign({}, config), { cookieDomain: config.olderCookieDomain }), + res, + token, + "", + 0, + "cookie", + req, + userContext + ); didClearCookies = true; } } if (didClearCookies) { throw new error_1.default({ - message: "The request contains multiple session cookies. We are clearing the cookie from olderCookieDomain. Session will be refreshed in the next refresh call.", + message: + "The request contains multiple session cookies. We are clearing the cookie from olderCookieDomain. Session will be refreshed in the next refresh call.", type: error_1.default.CLEAR_DUPLICATE_SESSION_COOKIES, }); } @@ -205,19 +233,17 @@ function parseCookieStringFromRequestHeaderAllowingDuplicates(cookieString) { .trim() .split("=") .map((part) => { - try { - return decodeURIComponent(part); - } - catch (e) { - // this is there in case the cookie value is not encoded. This can happe - // if the user has set their own cookie in a different format. - return part; - } - }); + try { + return decodeURIComponent(part); + } catch (e) { + // this is there in case the cookie value is not encoded. This can happe + // if the user has set their own cookie in a different format. + return part; + } + }); if (cookies.hasOwnProperty(name)) { cookies[name].push(value); - } - else { + } else { cookies[name] = [value]; } } diff --git a/lib/build/recipe/session/error.d.ts b/lib/build/recipe/session/error.d.ts index 8e472802c..fae7a4fd4 100644 --- a/lib/build/recipe/session/error.d.ts +++ b/lib/build/recipe/session/error.d.ts @@ -8,29 +8,36 @@ export default class SessionError extends STError { static TOKEN_THEFT_DETECTED: "TOKEN_THEFT_DETECTED"; static INVALID_CLAIMS: "INVALID_CLAIMS"; static CLEAR_DUPLICATE_SESSION_COOKIES: "CLEAR_DUPLICATE_SESSION_COOKIES"; - constructor(options: { - message: string; - type: "UNAUTHORISED"; - payload?: { - clearTokens: boolean; - }; - } | { - message: string; - type: "TRY_REFRESH_TOKEN"; - } | { - message: string; - type: "TOKEN_THEFT_DETECTED"; - payload: { - userId: string; - recipeUserId: RecipeUserId; - sessionHandle: string; - }; - } | { - message: string; - type: "INVALID_CLAIMS"; - payload: ClaimValidationError[]; - } | { - message: string; - type: "CLEAR_DUPLICATE_SESSION_COOKIES"; - }); + constructor( + options: + | { + message: string; + type: "UNAUTHORISED"; + payload?: { + clearTokens: boolean; + }; + } + | { + message: string; + type: "TRY_REFRESH_TOKEN"; + } + | { + message: string; + type: "TOKEN_THEFT_DETECTED"; + payload: { + userId: string; + recipeUserId: RecipeUserId; + sessionHandle: string; + }; + } + | { + message: string; + type: "INVALID_CLAIMS"; + payload: ClaimValidationError[]; + } + | { + message: string; + type: "CLEAR_DUPLICATE_SESSION_COOKIES"; + } + ); } diff --git a/lib/build/recipe/session/error.js b/lib/build/recipe/session/error.js index d4e0f8267..08857eece 100644 --- a/lib/build/recipe/session/error.js +++ b/lib/build/recipe/session/error.js @@ -13,17 +13,24 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); class SessionError extends error_1.default { constructor(options) { - super(options.type === "UNAUTHORISED" && options.payload === undefined - ? Object.assign(Object.assign({}, options), { payload: { - clearTokens: true, - } }) : Object.assign({}, options)); + super( + options.type === "UNAUTHORISED" && options.payload === undefined + ? Object.assign(Object.assign({}, options), { + payload: { + clearTokens: true, + }, + }) + : Object.assign({}, options) + ); this.fromRecipe = "session"; } } diff --git a/lib/build/recipe/session/framework/awsLambda.js b/lib/build/recipe/session/framework/awsLambda.js index 14c216353..881bc51bb 100644 --- a/lib/build/recipe/session/framework/awsLambda.js +++ b/lib/build/recipe/session/framework/awsLambda.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySession = verifySession; const framework_1 = require("../../../framework/awsLambda/framework"); @@ -19,8 +21,7 @@ function verifySession(handler, verifySessionOptions) { event.session = await sessionRecipe.verifySession(verifySessionOptions, request, response, userContext); let handlerResult = await handler(event, context, callback); return response.sendResponse(handlerResult); - } - catch (err) { + } catch (err) { await supertokens.errorHandler(err, request, response, userContext); if (response.responseSet) { return response.sendResponse({}); diff --git a/lib/build/recipe/session/framework/custom.d.ts b/lib/build/recipe/session/framework/custom.d.ts index aa39e8b02..1c554414c 100644 --- a/lib/build/recipe/session/framework/custom.d.ts +++ b/lib/build/recipe/session/framework/custom.d.ts @@ -3,6 +3,8 @@ import type { VerifySessionOptions } from ".."; import { BaseRequest, BaseResponse } from "../../../framework"; import { NextFunction } from "../../../framework/custom/framework"; import { SessionContainerInterface } from "../types"; -export declare function verifySession(options?: VerifySessionOptions): (req: T, res: BaseResponse, next?: NextFunction) => Promise; +export declare function verifySession< + T extends BaseRequest & { + session?: SessionContainerInterface; + } +>(options?: VerifySessionOptions): (req: T, res: BaseResponse, next?: NextFunction) => Promise; diff --git a/lib/build/recipe/session/framework/custom.js b/lib/build/recipe/session/framework/custom.js index dfe2da746..f1715c86c 100644 --- a/lib/build/recipe/session/framework/custom.js +++ b/lib/build/recipe/session/framework/custom.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySession = verifySession; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -31,14 +33,12 @@ function verifySession(options) { next(); } return undefined; - } - catch (err) { + } catch (err) { try { const supertokens = supertokens_1.default.getInstanceOrThrowError(); await supertokens.errorHandler(err, req, res, userContext); return undefined; - } - catch (_a) { + } catch (_a) { if (next !== undefined) { next(err); } diff --git a/lib/build/recipe/session/framework/express.d.ts b/lib/build/recipe/session/framework/express.d.ts index 48db51d80..bcb0bf234 100644 --- a/lib/build/recipe/session/framework/express.d.ts +++ b/lib/build/recipe/session/framework/express.d.ts @@ -2,4 +2,6 @@ import type { VerifySessionOptions } from ".."; import type { SessionRequest } from "../../../framework/express/framework"; import type { NextFunction, Response } from "express"; -export declare function verifySession(options?: VerifySessionOptions): (req: SessionRequest, res: Response, next: NextFunction) => Promise; +export declare function verifySession( + options?: VerifySessionOptions +): (req: SessionRequest, res: Response, next: NextFunction) => Promise; diff --git a/lib/build/recipe/session/framework/express.js b/lib/build/recipe/session/framework/express.js index 36580434e..c96f54f03 100644 --- a/lib/build/recipe/session/framework/express.js +++ b/lib/build/recipe/session/framework/express.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySession = verifySession; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -31,13 +33,11 @@ function verifySession(options) { const sessionRecipe = recipe_1.default.getInstanceOrThrowError(); req.session = await sessionRecipe.verifySession(options, request, response, userContext); next(); - } - catch (err) { + } catch (err) { try { const supertokens = supertokens_1.default.getInstanceOrThrowError(); await supertokens.errorHandler(err, request, response, userContext); - } - catch (_a) { + } catch (_a) { next(err); } } diff --git a/lib/build/recipe/session/framework/fastify.d.ts b/lib/build/recipe/session/framework/fastify.d.ts index 1dc347fa7..74724d38d 100644 --- a/lib/build/recipe/session/framework/fastify.d.ts +++ b/lib/build/recipe/session/framework/fastify.d.ts @@ -2,4 +2,6 @@ import { VerifySessionOptions } from ".."; import { SessionRequest } from "../../../framework/fastify/framework"; import { FastifyReply, FastifyRequest as OriginalFastifyRequest } from "../../../framework/fastify/types"; -export declare function verifySession(options?: VerifySessionOptions): (req: SessionRequest, res: FastifyReply) => Promise; +export declare function verifySession( + options?: VerifySessionOptions +): (req: SessionRequest, res: FastifyReply) => Promise; diff --git a/lib/build/recipe/session/framework/fastify.js b/lib/build/recipe/session/framework/fastify.js index 637e2e1bb..497d9e224 100644 --- a/lib/build/recipe/session/framework/fastify.js +++ b/lib/build/recipe/session/framework/fastify.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySession = verifySession; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -30,8 +32,7 @@ function verifySession(options) { const userContext = (0, utils_1.makeDefaultUserContextFromAPI)(request); try { req.session = await sessionRecipe.verifySession(options, request, response, userContext); - } - catch (err) { + } catch (err) { const supertokens = supertokens_1.default.getInstanceOrThrowError(); await supertokens.errorHandler(err, request, response, userContext); throw err; diff --git a/lib/build/recipe/session/framework/hapi.d.ts b/lib/build/recipe/session/framework/hapi.d.ts index 8241dc4a2..97456f934 100644 --- a/lib/build/recipe/session/framework/hapi.d.ts +++ b/lib/build/recipe/session/framework/hapi.d.ts @@ -2,4 +2,6 @@ import { VerifySessionOptions } from ".."; import { ResponseToolkit } from "@hapi/hapi"; import { SessionRequest } from "../../../framework/hapi/framework"; -export declare function verifySession(options?: VerifySessionOptions): (req: SessionRequest, h: ResponseToolkit) => Promise; +export declare function verifySession( + options?: VerifySessionOptions +): (req: SessionRequest, h: ResponseToolkit) => Promise; diff --git a/lib/build/recipe/session/framework/hapi.js b/lib/build/recipe/session/framework/hapi.js index 474bbc3d2..5580ed7eb 100644 --- a/lib/build/recipe/session/framework/hapi.js +++ b/lib/build/recipe/session/framework/hapi.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySession = verifySession; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -30,8 +32,7 @@ function verifySession(options) { const userContext = (0, utils_1.makeDefaultUserContextFromAPI)(request); try { req.session = await sessionRecipe.verifySession(options, request, response, userContext); - } - catch (err) { + } catch (err) { try { const supertokens = supertokens_1.default.getInstanceOrThrowError(); await supertokens.errorHandler(err, request, response, userContext); @@ -42,8 +43,7 @@ function verifySession(options) { }); return resObj.takeover(); } - } - catch (_a) { + } catch (_a) { // We catch and ignore since we want to re-throw the original error if handling wasn't successful throw err; } diff --git a/lib/build/recipe/session/framework/index.js b/lib/build/recipe/session/framework/index.js index 7ecaaa14d..6e184ce2a 100644 --- a/lib/build/recipe/session/framework/index.js +++ b/lib/build/recipe/session/framework/index.js @@ -1,37 +1,56 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.awsLambda = exports.koa = exports.loopback = exports.hapi = exports.fastify = exports.express = void 0; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. diff --git a/lib/build/recipe/session/framework/koa.d.ts b/lib/build/recipe/session/framework/koa.d.ts index 7a73cb667..9e23ae80b 100644 --- a/lib/build/recipe/session/framework/koa.d.ts +++ b/lib/build/recipe/session/framework/koa.d.ts @@ -2,4 +2,6 @@ import type { VerifySessionOptions } from ".."; import type { Next } from "koa"; import type { SessionContext } from "../../../framework/koa/framework"; -export declare function verifySession(options?: VerifySessionOptions): (ctx: SessionContext, next: Next) => Promise; +export declare function verifySession( + options?: VerifySessionOptions +): (ctx: SessionContext, next: Next) => Promise; diff --git a/lib/build/recipe/session/framework/koa.js b/lib/build/recipe/session/framework/koa.js index ca1ba8f23..5afbae1a9 100644 --- a/lib/build/recipe/session/framework/koa.js +++ b/lib/build/recipe/session/framework/koa.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySession = verifySession; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -30,14 +32,12 @@ function verifySession(options) { const userContext = (0, utils_1.makeDefaultUserContextFromAPI)(request); try { ctx.session = await sessionRecipe.verifySession(options, request, response, userContext); - } - catch (err) { + } catch (err) { try { const supertokens = supertokens_1.default.getInstanceOrThrowError(); await supertokens.errorHandler(err, request, response, userContext); return; - } - catch (_a) { + } catch (_a) { // We catch and ignore since we want to re-throw the original error if handling wasn't successful throw err; } diff --git a/lib/build/recipe/session/framework/loopback.js b/lib/build/recipe/session/framework/loopback.js index 5f81b586c..c1ba1a949 100644 --- a/lib/build/recipe/session/framework/loopback.js +++ b/lib/build/recipe/session/framework/loopback.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifySession = verifySession; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -31,14 +33,12 @@ function verifySession(options) { const userContext = (0, utils_1.makeDefaultUserContextFromAPI)(request); try { middlewareCtx.session = await sessionRecipe.verifySession(options, request, response, userContext); - } - catch (err) { + } catch (err) { try { const supertokens = supertokens_1.default.getInstanceOrThrowError(); await supertokens.errorHandler(err, request, response, userContext); return; - } - catch (_a) { + } catch (_a) { // We catch and ignore since we want to re-throw the original error if handling wasn't successful throw err; } diff --git a/lib/build/recipe/session/index.d.ts b/lib/build/recipe/session/index.d.ts index a137c086a..216eef06d 100644 --- a/lib/build/recipe/session/index.d.ts +++ b/lib/build/recipe/session/index.d.ts @@ -1,28 +1,79 @@ // @ts-nocheck import SuperTokensError from "./error"; -import { VerifySessionOptions, SessionContainerInterface as SessionContainer, SessionInformation, APIInterface, APIOptions, SessionClaimValidator, SessionClaim, ClaimValidationError, RecipeInterface } from "./types"; +import { + VerifySessionOptions, + SessionContainerInterface as SessionContainer, + SessionInformation, + APIInterface, + APIOptions, + SessionClaimValidator, + SessionClaim, + ClaimValidationError, + RecipeInterface, +} from "./types"; import Recipe from "./recipe"; import { JSONObject, UserContext } from "../../types"; import RecipeUserId from "../../recipeUserId"; export default class SessionWrapper { static init: typeof Recipe.init; static Error: typeof SuperTokensError; - static createNewSession(req: any, res: any, tenantId: string, recipeUserId: RecipeUserId, accessTokenPayload?: any, sessionDataInDatabase?: any, userContext?: Record): Promise; - static createNewSessionWithoutRequestResponse(tenantId: string, recipeUserId: RecipeUserId, accessTokenPayload?: any, sessionDataInDatabase?: any, disableAntiCsrf?: boolean, userContext?: Record): Promise; - static validateClaimsForSessionHandle(sessionHandle: string, overrideGlobalClaimValidators?: (globalClaimValidators: SessionClaimValidator[], sessionInfo: SessionInformation, userContext: UserContext) => Promise | SessionClaimValidator[], userContext?: Record): Promise<{ - status: "SESSION_DOES_NOT_EXIST_ERROR"; - } | { - status: "OK"; - invalidClaims: ClaimValidationError[]; - }>; + static createNewSession( + req: any, + res: any, + tenantId: string, + recipeUserId: RecipeUserId, + accessTokenPayload?: any, + sessionDataInDatabase?: any, + userContext?: Record + ): Promise; + static createNewSessionWithoutRequestResponse( + tenantId: string, + recipeUserId: RecipeUserId, + accessTokenPayload?: any, + sessionDataInDatabase?: any, + disableAntiCsrf?: boolean, + userContext?: Record + ): Promise; + static validateClaimsForSessionHandle( + sessionHandle: string, + overrideGlobalClaimValidators?: ( + globalClaimValidators: SessionClaimValidator[], + sessionInfo: SessionInformation, + userContext: UserContext + ) => Promise | SessionClaimValidator[], + userContext?: Record + ): Promise< + | { + status: "SESSION_DOES_NOT_EXIST_ERROR"; + } + | { + status: "OK"; + invalidClaims: ClaimValidationError[]; + } + >; static getSession(req: any, res: any): Promise; - static getSession(req: any, res: any, options?: VerifySessionOptions & { - sessionRequired?: true; - }, userContext?: Record): Promise; - static getSession(req: any, res: any, options?: VerifySessionOptions & { - sessionRequired: false; - }, userContext?: Record): Promise; - static getSession(req: any, res: any, options?: VerifySessionOptions, userContext?: Record): Promise; + static getSession( + req: any, + res: any, + options?: VerifySessionOptions & { + sessionRequired?: true; + }, + userContext?: Record + ): Promise; + static getSession( + req: any, + res: any, + options?: VerifySessionOptions & { + sessionRequired: false; + }, + userContext?: Record + ): Promise; + static getSession( + req: any, + res: any, + options?: VerifySessionOptions, + userContext?: Record + ): Promise; /** * Tries to validate an access token and build a Session object from it. * @@ -44,33 +95,86 @@ export default class SessionWrapper { * @param userContext User context */ static getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string): Promise; - static getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string, options?: VerifySessionOptions & { - sessionRequired?: true; - }, userContext?: Record): Promise; - static getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string, options?: VerifySessionOptions & { - sessionRequired: false; - }, userContext?: Record): Promise; - static getSessionWithoutRequestResponse(accessToken: string, antiCsrfToken?: string, options?: VerifySessionOptions, userContext?: Record): Promise; - static getSessionInformation(sessionHandle: string, userContext?: Record): Promise; + static getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions & { + sessionRequired?: true; + }, + userContext?: Record + ): Promise; + static getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions & { + sessionRequired: false; + }, + userContext?: Record + ): Promise; + static getSessionWithoutRequestResponse( + accessToken: string, + antiCsrfToken?: string, + options?: VerifySessionOptions, + userContext?: Record + ): Promise; + static getSessionInformation( + sessionHandle: string, + userContext?: Record + ): Promise; static refreshSession(req: any, res: any, userContext?: Record): Promise; - static refreshSessionWithoutRequestResponse(refreshToken: string, disableAntiCsrf?: boolean, antiCsrfToken?: string, userContext?: Record): Promise; - static revokeAllSessionsForUser(userId: string, revokeSessionsForLinkedAccounts?: boolean, tenantId?: string, userContext?: Record): Promise; - static getAllSessionHandlesForUser(userId: string, fetchSessionsForAllLinkedAccounts?: boolean, tenantId?: string, userContext?: Record): Promise; + static refreshSessionWithoutRequestResponse( + refreshToken: string, + disableAntiCsrf?: boolean, + antiCsrfToken?: string, + userContext?: Record + ): Promise; + static revokeAllSessionsForUser( + userId: string, + revokeSessionsForLinkedAccounts?: boolean, + tenantId?: string, + userContext?: Record + ): Promise; + static getAllSessionHandlesForUser( + userId: string, + fetchSessionsForAllLinkedAccounts?: boolean, + tenantId?: string, + userContext?: Record + ): Promise; static revokeSession(sessionHandle: string, userContext?: Record): Promise; static revokeMultipleSessions(sessionHandles: string[], userContext?: Record): Promise; - static updateSessionDataInDatabase(sessionHandle: string, newSessionData: any, userContext?: Record): Promise; - static mergeIntoAccessTokenPayload(sessionHandle: string, accessTokenPayloadUpdate: JSONObject, userContext?: Record): Promise; - static createJWT(payload?: any, validitySeconds?: number, useStaticSigningKey?: boolean, userContext?: Record): Promise<{ - status: "OK"; - jwt: string; - } | { - status: "UNSUPPORTED_ALGORITHM_ERROR"; - }>; - static getJWKS(userContext?: Record): Promise<{ + static updateSessionDataInDatabase( + sessionHandle: string, + newSessionData: any, + userContext?: Record + ): Promise; + static mergeIntoAccessTokenPayload( + sessionHandle: string, + accessTokenPayloadUpdate: JSONObject, + userContext?: Record + ): Promise; + static createJWT( + payload?: any, + validitySeconds?: number, + useStaticSigningKey?: boolean, + userContext?: Record + ): Promise< + | { + status: "OK"; + jwt: string; + } + | { + status: "UNSUPPORTED_ALGORITHM_ERROR"; + } + >; + static getJWKS( + userContext?: Record + ): Promise<{ keys: import("../jwt").JsonWebKey[]; validityInSeconds?: number; }>; - static getOpenIdDiscoveryConfiguration(userContext?: Record): Promise<{ + static getOpenIdDiscoveryConfiguration( + userContext?: Record + ): Promise<{ status: "OK"; issuer: string; jwks_uri: string; @@ -84,15 +188,35 @@ export default class SessionWrapper { id_token_signing_alg_values_supported: string[]; response_types_supported: string[]; }>; - static fetchAndSetClaim(sessionHandle: string, claim: SessionClaim, userContext?: Record): Promise; - static setClaimValue(sessionHandle: string, claim: SessionClaim, value: T, userContext?: Record): Promise; - static getClaimValue(sessionHandle: string, claim: SessionClaim, userContext?: Record): Promise<{ - status: "SESSION_DOES_NOT_EXIST_ERROR"; - } | { - status: "OK"; - value: T | undefined; - }>; - static removeClaim(sessionHandle: string, claim: SessionClaim, userContext?: Record): Promise; + static fetchAndSetClaim( + sessionHandle: string, + claim: SessionClaim, + userContext?: Record + ): Promise; + static setClaimValue( + sessionHandle: string, + claim: SessionClaim, + value: T, + userContext?: Record + ): Promise; + static getClaimValue( + sessionHandle: string, + claim: SessionClaim, + userContext?: Record + ): Promise< + | { + status: "SESSION_DOES_NOT_EXIST_ERROR"; + } + | { + status: "OK"; + value: T | undefined; + } + >; + static removeClaim( + sessionHandle: string, + claim: SessionClaim, + userContext?: Record + ): Promise; } export declare let init: typeof Recipe.init; export declare let createNewSession: typeof SessionWrapper.createNewSession; @@ -117,4 +241,12 @@ export declare let Error: typeof SuperTokensError; export declare let createJWT: typeof SessionWrapper.createJWT; export declare let getJWKS: typeof SessionWrapper.getJWKS; export declare let getOpenIdDiscoveryConfiguration: typeof SessionWrapper.getOpenIdDiscoveryConfiguration; -export type { VerifySessionOptions, RecipeInterface, SessionContainer, APIInterface, APIOptions, SessionInformation, SessionClaimValidator, }; +export type { + VerifySessionOptions, + RecipeInterface, + SessionContainer, + APIInterface, + APIOptions, + SessionInformation, + SessionClaimValidator, +}; diff --git a/lib/build/recipe/session/index.js b/lib/build/recipe/session/index.js index 4ad2743bc..aa5c4c2ec 100644 --- a/lib/build/recipe/session/index.js +++ b/lib/build/recipe/session/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getOpenIdDiscoveryConfiguration = exports.getJWKS = exports.createJWT = exports.Error = exports.validateClaimsForSessionHandle = exports.removeClaim = exports.getClaimValue = exports.setClaimValue = exports.fetchAndSetClaim = exports.mergeIntoAccessTokenPayload = exports.updateSessionDataInDatabase = exports.revokeMultipleSessions = exports.revokeSession = exports.getAllSessionHandlesForUser = exports.revokeAllSessionsForUser = exports.refreshSessionWithoutRequestResponse = exports.refreshSession = exports.getSessionInformation = exports.getSessionWithoutRequestResponse = exports.getSession = exports.createNewSessionWithoutRequestResponse = exports.createNewSession = exports.init = void 0; const error_1 = __importDefault(require("./error")); @@ -29,7 +31,15 @@ const constants_1 = require("../multitenancy/constants"); const constants_2 = require("./constants"); const utils_2 = require("../../utils"); class SessionWrapper { - static async createNewSession(req, res, tenantId, recipeUserId, accessTokenPayload = {}, sessionDataInDatabase = {}, userContext) { + static async createNewSession( + req, + res, + tenantId, + recipeUserId, + accessTokenPayload = {}, + sessionDataInDatabase = {}, + userContext + ) { const recipeInstance = recipe_1.default.getInstanceOrThrowError(); const config = recipeInstance.config; const appInfo = recipeInstance.getAppInfo(); @@ -52,7 +62,14 @@ class SessionWrapper { tenantId, }); } - static async createNewSessionWithoutRequestResponse(tenantId, recipeUserId, accessTokenPayload = {}, sessionDataInDatabase = {}, disableAntiCsrf = false, userContext) { + static async createNewSessionWithoutRequestResponse( + tenantId, + recipeUserId, + accessTokenPayload = {}, + sessionDataInDatabase = {}, + disableAntiCsrf = false, + userContext + ) { const ctx = (0, utils_2.getUserContext)(userContext); const recipeInstance = recipe_1.default.getInstanceOrThrowError(); const claimsAddedByOtherRecipes = recipeInstance.getClaimsAddedByOtherRecipes(); @@ -92,7 +109,9 @@ class SessionWrapper { status: "SESSION_DOES_NOT_EXIST_ERROR", }; } - const claimValidatorsAddedByOtherRecipes = recipe_1.default.getInstanceOrThrowError().getClaimValidatorsAddedByOtherRecipes(); + const claimValidatorsAddedByOtherRecipes = recipe_1.default + .getInstanceOrThrowError() + .getClaimValidatorsAddedByOtherRecipes(); const globalClaimValidators = await recipeImpl.getGlobalClaimValidators({ userId: sessionInfo.userId, recipeUserId: sessionInfo.recipeUserId, @@ -100,9 +119,10 @@ class SessionWrapper { claimValidatorsAddedByOtherRecipes, userContext: ctx, }); - const claimValidators = overrideGlobalClaimValidators !== undefined - ? await overrideGlobalClaimValidators(globalClaimValidators, sessionInfo, ctx) - : globalClaimValidators; + const claimValidators = + overrideGlobalClaimValidators !== undefined + ? await overrideGlobalClaimValidators(globalClaimValidators, sessionInfo, ctx) + : globalClaimValidators; let claimValidationResponse = await recipeImpl.validateClaims({ userId: sessionInfo.userId, recipeUserId: sessionInfo.recipeUserId, @@ -111,11 +131,13 @@ class SessionWrapper { userContext: ctx, }); if (claimValidationResponse.accessTokenPayloadUpdate !== undefined) { - if (!(await recipeImpl.mergeIntoAccessTokenPayload({ - sessionHandle, - accessTokenPayloadUpdate: claimValidationResponse.accessTokenPayloadUpdate, - userContext: ctx, - }))) { + if ( + !(await recipeImpl.mergeIntoAccessTokenPayload({ + sessionHandle, + accessTokenPayloadUpdate: claimValidationResponse.accessTokenPayloadUpdate, + userContext: ctx, + })) + ) { return { status: "SESSION_DOES_NOT_EXIST_ERROR", }; @@ -149,7 +171,11 @@ class SessionWrapper { userContext: ctx, }); if (session !== undefined) { - const claimValidators = await (0, utils_1.getRequiredClaimValidators)(session, options === null || options === void 0 ? void 0 : options.overrideGlobalClaimValidators, ctx); + const claimValidators = await (0, utils_1.getRequiredClaimValidators)( + session, + options === null || options === void 0 ? void 0 : options.overrideGlobalClaimValidators, + ctx + ); await session.assertClaims(claimValidators, ctx); } return session; diff --git a/lib/build/recipe/session/jwt.js b/lib/build/recipe/session/jwt.js index 29533f23e..4091da16d 100644 --- a/lib/build/recipe/session/jwt.js +++ b/lib/build/recipe/session/jwt.js @@ -18,16 +18,20 @@ exports.parseJWTWithoutSignatureVerification = parseJWTWithoutSignatureVerificat const logger_1 = require("../../logger"); const utils_1 = require("../../utils"); const HEADERS = new Set([ - (0, utils_1.encodeBase64)(JSON.stringify({ - alg: "RS256", - typ: "JWT", - version: "1", - })), - (0, utils_1.encodeBase64)(JSON.stringify({ - alg: "RS256", - typ: "JWT", - version: "2", - })), + (0, utils_1.encodeBase64)( + JSON.stringify({ + alg: "RS256", + typ: "JWT", + version: "1", + }) + ), + (0, utils_1.encodeBase64)( + JSON.stringify({ + alg: "RS256", + typ: "JWT", + version: "2", + }) + ), ]); function parseJWTWithoutSignatureVerification(jwt) { const splittedInput = jwt.split("."); @@ -49,9 +53,10 @@ function parseJWTWithoutSignatureVerification(jwt) { } version = Number.parseInt(parsedHeader.version); (0, logger_1.logDebugMessage)("parseJWTWithoutSignatureVerification: version from header: " + version); - } - else { - (0, logger_1.logDebugMessage)("parseJWTWithoutSignatureVerification: assuming latest version (3) because version header is missing"); + } else { + (0, logger_1.logDebugMessage)( + "parseJWTWithoutSignatureVerification: assuming latest version (3) because version header is missing" + ); version = latestVersion; } kid = parsedHeader.kid; diff --git a/lib/build/recipe/session/recipe.d.ts b/lib/build/recipe/session/recipe.d.ts index c15990126..b0c7fe68a 100644 --- a/lib/build/recipe/session/recipe.d.ts +++ b/lib/build/recipe/session/recipe.d.ts @@ -1,6 +1,14 @@ // @ts-nocheck import RecipeModule from "../../recipeModule"; -import { TypeInput, TypeNormalisedInput, RecipeInterface, APIInterface, VerifySessionOptions, SessionClaimValidator, SessionClaim } from "./types"; +import { + TypeInput, + TypeNormalisedInput, + RecipeInterface, + APIInterface, + VerifySessionOptions, + SessionClaimValidator, + SessionClaim, +} from "./types"; import STError from "./error"; import { NormalisedAppinfo, RecipeListFunction, APIHandled, HTTPMethod, UserContext } from "../../types"; import NormalisedURLPath from "../../normalisedURLPath"; @@ -23,9 +31,27 @@ export default class SessionRecipe extends RecipeModule { addClaimValidatorFromOtherRecipe: (builder: SessionClaimValidator) => void; getClaimValidatorsAddedByOtherRecipes: () => SessionClaimValidator[]; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, _tenantId: string, req: BaseRequest, res: BaseResponse, _path: NormalisedURLPath, _method: HTTPMethod, userContext: UserContext) => Promise; - handleError: (err: STError, request: BaseRequest, response: BaseResponse, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + _tenantId: string, + req: BaseRequest, + res: BaseResponse, + _path: NormalisedURLPath, + _method: HTTPMethod, + userContext: UserContext + ) => Promise; + handleError: ( + err: STError, + request: BaseRequest, + response: BaseResponse, + userContext: UserContext + ) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; - verifySession: (options: VerifySessionOptions | undefined, request: BaseRequest, response: BaseResponse, userContext: UserContext) => Promise; + verifySession: ( + options: VerifySessionOptions | undefined, + request: BaseRequest, + response: BaseResponse, + userContext: UserContext + ) => Promise; } diff --git a/lib/build/recipe/session/recipe.js b/lib/build/recipe/session/recipe.js index 9bbd98052..d9f1fd14d 100644 --- a/lib/build/recipe/session/recipe.js +++ b/lib/build/recipe/session/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipeModule_1 = __importDefault(require("../../recipeModule")); const error_1 = __importDefault(require("./error")); @@ -85,11 +87,9 @@ class SessionRecipe extends recipeModule_1.default { }; if (id === constants_1.REFRESH_API_PATH) { return await (0, refresh_1.default)(this.apiImpl, options, userContext); - } - else if (id === constants_1.SIGNOUT_API_PATH) { + } else if (id === constants_1.SIGNOUT_API_PATH) { return await (0, signout_1.default)(this.apiImpl, options, userContext); - } - else { + } else { return false; } }; @@ -97,40 +97,65 @@ class SessionRecipe extends recipeModule_1.default { if (err.fromRecipe === SessionRecipe.RECIPE_ID) { if (err.type === error_1.default.UNAUTHORISED) { (0, logger_1.logDebugMessage)("errorHandler: returning UNAUTHORISED"); - if (err.payload === undefined || + if ( + err.payload === undefined || err.payload.clearTokens === undefined || - err.payload.clearTokens === true) { + err.payload.clearTokens === true + ) { (0, logger_1.logDebugMessage)("errorHandler: Clearing tokens because of UNAUTHORISED response"); - (0, cookieAndHeaders_1.clearSessionFromAllTokenTransferMethods)(this.config, response, request, userContext); + (0, cookieAndHeaders_1.clearSessionFromAllTokenTransferMethods)( + this.config, + response, + request, + userContext + ); } return await this.config.errorHandlers.onUnauthorised(err.message, request, response, userContext); - } - else if (err.type === error_1.default.TRY_REFRESH_TOKEN) { + } else if (err.type === error_1.default.TRY_REFRESH_TOKEN) { (0, logger_1.logDebugMessage)("errorHandler: returning TRY_REFRESH_TOKEN"); - return await this.config.errorHandlers.onTryRefreshToken(err.message, request, response, userContext); - } - else if (err.type === error_1.default.TOKEN_THEFT_DETECTED) { + return await this.config.errorHandlers.onTryRefreshToken( + err.message, + request, + response, + userContext + ); + } else if (err.type === error_1.default.TOKEN_THEFT_DETECTED) { (0, logger_1.logDebugMessage)("errorHandler: returning TOKEN_THEFT_DETECTED"); - (0, logger_1.logDebugMessage)("errorHandler: Clearing tokens because of TOKEN_THEFT_DETECTED response"); - (0, cookieAndHeaders_1.clearSessionFromAllTokenTransferMethods)(this.config, response, request, userContext); - return await this.config.errorHandlers.onTokenTheftDetected(err.payload.sessionHandle, err.payload.userId, err.payload.recipeUserId, request, response, userContext); - } - else if (err.type === error_1.default.INVALID_CLAIMS) { + (0, logger_1.logDebugMessage)( + "errorHandler: Clearing tokens because of TOKEN_THEFT_DETECTED response" + ); + (0, cookieAndHeaders_1.clearSessionFromAllTokenTransferMethods)( + this.config, + response, + request, + userContext + ); + return await this.config.errorHandlers.onTokenTheftDetected( + err.payload.sessionHandle, + err.payload.userId, + err.payload.recipeUserId, + request, + response, + userContext + ); + } else if (err.type === error_1.default.INVALID_CLAIMS) { return await this.config.errorHandlers.onInvalidClaim(err.payload, request, response, userContext); - } - else if (err.type === error_1.default.CLEAR_DUPLICATE_SESSION_COOKIES) { + } else if (err.type === error_1.default.CLEAR_DUPLICATE_SESSION_COOKIES) { (0, logger_1.logDebugMessage)("errorHandler: returning CLEAR_DUPLICATE_SESSION_COOKIES"); // This error occurs in the `refreshPOST` API when multiple session // cookies are found in the request and the user has set `olderCookieDomain`. // We remove session cookies from the olderCookieDomain. The response must return `200 OK` // to avoid logging out the user, allowing the session to continue with the valid cookie. - return await this.config.errorHandlers.onClearDuplicateSessionCookies(err.message, request, response, userContext); - } - else { + return await this.config.errorHandlers.onClearDuplicateSessionCookies( + err.message, + request, + response, + userContext + ); + } else { throw err; } - } - else { + } else { throw err; } }; @@ -156,18 +181,31 @@ class SessionRecipe extends recipeModule_1.default { }); }; this.config = (0, utils_1.validateAndNormaliseUserInput)(this, appInfo, config); - const antiCsrfToLog = typeof this.config.antiCsrfFunctionOrString === "string" - ? this.config.antiCsrfFunctionOrString - : "function"; + const antiCsrfToLog = + typeof this.config.antiCsrfFunctionOrString === "string" + ? this.config.antiCsrfFunctionOrString + : "function"; (0, logger_1.logDebugMessage)("session init: antiCsrf: " + antiCsrfToLog); (0, logger_1.logDebugMessage)("session init: cookieDomain: " + this.config.cookieDomain); - const sameSiteToPrint = config !== undefined && config.cookieSameSite !== undefined ? config.cookieSameSite : "default function"; + const sameSiteToPrint = + config !== undefined && config.cookieSameSite !== undefined ? config.cookieSameSite : "default function"; (0, logger_1.logDebugMessage)("session init: cookieSameSite: " + sameSiteToPrint); (0, logger_1.logDebugMessage)("session init: cookieSecure: " + this.config.cookieSecure); - (0, logger_1.logDebugMessage)("session init: refreshTokenPath: " + this.config.refreshTokenPath.getAsStringDangerous()); - (0, logger_1.logDebugMessage)("session init: sessionExpiredStatusCode: " + this.config.sessionExpiredStatusCode); + (0, logger_1.logDebugMessage)( + "session init: refreshTokenPath: " + this.config.refreshTokenPath.getAsStringDangerous() + ); + (0, logger_1.logDebugMessage)( + "session init: sessionExpiredStatusCode: " + this.config.sessionExpiredStatusCode + ); this.isInServerlessEnv = isInServerlessEnv; - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.config, this.getAppInfo(), () => this.recipeInterfaceImpl)); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + this.config, + this.getAppInfo(), + () => this.recipeInterfaceImpl + ) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); { let builder = new supertokens_js_override_1.default((0, implementation_1.default)()); @@ -178,15 +216,25 @@ class SessionRecipe extends recipeModule_1.default { if (SessionRecipe.instance !== undefined) { return SessionRecipe.instance; } - throw new Error("Initialisation not done. Did you forget to call the SuperTokens.init or Session.init function?"); + throw new Error( + "Initialisation not done. Did you forget to call the SuperTokens.init or Session.init function?" + ); } static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (SessionRecipe.instance === undefined) { - SessionRecipe.instance = new SessionRecipe(SessionRecipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(SessionRecipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + SessionRecipe.instance = new SessionRecipe( + SessionRecipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + SessionRecipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return SessionRecipe.instance; - } - else { + } else { throw new Error("Session recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/session/recipeImplementation.d.ts b/lib/build/recipe/session/recipeImplementation.d.ts index f411d4c29..28f00fa8e 100644 --- a/lib/build/recipe/session/recipeImplementation.d.ts +++ b/lib/build/recipe/session/recipeImplementation.d.ts @@ -8,4 +8,9 @@ export type Helpers = { appInfo: NormalisedAppinfo; getRecipeImpl: () => RecipeInterface; }; -export default function getRecipeInterface(querier: Querier, config: TypeNormalisedInput, appInfo: NormalisedAppinfo, getRecipeImplAfterOverrides: () => RecipeInterface): RecipeInterface; +export default function getRecipeInterface( + querier: Querier, + config: TypeNormalisedInput, + appInfo: NormalisedAppinfo, + getRecipeImplAfterOverrides: () => RecipeInterface +): RecipeInterface; diff --git a/lib/build/recipe/session/recipeImplementation.js b/lib/build/recipe/session/recipeImplementation.js index fd5a61573..52b9a13f0 100644 --- a/lib/build/recipe/session/recipeImplementation.js +++ b/lib/build/recipe/session/recipeImplementation.js @@ -1,40 +1,61 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const SessionFunctions = __importStar(require("./sessionFunctions")); @@ -52,33 +73,68 @@ const constants_2 = require("./constants"); const utils_2 = require("../../utils"); function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverrides) { let obj = { - createNewSession: async function ({ recipeUserId, accessTokenPayload = {}, sessionDataInDatabase = {}, disableAntiCsrf, tenantId, userContext, }) { + createNewSession: async function ({ + recipeUserId, + accessTokenPayload = {}, + sessionDataInDatabase = {}, + disableAntiCsrf, + tenantId, + userContext, + }) { (0, logger_1.logDebugMessage)("createNewSession: Started"); - let response = await SessionFunctions.createNewSession(helpers, tenantId, recipeUserId, disableAntiCsrf === true, accessTokenPayload, sessionDataInDatabase, userContext); + let response = await SessionFunctions.createNewSession( + helpers, + tenantId, + recipeUserId, + disableAntiCsrf === true, + accessTokenPayload, + sessionDataInDatabase, + userContext + ); (0, logger_1.logDebugMessage)("createNewSession: Finished"); const payload = (0, jwt_1.parseJWTWithoutSignatureVerification)(response.accessToken.token).payload; - return new sessionClass_1.default(helpers, response.accessToken.token, (0, cookieAndHeaders_1.buildFrontToken)(response.session.userId, response.accessToken.expiry, payload), response.refreshToken, response.antiCsrfToken, response.session.handle, response.session.userId, response.session.recipeUserId, payload, undefined, true, tenantId); + return new sessionClass_1.default( + helpers, + response.accessToken.token, + (0, cookieAndHeaders_1.buildFrontToken)(response.session.userId, response.accessToken.expiry, payload), + response.refreshToken, + response.antiCsrfToken, + response.session.handle, + response.session.userId, + response.session.recipeUserId, + payload, + undefined, + true, + tenantId + ); }, getGlobalClaimValidators: async function (input) { return input.claimValidatorsAddedByOtherRecipes; }, - getSession: async function ({ accessToken: accessTokenString, antiCsrfToken, options, userContext, }) { - if ((options === null || options === void 0 ? void 0 : options.antiCsrfCheck) !== false && + getSession: async function ({ accessToken: accessTokenString, antiCsrfToken, options, userContext }) { + if ( + (options === null || options === void 0 ? void 0 : options.antiCsrfCheck) !== false && typeof config.antiCsrfFunctionOrString === "string" && - config.antiCsrfFunctionOrString === "VIA_CUSTOM_HEADER") { - throw new Error("Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false"); + config.antiCsrfFunctionOrString === "VIA_CUSTOM_HEADER" + ) { + throw new Error( + "Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false" + ); } (0, logger_1.logDebugMessage)("getSession: Started"); if (accessTokenString === undefined) { if ((options === null || options === void 0 ? void 0 : options.sessionRequired) === false) { - (0, logger_1.logDebugMessage)("getSession: returning undefined because accessToken is undefined and sessionRequired is false"); + (0, logger_1.logDebugMessage)( + "getSession: returning undefined because accessToken is undefined and sessionRequired is false" + ); // there is no session that exists here, and the user wants session verification // to be optional. So we return undefined. return undefined; } (0, logger_1.logDebugMessage)("getSession: UNAUTHORISED because accessToken in request is undefined"); throw new error_1.default({ - message: "Session does not exist. Are you sending the session tokens in the request with the appropriate token transfer method?", + message: + "Session does not exist. Are you sending the session tokens in the request with the appropriate token transfer method?", type: error_1.default.UNAUTHORISED, payload: { // we do not clear the session here because of a @@ -91,28 +147,56 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride try { accessToken = (0, jwt_1.parseJWTWithoutSignatureVerification)(accessTokenString); (0, accessToken_1.validateAccessTokenStructure)(accessToken.payload, accessToken.version); - } - catch (error) { + } catch (error) { if ((options === null || options === void 0 ? void 0 : options.sessionRequired) === false) { - (0, logger_1.logDebugMessage)("getSession: Returning undefined because parsing failed and sessionRequired is false"); + (0, logger_1.logDebugMessage)( + "getSession: Returning undefined because parsing failed and sessionRequired is false" + ); return undefined; } - (0, logger_1.logDebugMessage)("getSession: UNAUTHORISED because the accessToken couldn't be parsed or had an invalid structure"); + (0, logger_1.logDebugMessage)( + "getSession: UNAUTHORISED because the accessToken couldn't be parsed or had an invalid structure" + ); throw new error_1.default({ message: "Token parsing failed", type: "UNAUTHORISED", payload: { clearTokens: false }, }); } - const response = await SessionFunctions.getSession(helpers, accessToken, antiCsrfToken, (options === null || options === void 0 ? void 0 : options.antiCsrfCheck) !== false, (options === null || options === void 0 ? void 0 : options.checkDatabase) === true, config, userContext); + const response = await SessionFunctions.getSession( + helpers, + accessToken, + antiCsrfToken, + (options === null || options === void 0 ? void 0 : options.antiCsrfCheck) !== false, + (options === null || options === void 0 ? void 0 : options.checkDatabase) === true, + config, + userContext + ); (0, logger_1.logDebugMessage)("getSession: Success!"); - const payload = accessToken.version >= 3 - ? response.accessToken !== undefined - ? (0, jwt_1.parseJWTWithoutSignatureVerification)(response.accessToken.token).payload - : accessToken.payload - : response.session.userDataInJWT; - const session = new sessionClass_1.default(helpers, response.accessToken !== undefined ? response.accessToken.token : accessTokenString, (0, cookieAndHeaders_1.buildFrontToken)(response.session.userId, response.accessToken !== undefined ? response.accessToken.expiry : response.session.expiryTime, payload), undefined, // refresh - antiCsrfToken, response.session.handle, response.session.userId, response.session.recipeUserId, payload, undefined, response.accessToken !== undefined, response.session.tenantId); + const payload = + accessToken.version >= 3 + ? response.accessToken !== undefined + ? (0, jwt_1.parseJWTWithoutSignatureVerification)(response.accessToken.token).payload + : accessToken.payload + : response.session.userDataInJWT; + const session = new sessionClass_1.default( + helpers, + response.accessToken !== undefined ? response.accessToken.token : accessTokenString, + (0, cookieAndHeaders_1.buildFrontToken)( + response.session.userId, + response.accessToken !== undefined ? response.accessToken.expiry : response.session.expiryTime, + payload + ), + undefined, // refresh + antiCsrfToken, + response.session.handle, + response.session.userId, + response.session.recipeUserId, + payload, + undefined, + response.accessToken !== undefined, + response.session.tenantId + ); return session; }, validateClaims: async function (input) { @@ -120,48 +204,95 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride let accessTokenPayloadUpdate = undefined; const origSessionClaimPayloadJSON = JSON.stringify(accessTokenPayload); for (const validator of input.claimValidators) { - (0, logger_1.logDebugMessage)("updateClaimsInPayloadIfNeeded checking shouldRefetch for " + validator.id); + (0, logger_1.logDebugMessage)( + "updateClaimsInPayloadIfNeeded checking shouldRefetch for " + validator.id + ); if ("claim" in validator && (await validator.shouldRefetch(accessTokenPayload, input.userContext))) { (0, logger_1.logDebugMessage)("updateClaimsInPayloadIfNeeded refetching " + validator.id); - const value = await validator.claim.fetchValue(input.userId, input.recipeUserId, accessTokenPayload.tId === undefined ? constants_1.DEFAULT_TENANT_ID : accessTokenPayload.tId, accessTokenPayload, input.userContext); - (0, logger_1.logDebugMessage)("updateClaimsInPayloadIfNeeded " + validator.id + " refetch result " + JSON.stringify(value)); + const value = await validator.claim.fetchValue( + input.userId, + input.recipeUserId, + accessTokenPayload.tId === undefined ? constants_1.DEFAULT_TENANT_ID : accessTokenPayload.tId, + accessTokenPayload, + input.userContext + ); + (0, logger_1.logDebugMessage)( + "updateClaimsInPayloadIfNeeded " + validator.id + " refetch result " + JSON.stringify(value) + ); if (value !== undefined) { - accessTokenPayload = validator.claim.addToPayload_internal(accessTokenPayload, value, input.userContext); + accessTokenPayload = validator.claim.addToPayload_internal( + accessTokenPayload, + value, + input.userContext + ); } } } if (JSON.stringify(accessTokenPayload) !== origSessionClaimPayloadJSON) { accessTokenPayloadUpdate = accessTokenPayload; } - const invalidClaims = await (0, utils_1.validateClaimsInPayload)(input.claimValidators, accessTokenPayload, input.userContext); + const invalidClaims = await (0, utils_1.validateClaimsInPayload)( + input.claimValidators, + accessTokenPayload, + input.userContext + ); return { invalidClaims, accessTokenPayloadUpdate, }; }, - getSessionInformation: async function ({ sessionHandle, userContext, }) { + getSessionInformation: async function ({ sessionHandle, userContext }) { return SessionFunctions.getSessionInformation(helpers, sessionHandle, userContext); }, - refreshSession: async function ({ refreshToken, antiCsrfToken, disableAntiCsrf, userContext, }) { - if (disableAntiCsrf !== true && + refreshSession: async function ({ refreshToken, antiCsrfToken, disableAntiCsrf, userContext }) { + if ( + disableAntiCsrf !== true && typeof config.antiCsrfFunctionOrString === "string" && - config.antiCsrfFunctionOrString === "VIA_CUSTOM_HEADER") { - throw new Error("Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false"); + config.antiCsrfFunctionOrString === "VIA_CUSTOM_HEADER" + ) { + throw new Error( + "Since the anti-csrf mode is VIA_CUSTOM_HEADER getSession can't check the CSRF token. Please either use VIA_TOKEN or set antiCsrfCheck to false" + ); } (0, logger_1.logDebugMessage)("refreshSession: Started"); - const response = await SessionFunctions.refreshSession(helpers, refreshToken, antiCsrfToken, disableAntiCsrf, config.useDynamicAccessTokenSigningKey, userContext); + const response = await SessionFunctions.refreshSession( + helpers, + refreshToken, + antiCsrfToken, + disableAntiCsrf, + config.useDynamicAccessTokenSigningKey, + userContext + ); (0, logger_1.logDebugMessage)("refreshSession: Success!"); const payload = (0, jwt_1.parseJWTWithoutSignatureVerification)(response.accessToken.token).payload; - return new sessionClass_1.default(helpers, response.accessToken.token, (0, cookieAndHeaders_1.buildFrontToken)(response.session.userId, response.accessToken.expiry, payload), response.refreshToken, response.antiCsrfToken, response.session.handle, response.session.userId, response.session.recipeUserId, payload, undefined, true, payload.tId); + return new sessionClass_1.default( + helpers, + response.accessToken.token, + (0, cookieAndHeaders_1.buildFrontToken)(response.session.userId, response.accessToken.expiry, payload), + response.refreshToken, + response.antiCsrfToken, + response.session.handle, + response.session.userId, + response.session.recipeUserId, + payload, + undefined, + true, + payload.tId + ); }, regenerateAccessToken: async function (input) { - let newAccessTokenPayload = input.newAccessTokenPayload === null || input.newAccessTokenPayload === undefined - ? {} - : input.newAccessTokenPayload; - let response = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/session/regenerate"), { - accessToken: input.accessToken, - userDataInJWT: newAccessTokenPayload, - }, input.userContext); + let newAccessTokenPayload = + input.newAccessTokenPayload === null || input.newAccessTokenPayload === undefined + ? {} + : input.newAccessTokenPayload; + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/session/regenerate"), + { + accessToken: input.accessToken, + userDataInJWT: newAccessTokenPayload, + }, + input.userContext + ); if (response.status === "UNAUTHORISED") { return undefined; } @@ -177,22 +308,48 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride accessToken: response.accessToken, }; }, - revokeAllSessionsForUser: function ({ userId, tenantId, revokeAcrossAllTenants, revokeSessionsForLinkedAccounts, userContext, }) { - return SessionFunctions.revokeAllSessionsForUser(helpers, userId, revokeSessionsForLinkedAccounts, tenantId, revokeAcrossAllTenants, userContext); + revokeAllSessionsForUser: function ({ + userId, + tenantId, + revokeAcrossAllTenants, + revokeSessionsForLinkedAccounts, + userContext, + }) { + return SessionFunctions.revokeAllSessionsForUser( + helpers, + userId, + revokeSessionsForLinkedAccounts, + tenantId, + revokeAcrossAllTenants, + userContext + ); }, - getAllSessionHandlesForUser: function ({ userId, fetchSessionsForAllLinkedAccounts, tenantId, fetchAcrossAllTenants, userContext, }) { - return SessionFunctions.getAllSessionHandlesForUser(helpers, userId, fetchSessionsForAllLinkedAccounts, tenantId, fetchAcrossAllTenants, userContext); + getAllSessionHandlesForUser: function ({ + userId, + fetchSessionsForAllLinkedAccounts, + tenantId, + fetchAcrossAllTenants, + userContext, + }) { + return SessionFunctions.getAllSessionHandlesForUser( + helpers, + userId, + fetchSessionsForAllLinkedAccounts, + tenantId, + fetchAcrossAllTenants, + userContext + ); }, - revokeSession: function ({ sessionHandle, userContext, }) { + revokeSession: function ({ sessionHandle, userContext }) { return SessionFunctions.revokeSession(helpers, sessionHandle, userContext); }, - revokeMultipleSessions: function ({ sessionHandles, userContext, }) { + revokeMultipleSessions: function ({ sessionHandles, userContext }) { return SessionFunctions.revokeMultipleSessions(helpers, sessionHandles, userContext); }, - updateSessionDataInDatabase: function ({ sessionHandle, newSessionData, userContext, }) { + updateSessionDataInDatabase: function ({ sessionHandle, newSessionData, userContext }) { return SessionFunctions.updateSessionDataInDatabase(helpers, sessionHandle, newSessionData, userContext); }, - mergeIntoAccessTokenPayload: async function ({ sessionHandle, accessTokenPayloadUpdate, userContext, }) { + mergeIntoAccessTokenPayload: async function ({ sessionHandle, accessTokenPayloadUpdate, userContext }) { const sessionInfo = await this.getSessionInformation({ sessionHandle, userContext }); if (sessionInfo === undefined) { return false; @@ -207,7 +364,12 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride delete newAccessTokenPayload[key]; } } - return SessionFunctions.updateAccessTokenPayload(helpers, sessionHandle, newAccessTokenPayload, userContext); + return SessionFunctions.updateAccessTokenPayload( + helpers, + sessionHandle, + newAccessTokenPayload, + userContext + ); }, fetchAndSetClaim: async function (input) { const sessionInfo = await this.getSessionInformation({ @@ -217,7 +379,13 @@ function getRecipeInterface(querier, config, appInfo, getRecipeImplAfterOverride if (sessionInfo === undefined) { return false; } - const accessTokenPayloadUpdate = await input.claim.build(sessionInfo.userId, sessionInfo.recipeUserId, sessionInfo.tenantId, sessionInfo.customClaimsInAccessTokenPayload, input.userContext); + const accessTokenPayloadUpdate = await input.claim.build( + sessionInfo.userId, + sessionInfo.recipeUserId, + sessionInfo.tenantId, + sessionInfo.customClaimsInAccessTokenPayload, + input.userContext + ); return this.mergeIntoAccessTokenPayload({ sessionHandle: input.sessionHandle, accessTokenPayloadUpdate, diff --git a/lib/build/recipe/session/sessionClass.d.ts b/lib/build/recipe/session/sessionClass.d.ts index 2d586ade3..2a1ea04f2 100644 --- a/lib/build/recipe/session/sessionClass.d.ts +++ b/lib/build/recipe/session/sessionClass.d.ts @@ -15,7 +15,20 @@ export default class Session implements SessionContainerInterface { protected reqResInfo: ReqResInfo | undefined; protected accessTokenUpdated: boolean; protected tenantId: string; - constructor(helpers: Helpers, accessToken: string, frontToken: string, refreshToken: TokenInfo | undefined, antiCsrfToken: string | undefined, sessionHandle: string, userId: string, recipeUserId: RecipeUserId, userDataInAccessToken: any, reqResInfo: ReqResInfo | undefined, accessTokenUpdated: boolean, tenantId: string); + constructor( + helpers: Helpers, + accessToken: string, + frontToken: string, + refreshToken: TokenInfo | undefined, + antiCsrfToken: string | undefined, + sessionHandle: string, + userId: string, + recipeUserId: RecipeUserId, + userDataInAccessToken: any, + reqResInfo: ReqResInfo | undefined, + accessTokenUpdated: boolean, + tenantId: string + ); getRecipeUserId(_userContext?: Record): RecipeUserId; revokeSession(userContext?: Record): Promise; getSessionDataFromDatabase(userContext?: Record): Promise; diff --git a/lib/build/recipe/session/sessionClass.js b/lib/build/recipe/session/sessionClass.js index 3ed4194e3..89f426db5 100644 --- a/lib/build/recipe/session/sessionClass.js +++ b/lib/build/recipe/session/sessionClass.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * @@ -25,7 +27,20 @@ const logger_1 = require("../../logger"); const constants_1 = require("./constants"); const utils_2 = require("../../utils"); class Session { - constructor(helpers, accessToken, frontToken, refreshToken, antiCsrfToken, sessionHandle, userId, recipeUserId, userDataInAccessToken, reqResInfo, accessTokenUpdated, tenantId) { + constructor( + helpers, + accessToken, + frontToken, + refreshToken, + antiCsrfToken, + sessionHandle, + userId, + recipeUserId, + userDataInAccessToken, + reqResInfo, + accessTokenUpdated, + tenantId + ) { this.helpers = helpers; this.accessToken = accessToken; this.frontToken = frontToken; @@ -43,9 +58,10 @@ class Session { return this.recipeUserId; } async revokeSession(userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); await this.helpers.getRecipeImpl().revokeSession({ sessionHandle: this.sessionHandle, userContext: ctx, @@ -57,19 +73,28 @@ class Session { // If we instead clear the cookies only when revokeSession // returns true, it can cause this kind of a bug: // https://github.com/supertokens/supertokens-node/issues/343 - (0, cookieAndHeaders_1.clearSession)(this.helpers.config, this.reqResInfo.res, this.reqResInfo.transferMethod, this.reqResInfo.req, ctx); + (0, cookieAndHeaders_1.clearSession)( + this.helpers.config, + this.reqResInfo.res, + this.reqResInfo.transferMethod, + this.reqResInfo.req, + ctx + ); } } async getSessionDataFromDatabase(userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); let sessionInfo = await this.helpers.getRecipeImpl().getSessionInformation({ sessionHandle: this.sessionHandle, userContext: ctx, }); if (sessionInfo === undefined) { - (0, logger_1.logDebugMessage)("getSessionDataFromDatabase: Throwing UNAUTHORISED because session does not exist anymore"); + (0, logger_1.logDebugMessage)( + "getSessionDataFromDatabase: Throwing UNAUTHORISED because session does not exist anymore" + ); throw new error_1.default({ message: "Session does not exist anymore", type: error_1.default.UNAUTHORISED, @@ -78,15 +103,20 @@ class Session { return sessionInfo.sessionDataInDatabase; } async updateSessionDataInDatabase(newSessionData, userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); - if (!(await this.helpers.getRecipeImpl().updateSessionDataInDatabase({ - sessionHandle: this.sessionHandle, - newSessionData, - userContext: ctx, - }))) { - (0, logger_1.logDebugMessage)("updateSessionDataInDatabase: Throwing UNAUTHORISED because session does not exist anymore"); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); + if ( + !(await this.helpers.getRecipeImpl().updateSessionDataInDatabase({ + sessionHandle: this.sessionHandle, + newSessionData, + userContext: ctx, + })) + ) { + (0, logger_1.logDebugMessage)( + "updateSessionDataInDatabase: Throwing UNAUTHORISED because session does not exist anymore" + ); throw new error_1.default({ message: "Session does not exist anymore", type: error_1.default.UNAUTHORISED, @@ -120,9 +150,10 @@ class Session { } // Any update to this function should also be reflected in the respective JWT version async mergeIntoAccessTokenPayload(accessTokenPayloadUpdate, userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); let newAccessTokenPayload = Object.assign({}, this.getAccessTokenPayload(ctx)); for (const key of constants_1.protectedProps) { delete newAccessTokenPayload[key]; @@ -139,7 +170,9 @@ class Session { userContext: ctx, }); if (response === undefined) { - (0, logger_1.logDebugMessage)("mergeIntoAccessTokenPayload: Throwing UNAUTHORISED because session does not exist anymore"); + (0, logger_1.logDebugMessage)( + "mergeIntoAccessTokenPayload: Throwing UNAUTHORISED because session does not exist anymore" + ); throw new error_1.default({ message: "Session does not exist anymore", type: error_1.default.UNAUTHORISED, @@ -150,30 +183,47 @@ class Session { const payload = respToken.version < 3 ? response.session.userDataInJWT : respToken.payload; this.userDataInAccessToken = payload; this.accessToken = response.accessToken.token; - this.frontToken = (0, cookieAndHeaders_1.buildFrontToken)(this.userId, response.accessToken.expiry, payload); + this.frontToken = (0, cookieAndHeaders_1.buildFrontToken)( + this.userId, + response.accessToken.expiry, + payload + ); this.accessTokenUpdated = true; if (this.reqResInfo !== undefined) { // We need to cast to let TS know that the accessToken in the response is defined (and we don't overwrite it with undefined) - (0, utils_1.setAccessTokenInResponse)(this.reqResInfo.res, this.accessToken, this.frontToken, this.helpers.config, this.reqResInfo.transferMethod, this.reqResInfo.req, ctx); + (0, utils_1.setAccessTokenInResponse)( + this.reqResInfo.res, + this.accessToken, + this.frontToken, + this.helpers.config, + this.reqResInfo.transferMethod, + this.reqResInfo.req, + ctx + ); } - } - else { + } else { // This case means that the access token has expired between the validation and this update // We can't update the access token on the FE, as it will need to call refresh anyway but we handle this as a successful update during this request. // the changes will be reflected on the FE after refresh is called - this.userDataInAccessToken = Object.assign(Object.assign({}, this.getAccessTokenPayload(ctx)), response.session.userDataInJWT); + this.userDataInAccessToken = Object.assign( + Object.assign({}, this.getAccessTokenPayload(ctx)), + response.session.userDataInJWT + ); } } async getTimeCreated(userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); let sessionInfo = await this.helpers.getRecipeImpl().getSessionInformation({ sessionHandle: this.sessionHandle, userContext: ctx, }); if (sessionInfo === undefined) { - (0, logger_1.logDebugMessage)("getTimeCreated: Throwing UNAUTHORISED because session does not exist anymore"); + (0, logger_1.logDebugMessage)( + "getTimeCreated: Throwing UNAUTHORISED because session does not exist anymore" + ); throw new error_1.default({ message: "Session does not exist anymore", type: error_1.default.UNAUTHORISED, @@ -182,9 +232,10 @@ class Session { return sessionInfo.timeCreated; } async getExpiry(userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); let sessionInfo = await this.helpers.getRecipeImpl().getSessionInformation({ sessionHandle: this.sessionHandle, userContext: ctx, @@ -200,9 +251,10 @@ class Session { } // Any update to this function should also be reflected in the respective JWT version async assertClaims(claimValidators, userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); let validateClaimResponse = await this.helpers.getRecipeImpl().validateClaims({ accessTokenPayload: this.getAccessTokenPayload(ctx), userId: this.getUserId(ctx), @@ -226,32 +278,42 @@ class Session { } // Any update to this function should also be reflected in the respective JWT version async fetchAndSetClaim(claim, userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); - const update = await claim.build(this.getUserId(ctx), this.getRecipeUserId(ctx), this.getTenantId(ctx), this.getAccessTokenPayload(ctx), ctx); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); + const update = await claim.build( + this.getUserId(ctx), + this.getRecipeUserId(ctx), + this.getTenantId(ctx), + this.getAccessTokenPayload(ctx), + ctx + ); return this.mergeIntoAccessTokenPayload(update, ctx); } // Any update to this function should also be reflected in the respective JWT version setClaimValue(claim, value, userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); const update = claim.addToPayload_internal({}, value, (0, utils_2.getUserContext)(ctx)); return this.mergeIntoAccessTokenPayload(update, ctx); } // Any update to this function should also be reflected in the respective JWT version async getClaimValue(claim, userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); return claim.getValueFromPayload(await this.getAccessTokenPayload(ctx), ctx); } // Any update to this function should also be reflected in the respective JWT version removeClaim(claim, userContext) { - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); const update = claim.removeFromPayloadByMerge_internal({}, ctx); return this.mergeIntoAccessTokenPayload(update, ctx); } @@ -259,12 +321,30 @@ class Session { this.reqResInfo = info; if (this.accessTokenUpdated) { const { res, transferMethod } = info; - const ctx = userContext === undefined && this.reqResInfo !== undefined - ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) - : (0, utils_2.getUserContext)(userContext); - (0, utils_1.setAccessTokenInResponse)(res, this.accessToken, this.frontToken, this.helpers.config, transferMethod, info.req, ctx); + const ctx = + userContext === undefined && this.reqResInfo !== undefined + ? (0, utils_2.makeDefaultUserContextFromAPI)(this.reqResInfo.req) + : (0, utils_2.getUserContext)(userContext); + (0, utils_1.setAccessTokenInResponse)( + res, + this.accessToken, + this.frontToken, + this.helpers.config, + transferMethod, + info.req, + ctx + ); if (this.refreshToken !== undefined) { - (0, cookieAndHeaders_1.setToken)(this.helpers.config, res, "refresh", this.refreshToken.token, this.refreshToken.expiry, transferMethod, info.req, ctx); + (0, cookieAndHeaders_1.setToken)( + this.helpers.config, + res, + "refresh", + this.refreshToken.token, + this.refreshToken.expiry, + transferMethod, + info.req, + ctx + ); } if (this.antiCsrfToken !== undefined) { (0, cookieAndHeaders_1.setAntiCsrfTokenInHeaders)(res, this.antiCsrfToken); diff --git a/lib/build/recipe/session/sessionFunctions.d.ts b/lib/build/recipe/session/sessionFunctions.d.ts index 366bb8b34..601e51917 100644 --- a/lib/build/recipe/session/sessionFunctions.d.ts +++ b/lib/build/recipe/session/sessionFunctions.d.ts @@ -7,11 +7,27 @@ import { UserContext } from "../../types"; /** * @description call this to "login" a user. */ -export declare function createNewSession(helpers: Helpers, tenantId: string, recipeUserId: RecipeUserId, disableAntiCsrf: boolean, accessTokenPayload: any, sessionDataInDatabase: any, userContext: UserContext): Promise; +export declare function createNewSession( + helpers: Helpers, + tenantId: string, + recipeUserId: RecipeUserId, + disableAntiCsrf: boolean, + accessTokenPayload: any, + sessionDataInDatabase: any, + userContext: UserContext +): Promise; /** * @description authenticates a session. To be used in APIs that require authentication */ -export declare function getSession(helpers: Helpers, parsedAccessToken: ParsedJWTInfo, antiCsrfToken: string | undefined, doAntiCsrfCheck: boolean, alwaysCheckCore: boolean, config: TypeNormalisedInput, userContext: UserContext): Promise<{ +export declare function getSession( + helpers: Helpers, + parsedAccessToken: ParsedJWTInfo, + antiCsrfToken: string | undefined, + doAntiCsrfCheck: boolean, + alwaysCheckCore: boolean, + config: TypeNormalisedInput, + userContext: UserContext +): Promise<{ session: { handle: string; userId: string; @@ -30,33 +46,76 @@ export declare function getSession(helpers: Helpers, parsedAccessToken: ParsedJW * @description Retrieves session information from storage for a given session handle * @returns session data stored in the database, including userData and access token payload, or undefined if sessionHandle is invalid */ -export declare function getSessionInformation(helpers: Helpers, sessionHandle: string, userContext: UserContext): Promise; +export declare function getSessionInformation( + helpers: Helpers, + sessionHandle: string, + userContext: UserContext +): Promise; /** * @description generates new access and refresh tokens for a given refresh token. Called when client's access token has expired. * @sideEffects calls onTokenTheftDetection if token theft is detected. */ -export declare function refreshSession(helpers: Helpers, refreshToken: string, antiCsrfToken: string | undefined, disableAntiCsrf: boolean, useDynamicAccessTokenSigningKey: boolean, userContext: UserContext): Promise; +export declare function refreshSession( + helpers: Helpers, + refreshToken: string, + antiCsrfToken: string | undefined, + disableAntiCsrf: boolean, + useDynamicAccessTokenSigningKey: boolean, + userContext: UserContext +): Promise; /** * @description deletes session info of a user from db. This only invalidates the refresh token. Not the access token. * Access tokens cannot be immediately invalidated. Unless we add a blacklisting method. Or changed the private key to sign them. */ -export declare function revokeAllSessionsForUser(helpers: Helpers, userId: string, revokeSessionsForLinkedAccounts: boolean, tenantId: string | undefined, revokeAcrossAllTenants: boolean | undefined, userContext: UserContext): Promise; +export declare function revokeAllSessionsForUser( + helpers: Helpers, + userId: string, + revokeSessionsForLinkedAccounts: boolean, + tenantId: string | undefined, + revokeAcrossAllTenants: boolean | undefined, + userContext: UserContext +): Promise; /** * @description gets all session handles for current user. Please do not call this unless this user is authenticated. */ -export declare function getAllSessionHandlesForUser(helpers: Helpers, userId: string, fetchSessionsForAllLinkedAccounts: boolean, tenantId: string | undefined, fetchAcrossAllTenants: boolean | undefined, userContext: UserContext): Promise; +export declare function getAllSessionHandlesForUser( + helpers: Helpers, + userId: string, + fetchSessionsForAllLinkedAccounts: boolean, + tenantId: string | undefined, + fetchAcrossAllTenants: boolean | undefined, + userContext: UserContext +): Promise; /** * @description call to destroy one session * @returns true if session was deleted from db. Else false in case there was nothing to delete */ -export declare function revokeSession(helpers: Helpers, sessionHandle: string, userContext: UserContext): Promise; +export declare function revokeSession( + helpers: Helpers, + sessionHandle: string, + userContext: UserContext +): Promise; /** * @description call to destroy multiple sessions * @returns list of sessions revoked */ -export declare function revokeMultipleSessions(helpers: Helpers, sessionHandles: string[], userContext: UserContext): Promise; +export declare function revokeMultipleSessions( + helpers: Helpers, + sessionHandles: string[], + userContext: UserContext +): Promise; /** * @description: It provides no locking mechanism in case other processes are updating session data for this session as well. */ -export declare function updateSessionDataInDatabase(helpers: Helpers, sessionHandle: string, newSessionData: any, userContext: UserContext): Promise; -export declare function updateAccessTokenPayload(helpers: Helpers, sessionHandle: string, newAccessTokenPayload: any, userContext: UserContext): Promise; +export declare function updateSessionDataInDatabase( + helpers: Helpers, + sessionHandle: string, + newSessionData: any, + userContext: UserContext +): Promise; +export declare function updateAccessTokenPayload( + helpers: Helpers, + sessionHandle: string, + newAccessTokenPayload: any, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/session/sessionFunctions.js b/lib/build/recipe/session/sessionFunctions.js index 01c42e8ce..bb70ccebe 100644 --- a/lib/build/recipe/session/sessionFunctions.js +++ b/lib/build/recipe/session/sessionFunctions.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createNewSession = createNewSession; exports.getSession = getSession; @@ -39,7 +41,15 @@ const combinedRemoteJWKSet_1 = require("../../combinedRemoteJWKSet"); /** * @description call this to "login" a user. */ -async function createNewSession(helpers, tenantId, recipeUserId, disableAntiCsrf, accessTokenPayload, sessionDataInDatabase, userContext) { +async function createNewSession( + helpers, + tenantId, + recipeUserId, + disableAntiCsrf, + accessTokenPayload, + sessionDataInDatabase, + userContext +) { accessTokenPayload = accessTokenPayload === null || accessTokenPayload === undefined ? {} : accessTokenPayload; sessionDataInDatabase = sessionDataInDatabase === null || sessionDataInDatabase === undefined ? {} : sessionDataInDatabase; @@ -51,7 +61,11 @@ async function createNewSession(helpers, tenantId, recipeUserId, disableAntiCsrf // We dont need to check if anti csrf is a function here because checking for "VIA_TOKEN" is enough enableAntiCsrf: !disableAntiCsrf && helpers.config.antiCsrfFunctionOrString === "VIA_TOKEN", }; - let response = await helpers.querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId}/recipe/session`), requestBody, userContext); + let response = await helpers.querier.sendPostRequest( + new normalisedURLPath_1.default(`/${tenantId}/recipe/session`), + requestBody, + userContext + ); return { session: { handle: response.session.handle, @@ -76,16 +90,27 @@ async function createNewSession(helpers, tenantId, recipeUserId, disableAntiCsrf /** * @description authenticates a session. To be used in APIs that require authentication */ -async function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfCheck, alwaysCheckCore, config, userContext) { +async function getSession( + helpers, + parsedAccessToken, + antiCsrfToken, + doAntiCsrfCheck, + alwaysCheckCore, + config, + userContext +) { var _a, _b; let accessTokenInfo; try { /** * get access token info using jwks */ - accessTokenInfo = await (0, accessToken_1.getInfoFromAccessToken)(parsedAccessToken, (0, combinedRemoteJWKSet_1.getCombinedJWKS)(config), helpers.config.antiCsrfFunctionOrString === "VIA_TOKEN" && doAntiCsrfCheck); - } - catch (err) { + accessTokenInfo = await (0, accessToken_1.getInfoFromAccessToken)( + parsedAccessToken, + (0, combinedRemoteJWKSet_1.getCombinedJWKS)(config), + helpers.config.antiCsrfFunctionOrString === "VIA_TOKEN" && doAntiCsrfCheck + ); + } catch (err) { /** * if error type is not TRY_REFRESH_TOKEN, we return the * error to the user @@ -126,8 +151,7 @@ async function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfC if (timeCreated <= Date.now() - config.jwksRefreshIntervalSec * 1000) { throw err; } - } - else { + } else { // Since v3 (and above) tokens contain a kid we can trust the cache-refresh mechanism of the jose library. // This means we do not need to call the core since the signature wouldn't pass verification anyway. throw err; @@ -136,7 +160,9 @@ async function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfC if (parsedAccessToken.version >= 3) { const tokenUsesDynamicKey = parsedAccessToken.kid.startsWith("d-"); if (tokenUsesDynamicKey !== helpers.config.useDynamicAccessTokenSigningKey) { - (0, logger_1.logDebugMessage)("getSession: Returning TRY_REFRESH_TOKEN because the access token doesn't match the useDynamicAccessTokenSigningKey in the config"); + (0, logger_1.logDebugMessage)( + "getSession: Returning TRY_REFRESH_TOKEN because the access token doesn't match the useDynamicAccessTokenSigningKey in the config" + ); throw new error_1.default({ message: "The access token doesn't match the useDynamicAccessTokenSigningKey setting", type: error_1.default.TRY_REFRESH_TOKEN, @@ -153,14 +179,18 @@ async function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfC if (accessTokenInfo !== undefined) { if (antiCsrfToken === undefined || antiCsrfToken !== accessTokenInfo.antiCsrfToken) { if (antiCsrfToken === undefined) { - (0, logger_1.logDebugMessage)("getSession: Returning TRY_REFRESH_TOKEN because antiCsrfToken is missing from request"); + (0, logger_1.logDebugMessage)( + "getSession: Returning TRY_REFRESH_TOKEN because antiCsrfToken is missing from request" + ); throw new error_1.default({ - message: "Provided antiCsrfToken is undefined. If you do not want anti-csrf check for this API, please set doAntiCsrfCheck to false for this API", + message: + "Provided antiCsrfToken is undefined. If you do not want anti-csrf check for this API, please set doAntiCsrfCheck to false for this API", type: error_1.default.TRY_REFRESH_TOKEN, }); - } - else { - (0, logger_1.logDebugMessage)("getSession: Returning TRY_REFRESH_TOKEN because the passed antiCsrfToken is not the same as in the access token"); + } else { + (0, logger_1.logDebugMessage)( + "getSession: Returning TRY_REFRESH_TOKEN because the passed antiCsrfToken is not the same as in the access token" + ); throw new error_1.default({ message: "anti-csrf check failed", type: error_1.default.TRY_REFRESH_TOKEN, @@ -168,9 +198,10 @@ async function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfC } } } - } - else if (typeof helpers.config.antiCsrfFunctionOrString === "string" && - helpers.config.antiCsrfFunctionOrString === "VIA_CUSTOM_HEADER") { + } else if ( + typeof helpers.config.antiCsrfFunctionOrString === "string" && + helpers.config.antiCsrfFunctionOrString === "VIA_CUSTOM_HEADER" + ) { // The function should never be called by this (we check this outside the function as well) // There we can add a bit more information to the error, so that's the primary check, this is just making sure. throw new Error("Please either use VIA_TOKEN, NONE or call with doAntiCsrfCheck false"); @@ -196,28 +227,36 @@ async function getSession(helpers, parsedAccessToken, antiCsrfToken, doAntiCsrfC enableAntiCsrf: helpers.config.antiCsrfFunctionOrString === "VIA_TOKEN", checkDatabase: alwaysCheckCore, }; - let response = await helpers.querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/session/verify"), requestBody, userContext); + let response = await helpers.querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/session/verify"), + requestBody, + userContext + ); if (response.status === "OK") { delete response.status; - return Object.assign(Object.assign({}, response), { session: { + return Object.assign(Object.assign({}, response), { + session: { handle: response.session.handle, userId: response.session.userId, recipeUserId: new recipeUserId_1.default(response.session.recipeUserId), - expiryTime: ((_a = response.accessToken) === null || _a === void 0 ? void 0 : _a.expiry) || // if we got a new accesstoken we take the expiry time from there + expiryTime: + ((_a = response.accessToken) === null || _a === void 0 ? void 0 : _a.expiry) || // if we got a new accesstoken we take the expiry time from there (accessTokenInfo === null || accessTokenInfo === void 0 ? void 0 : accessTokenInfo.expiryTime) || // if we didn't get a new access token but could validate the token take that info (alwaysCheckCore === true, or parentRefreshTokenHash1 !== null) parsedAccessToken.payload["expiryTime"], // if the token didn't pass validation, but we got here, it means it was a v2 token that we didn't have the key cached for. - tenantId: ((_b = response.session) === null || _b === void 0 ? void 0 : _b.tenantId) || (accessTokenInfo === null || accessTokenInfo === void 0 ? void 0 : accessTokenInfo.tenantId) || constants_1.DEFAULT_TENANT_ID, + tenantId: + ((_b = response.session) === null || _b === void 0 ? void 0 : _b.tenantId) || + (accessTokenInfo === null || accessTokenInfo === void 0 ? void 0 : accessTokenInfo.tenantId) || + constants_1.DEFAULT_TENANT_ID, userDataInJWT: response.session.userDataInJWT, - } }); - } - else if (response.status === "UNAUTHORISED") { + }, + }); + } else if (response.status === "UNAUTHORISED") { (0, logger_1.logDebugMessage)("getSession: Returning UNAUTHORISED because of core response"); throw new error_1.default({ message: response.message, type: error_1.default.UNAUTHORISED, }); - } - else { + } else { (0, logger_1.logDebugMessage)("getSession: Returning TRY_REFRESH_TOKEN because of core response."); throw new error_1.default({ message: response.message, @@ -234,9 +273,13 @@ async function getSessionInformation(helpers, sessionHandle, userContext) { if ((0, utils_1.maxVersion)(apiVersion, "2.7") === "2.7") { throw new Error("Please use core version >= 3.5 to call this function."); } - let response = await helpers.querier.sendGetRequest(new normalisedURLPath_1.default(`/recipe/session`), { - sessionHandle, - }, userContext); + let response = await helpers.querier.sendGetRequest( + new normalisedURLPath_1.default(`/recipe/session`), + { + sessionHandle, + }, + userContext + ); if (response.status === "OK") { // Change keys to make them more readable return { @@ -249,8 +292,7 @@ async function getSessionInformation(helpers, sessionHandle, userContext) { customClaimsInAccessTokenPayload: response.userDataInJWT, tenantId: response.tenantId, }; - } - else { + } else { return undefined; } } @@ -258,21 +300,34 @@ async function getSessionInformation(helpers, sessionHandle, userContext) { * @description generates new access and refresh tokens for a given refresh token. Called when client's access token has expired. * @sideEffects calls onTokenTheftDetection if token theft is detected. */ -async function refreshSession(helpers, refreshToken, antiCsrfToken, disableAntiCsrf, useDynamicAccessTokenSigningKey, userContext) { +async function refreshSession( + helpers, + refreshToken, + antiCsrfToken, + disableAntiCsrf, + useDynamicAccessTokenSigningKey, + userContext +) { let requestBody = { refreshToken, antiCsrfToken, enableAntiCsrf: !disableAntiCsrf && helpers.config.antiCsrfFunctionOrString === "VIA_TOKEN", useDynamicSigningKey: useDynamicAccessTokenSigningKey, }; - if (typeof helpers.config.antiCsrfFunctionOrString === "string" && + if ( + typeof helpers.config.antiCsrfFunctionOrString === "string" && helpers.config.antiCsrfFunctionOrString === "VIA_CUSTOM_HEADER" && - !disableAntiCsrf) { + !disableAntiCsrf + ) { // The function should never be called by this (we check this outside the function as well) // There we can add a bit more information to the error, so that's the primary check, this is just making sure. throw new Error("Please either use VIA_TOKEN, NONE or call with doAntiCsrfCheck false"); } - let response = await helpers.querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/session/refresh"), requestBody, userContext); + let response = await helpers.querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/session/refresh"), + requestBody, + userContext + ); if (response.status === "OK") { return { session: { @@ -294,15 +349,13 @@ async function refreshSession(helpers, refreshToken, antiCsrfToken, disableAntiC }, antiCsrfToken: response.antiCsrfToken, }; - } - else if (response.status === "UNAUTHORISED") { + } else if (response.status === "UNAUTHORISED") { (0, logger_1.logDebugMessage)("refreshSession: Returning UNAUTHORISED because of core response"); throw new error_1.default({ message: response.message, type: error_1.default.UNAUTHORISED, }); - } - else { + } else { (0, logger_1.logDebugMessage)("refreshSession: Returning TOKEN_THEFT_DETECTED because of core response"); throw new error_1.default({ message: "Token theft detected", @@ -319,29 +372,55 @@ async function refreshSession(helpers, refreshToken, antiCsrfToken, disableAntiC * @description deletes session info of a user from db. This only invalidates the refresh token. Not the access token. * Access tokens cannot be immediately invalidated. Unless we add a blacklisting method. Or changed the private key to sign them. */ -async function revokeAllSessionsForUser(helpers, userId, revokeSessionsForLinkedAccounts, tenantId, revokeAcrossAllTenants, userContext) { +async function revokeAllSessionsForUser( + helpers, + userId, + revokeSessionsForLinkedAccounts, + tenantId, + revokeAcrossAllTenants, + userContext +) { if (tenantId === undefined) { tenantId = constants_1.DEFAULT_TENANT_ID; } - let response = await helpers.querier.sendPostRequest(new normalisedURLPath_1.default(revokeAcrossAllTenants ? `/recipe/session/remove` : `/${tenantId}/recipe/session/remove`), { - userId, - revokeSessionsForLinkedAccounts, - revokeAcrossAllTenants, - }, userContext); + let response = await helpers.querier.sendPostRequest( + new normalisedURLPath_1.default( + revokeAcrossAllTenants ? `/recipe/session/remove` : `/${tenantId}/recipe/session/remove` + ), + { + userId, + revokeSessionsForLinkedAccounts, + revokeAcrossAllTenants, + }, + userContext + ); return response.sessionHandlesRevoked; } /** * @description gets all session handles for current user. Please do not call this unless this user is authenticated. */ -async function getAllSessionHandlesForUser(helpers, userId, fetchSessionsForAllLinkedAccounts, tenantId, fetchAcrossAllTenants, userContext) { +async function getAllSessionHandlesForUser( + helpers, + userId, + fetchSessionsForAllLinkedAccounts, + tenantId, + fetchAcrossAllTenants, + userContext +) { if (tenantId === undefined) { tenantId = constants_1.DEFAULT_TENANT_ID; } - let response = await helpers.querier.sendGetRequest(new normalisedURLPath_1.default(fetchAcrossAllTenants ? `/recipe/session/user` : `/${tenantId}/recipe/session/user`), { - userId, - fetchSessionsForAllLinkedAccounts, - fetchAcrossAllTenants, - }, userContext); + let response = await helpers.querier.sendGetRequest( + new normalisedURLPath_1.default( + fetchAcrossAllTenants ? `/recipe/session/user` : `/${tenantId}/recipe/session/user` + ), + { + userId, + fetchSessionsForAllLinkedAccounts, + fetchAcrossAllTenants, + }, + userContext + ); return response.sessionHandles; } /** @@ -349,9 +428,13 @@ async function getAllSessionHandlesForUser(helpers, userId, fetchSessionsForAllL * @returns true if session was deleted from db. Else false in case there was nothing to delete */ async function revokeSession(helpers, sessionHandle, userContext) { - let response = await helpers.querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/session/remove"), { - sessionHandles: [sessionHandle], - }, userContext); + let response = await helpers.querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/session/remove"), + { + sessionHandles: [sessionHandle], + }, + userContext + ); return response.sessionHandlesRevoked.length === 1; } /** @@ -359,9 +442,13 @@ async function revokeSession(helpers, sessionHandle, userContext) { * @returns list of sessions revoked */ async function revokeMultipleSessions(helpers, sessionHandles, userContext) { - let response = await helpers.querier.sendPostRequest(new normalisedURLPath_1.default(`/recipe/session/remove`), { - sessionHandles, - }, userContext); + let response = await helpers.querier.sendPostRequest( + new normalisedURLPath_1.default(`/recipe/session/remove`), + { + sessionHandles, + }, + userContext + ); return response.sessionHandlesRevoked; } /** @@ -369,10 +456,15 @@ async function revokeMultipleSessions(helpers, sessionHandles, userContext) { */ async function updateSessionDataInDatabase(helpers, sessionHandle, newSessionData, userContext) { newSessionData = newSessionData === null || newSessionData === undefined ? {} : newSessionData; - let response = await helpers.querier.sendPutRequest(new normalisedURLPath_1.default(`/recipe/session/data`), { - sessionHandle, - userDataInDatabase: newSessionData, - }, {}, userContext); + let response = await helpers.querier.sendPutRequest( + new normalisedURLPath_1.default(`/recipe/session/data`), + { + sessionHandle, + userDataInDatabase: newSessionData, + }, + {}, + userContext + ); if (response.status === "UNAUTHORISED") { return false; } @@ -381,10 +473,15 @@ async function updateSessionDataInDatabase(helpers, sessionHandle, newSessionDat async function updateAccessTokenPayload(helpers, sessionHandle, newAccessTokenPayload, userContext) { newAccessTokenPayload = newAccessTokenPayload === null || newAccessTokenPayload === undefined ? {} : newAccessTokenPayload; - let response = await helpers.querier.sendPutRequest(new normalisedURLPath_1.default("/recipe/jwt/data"), { - sessionHandle, - userDataInJWT: newAccessTokenPayload, - }, {}, userContext); + let response = await helpers.querier.sendPutRequest( + new normalisedURLPath_1.default("/recipe/jwt/data"), + { + sessionHandle, + userDataInJWT: newAccessTokenPayload, + }, + {}, + userContext + ); if (response.status === "UNAUTHORISED") { return false; } diff --git a/lib/build/recipe/session/sessionRequestFunctions.d.ts b/lib/build/recipe/session/sessionRequestFunctions.d.ts index 6d04f5c0f..46796682e 100644 --- a/lib/build/recipe/session/sessionRequestFunctions.d.ts +++ b/lib/build/recipe/session/sessionRequestFunctions.d.ts @@ -1,10 +1,23 @@ // @ts-nocheck import Recipe from "./recipe"; -import { VerifySessionOptions, RecipeInterface, TokenTransferMethod, TypeNormalisedInput, SessionContainerInterface } from "./types"; +import { + VerifySessionOptions, + RecipeInterface, + TokenTransferMethod, + TypeNormalisedInput, + SessionContainerInterface, +} from "./types"; import { ParsedJWTInfo } from "./jwt"; import { NormalisedAppinfo, UserContext } from "../../types"; import RecipeUserId from "../../recipeUserId"; -export declare function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, options, userContext, }: { +export declare function getSessionFromRequest({ + req, + res, + config, + recipeInterfaceImpl, + options, + userContext, +}: { req: any; res: any; config: TypeNormalisedInput; @@ -12,19 +25,42 @@ export declare function getSessionFromRequest({ req, res, config, recipeInterfac options?: VerifySessionOptions; userContext: UserContext; }): Promise; -export declare function getAccessTokenFromRequest(config: TypeNormalisedInput, req: any, allowedTransferMethod: TokenTransferMethod | "any", userContext: UserContext): { +export declare function getAccessTokenFromRequest( + config: TypeNormalisedInput, + req: any, + allowedTransferMethod: TokenTransferMethod | "any", + userContext: UserContext +): { requestTransferMethod: TokenTransferMethod | undefined; accessToken: ParsedJWTInfo | undefined; allowedTransferMethod: TokenTransferMethod | "any"; }; -export declare function refreshSessionInRequest({ res, req, userContext, config, recipeInterfaceImpl, }: { +export declare function refreshSessionInRequest({ + res, + req, + userContext, + config, + recipeInterfaceImpl, +}: { res: any; req: any; userContext: UserContext; config: TypeNormalisedInput; recipeInterfaceImpl: RecipeInterface; }): Promise; -export declare function createNewSessionInRequest({ req, res, userContext, recipeInstance, accessTokenPayload, userId, recipeUserId, config, appInfo, sessionDataInDatabase, tenantId, }: { +export declare function createNewSessionInRequest({ + req, + res, + userContext, + recipeInstance, + accessTokenPayload, + userId, + recipeUserId, + config, + appInfo, + sessionDataInDatabase, + tenantId, +}: { req: any; res: any; userContext: UserContext; diff --git a/lib/build/recipe/session/sessionRequestFunctions.js b/lib/build/recipe/session/sessionRequestFunctions.js index 0930ce17c..08e5f4e45 100644 --- a/lib/build/recipe/session/sessionRequestFunctions.js +++ b/lib/build/recipe/session/sessionRequestFunctions.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSessionFromRequest = getSessionFromRequest; exports.getAccessTokenFromRequest = getAccessTokenFromRequest; @@ -20,7 +22,7 @@ const accessToken_1 = require("./accessToken"); const error_1 = __importDefault(require("./error")); // We are defining this here (and not exporting it) to reduce the scope of legacy code const LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME = "sIdRefreshToken"; -async function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, options, userContext, }) { +async function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, options, userContext }) { (0, logger_1.logDebugMessage)("getSession: Started"); const configuredFramework = supertokens_1.default.getInstanceOrThrowError().framework; if (configuredFramework !== "custom") { @@ -35,7 +37,9 @@ async function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, op (0, logger_1.logDebugMessage)("getSession: Wrapping done"); // This token isn't handled by getToken to limit the scope of this legacy/migration code if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - (0, logger_1.logDebugMessage)("getSession: Throwing TRY_REFRESH_TOKEN because the request is using a legacy session"); + (0, logger_1.logDebugMessage)( + "getSession: Throwing TRY_REFRESH_TOKEN because the request is using a legacy session" + ); // This could create a spike on refresh calls during the update of the backend SDK throw new error_1.default({ message: "using legacy session, please call the refresh API", @@ -49,7 +53,12 @@ async function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, op forCreateNewSession: false, userContext, }); - const { requestTransferMethod, accessToken } = getAccessTokenFromRequest(config, req, allowedTransferMethod, userContext); + const { requestTransferMethod, accessToken } = getAccessTokenFromRequest( + config, + req, + allowedTransferMethod, + userContext + ); let antiCsrfToken = (0, cookieAndHeaders_1.getAntiCsrfTokenFromHeaders)(req); let doAntiCsrfCheck = options !== undefined ? options.antiCsrfCheck : undefined; if (doAntiCsrfCheck === undefined) { @@ -73,9 +82,12 @@ async function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, op if (doAntiCsrfCheck && antiCsrf === "VIA_CUSTOM_HEADER") { if (antiCsrf === "VIA_CUSTOM_HEADER") { if ((0, utils_2.getRidFromHeader)(req) === undefined) { - (0, logger_1.logDebugMessage)("getSession: Returning TRY_REFRESH_TOKEN because custom header (rid) was not passed"); + (0, logger_1.logDebugMessage)( + "getSession: Returning TRY_REFRESH_TOKEN because custom header (rid) was not passed" + ); throw new error_1.default({ - message: "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request, or set doAntiCsrfCheck to false for this API", + message: + "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request, or set doAntiCsrfCheck to false for this API", type: error_1.default.TRY_REFRESH_TOKEN, }); } @@ -91,22 +103,30 @@ async function getSessionFromRequest({ req, res, config, recipeInterfaceImpl, op userContext, }); if (session !== undefined) { - const claimValidators = await (0, utils_1.getRequiredClaimValidators)(session, options === null || options === void 0 ? void 0 : options.overrideGlobalClaimValidators, userContext); + const claimValidators = await (0, utils_1.getRequiredClaimValidators)( + session, + options === null || options === void 0 ? void 0 : options.overrideGlobalClaimValidators, + userContext + ); await session.assertClaims(claimValidators, userContext); // requestTransferMethod can only be undefined here if the user overridden getSession // to load the session by a custom method in that (very niche) case they also need to // override how the session is attached to the response. // In that scenario the transferMethod passed to attachToRequestResponse likely doesn't // matter, still, we follow the general fallback logic - await session.attachToRequestResponse({ - req, - res, - transferMethod: requestTransferMethod !== undefined - ? requestTransferMethod - : allowedTransferMethod !== "any" - ? allowedTransferMethod - : "header", - }, userContext); + await session.attachToRequestResponse( + { + req, + res, + transferMethod: + requestTransferMethod !== undefined + ? requestTransferMethod + : allowedTransferMethod !== "any" + ? allowedTransferMethod + : "header", + }, + userContext + ); } return session; } @@ -121,29 +141,40 @@ function getAccessTokenFromRequest(config, req, allowedTransferMethod, userConte (0, accessToken_1.validateAccessTokenStructure)(info.payload, info.version); (0, logger_1.logDebugMessage)("getSession: got access token from " + transferMethod); accessTokens[transferMethod] = info; - } - catch (_a) { - (0, logger_1.logDebugMessage)(`getSession: ignoring token in ${transferMethod}, because it doesn't match our access token structure`); + } catch (_a) { + (0, logger_1.logDebugMessage)( + `getSession: ignoring token in ${transferMethod}, because it doesn't match our access token structure` + ); } } } let requestTransferMethod; let accessToken; - if ((allowedTransferMethod === "any" || allowedTransferMethod === "header") && - accessTokens["header"] !== undefined) { + if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "header") && + accessTokens["header"] !== undefined + ) { (0, logger_1.logDebugMessage)("getSession: using header transfer method"); requestTransferMethod = "header"; accessToken = accessTokens["header"]; - } - else if ((allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && - accessTokens["cookie"] !== undefined) { + } else if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && + accessTokens["cookie"] !== undefined + ) { (0, logger_1.logDebugMessage)("getSession: using cookie transfer method"); // If multiple access tokens exist in the request cookie, throw TRY_REFRESH_TOKEN. // This prompts the client to call the refresh endpoint, clearing olderCookieDomain cookies (if set). // ensuring outdated token payload isn't used. - const hasMultipleAccessTokenCookies = (0, cookieAndHeaders_1.hasMultipleCookiesForTokenType)(config, req, "access", userContext); + const hasMultipleAccessTokenCookies = (0, cookieAndHeaders_1.hasMultipleCookiesForTokenType)( + config, + req, + "access", + userContext + ); if (hasMultipleAccessTokenCookies) { - (0, logger_1.logDebugMessage)("getSession: Throwing TRY_REFRESH_TOKEN because multiple access tokens are present in request cookies"); + (0, logger_1.logDebugMessage)( + "getSession: Throwing TRY_REFRESH_TOKEN because multiple access tokens are present in request cookies" + ); throw new error_1.default({ message: "Multiple access tokens present in the request cookies.", type: error_1.default.TRY_REFRESH_TOKEN, @@ -158,7 +189,7 @@ function getAccessTokenFromRequest(config, req, allowedTransferMethod, userConte In all cases: if sIdRefreshToken token exists (so it's a legacy session) we clear it. Check http://localhost:3002/docs/contribute/decisions/session/0008 for further details and a table of expected behaviours */ -async function refreshSessionInRequest({ res, req, userContext, config, recipeInterfaceImpl, }) { +async function refreshSessionInRequest({ res, req, userContext, config, recipeInterfaceImpl }) { (0, logger_1.logDebugMessage)("refreshSession: Started"); const configuredFramework = supertokens_1.default.getInstanceOrThrowError().framework; if (configuredFramework !== "custom") { @@ -176,7 +207,13 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn // We check all token transfer methods for available refresh tokens // We do this so that we can later clear all we are not overwriting for (const transferMethod of constants_1.availableTokenTransferMethods) { - refreshTokens[transferMethod] = (0, cookieAndHeaders_1.getToken)(config, req, "refresh", transferMethod, userContext); + refreshTokens[transferMethod] = (0, cookieAndHeaders_1.getToken)( + config, + req, + "refresh", + transferMethod, + userContext + ); if (refreshTokens[transferMethod] !== undefined) { (0, logger_1.logDebugMessage)("refreshSession: got refresh token from " + transferMethod); } @@ -189,31 +226,46 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn (0, logger_1.logDebugMessage)("refreshSession: getTokenTransferMethod returned " + allowedTransferMethod); let requestTransferMethod; let refreshToken; - if ((allowedTransferMethod === "any" || allowedTransferMethod === "header") && - refreshTokens["header"] !== undefined) { + if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "header") && + refreshTokens["header"] !== undefined + ) { (0, logger_1.logDebugMessage)("refreshSession: using header transfer method"); requestTransferMethod = "header"; refreshToken = refreshTokens["header"]; - } - else if ((allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && refreshTokens["cookie"]) { + } else if ((allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && refreshTokens["cookie"]) { (0, logger_1.logDebugMessage)("refreshSession: using cookie transfer method"); requestTransferMethod = "cookie"; refreshToken = refreshTokens["cookie"]; - } - else { + } else { // 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) { - (0, logger_1.logDebugMessage)("refreshSession: cleared legacy id refresh token because refresh token was not found"); - (0, cookieAndHeaders_1.setCookie)(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath", req, userContext); + (0, logger_1.logDebugMessage)( + "refreshSession: cleared legacy id refresh token because refresh token was not found" + ); + (0, cookieAndHeaders_1.setCookie)( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath", + req, + userContext + ); } // We need to clear the access token cookie if // - the refresh token is not found, and // - the allowedTransferMethod is 'cookie' or 'any', and // - an access token cookie exists (otherwise it'd be a no-op) // See: https://github.com/supertokens/supertokens-node/issues/790 - if ((allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && - (0, cookieAndHeaders_1.getToken)(config, req, "access", "cookie", userContext) !== undefined) { - (0, logger_1.logDebugMessage)("refreshSession: cleared all session tokens and returning UNAUTHORISED because refresh token in request is undefined"); + if ( + (allowedTransferMethod === "any" || allowedTransferMethod === "cookie") && + (0, cookieAndHeaders_1.getToken)(config, req, "access", "cookie", userContext) !== undefined + ) { + (0, logger_1.logDebugMessage)( + "refreshSession: cleared all session tokens and returning UNAUTHORISED because refresh token in request is undefined" + ); // We're clearing all session tokens instead of just the access token and then throwing an UNAUTHORISED // error with `clearTokens: false`. This approach avoids confusion and we don't want to retain session // tokens on the client in any case if the refresh API is called without a refresh token but with an access token. @@ -244,7 +296,9 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn } if (antiCsrf === "VIA_CUSTOM_HEADER" && !disableAntiCsrf) { if ((0, utils_2.getRidFromHeader)(req) === undefined) { - (0, logger_1.logDebugMessage)("refreshSession: Returning UNAUTHORISED because custom header (rid) was not passed"); + (0, logger_1.logDebugMessage)( + "refreshSession: Returning UNAUTHORISED because custom header (rid) was not passed" + ); throw new error_1.default({ message: "anti-csrf check failed. Please pass 'rid: \"session\"' header in the request.", type: error_1.default.UNAUTHORISED, @@ -263,15 +317,27 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn disableAntiCsrf, userContext, }); - } - catch (ex) { - if (error_1.default.isErrorFromSuperTokens(ex) && - (ex.type === error_1.default.TOKEN_THEFT_DETECTED || ex.payload.clearTokens === true)) { + } catch (ex) { + if ( + error_1.default.isErrorFromSuperTokens(ex) && + (ex.type === error_1.default.TOKEN_THEFT_DETECTED || ex.payload.clearTokens === true) + ) { // We clear the LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME here because we want to limit the scope of this legacy/migration code // so the token clearing functions in the error handlers do not if (req.getCookieValue(LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME) !== undefined) { - (0, logger_1.logDebugMessage)("refreshSession: cleared legacy id refresh token because refresh is clearing other tokens"); - (0, cookieAndHeaders_1.setCookie)(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath", req, userContext); + (0, logger_1.logDebugMessage)( + "refreshSession: cleared legacy id refresh token because refresh is clearing other tokens" + ); + (0, cookieAndHeaders_1.setCookie)( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath", + req, + userContext + ); } } throw ex; @@ -283,20 +349,44 @@ async function refreshSessionInRequest({ res, req, userContext, config, recipeIn (0, cookieAndHeaders_1.clearSession)(config, res, transferMethod, req, userContext); } } - await session.attachToRequestResponse({ - req, - res, - transferMethod: requestTransferMethod, - }, userContext); + await session.attachToRequestResponse( + { + req, + res, + transferMethod: requestTransferMethod, + }, + userContext + ); (0, logger_1.logDebugMessage)("refreshSession: Success!"); // 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) { (0, logger_1.logDebugMessage)("refreshSession: cleared legacy id refresh token after successful refresh"); - (0, cookieAndHeaders_1.setCookie)(config, res, LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, "", 0, "accessTokenPath", req, userContext); + (0, cookieAndHeaders_1.setCookie)( + config, + res, + LEGACY_ID_REFRESH_TOKEN_COOKIE_NAME, + "", + 0, + "accessTokenPath", + req, + userContext + ); } return session; } -async function createNewSessionInRequest({ req, res, userContext, recipeInstance, accessTokenPayload, userId, recipeUserId, config, appInfo, sessionDataInDatabase, tenantId, }) { +async function createNewSessionInRequest({ + req, + res, + userContext, + recipeInstance, + accessTokenPayload, + userId, + recipeUserId, + config, + appInfo, + sessionDataInDatabase, + tenantId, +}) { (0, logger_1.logDebugMessage)("createNewSession: Started"); const configuredFramework = supertokens_1.default.getInstanceOrThrowError().framework; if (configuredFramework !== "custom") { @@ -326,30 +416,37 @@ async function createNewSessionInRequest({ req, res, userContext, recipeInstance // We default to header if we can't "parse" it or if it's undefined if (authModeHeader === "cookie") { outputTransferMethod = authModeHeader; - } - else { + } else { outputTransferMethod = "header"; } } (0, logger_1.logDebugMessage)("createNewSession: using transfer method " + outputTransferMethod); - if (outputTransferMethod === "cookie" && + if ( + outputTransferMethod === "cookie" && config.getCookieSameSite({ request: req, userContext, }) === "none" && !config.cookieSecure && - !((appInfo.topLevelAPIDomain === "localhost" || (0, utils_2.isAnIpAddress)(appInfo.topLevelAPIDomain)) && + !( + (appInfo.topLevelAPIDomain === "localhost" || (0, utils_2.isAnIpAddress)(appInfo.topLevelAPIDomain)) && (appInfo.getTopLevelWebsiteDomain({ request: req, userContext, }) === "localhost" || - (0, utils_2.isAnIpAddress)(appInfo.getTopLevelWebsiteDomain({ - request: req, - userContext, - }))))) { + (0, utils_2.isAnIpAddress)( + appInfo.getTopLevelWebsiteDomain({ + request: req, + userContext, + }) + )) + ) + ) { // We can allow insecure cookie when both website & API domain are localhost or an IP // When either of them is a different domain, API domain needs to have https and a secure cookie to work - throw new Error("Since your API and website domain are different, for sessions to work, please use https on your apiDomain and dont set cookieSecure to false."); + throw new Error( + "Since your API and website domain are different, for sessions to work, please use https on your apiDomain and dont set cookieSecure to false." + ); } const disableAntiCsrf = outputTransferMethod === "header"; const session = await recipeInstance.recipeInterfaceImpl.createNewSession({ @@ -363,17 +460,22 @@ async function createNewSessionInRequest({ req, res, userContext, recipeInstance }); (0, logger_1.logDebugMessage)("createNewSession: Session created in core built"); for (const transferMethod of constants_1.availableTokenTransferMethods) { - if (transferMethod !== outputTransferMethod && - (0, cookieAndHeaders_1.getToken)(config, req, "access", transferMethod, userContext) !== undefined) { + if ( + transferMethod !== outputTransferMethod && + (0, cookieAndHeaders_1.getToken)(config, req, "access", transferMethod, userContext) !== undefined + ) { (0, cookieAndHeaders_1.clearSession)(config, res, transferMethod, req, userContext); } } (0, logger_1.logDebugMessage)("createNewSession: Cleared old tokens"); - await session.attachToRequestResponse({ - req, - res, - transferMethod: outputTransferMethod, - }, userContext); + await session.attachToRequestResponse( + { + req, + res, + transferMethod: outputTransferMethod, + }, + userContext + ); (0, logger_1.logDebugMessage)("createNewSession: Attached new tokens to res"); return session; } diff --git a/lib/build/recipe/session/types.d.ts b/lib/build/recipe/session/types.d.ts index 8a6a92a71..da7995030 100644 --- a/lib/build/recipe/session/types.d.ts +++ b/lib/build/recipe/session/types.d.ts @@ -58,7 +58,10 @@ export type TypeInput = { exposeAccessTokenToFrontendInCookieBasedAuth?: boolean; jwksRefreshIntervalSec?: number; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -77,10 +80,11 @@ export type TypeNormalisedInput = { getResponseHeaderNameForTokenType: (req: BaseRequest, tokenType: TokenType, userContext: UserContext) => string; sessionExpiredStatusCode: number; errorHandlers: NormalisedErrorHandlers; - antiCsrfFunctionOrString: "VIA_TOKEN" | "VIA_CUSTOM_HEADER" | "NONE" | ((input: { - request: BaseRequest | undefined; - userContext: UserContext; - }) => "VIA_CUSTOM_HEADER" | "NONE"); + antiCsrfFunctionOrString: + | "VIA_TOKEN" + | "VIA_CUSTOM_HEADER" + | "NONE" + | ((input: { request: BaseRequest | undefined; userContext: UserContext }) => "VIA_CUSTOM_HEADER" | "NONE"); getTokenTransferMethod: (input: { req: BaseRequest; forCreateNewSession: boolean; @@ -90,7 +94,10 @@ export type TypeNormalisedInput = { exposeAccessTokenToFrontendInCookieBasedAuth: boolean; jwksRefreshIntervalSec: number; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -101,10 +108,22 @@ export interface ErrorHandlerMiddleware { (message: string, request: BaseRequest, response: BaseResponse, userContext: UserContext): Promise; } export interface TokenTheftErrorHandlerMiddleware { - (sessionHandle: string, userId: string, recipeUserId: RecipeUserId, request: BaseRequest, response: BaseResponse, userContext: UserContext): Promise; + ( + sessionHandle: string, + userId: string, + recipeUserId: RecipeUserId, + request: BaseRequest, + response: BaseResponse, + userContext: UserContext + ): Promise; } export interface InvalidClaimErrorHandlerMiddleware { - (validatorErrors: ClaimValidationError[], request: BaseRequest, response: BaseResponse, userContext: UserContext): Promise; + ( + validatorErrors: ClaimValidationError[], + request: BaseRequest, + response: BaseResponse, + userContext: UserContext + ): Promise; } export interface NormalisedErrorHandlers { onUnauthorised: ErrorHandlerMiddleware; @@ -117,7 +136,11 @@ export interface VerifySessionOptions { antiCsrfCheck?: boolean; sessionRequired?: boolean; checkDatabase?: boolean; - overrideGlobalClaimValidators?: (globalClaimValidators: SessionClaimValidator[], session: SessionContainerInterface, userContext: UserContext) => Promise | SessionClaimValidator[]; + overrideGlobalClaimValidators?: ( + globalClaimValidators: SessionClaimValidator[], + session: SessionContainerInterface, + userContext: UserContext + ) => Promise | SessionClaimValidator[]; } export type RecipeInterface = { createNewSession(input: { @@ -173,14 +196,8 @@ export type RecipeInterface = { fetchAcrossAllTenants?: boolean; userContext: UserContext; }): Promise; - revokeSession(input: { - sessionHandle: string; - userContext: UserContext; - }): Promise; - revokeMultipleSessions(input: { - sessionHandles: string[]; - userContext: UserContext; - }): Promise; + revokeSession(input: { sessionHandle: string; userContext: UserContext }): Promise; + revokeMultipleSessions(input: { sessionHandles: string[]; userContext: UserContext }): Promise; updateSessionDataInDatabase(input: { sessionHandle: string; newSessionData: any; @@ -198,21 +215,24 @@ export type RecipeInterface = { accessToken: string; newAccessTokenPayload?: any; userContext: UserContext; - }): Promise<{ - status: "OK"; - session: { - handle: string; - userId: string; - recipeUserId: RecipeUserId; - userDataInJWT: any; - tenantId: string; - }; - accessToken?: { - token: string; - expiry: number; - createdTime: number; - }; - } | undefined>; + }): Promise< + | { + status: "OK"; + session: { + handle: string; + userId: string; + recipeUserId: RecipeUserId; + userDataInJWT: any; + tenantId: string; + }; + accessToken?: { + token: string; + expiry: number; + createdTime: number; + }; + } + | undefined + >; validateClaims(input: { userId: string; recipeUserId: RecipeUserId; @@ -238,17 +258,16 @@ export type RecipeInterface = { sessionHandle: string; claim: SessionClaim; userContext: UserContext; - }): Promise<{ - status: "SESSION_DOES_NOT_EXIST_ERROR"; - } | { - status: "OK"; - value: T | undefined; - }>; - removeClaim(input: { - sessionHandle: string; - claim: SessionClaim; - userContext: UserContext; - }): Promise; + }): Promise< + | { + status: "SESSION_DOES_NOT_EXIST_ERROR"; + } + | { + status: "OK"; + value: T | undefined; + } + >; + removeClaim(input: { sessionHandle: string; claim: SessionClaim; userContext: UserContext }): Promise; }; export interface SessionContainerInterface { revokeSession(userContext?: Record): Promise; @@ -291,17 +310,21 @@ export type APIInterface = { * since it's not something that is directly called by the user on the * frontend anyway */ - refreshPOST: undefined | ((input: { - options: APIOptions; - userContext: UserContext; - }) => Promise); - signOutPOST: undefined | ((input: { - options: APIOptions; - session: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - } | GeneralErrorResponse>); + refreshPOST: + | undefined + | ((input: { options: APIOptions; userContext: UserContext }) => Promise); + signOutPOST: + | undefined + | ((input: { + options: APIOptions; + session: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + } + | GeneralErrorResponse + >); verifySession(input: { verifySessionOptions: VerifySessionOptions | undefined; options: APIOptions; @@ -318,25 +341,30 @@ export type SessionInformation = { timeCreated: number; tenantId: string; }; -export type ClaimValidationResult = { - isValid: true; -} | { - isValid: false; - reason?: JSONValue; -}; +export type ClaimValidationResult = + | { + isValid: true; + } + | { + isValid: false; + reason?: JSONValue; + }; export type ClaimValidationError = { id: string; reason?: JSONValue; }; -export type SessionClaimValidator = (// We split the type like this to express that either both claim and shouldRefetch is defined or neither. -{ - claim: SessionClaim; - /** - * Decides if we need to refetch the claim value before checking the payload with `isValid`. - * E.g.: if the information in the payload is expired, or is not sufficient for this check. - */ - shouldRefetch: (payload: any, userContext: UserContext) => Promise | boolean; -} | {}) & { +export type SessionClaimValidator = ( + | // We split the type like this to express that either both claim and shouldRefetch is defined or neither. + { + claim: SessionClaim; + /** + * Decides if we need to refetch the claim value before checking the payload with `isValid`. + * E.g.: if the information in the payload is expired, or is not sufficient for this check. + */ + shouldRefetch: (payload: any, userContext: UserContext) => Promise | boolean; + } + | {} +) & { id: string; /** * Decides if the claim is valid based on the payload (and not checking DB or anything else) @@ -351,7 +379,13 @@ export declare abstract class SessionClaim { * The undefined return value signifies that we don't want to update the claim payload and or the claim value is not present in the database * This can happen for example with a second factor auth claim, where we don't want to add the claim to the session automatically. */ - abstract fetchValue(userId: string, recipeUserId: RecipeUserId, tenantId: string, currentPayload: JSONObject | undefined, userContext: UserContext): Promise | T | undefined; + abstract fetchValue( + userId: string, + recipeUserId: RecipeUserId, + tenantId: string, + currentPayload: JSONObject | undefined, + userContext: UserContext + ): Promise | T | undefined; /** * Saves the provided value into the payload, by cloning and updating the entire object. * @@ -376,7 +410,13 @@ export declare abstract class SessionClaim { * @returns Claim value */ abstract getValueFromPayload(payload: JSONObject, userContext: UserContext): T | undefined; - build(userId: string, recipeUserId: RecipeUserId, tenantId: string, currentPayload: JSONObject | undefined, userContext: UserContext): Promise; + build( + userId: string, + recipeUserId: RecipeUserId, + tenantId: string, + currentPayload: JSONObject | undefined, + userContext: UserContext + ): Promise; } export type ReqResInfo = { res: BaseResponse; diff --git a/lib/build/recipe/session/utils.d.ts b/lib/build/recipe/session/utils.d.ts index 54b2c6528..02fa11722 100644 --- a/lib/build/recipe/session/utils.d.ts +++ b/lib/build/recipe/session/utils.d.ts @@ -1,22 +1,85 @@ // @ts-nocheck -import { TypeInput, TypeNormalisedInput, ClaimValidationError, SessionClaimValidator, SessionContainerInterface, VerifySessionOptions, TokenTransferMethod, TokenType } from "./types"; +import { + TypeInput, + TypeNormalisedInput, + ClaimValidationError, + SessionClaimValidator, + SessionContainerInterface, + VerifySessionOptions, + TokenTransferMethod, + TokenType, +} from "./types"; import SessionRecipe from "./recipe"; import { NormalisedAppinfo, UserContext } from "../../types"; import type { BaseRequest, BaseResponse } from "../../framework"; import RecipeUserId from "../../recipeUserId"; -export declare function sendTryRefreshTokenResponse(recipeInstance: SessionRecipe, _: string, __: BaseRequest, response: BaseResponse, ___: UserContext): Promise; -export declare function sendUnauthorisedResponse(recipeInstance: SessionRecipe, _: string, __: BaseRequest, response: BaseResponse, ___: UserContext): Promise; -export declare function sendInvalidClaimResponse(recipeInstance: SessionRecipe, claimValidationErrors: ClaimValidationError[], __: BaseRequest, response: BaseResponse, ___: UserContext): Promise; -export declare function sendTokenTheftDetectedResponse(recipeInstance: SessionRecipe, sessionHandle: string, _: string, __: RecipeUserId, ___: BaseRequest, response: BaseResponse, userContext: UserContext): Promise; +export declare function sendTryRefreshTokenResponse( + recipeInstance: SessionRecipe, + _: string, + __: BaseRequest, + response: BaseResponse, + ___: UserContext +): Promise; +export declare function sendUnauthorisedResponse( + recipeInstance: SessionRecipe, + _: string, + __: BaseRequest, + response: BaseResponse, + ___: UserContext +): Promise; +export declare function sendInvalidClaimResponse( + recipeInstance: SessionRecipe, + claimValidationErrors: ClaimValidationError[], + __: BaseRequest, + response: BaseResponse, + ___: UserContext +): Promise; +export declare function sendTokenTheftDetectedResponse( + recipeInstance: SessionRecipe, + sessionHandle: string, + _: string, + __: RecipeUserId, + ___: BaseRequest, + response: BaseResponse, + userContext: UserContext +): Promise; export declare function normaliseSessionScopeOrThrowError(sessionScope: string): string; export declare function getURLProtocol(url: string): string; -export declare function validateAndNormaliseUserInput(recipeInstance: SessionRecipe, appInfo: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + recipeInstance: SessionRecipe, + appInfo: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; export declare function normaliseSameSiteOrThrowError(sameSite: string): "strict" | "lax" | "none"; -export declare function setAccessTokenInResponse(res: BaseResponse, accessToken: string, frontToken: string, config: TypeNormalisedInput, transferMethod: TokenTransferMethod, req: BaseRequest, userContext: UserContext): void; -export declare function getRequiredClaimValidators(session: SessionContainerInterface, overrideGlobalClaimValidators: VerifySessionOptions["overrideGlobalClaimValidators"], userContext: UserContext): Promise; -export declare function validateClaimsInPayload(claimValidators: SessionClaimValidator[], newAccessTokenPayload: any, userContext: UserContext): Promise<{ - id: string; - reason: import("../../types").JSONValue; -}[]>; -export declare function getCookieNameForTokenType(_req: BaseRequest, tokenType: TokenType): "sAccessToken" | "sRefreshToken"; -export declare function getResponseHeaderNameForTokenType(_req: BaseRequest, tokenType: TokenType): "st-access-token" | "st-refresh-token"; +export declare function setAccessTokenInResponse( + res: BaseResponse, + accessToken: string, + frontToken: string, + config: TypeNormalisedInput, + transferMethod: TokenTransferMethod, + req: BaseRequest, + userContext: UserContext +): void; +export declare function getRequiredClaimValidators( + session: SessionContainerInterface, + overrideGlobalClaimValidators: VerifySessionOptions["overrideGlobalClaimValidators"], + userContext: UserContext +): Promise; +export declare function validateClaimsInPayload( + claimValidators: SessionClaimValidator[], + newAccessTokenPayload: any, + userContext: UserContext +): Promise< + { + id: string; + reason: import("../../types").JSONValue; + }[] +>; +export declare function getCookieNameForTokenType( + _req: BaseRequest, + tokenType: TokenType +): "sAccessToken" | "sRefreshToken"; +export declare function getResponseHeaderNameForTokenType( + _req: BaseRequest, + tokenType: TokenType +): "st-access-token" | "st-refresh-token"; diff --git a/lib/build/recipe/session/utils.js b/lib/build/recipe/session/utils.js index ce146660f..20c44a3dc 100644 --- a/lib/build/recipe/session/utils.js +++ b/lib/build/recipe/session/utils.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.sendTryRefreshTokenResponse = sendTryRefreshTokenResponse; exports.sendUnauthorisedResponse = sendUnauthorisedResponse; @@ -38,10 +40,18 @@ const utils_1 = require("../../utils"); const utils_2 = require("../../utils"); const logger_1 = require("../../logger"); async function sendTryRefreshTokenResponse(recipeInstance, _, __, response, ___) { - (0, utils_2.sendNon200ResponseWithMessage)(response, "try refresh token", recipeInstance.config.sessionExpiredStatusCode); + (0, utils_2.sendNon200ResponseWithMessage)( + response, + "try refresh token", + recipeInstance.config.sessionExpiredStatusCode + ); } async function sendUnauthorisedResponse(recipeInstance, _, __, response, ___) { - (0, utils_2.sendNon200ResponseWithMessage)(response, "unauthorised", recipeInstance.config.sessionExpiredStatusCode); + (0, utils_2.sendNon200ResponseWithMessage)( + response, + "unauthorised", + recipeInstance.config.sessionExpiredStatusCode + ); } async function sendInvalidClaimResponse(recipeInstance, claimValidationErrors, __, response, ___) { (0, utils_2.sendNon200Response)(response, recipeInstance.config.invalidClaimStatusCode, { @@ -51,7 +61,11 @@ async function sendInvalidClaimResponse(recipeInstance, claimValidationErrors, _ } async function sendTokenTheftDetectedResponse(recipeInstance, sessionHandle, _, __, ___, response, userContext) { await recipeInstance.recipeInterfaceImpl.revokeSession({ sessionHandle, userContext }); - (0, utils_2.sendNon200ResponseWithMessage)(response, "token theft detected", recipeInstance.config.sessionExpiredStatusCode); + (0, utils_2.sendNon200ResponseWithMessage)( + response, + "token theft detected", + recipeInstance.config.sessionExpiredStatusCode + ); } function normaliseSessionScopeOrThrowError(sessionScope) { function helper(sessionScope) { @@ -67,8 +81,7 @@ function normaliseSessionScopeOrThrowError(sessionScope) { let urlObj = new URL(sessionScope); sessionScope = urlObj.hostname; return sessionScope; - } - catch (err) { + } catch (err) { throw new Error("Please provide a valid sessionScope"); } } @@ -87,23 +100,30 @@ function getURLProtocol(url) { } function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { var _a, _b, _c, _d, _e, _f; - let cookieDomain = config === undefined || config.cookieDomain === undefined - ? undefined - : normaliseSessionScopeOrThrowError(config.cookieDomain); - let olderCookieDomain = config === undefined || config.olderCookieDomain === undefined || config.olderCookieDomain === "" - ? config === null || config === void 0 ? void 0 : config.olderCookieDomain - : normaliseSessionScopeOrThrowError(config.olderCookieDomain); - let accessTokenPath = config === undefined || config.accessTokenPath === undefined - ? new normalisedURLPath_1.default("/") - : new normalisedURLPath_1.default(config.accessTokenPath); + let cookieDomain = + config === undefined || config.cookieDomain === undefined + ? undefined + : normaliseSessionScopeOrThrowError(config.cookieDomain); + let olderCookieDomain = + config === undefined || config.olderCookieDomain === undefined || config.olderCookieDomain === "" + ? config === null || config === void 0 + ? void 0 + : config.olderCookieDomain + : normaliseSessionScopeOrThrowError(config.olderCookieDomain); + let accessTokenPath = + config === undefined || config.accessTokenPath === undefined + ? new normalisedURLPath_1.default("/") + : new normalisedURLPath_1.default(config.accessTokenPath); let protocolOfAPIDomain = getURLProtocol(appInfo.apiDomain.getAsStringDangerous()); let cookieSameSite = (input) => { - let protocolOfWebsiteDomain = getURLProtocol(appInfo - .getOrigin({ - request: input.request, - userContext: input.userContext, - }) - .getAsStringDangerous()); + let protocolOfWebsiteDomain = getURLProtocol( + appInfo + .getOrigin({ + request: input.request, + userContext: input.userContext, + }) + .getAsStringDangerous() + ); return appInfo.topLevelAPIDomain !== appInfo.getTopLevelWebsiteDomain(input) || protocolOfAPIDomain !== protocolOfWebsiteDomain ? "none" @@ -113,11 +133,16 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { let normalisedCookieSameSite = normaliseSameSiteOrThrowError(config.cookieSameSite); cookieSameSite = () => normalisedCookieSameSite; } - let cookieSecure = config === undefined || config.cookieSecure === undefined - ? appInfo.apiDomain.getAsStringDangerous().startsWith("https") - : config.cookieSecure; - let sessionExpiredStatusCode = config === undefined || config.sessionExpiredStatusCode === undefined ? 401 : config.sessionExpiredStatusCode; - const invalidClaimStatusCode = (_a = config === null || config === void 0 ? void 0 : config.invalidClaimStatusCode) !== null && _a !== void 0 ? _a : 403; + let cookieSecure = + config === undefined || config.cookieSecure === undefined + ? appInfo.apiDomain.getAsStringDangerous().startsWith("https") + : config.cookieSecure; + let sessionExpiredStatusCode = + config === undefined || config.sessionExpiredStatusCode === undefined ? 401 : config.sessionExpiredStatusCode; + const invalidClaimStatusCode = + (_a = config === null || config === void 0 ? void 0 : config.invalidClaimStatusCode) !== null && _a !== void 0 + ? _a + : 403; if (sessionExpiredStatusCode === invalidClaimStatusCode) { throw new Error("sessionExpiredStatusCode and sessionExpiredStatusCode must be different"); } @@ -126,7 +151,7 @@ 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 }) => { const sameSite = cookieSameSite({ request, userContext, @@ -141,7 +166,15 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { } let errorHandlers = { onTokenTheftDetected: async (sessionHandle, userId, recipeUserId, request, response, userContext) => { - return await sendTokenTheftDetectedResponse(recipeInstance, sessionHandle, userId, recipeUserId, request, response, userContext); + return await sendTokenTheftDetectedResponse( + recipeInstance, + sessionHandle, + userId, + recipeUserId, + request, + response, + userContext + ); }, onTryRefreshToken: async (message, request, response, userContext) => { return await sendTryRefreshTokenResponse(recipeInstance, message, request, response, userContext); @@ -173,17 +206,41 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { errorHandlers.onClearDuplicateSessionCookies = config.errorHandlers.onClearDuplicateSessionCookies; } } - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { - useDynamicAccessTokenSigningKey: (_b = config === null || config === void 0 ? void 0 : config.useDynamicAccessTokenSigningKey) !== null && _b !== void 0 ? _b : true, - exposeAccessTokenToFrontendInCookieBasedAuth: (_c = config === null || config === void 0 ? void 0 : config.exposeAccessTokenToFrontendInCookieBasedAuth) !== null && _c !== void 0 ? _c : false, + useDynamicAccessTokenSigningKey: + (_b = config === null || config === void 0 ? void 0 : config.useDynamicAccessTokenSigningKey) !== null && + _b !== void 0 + ? _b + : true, + exposeAccessTokenToFrontendInCookieBasedAuth: + (_c = + config === null || config === void 0 ? void 0 : config.exposeAccessTokenToFrontendInCookieBasedAuth) !== + null && _c !== void 0 + ? _c + : false, refreshTokenPath: appInfo.apiBasePath.appendPath(new normalisedURLPath_1.default(constants_1.REFRESH_API_PATH)), accessTokenPath, - getTokenTransferMethod: (config === null || config === void 0 ? void 0 : config.getTokenTransferMethod) === undefined - ? defaultGetTokenTransferMethod - : config.getTokenTransferMethod, - getCookieNameForTokenType: (_d = config === null || config === void 0 ? void 0 : config.getCookieNameForTokenType) !== null && _d !== void 0 ? _d : getCookieNameForTokenType, - getResponseHeaderNameForTokenType: (_e = config === null || config === void 0 ? void 0 : config.getResponseHeaderNameForTokenType) !== null && _e !== void 0 ? _e : getResponseHeaderNameForTokenType, + getTokenTransferMethod: + (config === null || config === void 0 ? void 0 : config.getTokenTransferMethod) === undefined + ? defaultGetTokenTransferMethod + : config.getTokenTransferMethod, + getCookieNameForTokenType: + (_d = config === null || config === void 0 ? void 0 : config.getCookieNameForTokenType) !== null && + _d !== void 0 + ? _d + : getCookieNameForTokenType, + getResponseHeaderNameForTokenType: + (_e = config === null || config === void 0 ? void 0 : config.getResponseHeaderNameForTokenType) !== null && + _e !== void 0 + ? _e + : getResponseHeaderNameForTokenType, cookieDomain, olderCookieDomain, getCookieSameSite: cookieSameSite, @@ -193,7 +250,11 @@ function validateAndNormaliseUserInput(recipeInstance, appInfo, config) { antiCsrfFunctionOrString: antiCsrf, override, invalidClaimStatusCode, - jwksRefreshIntervalSec: (_f = config === null || config === void 0 ? void 0 : config.jwksRefreshIntervalSec) !== null && _f !== void 0 ? _f : 3600 * 4, + jwksRefreshIntervalSec: + (_f = config === null || config === void 0 ? void 0 : config.jwksRefreshIntervalSec) !== null && + _f !== void 0 + ? _f + : 3600 * 4, }; } function normaliseSameSiteOrThrowError(sameSite) { @@ -206,30 +267,50 @@ function normaliseSameSiteOrThrowError(sameSite) { } function setAccessTokenInResponse(res, accessToken, frontToken, config, transferMethod, req, userContext) { (0, cookieAndHeaders_1.setFrontTokenInHeaders)(res, frontToken); - (0, cookieAndHeaders_1.setToken)(config, res, "access", accessToken, - // We set the expiration to 1 year, because we can't really access the expiration of the refresh token everywhere we are setting it. - // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. - // Even if the token is expired the presence of the token indicates that the user could have a valid refresh token - // Some browsers now cap the maximum expiry at 400 days, so we set it to 1 year, which should suffice. - Date.now() + constants_1.oneYearInMs, transferMethod, req, userContext); - if (config.exposeAccessTokenToFrontendInCookieBasedAuth && transferMethod === "cookie") { - (0, cookieAndHeaders_1.setToken)(config, res, "access", accessToken, - // We set the expiration to 1 years, because we can't really access the expiration of the refresh token everywhere we are setting it. + (0, cookieAndHeaders_1.setToken)( + config, + res, + "access", + accessToken, + // We set the expiration to 1 year, because we can't really access the expiration of the refresh token everywhere we are setting it. // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. // Even if the token is expired the presence of the token indicates that the user could have a valid refresh token // Some browsers now cap the maximum expiry at 400 days, so we set it to 1 year, which should suffice. - Date.now() + constants_1.oneYearInMs, "header", req, userContext); + Date.now() + constants_1.oneYearInMs, + transferMethod, + req, + userContext + ); + if (config.exposeAccessTokenToFrontendInCookieBasedAuth && transferMethod === "cookie") { + (0, cookieAndHeaders_1.setToken)( + config, + res, + "access", + accessToken, + // We set the expiration to 1 years, because we can't really access the expiration of the refresh token everywhere we are setting it. + // This should be safe to do, since this is only the validity of the cookie (set here or on the frontend) but we check the expiration of the JWT anyway. + // Even if the token is expired the presence of the token indicates that the user could have a valid refresh token + // Some browsers now cap the maximum expiry at 400 days, so we set it to 1 year, which should suffice. + Date.now() + constants_1.oneYearInMs, + "header", + req, + userContext + ); } } async function getRequiredClaimValidators(session, overrideGlobalClaimValidators, userContext) { - const claimValidatorsAddedByOtherRecipes = recipe_1.default.getInstanceOrThrowError().getClaimValidatorsAddedByOtherRecipes(); - const globalClaimValidators = await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.getGlobalClaimValidators({ - userId: session.getUserId(userContext), - recipeUserId: session.getRecipeUserId(userContext), - tenantId: session.getTenantId(userContext), - claimValidatorsAddedByOtherRecipes, - userContext, - }); + const claimValidatorsAddedByOtherRecipes = recipe_1.default + .getInstanceOrThrowError() + .getClaimValidatorsAddedByOtherRecipes(); + const globalClaimValidators = await recipe_1.default + .getInstanceOrThrowError() + .recipeInterfaceImpl.getGlobalClaimValidators({ + userId: session.getUserId(userContext), + recipeUserId: session.getRecipeUserId(userContext), + tenantId: session.getTenantId(userContext), + claimValidatorsAddedByOtherRecipes, + userContext, + }); return overrideGlobalClaimValidators !== undefined ? await overrideGlobalClaimValidators(globalClaimValidators, session, userContext) : globalClaimValidators; @@ -238,7 +319,9 @@ async function validateClaimsInPayload(claimValidators, newAccessTokenPayload, u const validationErrors = []; for (const validator of claimValidators) { const claimValidationResult = await validator.validate(newAccessTokenPayload, userContext); - (0, logger_1.logDebugMessage)("validateClaimsInPayload " + validator.id + " validation res " + JSON.stringify(claimValidationResult)); + (0, logger_1.logDebugMessage)( + "validateClaimsInPayload " + validator.id + " validation res " + JSON.stringify(claimValidationResult) + ); if (!claimValidationResult.isValid) { validationErrors.push({ id: validator.id, @@ -248,7 +331,7 @@ async function validateClaimsInPayload(claimValidators, newAccessTokenPayload, u } return validationErrors; } -function defaultGetTokenTransferMethod({ req, forCreateNewSession, }) { +function defaultGetTokenTransferMethod({ req, forCreateNewSession }) { // We allow fallback (checking headers then cookies) by default when validating if (!forCreateNewSession) { return "any"; diff --git a/lib/build/recipe/thirdparty/api/appleRedirect.d.ts b/lib/build/recipe/thirdparty/api/appleRedirect.d.ts index e1011ab6d..ae0e54770 100644 --- a/lib/build/recipe/thirdparty/api/appleRedirect.d.ts +++ b/lib/build/recipe/thirdparty/api/appleRedirect.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function appleRedirectHandler(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function appleRedirectHandler( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/thirdparty/api/authorisationUrl.d.ts b/lib/build/recipe/thirdparty/api/authorisationUrl.d.ts index 95ae35f51..dac53edea 100644 --- a/lib/build/recipe/thirdparty/api/authorisationUrl.d.ts +++ b/lib/build/recipe/thirdparty/api/authorisationUrl.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function authorisationUrlAPI(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function authorisationUrlAPI( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/thirdparty/api/authorisationUrl.js b/lib/build/recipe/thirdparty/api/authorisationUrl.js index 5703c5b1b..f0f68f532 100644 --- a/lib/build/recipe/thirdparty/api/authorisationUrl.js +++ b/lib/build/recipe/thirdparty/api/authorisationUrl.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = authorisationUrlAPI; const utils_1 = require("../../../utils"); diff --git a/lib/build/recipe/thirdparty/api/implementation.js b/lib/build/recipe/thirdparty/api/implementation.js index f67550fd9..89684ce03 100644 --- a/lib/build/recipe/thirdparty/api/implementation.js +++ b/lib/build/recipe/thirdparty/api/implementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIInterface; const emailverification_1 = __importDefault(require("../../emailverification")); @@ -20,13 +22,19 @@ function getAPIInterface() { }, signInUpPOST: async function (input) { const errorCodeMap = { - SIGN_UP_NOT_ALLOWED: "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_006)", - SIGN_IN_NOT_ALLOWED: "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_004)", + SIGN_UP_NOT_ALLOWED: + "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_006)", + SIGN_IN_NOT_ALLOWED: + "Cannot sign in / up due to security reasons. Please try a different login method or contact support. (ERR_CODE_004)", LINKING_TO_SESSION_USER_FAILED: { - EMAIL_VERIFICATION_REQUIRED: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_020)", - RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_021)", - ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_022)", - SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_023)", + EMAIL_VERIFICATION_REQUIRED: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_020)", + RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_021)", + ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_022)", + SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR: + "Cannot sign in / up due to security reasons. Please contact support. (ERR_CODE_023)", }, }; const { provider, tenantId, options, userContext } = input; @@ -36,11 +44,9 @@ function getAPIInterface() { redirectURIInfo: input.redirectURIInfo, userContext, }); - } - else if ("oAuthTokens" in input && input.oAuthTokens !== undefined) { + } else if ("oAuthTokens" in input && input.oAuthTokens !== undefined) { oAuthTokensToUse = input.oAuthTokens; - } - else { + } else { throw Error("should never come here"); } const userInfo = await provider.getUserInfo({ oAuthTokens: oAuthTokensToUse, userContext }); @@ -65,19 +71,21 @@ function getAPIInterface() { // We essentially did this above when calling exchangeAuthCodeForOAuthTokens return true; }; - const authenticatingUser = await authUtils_1.AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired({ - accountInfo: { - thirdParty: { - userId: userInfo.thirdPartyUserId, - id: provider.id, + const authenticatingUser = await authUtils_1.AuthUtils.getAuthenticatingUserAndAddToCurrentTenantIfRequired( + { + accountInfo: { + thirdParty: { + userId: userInfo.thirdPartyUserId, + id: provider.id, + }, }, - }, - recipeId, - userContext: input.userContext, - session: input.session, - tenantId, - checkCredentialsOnTenant, - }); + recipeId, + userContext: input.userContext, + session: input.session, + tenantId, + checkCredentialsOnTenant, + } + ); const isSignUp = authenticatingUser === undefined; if (authenticatingUser !== undefined) { // This is a sign in. So before we proceed, we need to check if an email change @@ -92,7 +100,11 @@ function getAPIInterface() { // So we just check that as well before calling isEmailChangeAllowed const recipeUserId = authenticatingUser.loginMethod.recipeUserId; if (!emailInfo.isVerified && recipe_1.default.getInstance() !== undefined) { - emailInfo.isVerified = await emailverification_1.default.isEmailVerified(recipeUserId, emailInfo.id, userContext); + emailInfo.isVerified = await emailverification_1.default.isEmailVerified( + recipeUserId, + emailInfo.id, + userContext + ); } } const preAuthChecks = await authUtils_1.AuthUtils.preAuthChecks({ @@ -104,7 +116,8 @@ function getAPIInterface() { id: provider.id, }, }, - authenticatingUser: authenticatingUser === null || authenticatingUser === void 0 ? void 0 : authenticatingUser.user, + authenticatingUser: + authenticatingUser === null || authenticatingUser === void 0 ? void 0 : authenticatingUser.user, factorIds: ["thirdparty"], isSignUp, isVerified: emailInfo.isVerified, @@ -120,10 +133,16 @@ function getAPIInterface() { shouldTryLinkingWithSessionUser: input.shouldTryLinkingWithSessionUser, }); if (preAuthChecks.status !== "OK") { - (0, logger_1.logDebugMessage)("signInUpPOST: erroring out because preAuthChecks returned " + preAuthChecks.status); + (0, logger_1.logDebugMessage)( + "signInUpPOST: erroring out because preAuthChecks returned " + preAuthChecks.status + ); // On the frontend, this should show a UI of asking the user // to login using a different method. - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(preAuthChecks, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + preAuthChecks, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } let response = await options.recipeImplementation.signInUp({ thirdPartyId: provider.id, @@ -142,8 +161,14 @@ function getAPIInterface() { return response; } if (response.status !== "OK") { - (0, logger_1.logDebugMessage)("signInUpPOST: erroring out because signInUp returned " + response.status); - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(response, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + (0, logger_1.logDebugMessage)( + "signInUpPOST: erroring out because signInUp returned " + response.status + ); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + response, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } // Here we do these checks after sign in is done cause: // - We first want to check if the credentials are correct first or not @@ -163,8 +188,14 @@ function getAPIInterface() { session: input.session, }); if (postAuthChecks.status !== "OK") { - (0, logger_1.logDebugMessage)("signInUpPOST: erroring out because postAuthChecks returned " + postAuthChecks.status); - return authUtils_1.AuthUtils.getErrorStatusResponseWithReason(postAuthChecks, errorCodeMap, "SIGN_IN_UP_NOT_ALLOWED"); + (0, logger_1.logDebugMessage)( + "signInUpPOST: erroring out because postAuthChecks returned " + postAuthChecks.status + ); + return authUtils_1.AuthUtils.getErrorStatusResponseWithReason( + postAuthChecks, + errorCodeMap, + "SIGN_IN_UP_NOT_ALLOWED" + ); } return { status: "OK", diff --git a/lib/build/recipe/thirdparty/api/signinup.d.ts b/lib/build/recipe/thirdparty/api/signinup.d.ts index 0415d8bdc..06f84bb63 100644 --- a/lib/build/recipe/thirdparty/api/signinup.d.ts +++ b/lib/build/recipe/thirdparty/api/signinup.d.ts @@ -1,4 +1,9 @@ // @ts-nocheck import { APIInterface, APIOptions } from "../"; import { UserContext } from "../../../types"; -export default function signInUpAPI(apiImplementation: APIInterface, tenantId: string, options: APIOptions, userContext: UserContext): Promise; +export default function signInUpAPI( + apiImplementation: APIInterface, + tenantId: string, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/thirdparty/api/signinup.js b/lib/build/recipe/thirdparty/api/signinup.js index f9d0b71db..ecf9310bf 100644 --- a/lib/build/recipe/thirdparty/api/signinup.js +++ b/lib/build/recipe/thirdparty/api/signinup.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = signInUpAPI; const error_1 = __importDefault(require("../error")); @@ -44,11 +46,9 @@ async function signInUpAPI(apiImplementation, tenantId, options, userContext) { }); } redirectURIInfo = bodyParams.redirectURIInfo; - } - else if (bodyParams.oAuthTokens !== undefined) { + } else if (bodyParams.oAuthTokens !== undefined) { oAuthTokens = bodyParams.oAuthTokens; - } - else { + } else { throw new error_1.default({ type: error_1.default.BAD_INPUT_ERROR, message: "Please provide one of redirectURIInfo or oAuthTokens in the request body", @@ -67,8 +67,16 @@ async function signInUpAPI(apiImplementation, tenantId, options, userContext) { }); } const provider = providerResponse; - const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)(options.req, bodyParams); - const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded(options.req, options.res, shouldTryLinkingWithSessionUser, userContext); + const shouldTryLinkingWithSessionUser = (0, utils_1.getNormalisedShouldTryLinkingWithSessionUserFlag)( + options.req, + bodyParams + ); + const session = await authUtils_1.AuthUtils.loadSessionInAuthAPIIfNeeded( + options.req, + options.res, + shouldTryLinkingWithSessionUser, + userContext + ); if (session !== undefined) { tenantId = session.getTenantId(); } @@ -83,9 +91,14 @@ async function signInUpAPI(apiImplementation, tenantId, options, userContext) { userContext, }); if (result.status === "OK") { - (0, utils_1.send200Response)(options.res, Object.assign({ status: result.status }, (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext))); - } - else { + (0, utils_1.send200Response)( + options.res, + Object.assign( + { status: result.status }, + (0, utils_1.getBackwardsCompatibleUserInfo)(options.req, result, userContext) + ) + ); + } else { (0, utils_1.send200Response)(options.res, result); } return true; diff --git a/lib/build/recipe/thirdparty/error.d.ts b/lib/build/recipe/thirdparty/error.d.ts index c65582222..89e4828d2 100644 --- a/lib/build/recipe/thirdparty/error.d.ts +++ b/lib/build/recipe/thirdparty/error.d.ts @@ -1,14 +1,8 @@ // @ts-nocheck import STError from "../../error"; export default class ThirdPartyError extends STError { - constructor(options: { - type: "BAD_INPUT_ERROR"; - message: string; - }); + constructor(options: { type: "BAD_INPUT_ERROR"; message: string }); } export declare class ClientTypeNotFoundError extends STError { - constructor(options: { - type: "CLIENT_TYPE_NOT_FOUND_ERROR"; - message: string; - }); + constructor(options: { type: "CLIENT_TYPE_NOT_FOUND_ERROR"; message: string }); } diff --git a/lib/build/recipe/thirdparty/error.js b/lib/build/recipe/thirdparty/error.js index 3624b9ffc..8e62fdaab 100644 --- a/lib/build/recipe/thirdparty/error.js +++ b/lib/build/recipe/thirdparty/error.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClientTypeNotFoundError = void 0; const error_1 = __importDefault(require("../../error")); diff --git a/lib/build/recipe/thirdparty/index.d.ts b/lib/build/recipe/thirdparty/index.d.ts index 3e318201b..8fdd56cac 100644 --- a/lib/build/recipe/thirdparty/index.d.ts +++ b/lib/build/recipe/thirdparty/index.d.ts @@ -8,34 +8,68 @@ import RecipeUserId from "../../recipeUserId"; export default class Wrapper { static init: typeof Recipe.init; static Error: typeof SuperTokensError; - static getProvider(tenantId: string, thirdPartyId: string, clientType: string | undefined, userContext?: Record): Promise; - static manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session?: undefined, userContext?: Record): Promise<{ - status: "OK"; - createdNewRecipeUser: boolean; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; - reason: string; - } | { - status: "SIGN_IN_UP_NOT_ALLOWED"; - reason: string; - }>; - static manuallyCreateOrUpdateUser(tenantId: string, thirdPartyId: string, thirdPartyUserId: string, email: string, isVerified: boolean, session: SessionContainerInterface, userContext?: Record): Promise<{ - status: "OK"; - createdNewRecipeUser: boolean; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; - reason: string; - } | { - status: "SIGN_IN_UP_NOT_ALLOWED"; - reason: string; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + static getProvider( + tenantId: string, + thirdPartyId: string, + clientType: string | undefined, + userContext?: Record + ): Promise; + static manuallyCreateOrUpdateUser( + tenantId: string, + thirdPartyId: string, + thirdPartyUserId: string, + email: string, + isVerified: boolean, + session?: undefined, + userContext?: Record + ): Promise< + | { + status: "OK"; + createdNewRecipeUser: boolean; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } + | { + status: "SIGN_IN_UP_NOT_ALLOWED"; + reason: string; + } + >; + static manuallyCreateOrUpdateUser( + tenantId: string, + thirdPartyId: string, + thirdPartyUserId: string, + email: string, + isVerified: boolean, + session: SessionContainerInterface, + userContext?: Record + ): Promise< + | { + status: "OK"; + createdNewRecipeUser: boolean; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } + | { + status: "SIGN_IN_UP_NOT_ALLOWED"; + reason: string; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; } export declare let init: typeof Recipe.init; export declare let Error: typeof SuperTokensError; diff --git a/lib/build/recipe/thirdparty/index.js b/lib/build/recipe/thirdparty/index.js index 9f6c4bb7a..338aa0b14 100644 --- a/lib/build/recipe/thirdparty/index.js +++ b/lib/build/recipe/thirdparty/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.manuallyCreateOrUpdateUser = exports.getProvider = exports.Error = exports.init = void 0; const recipe_1 = __importDefault(require("./recipe")); @@ -31,7 +33,15 @@ class Wrapper { userContext: (0, utils_1.getUserContext)(userContext), }); } - static async manuallyCreateOrUpdateUser(tenantId, thirdPartyId, thirdPartyUserId, email, isVerified, session, userContext) { + static async manuallyCreateOrUpdateUser( + tenantId, + thirdPartyId, + thirdPartyUserId, + email, + isVerified, + session, + userContext + ) { return await recipe_1.default.getInstanceOrThrowError().recipeInterfaceImpl.manuallyCreateOrUpdateUser({ thirdPartyId, thirdPartyUserId, diff --git a/lib/build/recipe/thirdparty/providers/activeDirectory.js b/lib/build/recipe/thirdparty/providers/activeDirectory.js index 6d8507017..622561f25 100644 --- a/lib/build/recipe/thirdparty/providers/activeDirectory.js +++ b/lib/build/recipe/thirdparty/providers/activeDirectory.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = ActiveDirectory; const custom_1 = __importDefault(require("./custom")); @@ -34,7 +36,9 @@ function ActiveDirectory(input) { } if (config.oidcDiscoveryEndpoint !== undefined) { // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)(config.oidcDiscoveryEndpoint); + config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)( + config.oidcDiscoveryEndpoint + ); } if (config.scope === undefined) { config.scope = ["openid", "email"]; diff --git a/lib/build/recipe/thirdparty/providers/apple.js b/lib/build/recipe/thirdparty/providers/apple.js index 418fa109a..c64e67f37 100644 --- a/lib/build/recipe/thirdparty/providers/apple.js +++ b/lib/build/recipe/thirdparty/providers/apple.js @@ -13,39 +13,58 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Apple; const custom_1 = __importStar(require("./custom")); @@ -70,7 +89,10 @@ function Apple(input) { if (input.config.oidcDiscoveryEndpoint === undefined) { input.config.oidcDiscoveryEndpoint = "https://appleid.apple.com/.well-known/openid-configuration"; } - input.config.authorizationEndpointQueryParams = Object.assign({ response_mode: "form_post" }, input.config.authorizationEndpointQueryParams); + input.config.authorizationEndpointQueryParams = Object.assign( + { response_mode: "form_post" }, + input.config.authorizationEndpointQueryParams + ); const oOverride = input.override; input.override = function (originalImplementation) { const oGetConfig = originalImplementation.getConfigForClientType; @@ -80,16 +102,27 @@ function Apple(input) { config.scope = ["openid", "email"]; } if (config.clientSecret === undefined) { - if (config.additionalConfig === undefined || + if ( + config.additionalConfig === undefined || config.additionalConfig.keyId === undefined || config.additionalConfig.teamId === undefined || - config.additionalConfig.privateKey === undefined) { - throw new Error("Please ensure that keyId, teamId and privateKey are provided in the additionalConfig"); + config.additionalConfig.privateKey === undefined + ) { + throw new Error( + "Please ensure that keyId, teamId and privateKey are provided in the additionalConfig" + ); } - config.clientSecret = await getClientSecret(config.clientId, config.additionalConfig.keyId, config.additionalConfig.teamId, config.additionalConfig.privateKey); + config.clientSecret = await getClientSecret( + config.clientId, + config.additionalConfig.keyId, + config.additionalConfig.teamId, + config.additionalConfig.privateKey + ); } // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)(config.oidcDiscoveryEndpoint); + config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)( + config.oidcDiscoveryEndpoint + ); return config; }; const oExchangeAuthCodeForOAuthTokens = originalImplementation.exchangeAuthCodeForOAuthTokens; @@ -99,8 +132,7 @@ function Apple(input) { if (user !== undefined) { if (typeof user === "string") { response.user = JSON.parse(user); - } - else if (typeof user === "object") { + } else if (typeof user === "object") { response.user = user; } } @@ -113,10 +145,35 @@ function Apple(input) { const user = input.oAuthTokens.user; if (user !== undefined) { if (typeof user === "string") { - response.rawUserInfoFromProvider = Object.assign(Object.assign({}, response.rawUserInfoFromProvider), { fromIdTokenPayload: Object.assign(Object.assign({}, (_a = response.rawUserInfoFromProvider) === null || _a === void 0 ? void 0 : _a.fromIdTokenPayload), { user: JSON.parse(user) }) }); - } - else if (typeof user === "object") { - response.rawUserInfoFromProvider = Object.assign(Object.assign({}, response.rawUserInfoFromProvider), { fromIdTokenPayload: Object.assign(Object.assign({}, (_b = response.rawUserInfoFromProvider) === null || _b === void 0 ? void 0 : _b.fromIdTokenPayload), { user }) }); + response.rawUserInfoFromProvider = Object.assign( + Object.assign({}, response.rawUserInfoFromProvider), + { + fromIdTokenPayload: Object.assign( + Object.assign( + {}, + (_a = response.rawUserInfoFromProvider) === null || _a === void 0 + ? void 0 + : _a.fromIdTokenPayload + ), + { user: JSON.parse(user) } + ), + } + ); + } else if (typeof user === "object") { + response.rawUserInfoFromProvider = Object.assign( + Object.assign({}, response.rawUserInfoFromProvider), + { + fromIdTokenPayload: Object.assign( + Object.assign( + {}, + (_b = response.rawUserInfoFromProvider) === null || _b === void 0 + ? void 0 + : _b.fromIdTokenPayload + ), + { user } + ), + } + ); } } return response; diff --git a/lib/build/recipe/thirdparty/providers/bitbucket.js b/lib/build/recipe/thirdparty/providers/bitbucket.js index 9b3f5e4aa..6b97bb1ce 100644 --- a/lib/build/recipe/thirdparty/providers/bitbucket.js +++ b/lib/build/recipe/thirdparty/providers/bitbucket.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Bitbucket; const thirdpartyUtils_1 = require("../../../thirdpartyUtils"); @@ -58,16 +60,32 @@ function Bitbucket(input) { fromUserInfoAPI: {}, fromIdTokenPayload: {}, }; - const userInfoFromAccessToken = await (0, thirdpartyUtils_1.doGetRequest)("https://api.bitbucket.org/2.0/user", undefined, headers); + const userInfoFromAccessToken = await (0, thirdpartyUtils_1.doGetRequest)( + "https://api.bitbucket.org/2.0/user", + undefined, + headers + ); if (userInfoFromAccessToken.status >= 400) { - (0, logger_1.logDebugMessage)(`Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}`); - throw new Error(`Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}`); + (0, logger_1.logDebugMessage)( + `Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}` + ); + throw new Error( + `Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}` + ); } rawUserInfoFromProvider.fromUserInfoAPI = userInfoFromAccessToken.jsonResponse; - const userInfoFromEmail = await (0, thirdpartyUtils_1.doGetRequest)("https://api.bitbucket.org/2.0/user/emails", undefined, headers); + const userInfoFromEmail = await (0, thirdpartyUtils_1.doGetRequest)( + "https://api.bitbucket.org/2.0/user/emails", + undefined, + headers + ); if (userInfoFromEmail.status >= 400) { - (0, logger_1.logDebugMessage)(`Received response with status ${userInfoFromEmail.status} and body ${userInfoFromEmail.stringResponse}`); - throw new Error(`Received response with status ${userInfoFromEmail.status} and body ${userInfoFromEmail.stringResponse}`); + (0, logger_1.logDebugMessage)( + `Received response with status ${userInfoFromEmail.status} and body ${userInfoFromEmail.stringResponse}` + ); + throw new Error( + `Received response with status ${userInfoFromEmail.status} and body ${userInfoFromEmail.stringResponse}` + ); } rawUserInfoFromProvider.fromUserInfoAPI.email = userInfoFromEmail.jsonResponse; let email = undefined; @@ -80,12 +98,13 @@ function Bitbucket(input) { } return { thirdPartyUserId: rawUserInfoFromProvider.fromUserInfoAPI.uuid, - email: email === undefined - ? undefined - : { - id: email, - isVerified, - }, + email: + email === undefined + ? undefined + : { + id: email, + isVerified, + }, rawUserInfoFromProvider, }; }; diff --git a/lib/build/recipe/thirdparty/providers/boxySaml.js b/lib/build/recipe/thirdparty/providers/boxySaml.js index ce867aea6..30fc682e8 100644 --- a/lib/build/recipe/thirdparty/providers/boxySaml.js +++ b/lib/build/recipe/thirdparty/providers/boxySaml.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = BoxySAML; const custom_1 = __importDefault(require("./custom")); @@ -24,7 +26,12 @@ function BoxySAML(input) { if (input.config.name === undefined) { input.config.name = "SAML"; } - input.config.userInfoMap = Object.assign(Object.assign({}, input.config.userInfoMap), { fromUserInfoAPI: Object.assign({ userId: "id", email: "email" }, (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI) }); + input.config.userInfoMap = Object.assign(Object.assign({}, input.config.userInfoMap), { + fromUserInfoAPI: Object.assign( + { userId: "id", email: "email" }, + (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI + ), + }); const oOverride = input.override; input.override = function (originalImplementation) { const oGetConfig = originalImplementation.getConfigForClientType; diff --git a/lib/build/recipe/thirdparty/providers/configUtils.d.ts b/lib/build/recipe/thirdparty/providers/configUtils.d.ts index 5ec42b1ab..c4e9bbe88 100644 --- a/lib/build/recipe/thirdparty/providers/configUtils.d.ts +++ b/lib/build/recipe/thirdparty/providers/configUtils.d.ts @@ -1,7 +1,25 @@ // @ts-nocheck import { UserContext } from "../../../types"; -import { ProviderClientConfig, ProviderConfig, ProviderConfigForClientType, ProviderInput, TypeProvider } from "../types"; -export declare function getProviderConfigForClient(providerConfig: ProviderConfig, clientConfig: ProviderClientConfig): ProviderConfigForClientType; -export declare function findAndCreateProviderInstance(providers: ProviderInput[], thirdPartyId: string, clientType: string | undefined, userContext: UserContext): Promise; +import { + ProviderClientConfig, + ProviderConfig, + ProviderConfigForClientType, + ProviderInput, + TypeProvider, +} from "../types"; +export declare function getProviderConfigForClient( + providerConfig: ProviderConfig, + clientConfig: ProviderClientConfig +): ProviderConfigForClientType; +export declare function findAndCreateProviderInstance( + providers: ProviderInput[], + thirdPartyId: string, + clientType: string | undefined, + userContext: UserContext +): Promise; export declare function mergeConfig(staticConfig: ProviderConfig, coreConfig: ProviderConfig): ProviderConfig; -export declare function mergeProvidersFromCoreAndStatic(providerConfigsFromCore: ProviderConfig[], providerInputsFromStatic: ProviderInput[], includeAllProviders: boolean): ProviderInput[]; +export declare function mergeProvidersFromCoreAndStatic( + providerConfigsFromCore: ProviderConfig[], + providerInputsFromStatic: ProviderInput[], + includeAllProviders: boolean +): ProviderInput[]; diff --git a/lib/build/recipe/thirdparty/providers/configUtils.js b/lib/build/recipe/thirdparty/providers/configUtils.js index ab43a6900..830afb4b6 100644 --- a/lib/build/recipe/thirdparty/providers/configUtils.js +++ b/lib/build/recipe/thirdparty/providers/configUtils.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getProviderConfigForClient = getProviderConfigForClient; exports.findAndCreateProviderInstance = findAndCreateProviderInstance; @@ -36,41 +38,29 @@ function createProvider(input) { const clonedInput = Object.assign({}, input); if (clonedInput.config.thirdPartyId.startsWith("active-directory")) { return (0, _1.ActiveDirectory)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("apple")) { + } else if (clonedInput.config.thirdPartyId.startsWith("apple")) { return (0, _1.Apple)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("bitbucket")) { + } else if (clonedInput.config.thirdPartyId.startsWith("bitbucket")) { return (0, _1.Bitbucket)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("discord")) { + } else if (clonedInput.config.thirdPartyId.startsWith("discord")) { return (0, _1.Discord)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("facebook")) { + } else if (clonedInput.config.thirdPartyId.startsWith("facebook")) { return (0, _1.Facebook)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("github")) { + } else if (clonedInput.config.thirdPartyId.startsWith("github")) { return (0, _1.Github)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("gitlab")) { + } else if (clonedInput.config.thirdPartyId.startsWith("gitlab")) { return (0, _1.Gitlab)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("google-workspaces")) { + } else if (clonedInput.config.thirdPartyId.startsWith("google-workspaces")) { return (0, _1.GoogleWorkspaces)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("google")) { + } else if (clonedInput.config.thirdPartyId.startsWith("google")) { return (0, _1.Google)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("okta")) { + } else if (clonedInput.config.thirdPartyId.startsWith("okta")) { return (0, _1.Okta)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("linkedin")) { + } else if (clonedInput.config.thirdPartyId.startsWith("linkedin")) { return (0, _1.Linkedin)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("twitter")) { + } else if (clonedInput.config.thirdPartyId.startsWith("twitter")) { return (0, _1.Twitter)(clonedInput); - } - else if (clonedInput.config.thirdPartyId.startsWith("boxy-saml")) { + } else if (clonedInput.config.thirdPartyId.startsWith("boxy-saml")) { return (0, _1.BoxySAML)(clonedInput); } return (0, custom_1.default)(clonedInput); @@ -87,18 +77,31 @@ async function findAndCreateProviderInstance(providers, thirdPartyId, clientType } function mergeConfig(staticConfig, coreConfig) { var _a, _b, _c, _d; - const result = Object.assign(Object.assign(Object.assign({}, staticConfig), coreConfig), { userInfoMap: { - fromIdTokenPayload: Object.assign(Object.assign({}, (_a = staticConfig.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromIdTokenPayload), (_b = coreConfig.userInfoMap) === null || _b === void 0 ? void 0 : _b.fromIdTokenPayload), - fromUserInfoAPI: Object.assign(Object.assign({}, (_c = staticConfig.userInfoMap) === null || _c === void 0 ? void 0 : _c.fromUserInfoAPI), (_d = coreConfig.userInfoMap) === null || _d === void 0 ? void 0 : _d.fromUserInfoAPI), - } }); + const result = Object.assign(Object.assign(Object.assign({}, staticConfig), coreConfig), { + userInfoMap: { + fromIdTokenPayload: Object.assign( + Object.assign( + {}, + (_a = staticConfig.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromIdTokenPayload + ), + (_b = coreConfig.userInfoMap) === null || _b === void 0 ? void 0 : _b.fromIdTokenPayload + ), + fromUserInfoAPI: Object.assign( + Object.assign( + {}, + (_c = staticConfig.userInfoMap) === null || _c === void 0 ? void 0 : _c.fromUserInfoAPI + ), + (_d = coreConfig.userInfoMap) === null || _d === void 0 ? void 0 : _d.fromUserInfoAPI + ), + }, + }); const mergedClients = staticConfig.clients === undefined ? [] : [...staticConfig.clients]; const coreConfigClients = coreConfig.clients === undefined ? [] : coreConfig.clients; for (const client of coreConfigClients) { const index = mergedClients.findIndex((c) => c.clientType === client.clientType); if (index === -1) { mergedClients.push(client); - } - else { + } else { mergedClients[index] = Object.assign({}, client); } } @@ -108,11 +111,12 @@ function mergeConfig(staticConfig, coreConfig) { function mergeProvidersFromCoreAndStatic(providerConfigsFromCore, providerInputsFromStatic, includeAllProviders) { const mergedProviders = []; if (providerConfigsFromCore.length === 0) { - for (const config of providerInputsFromStatic.filter((config) => config.includeInNonPublicTenantsByDefault === true || includeAllProviders === true)) { + for (const config of providerInputsFromStatic.filter( + (config) => config.includeInNonPublicTenantsByDefault === true || includeAllProviders === true + )) { mergedProviders.push(config); } - } - else { + } else { for (const providerConfigFromCore of providerConfigsFromCore) { let mergedProviderInput = { config: providerConfigFromCore, diff --git a/lib/build/recipe/thirdparty/providers/custom.js b/lib/build/recipe/thirdparty/providers/custom.js index ef09264bf..b5a1255e0 100644 --- a/lib/build/recipe/thirdparty/providers/custom.js +++ b/lib/build/recipe/thirdparty/providers/custom.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DEV_OAUTH_REDIRECT_URL = void 0; exports.isUsingDevelopmentClientId = isUsingDevelopmentClientId; @@ -46,14 +48,27 @@ function accessField(obj, key) { function getSupertokensUserInfoResultFromRawUserInfo(config, rawUserInfoResponse) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m; let thirdPartyUserId = ""; - if (((_b = (_a = config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI) === null || _b === void 0 ? void 0 : _b.userId) !== undefined) { + if ( + ((_b = (_a = config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI) === null || + _b === void 0 + ? void 0 + : _b.userId) !== undefined + ) { const userId = accessField(rawUserInfoResponse.fromUserInfoAPI, config.userInfoMap.fromUserInfoAPI.userId); if (userId !== undefined) { thirdPartyUserId = userId; } } - if (((_d = (_c = config.userInfoMap) === null || _c === void 0 ? void 0 : _c.fromIdTokenPayload) === null || _d === void 0 ? void 0 : _d.userId) !== undefined) { - const userId = accessField(rawUserInfoResponse.fromIdTokenPayload, config.userInfoMap.fromIdTokenPayload.userId); + if ( + ((_d = (_c = config.userInfoMap) === null || _c === void 0 ? void 0 : _c.fromIdTokenPayload) === null || + _d === void 0 + ? void 0 + : _d.userId) !== undefined + ) { + const userId = accessField( + rawUserInfoResponse.fromIdTokenPayload, + config.userInfoMap.fromIdTokenPayload.userId + ); if (userId !== undefined) { thirdPartyUserId = userId; } @@ -65,14 +80,27 @@ function getSupertokensUserInfoResultFromRawUserInfo(config, rawUserInfoResponse thirdPartyUserId, }; let email = ""; - if (((_f = (_e = config.userInfoMap) === null || _e === void 0 ? void 0 : _e.fromUserInfoAPI) === null || _f === void 0 ? void 0 : _f.email) !== undefined) { + if ( + ((_f = (_e = config.userInfoMap) === null || _e === void 0 ? void 0 : _e.fromUserInfoAPI) === null || + _f === void 0 + ? void 0 + : _f.email) !== undefined + ) { const emailVal = accessField(rawUserInfoResponse.fromUserInfoAPI, config.userInfoMap.fromUserInfoAPI.email); if (emailVal !== undefined) { email = emailVal; } } - if (((_h = (_g = config.userInfoMap) === null || _g === void 0 ? void 0 : _g.fromIdTokenPayload) === null || _h === void 0 ? void 0 : _h.email) !== undefined) { - const emailVal = accessField(rawUserInfoResponse.fromIdTokenPayload, config.userInfoMap.fromIdTokenPayload.email); + if ( + ((_h = (_g = config.userInfoMap) === null || _g === void 0 ? void 0 : _g.fromIdTokenPayload) === null || + _h === void 0 + ? void 0 + : _h.email) !== undefined + ) { + const emailVal = accessField( + rawUserInfoResponse.fromIdTokenPayload, + config.userInfoMap.fromIdTokenPayload.email + ); if (emailVal !== undefined) { email = emailVal; } @@ -82,14 +110,30 @@ function getSupertokensUserInfoResultFromRawUserInfo(config, rawUserInfoResponse id: email, isVerified: false, }; - if (((_k = (_j = config.userInfoMap) === null || _j === void 0 ? void 0 : _j.fromUserInfoAPI) === null || _k === void 0 ? void 0 : _k.emailVerified) !== undefined) { - const emailVerifiedVal = accessField(rawUserInfoResponse.fromUserInfoAPI, config.userInfoMap.fromUserInfoAPI.emailVerified); + if ( + ((_k = (_j = config.userInfoMap) === null || _j === void 0 ? void 0 : _j.fromUserInfoAPI) === null || + _k === void 0 + ? void 0 + : _k.emailVerified) !== undefined + ) { + const emailVerifiedVal = accessField( + rawUserInfoResponse.fromUserInfoAPI, + config.userInfoMap.fromUserInfoAPI.emailVerified + ); result.email.isVerified = emailVerifiedVal === true || - (typeof emailVerifiedVal === "string" && emailVerifiedVal.toLowerCase() === "true"); + (typeof emailVerifiedVal === "string" && emailVerifiedVal.toLowerCase() === "true"); } - if (((_m = (_l = config.userInfoMap) === null || _l === void 0 ? void 0 : _l.fromIdTokenPayload) === null || _m === void 0 ? void 0 : _m.emailVerified) !== undefined) { - const emailVerifiedVal = accessField(rawUserInfoResponse.fromIdTokenPayload, config.userInfoMap.fromIdTokenPayload.emailVerified); + if ( + ((_m = (_l = config.userInfoMap) === null || _l === void 0 ? void 0 : _l.fromIdTokenPayload) === null || + _m === void 0 + ? void 0 + : _m.emailVerified) !== undefined + ) { + const emailVerifiedVal = accessField( + rawUserInfoResponse.fromIdTokenPayload, + config.userInfoMap.fromIdTokenPayload.emailVerified + ); result.email.isVerified = emailVerifiedVal === true || emailVerifiedVal === "true"; } } @@ -100,8 +144,14 @@ function NewProvider(input) { // These are safe defaults common to most providers. Each provider implementations override these // as necessary input.config.userInfoMap = { - fromIdTokenPayload: Object.assign({ userId: "sub", email: "email", emailVerified: "email_verified" }, (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromIdTokenPayload), - fromUserInfoAPI: Object.assign({ userId: "sub", email: "email", emailVerified: "email_verified" }, (_b = input.config.userInfoMap) === null || _b === void 0 ? void 0 : _b.fromUserInfoAPI), + fromIdTokenPayload: Object.assign( + { userId: "sub", email: "email", emailVerified: "email_verified" }, + (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromIdTokenPayload + ), + fromUserInfoAPI: Object.assign( + { userId: "sub", email: "email", emailVerified: "email_verified" }, + (_b = input.config.userInfoMap) === null || _b === void 0 ? void 0 : _b.fromUserInfoAPI + ), }; if (input.config.generateFakeEmail === undefined) { input.config.generateFakeEmail = async function ({ thirdPartyUserId }) { @@ -148,8 +198,7 @@ function NewProvider(input) { for (const [key, value] of Object.entries(impl.config.authorizationEndpointQueryParams)) { if (value === null) { delete queryParams[key]; - } - else { + } else { queryParams[key] = value; } } @@ -194,8 +243,7 @@ function NewProvider(input) { for (const key in impl.config.tokenEndpointBodyParams) { if (impl.config.tokenEndpointBodyParams[key] === null) { delete accessTokenAPIParams[key]; - } - else { + } else { accessTokenAPIParams[key] = impl.config.tokenEndpointBodyParams[key]; } } @@ -207,8 +255,12 @@ function NewProvider(input) { /* Transformation needed for dev keys END */ const tokenResponse = await (0, thirdpartyUtils_1.doPostRequest)(tokenAPIURL, accessTokenAPIParams); if (tokenResponse.status >= 400) { - (0, logger_1.logDebugMessage)(`Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}`); - throw new Error(`Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}`); + (0, logger_1.logDebugMessage)( + `Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}` + ); + throw new Error( + `Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}` + ); } return tokenResponse.jsonResponse; }, @@ -223,7 +275,8 @@ function NewProvider(input) { if (jwks === undefined) { jwks = (0, jose_1.createRemoteJWKSet)(new URL(impl.config.jwksURI)); } - rawUserInfoFromProvider.fromIdTokenPayload = await (0, thirdpartyUtils_1.verifyIdTokenFromJWKSEndpointAndGetPayload)(idToken, jwks, { + rawUserInfoFromProvider.fromIdTokenPayload = await (0, + thirdpartyUtils_1.verifyIdTokenFromJWKSEndpointAndGetPayload)(idToken, jwks, { audience: getActualClientIdFromDevelopmentClientId(impl.config.clientId), }); if (impl.config.validateIdTokenPayload !== undefined) { @@ -250,8 +303,7 @@ function NewProvider(input) { for (const [key, value] of Object.entries(impl.config.userInfoEndpointHeaders)) { if (value === null) { delete headers[key]; - } - else { + } else { headers[key] = value; } } @@ -260,16 +312,23 @@ function NewProvider(input) { for (const [key, value] of Object.entries(impl.config.userInfoEndpointQueryParams)) { if (value === null) { delete queryParams[key]; - } - else { + } else { queryParams[key] = value; } } } - const userInfoFromAccessToken = await (0, thirdpartyUtils_1.doGetRequest)(impl.config.userInfoEndpoint, queryParams, headers); + const userInfoFromAccessToken = await (0, thirdpartyUtils_1.doGetRequest)( + impl.config.userInfoEndpoint, + queryParams, + headers + ); if (userInfoFromAccessToken.status >= 400) { - (0, logger_1.logDebugMessage)(`Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}`); - throw new Error(`Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}`); + (0, logger_1.logDebugMessage)( + `Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}` + ); + throw new Error( + `Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}` + ); } rawUserInfoFromProvider.fromUserInfoAPI = userInfoFromAccessToken.jsonResponse; } diff --git a/lib/build/recipe/thirdparty/providers/discord.js b/lib/build/recipe/thirdparty/providers/discord.js index 67c75f88a..070e96da6 100644 --- a/lib/build/recipe/thirdparty/providers/discord.js +++ b/lib/build/recipe/thirdparty/providers/discord.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Discord; const custom_1 = __importDefault(require("./custom")); @@ -19,7 +21,12 @@ function Discord(input) { if (input.config.userInfoEndpoint === undefined) { input.config.userInfoEndpoint = "https://discord.com/api/users/@me"; } - input.config.userInfoMap = Object.assign(Object.assign({}, input.config.userInfoMap), { fromUserInfoAPI: Object.assign({ userId: "id", email: "email", emailVerified: "verified" }, (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI) }); + input.config.userInfoMap = Object.assign(Object.assign({}, input.config.userInfoMap), { + fromUserInfoAPI: Object.assign( + { userId: "id", email: "email", emailVerified: "verified" }, + (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI + ), + }); const oOverride = input.override; input.override = function (originalImplementation) { const oGetConfig = originalImplementation.getConfigForClientType; diff --git a/lib/build/recipe/thirdparty/providers/facebook.js b/lib/build/recipe/thirdparty/providers/facebook.js index d89074447..bb1d8f04f 100644 --- a/lib/build/recipe/thirdparty/providers/facebook.js +++ b/lib/build/recipe/thirdparty/providers/facebook.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Facebook; const custom_1 = __importDefault(require("./custom")); @@ -19,7 +21,12 @@ function Facebook(input) { if (input.config.userInfoEndpoint === undefined) { input.config.userInfoEndpoint = "https://graph.facebook.com/me"; } - input.config.userInfoMap = Object.assign(Object.assign({}, input.config.userInfoMap), { fromUserInfoAPI: Object.assign({ userId: "id" }, (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI) }); + input.config.userInfoMap = Object.assign(Object.assign({}, input.config.userInfoMap), { + fromUserInfoAPI: Object.assign( + { userId: "id" }, + (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI + ), + }); const oOverride = input.override; input.override = function (originalImplementation) { const oGetConfig = originalImplementation.getConfigForClientType; @@ -57,9 +64,27 @@ function Facebook(input) { user_age_range: ["age_range"], }; const scopeValues = originalImplementation.config.scope; - const fields = (_a = scopeValues === null || scopeValues === void 0 ? void 0 : scopeValues.map((scopeValue) => { var _a; return (_a = fieldsPermissionMap[scopeValue]) !== null && _a !== void 0 ? _a : []; }).flat().join(",")) !== null && _a !== void 0 ? _a : "id,email"; - originalImplementation.config.userInfoEndpointQueryParams = Object.assign({ access_token: input.oAuthTokens.access_token, fields, format: "json" }, originalImplementation.config.userInfoEndpointQueryParams); - originalImplementation.config.userInfoEndpointHeaders = Object.assign(Object.assign({}, originalImplementation.config.userInfoEndpointHeaders), { Authorization: null }); + const fields = + (_a = + scopeValues === null || scopeValues === void 0 + ? void 0 + : scopeValues + .map((scopeValue) => { + var _a; + return (_a = fieldsPermissionMap[scopeValue]) !== null && _a !== void 0 ? _a : []; + }) + .flat() + .join(",")) !== null && _a !== void 0 + ? _a + : "id,email"; + originalImplementation.config.userInfoEndpointQueryParams = Object.assign( + { access_token: input.oAuthTokens.access_token, fields, format: "json" }, + originalImplementation.config.userInfoEndpointQueryParams + ); + originalImplementation.config.userInfoEndpointHeaders = Object.assign( + Object.assign({}, originalImplementation.config.userInfoEndpointHeaders), + { Authorization: null } + ); return await oGetUserInfo(input); }; if (oOverride !== undefined) { diff --git a/lib/build/recipe/thirdparty/providers/github.js b/lib/build/recipe/thirdparty/providers/github.js index e51ac03fa..ae1ce1078 100644 --- a/lib/build/recipe/thirdparty/providers/github.js +++ b/lib/build/recipe/thirdparty/providers/github.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Github; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -55,18 +57,26 @@ function Github(input) { } if (input.config.validateAccessToken === undefined) { input.config.validateAccessToken = async ({ accessToken, clientConfig }) => { - const basicAuthToken = (0, utils_1.encodeBase64)(`${clientConfig.clientId}:${clientConfig.clientSecret === undefined ? "" : clientConfig.clientSecret}`); - const applicationResponse = await (0, thirdpartyUtils_1.doPostRequest)(`https://api.github.com/applications/${clientConfig.clientId}/token`, { - access_token: accessToken, - }, { - Authorization: `Basic ${basicAuthToken}`, - "Content-Type": "application/json", - }); + const basicAuthToken = (0, utils_1.encodeBase64)( + `${clientConfig.clientId}:${clientConfig.clientSecret === undefined ? "" : clientConfig.clientSecret}` + ); + const applicationResponse = await (0, thirdpartyUtils_1.doPostRequest)( + `https://api.github.com/applications/${clientConfig.clientId}/token`, + { + access_token: accessToken, + }, + { + Authorization: `Basic ${basicAuthToken}`, + "Content-Type": "application/json", + } + ); if (applicationResponse.status !== 200) { throw new Error("Invalid access token"); } - if (applicationResponse.jsonResponse.app === undefined || - applicationResponse.jsonResponse.app.client_id !== clientConfig.clientId) { + if ( + applicationResponse.jsonResponse.app === undefined || + applicationResponse.jsonResponse.app.client_id !== clientConfig.clientId + ) { throw new Error("Access token does not belong to your application"); } }; @@ -87,12 +97,22 @@ function Github(input) { Accept: "application/vnd.github.v3+json", }; const rawResponse = {}; - const emailInfoResp = await (0, thirdpartyUtils_1.doGetRequest)("https://api.github.com/user/emails", undefined, headers); + const emailInfoResp = await (0, thirdpartyUtils_1.doGetRequest)( + "https://api.github.com/user/emails", + undefined, + headers + ); if (emailInfoResp.status >= 400) { - throw new Error(`Getting userInfo failed with ${emailInfoResp.status}: ${emailInfoResp.stringResponse}`); + throw new Error( + `Getting userInfo failed with ${emailInfoResp.status}: ${emailInfoResp.stringResponse}` + ); } rawResponse.emails = emailInfoResp.jsonResponse; - const userInfoResp = await (0, thirdpartyUtils_1.doGetRequest)("https://api.github.com/user", undefined, headers); + const userInfoResp = await (0, thirdpartyUtils_1.doGetRequest)( + "https://api.github.com/user", + undefined, + headers + ); if (userInfoResp.status >= 400) { throw new Error(`Getting userInfo failed with ${userInfoResp.status}: ${userInfoResp.stringResponse}`); } diff --git a/lib/build/recipe/thirdparty/providers/gitlab.js b/lib/build/recipe/thirdparty/providers/gitlab.js index 99d480738..3a3462d02 100644 --- a/lib/build/recipe/thirdparty/providers/gitlab.js +++ b/lib/build/recipe/thirdparty/providers/gitlab.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Gitlab; const normalisedURLDomain_1 = __importDefault(require("../../../normalisedURLDomain")); @@ -39,12 +41,13 @@ function Gitlab(input) { const oidcDomain = new normalisedURLDomain_1.default(config.additionalConfig.gitlabBaseUrl); const oidcPath = new normalisedURLPath_1.default("/.well-known/openid-configuration"); config.oidcDiscoveryEndpoint = oidcDomain.getAsStringDangerous() + oidcPath.getAsStringDangerous(); - } - else if (config.oidcDiscoveryEndpoint === undefined) { + } else if (config.oidcDiscoveryEndpoint === undefined) { config.oidcDiscoveryEndpoint = "https://gitlab.com/.well-known/openid-configuration"; } // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)(config.oidcDiscoveryEndpoint); + config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)( + config.oidcDiscoveryEndpoint + ); return config; }; if (oOverride !== undefined) { diff --git a/lib/build/recipe/thirdparty/providers/google.js b/lib/build/recipe/thirdparty/providers/google.js index e7fa8d6d9..d645b01f7 100644 --- a/lib/build/recipe/thirdparty/providers/google.js +++ b/lib/build/recipe/thirdparty/providers/google.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Google; const custom_1 = __importDefault(require("./custom")); @@ -13,7 +15,10 @@ function Google(input) { if (input.config.oidcDiscoveryEndpoint === undefined) { input.config.oidcDiscoveryEndpoint = "https://accounts.google.com/.well-known/openid-configuration"; } - input.config.authorizationEndpointQueryParams = Object.assign({ included_grant_scopes: "true", access_type: "offline" }, input.config.authorizationEndpointQueryParams); + input.config.authorizationEndpointQueryParams = Object.assign( + { included_grant_scopes: "true", access_type: "offline" }, + input.config.authorizationEndpointQueryParams + ); const oOverride = input.override; input.override = function (originalImplementation) { const oGetConfig = originalImplementation.getConfigForClientType; @@ -23,7 +28,9 @@ function Google(input) { config.scope = ["openid", "email"]; } // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)(config.oidcDiscoveryEndpoint); + config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)( + config.oidcDiscoveryEndpoint + ); return config; }; if (oOverride !== undefined) { diff --git a/lib/build/recipe/thirdparty/providers/googleWorkspaces.js b/lib/build/recipe/thirdparty/providers/googleWorkspaces.js index ec0a97e80..c8a14360d 100644 --- a/lib/build/recipe/thirdparty/providers/googleWorkspaces.js +++ b/lib/build/recipe/thirdparty/providers/googleWorkspaces.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = GoogleWorkspaces; const google_1 = __importDefault(require("./google")); @@ -12,22 +14,35 @@ function GoogleWorkspaces(input) { if (input.config.validateIdTokenPayload === undefined) { input.config.validateIdTokenPayload = async function (input) { var _a, _b, _c; - if (((_a = input.clientConfig.additionalConfig) === null || _a === void 0 ? void 0 : _a.hd) !== undefined && - ((_b = input.clientConfig.additionalConfig) === null || _b === void 0 ? void 0 : _b.hd) !== "*") { - if (((_c = input.clientConfig.additionalConfig) === null || _c === void 0 ? void 0 : _c.hd) !== input.idTokenPayload.hd) { - throw new Error("the value for hd claim in the id token does not match the value provided in the config"); + if ( + ((_a = input.clientConfig.additionalConfig) === null || _a === void 0 ? void 0 : _a.hd) !== undefined && + ((_b = input.clientConfig.additionalConfig) === null || _b === void 0 ? void 0 : _b.hd) !== "*" + ) { + if ( + ((_c = input.clientConfig.additionalConfig) === null || _c === void 0 ? void 0 : _c.hd) !== + input.idTokenPayload.hd + ) { + throw new Error( + "the value for hd claim in the id token does not match the value provided in the config" + ); } } }; } - input.config.authorizationEndpointQueryParams = Object.assign({ included_grant_scopes: "true", access_type: "offline" }, input.config.authorizationEndpointQueryParams); + input.config.authorizationEndpointQueryParams = Object.assign( + { included_grant_scopes: "true", access_type: "offline" }, + input.config.authorizationEndpointQueryParams + ); const oOverride = input.override; input.override = function (originalImplementation) { const oGetConfig = originalImplementation.getConfigForClientType; originalImplementation.getConfigForClientType = async function (input) { const config = await oGetConfig(input); config.additionalConfig = Object.assign({ hd: "*" }, config.additionalConfig); - config.authorizationEndpointQueryParams = Object.assign(Object.assign({}, config.authorizationEndpointQueryParams), { hd: config.additionalConfig.hd }); + config.authorizationEndpointQueryParams = Object.assign( + Object.assign({}, config.authorizationEndpointQueryParams), + { hd: config.additionalConfig.hd } + ); return config; }; if (oOverride !== undefined) { diff --git a/lib/build/recipe/thirdparty/providers/index.js b/lib/build/recipe/thirdparty/providers/index.js index 869c34251..345d7f130 100644 --- a/lib/build/recipe/thirdparty/providers/index.js +++ b/lib/build/recipe/thirdparty/providers/index.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Twitter = exports.Gitlab = exports.Bitbucket = exports.Okta = exports.Linkedin = exports.GoogleWorkspaces = exports.Google = exports.Github = exports.Facebook = exports.Discord = exports.Apple = exports.BoxySAML = exports.ActiveDirectory = void 0; const activeDirectory_1 = __importDefault(require("./activeDirectory")); diff --git a/lib/build/recipe/thirdparty/providers/linkedin.js b/lib/build/recipe/thirdparty/providers/linkedin.js index 2caead1b8..e504ff128 100644 --- a/lib/build/recipe/thirdparty/providers/linkedin.js +++ b/lib/build/recipe/thirdparty/providers/linkedin.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Linkedin; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -55,11 +57,19 @@ function Linkedin(input) { fromIdTokenPayload: {}, }; // https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2?context=linkedin%2Fconsumer%2Fcontext#sample-api-response - const userInfoFromAccessToken = await (0, thirdpartyUtils_1.doGetRequest)("https://api.linkedin.com/v2/userinfo", undefined, headers); + const userInfoFromAccessToken = await (0, thirdpartyUtils_1.doGetRequest)( + "https://api.linkedin.com/v2/userinfo", + undefined, + headers + ); rawUserInfoFromProvider.fromUserInfoAPI = userInfoFromAccessToken.jsonResponse; if (userInfoFromAccessToken.status >= 400) { - (0, logger_1.logDebugMessage)(`Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}`); - throw new Error(`Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}`); + (0, logger_1.logDebugMessage)( + `Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}` + ); + throw new Error( + `Received response with status ${userInfoFromAccessToken.status} and body ${userInfoFromAccessToken.stringResponse}` + ); } return { thirdPartyUserId: rawUserInfoFromProvider.fromUserInfoAPI.sub, diff --git a/lib/build/recipe/thirdparty/providers/okta.js b/lib/build/recipe/thirdparty/providers/okta.js index df7b11fc1..dd1b9f97f 100644 --- a/lib/build/recipe/thirdparty/providers/okta.js +++ b/lib/build/recipe/thirdparty/providers/okta.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Okta; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -38,7 +40,9 @@ function Okta(input) { } if (config.oidcDiscoveryEndpoint !== undefined) { // The config could be coming from core where we didn't add the well-known previously - config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)(config.oidcDiscoveryEndpoint); + config.oidcDiscoveryEndpoint = (0, utils_1.normaliseOIDCEndpointToIncludeWellKnown)( + config.oidcDiscoveryEndpoint + ); } if (config.scope === undefined) { config.scope = ["openid", "email"]; diff --git a/lib/build/recipe/thirdparty/providers/twitter.js b/lib/build/recipe/thirdparty/providers/twitter.js index a981c5a2b..c78adeb33 100644 --- a/lib/build/recipe/thirdparty/providers/twitter.js +++ b/lib/build/recipe/thirdparty/providers/twitter.js @@ -1,37 +1,56 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Twitter; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. @@ -69,7 +88,15 @@ function Twitter(input) { if (input.config.requireEmail === undefined) { input.config.requireEmail = false; } - input.config.userInfoMap = Object.assign({ fromUserInfoAPI: Object.assign({ userId: "data.id" }, (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI) }, input.config.userInfoMap); + input.config.userInfoMap = Object.assign( + { + fromUserInfoAPI: Object.assign( + { userId: "data.id" }, + (_a = input.config.userInfoMap) === null || _a === void 0 ? void 0 : _a.fromUserInfoAPI + ), + }, + input.config.userInfoMap + ); const oOverride = input.override; input.override = function (originalImplementation) { const oGetConfig = originalImplementation.getConfigForClientType; @@ -89,18 +116,39 @@ function Twitter(input) { // We need to do this because we don't call the original implementation /* Transformation needed for dev keys BEGIN */ if ((0, custom_1.isUsingDevelopmentClientId)(originalImplementation.config.clientId)) { - clientId = (0, custom_1.getActualClientIdFromDevelopmentClientId)(originalImplementation.config.clientId); + clientId = (0, custom_1.getActualClientIdFromDevelopmentClientId)( + originalImplementation.config.clientId + ); redirectUri = custom_1.DEV_OAUTH_REDIRECT_URL; } /* Transformation needed for dev keys END */ - const basicAuthToken = (0, utils_1.encodeBase64)(`${clientId}:${originalImplementation.config.clientSecret}`); - const twitterOauthTokenParams = Object.assign({ grant_type: "authorization_code", client_id: clientId, code_verifier: input.redirectURIInfo.pkceCodeVerifier, redirect_uri: redirectUri, code: input.redirectURIInfo.redirectURIQueryParams.code }, originalImplementation.config.tokenEndpointBodyParams); - const tokenResponse = await (0, thirdpartyUtils_1.doPostRequest)(originalImplementation.config.tokenEndpoint, twitterOauthTokenParams, { - Authorization: `Basic ${basicAuthToken}`, - }); + const basicAuthToken = (0, utils_1.encodeBase64)( + `${clientId}:${originalImplementation.config.clientSecret}` + ); + const twitterOauthTokenParams = Object.assign( + { + grant_type: "authorization_code", + client_id: clientId, + code_verifier: input.redirectURIInfo.pkceCodeVerifier, + redirect_uri: redirectUri, + code: input.redirectURIInfo.redirectURIQueryParams.code, + }, + originalImplementation.config.tokenEndpointBodyParams + ); + const tokenResponse = await (0, thirdpartyUtils_1.doPostRequest)( + originalImplementation.config.tokenEndpoint, + twitterOauthTokenParams, + { + Authorization: `Basic ${basicAuthToken}`, + } + ); if (tokenResponse.status >= 400) { - (0, logger_1.logDebugMessage)(`Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}`); - throw new Error(`Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}`); + (0, logger_1.logDebugMessage)( + `Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}` + ); + throw new Error( + `Received response with status ${tokenResponse.status} and body ${tokenResponse.stringResponse}` + ); } return tokenResponse.jsonResponse; }; diff --git a/lib/build/recipe/thirdparty/providers/utils.d.ts b/lib/build/recipe/thirdparty/providers/utils.d.ts index 8121bfb8f..e09a4d2bc 100644 --- a/lib/build/recipe/thirdparty/providers/utils.d.ts +++ b/lib/build/recipe/thirdparty/providers/utils.d.ts @@ -1,24 +1,36 @@ // @ts-nocheck import * as jose from "jose"; import { ProviderConfigForClientType } from "../types"; -export declare function doGetRequest(url: string, queryParams?: { - [key: string]: string; -}, headers?: { - [key: string]: string; -}): Promise<{ +export declare function doGetRequest( + url: string, + queryParams?: { + [key: string]: string; + }, + headers?: { + [key: string]: string; + } +): Promise<{ jsonResponse: Record | undefined; status: number; stringResponse: string; }>; -export declare function doPostRequest(url: string, params: { - [key: string]: any; -}, headers?: { - [key: string]: string; -}): Promise<{ +export declare function doPostRequest( + url: string, + params: { + [key: string]: any; + }, + headers?: { + [key: string]: string; + } +): Promise<{ jsonResponse: Record | undefined; status: number; stringResponse: string; }>; -export declare function verifyIdTokenFromJWKSEndpointAndGetPayload(idToken: string, jwks: jose.JWTVerifyGetKey, otherOptions: jose.JWTVerifyOptions): Promise; +export declare function verifyIdTokenFromJWKSEndpointAndGetPayload( + idToken: string, + jwks: jose.JWTVerifyGetKey, + otherOptions: jose.JWTVerifyOptions +): Promise; export declare function discoverOIDCEndpoints(config: ProviderConfigForClientType): Promise; export declare function normaliseOIDCEndpointToIncludeWellKnown(url: string): string; diff --git a/lib/build/recipe/thirdparty/providers/utils.js b/lib/build/recipe/thirdparty/providers/utils.js index c0c50ecff..8706c9606 100644 --- a/lib/build/recipe/thirdparty/providers/utils.js +++ b/lib/build/recipe/thirdparty/providers/utils.js @@ -1,40 +1,61 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.doGetRequest = doGetRequest; exports.doPostRequest = doPostRequest; @@ -48,7 +69,9 @@ const normalisedURLPath_1 = __importDefault(require("../../../normalisedURLPath" const logger_1 = require("../../../logger"); const utils_1 = require("../../../utils"); async function doGetRequest(url, queryParams, headers) { - (0, logger_1.logDebugMessage)(`GET request to ${url}, with query params ${JSON.stringify(queryParams)} and headers ${JSON.stringify(headers)}`); + (0, logger_1.logDebugMessage)( + `GET request to ${url}, with query params ${JSON.stringify(queryParams)} and headers ${JSON.stringify(headers)}` + ); if ((headers === null || headers === void 0 ? void 0 : headers["Accept"]) === undefined) { headers = Object.assign(Object.assign({}, headers), { Accept: "application/json" }); } @@ -75,7 +98,9 @@ async function doPostRequest(url, params, headers) { } headers["Content-Type"] = "application/x-www-form-urlencoded"; headers["Accept"] = "application/json"; // few providers like github don't send back json response by default - (0, logger_1.logDebugMessage)(`POST request to ${url}, with params ${JSON.stringify(params)} and headers ${JSON.stringify(headers)}`); + (0, logger_1.logDebugMessage)( + `POST request to ${url}, with params ${JSON.stringify(params)} and headers ${JSON.stringify(headers)}` + ); const body = new URLSearchParams(params).toString(); let response = await (0, utils_1.doFetch)(url, { method: "POST", @@ -123,7 +148,9 @@ function normaliseOIDCEndpointToIncludeWellKnown(url) { const normalisedDomain = new normalisedURLDomain_1.default(url); const normalisedPath = new normalisedURLPath_1.default(url); const normalisedWellKnownPath = new normalisedURLPath_1.default("/.well-known/openid-configuration"); - return (normalisedDomain.getAsStringDangerous() + + return ( + normalisedDomain.getAsStringDangerous() + normalisedPath.getAsStringDangerous() + - normalisedWellKnownPath.getAsStringDangerous()); + normalisedWellKnownPath.getAsStringDangerous() + ); } diff --git a/lib/build/recipe/thirdparty/recipe.d.ts b/lib/build/recipe/thirdparty/recipe.d.ts index 1b54c3eb7..163ba5523 100644 --- a/lib/build/recipe/thirdparty/recipe.d.ts +++ b/lib/build/recipe/thirdparty/recipe.d.ts @@ -13,12 +13,27 @@ export default class Recipe extends RecipeModule { recipeInterfaceImpl: RecipeInterface; apiImpl: APIInterface; isInServerlessEnv: boolean; - constructor(recipeId: string, appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, config: TypeInput | undefined, _recipes: {}, _ingredients: {}); + constructor( + recipeId: string, + appInfo: NormalisedAppinfo, + isInServerlessEnv: boolean, + config: TypeInput | undefined, + _recipes: {}, + _ingredients: {} + ); static init(config?: TypeInput): RecipeListFunction; static getInstanceOrThrowError(): Recipe; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, tenantId: string, req: BaseRequest, res: BaseResponse, _path: NormalisedURLPath, _method: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + tenantId: string, + req: BaseRequest, + res: BaseResponse, + _path: NormalisedURLPath, + _method: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: STError, _request: BaseRequest, _response: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; diff --git a/lib/build/recipe/thirdparty/recipe.js b/lib/build/recipe/thirdparty/recipe.js index 9a1be6a77..1a5c7cfc7 100644 --- a/lib/build/recipe/thirdparty/recipe.js +++ b/lib/build/recipe/thirdparty/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const recipeModule_1 = __importDefault(require("../../recipeModule")); const utils_1 = require("./utils"); @@ -71,11 +73,9 @@ class Recipe extends recipeModule_1.default { }; if (id === constants_1.SIGN_IN_UP_API) { return await (0, signinup_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.AUTHORISATION_API) { + } else if (id === constants_1.AUTHORISATION_API) { return await (0, authorisationUrl_1.default)(this.apiImpl, tenantId, options, userContext); - } - else if (id === constants_1.APPLE_REDIRECT_HANDLER) { + } else if (id === constants_1.APPLE_REDIRECT_HANDLER) { return await (0, appleRedirect_1.default)(this.apiImpl, options, userContext); } return false; @@ -93,7 +93,12 @@ class Recipe extends recipeModule_1.default { this.isInServerlessEnv = isInServerlessEnv; this.providers = this.config.signInAndUpFeature.providers; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.providers)); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)( + querier_1.Querier.getNewInstanceOrThrowError(recipeId), + this.providers + ) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -111,12 +116,22 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : []), {}, { - emailDelivery: undefined, - }); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ), + {}, + { + emailDelivery: undefined, + } + ); return Recipe.instance; - } - else { + } else { throw new Error("ThirdParty recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/thirdparty/recipeImplementation.js b/lib/build/recipe/thirdparty/recipeImplementation.js index bc0556043..b02b2c6ba 100644 --- a/lib/build/recipe/thirdparty/recipeImplementation.js +++ b/lib/build/recipe/thirdparty/recipeImplementation.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeImplementation; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -15,9 +17,23 @@ const authUtils_1 = require("../../authUtils"); const constants_1 = require("../multitenancy/constants"); function getRecipeImplementation(querier, providers) { return { - manuallyCreateOrUpdateUser: async function ({ thirdPartyId, thirdPartyUserId, email, isVerified, tenantId, session, shouldTryLinkingWithSessionUser, userContext, }) { + manuallyCreateOrUpdateUser: async function ({ + thirdPartyId, + thirdPartyUserId, + email, + isVerified, + tenantId, + session, + shouldTryLinkingWithSessionUser, + userContext, + }) { const accountLinking = recipe_1.default.getInstance(); - const users = await (0, __1.listUsersByAccountInfo)(tenantId, { thirdParty: { id: thirdPartyId, userId: thirdPartyUserId } }, false, userContext); + const users = await (0, __1.listUsersByAccountInfo)( + tenantId, + { thirdParty: { id: thirdPartyId, userId: thirdPartyUserId } }, + false, + userContext + ); const user = users[0]; if (user !== undefined) { const isEmailChangeAllowed = await accountLinking.isEmailChangeAllowed({ @@ -30,17 +46,22 @@ function getRecipeImplementation(querier, providers) { if (!isEmailChangeAllowed.allowed) { return { status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR", - reason: isEmailChangeAllowed.reason === "PRIMARY_USER_CONFLICT" - ? "Email already associated with another primary user." - : "New email cannot be applied to existing account because of account takeover risks.", + reason: + isEmailChangeAllowed.reason === "PRIMARY_USER_CONFLICT" + ? "Email already associated with another primary user." + : "New email cannot be applied to existing account because of account takeover risks.", }; } } - let response = await querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId}/recipe/signinup`), { - thirdPartyId, - thirdPartyUserId, - email: { id: email, isVerified }, - }, userContext); + let response = await querier.sendPostRequest( + new normalisedURLPath_1.default(`/${tenantId}/recipe/signinup`), + { + thirdPartyId, + thirdPartyUserId, + email: { id: email, isVerified }, + }, + userContext + ); if (response.status !== "OK") { return response; } @@ -53,15 +74,17 @@ function getRecipeImplementation(querier, providers) { }); // we do this so that we get the updated user (in case the above // function updated the verification status) and can return that - response.user = (await (0, __1.getUser)(response.recipeUserId.getAsString(), userContext)); - const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo({ - tenantId, - shouldTryLinkingWithSessionUser, - inputUser: response.user, - recipeUserId: response.recipeUserId, - session, - userContext, - }); + response.user = await (0, __1.getUser)(response.recipeUserId.getAsString(), userContext); + const linkResult = await authUtils_1.AuthUtils.linkToSessionIfRequiredElseCreatePrimaryUserIdOrLinkByAccountInfo( + { + tenantId, + shouldTryLinkingWithSessionUser, + inputUser: response.user, + recipeUserId: response.recipeUserId, + session, + userContext, + } + ); if (linkResult.status !== "OK") { return linkResult; } @@ -72,7 +95,18 @@ function getRecipeImplementation(querier, providers) { recipeUserId: response.recipeUserId, }; }, - signInUp: async function ({ thirdPartyId, thirdPartyUserId, email, isVerified, tenantId, userContext, oAuthTokens, session, shouldTryLinkingWithSessionUser, rawUserInfoFromProvider, }) { + signInUp: async function ({ + thirdPartyId, + thirdPartyUserId, + email, + isVerified, + tenantId, + userContext, + oAuthTokens, + session, + shouldTryLinkingWithSessionUser, + rawUserInfoFromProvider, + }) { let response = await this.manuallyCreateOrUpdateUser({ thirdPartyId, thirdPartyUserId, @@ -86,14 +120,14 @@ function getRecipeImplementation(querier, providers) { if (response.status === "EMAIL_CHANGE_NOT_ALLOWED_ERROR") { return { status: "SIGN_IN_UP_NOT_ALLOWED", - reason: response.reason === "Email already associated with another primary user." - ? "Cannot sign in / up because new email cannot be applied to existing account. Please contact support. (ERR_CODE_005)" - : "Cannot sign in / up because new email cannot be applied to existing account. Please contact support. (ERR_CODE_024)", + reason: + response.reason === "Email already associated with another primary user." + ? "Cannot sign in / up because new email cannot be applied to existing account. Please contact support. (ERR_CODE_005)" + : "Cannot sign in / up because new email cannot be applied to existing account. Please contact support. (ERR_CODE_024)", }; } if (response.status === "OK") { - return Object.assign(Object.assign({}, response), { oAuthTokens, - rawUserInfoFromProvider }); + return Object.assign(Object.assign({}, response), { oAuthTokens, rawUserInfoFromProvider }); } return response; }, @@ -103,8 +137,17 @@ function getRecipeImplementation(querier, providers) { if (tenantConfig === undefined) { throw new Error("Tenant not found"); } - const mergedProviders = (0, configUtils_1.mergeProvidersFromCoreAndStatic)(tenantConfig.thirdParty.providers, providers, tenantId === constants_1.DEFAULT_TENANT_ID); - const provider = await (0, configUtils_1.findAndCreateProviderInstance)(mergedProviders, thirdPartyId, clientType, userContext); + const mergedProviders = (0, configUtils_1.mergeProvidersFromCoreAndStatic)( + tenantConfig.thirdParty.providers, + providers, + tenantId === constants_1.DEFAULT_TENANT_ID + ); + const provider = await (0, configUtils_1.findAndCreateProviderInstance)( + mergedProviders, + thirdPartyId, + clientType, + userContext + ); return provider; }, }; diff --git a/lib/build/recipe/thirdparty/types.d.ts b/lib/build/recipe/thirdparty/types.d.ts index 1919e940b..3cb5641ec 100644 --- a/lib/build/recipe/thirdparty/types.d.ts +++ b/lib/build/recipe/thirdparty/types.d.ts @@ -115,10 +115,7 @@ export type TypeProvider = { }; userContext?: UserContext; }) => Promise; - getUserInfo: (input: { - oAuthTokens: any; - userContext?: UserContext; - }) => Promise; + getUserInfo: (input: { oAuthTokens: any; userContext?: UserContext }) => Promise; }; export type ProviderConfig = CommonProviderConfig & { clients?: ProviderClientConfig[]; @@ -137,14 +134,20 @@ export type TypeNormalisedInputSignInAndUp = { export type TypeInput = { signInAndUpFeature?: TypeInputSignInAndUp; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { signInAndUpFeature: TypeNormalisedInputSignInAndUp; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -175,29 +178,37 @@ export type RecipeInterface = { shouldTryLinkingWithSessionUser: boolean | undefined; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - createdNewRecipeUser: boolean; - recipeUserId: RecipeUserId; - user: User; - oAuthTokens: { - [key: string]: any; - }; - rawUserInfoFromProvider: { - fromIdTokenPayload?: { - [key: string]: any; - }; - fromUserInfoAPI?: { - [key: string]: any; - }; - }; - } | { - status: "SIGN_IN_UP_NOT_ALLOWED"; - reason: string; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + createdNewRecipeUser: boolean; + recipeUserId: RecipeUserId; + user: User; + oAuthTokens: { + [key: string]: any; + }; + rawUserInfoFromProvider: { + fromIdTokenPayload?: { + [key: string]: any; + }; + fromUserInfoAPI?: { + [key: string]: any; + }; + }; + } + | { + status: "SIGN_IN_UP_NOT_ALLOWED"; + reason: string; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; manuallyCreateOrUpdateUser(input: { thirdPartyId: string; thirdPartyUserId: string; @@ -207,21 +218,30 @@ export type RecipeInterface = { shouldTryLinkingWithSessionUser: boolean | undefined; tenantId: string; userContext: UserContext; - }): Promise<{ - status: "OK"; - createdNewRecipeUser: boolean; - user: User; - recipeUserId: RecipeUserId; - } | { - status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; - reason: string; - } | { - status: "SIGN_IN_UP_NOT_ALLOWED"; - reason: string; - } | { - status: "LINKING_TO_SESSION_USER_FAILED"; - reason: "EMAIL_VERIFICATION_REQUIRED" | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; - }>; + }): Promise< + | { + status: "OK"; + createdNewRecipeUser: boolean; + user: User; + recipeUserId: RecipeUserId; + } + | { + status: "EMAIL_CHANGE_NOT_ALLOWED_ERROR"; + reason: string; + } + | { + status: "SIGN_IN_UP_NOT_ALLOWED"; + reason: string; + } + | { + status: "LINKING_TO_SESSION_USER_FAILED"; + reason: + | "EMAIL_VERIFICATION_REQUIRED" + | "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR" + | "SESSION_USER_ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR"; + } + >; }; export type APIOptions = { recipeImplementation: RecipeInterface; @@ -234,62 +254,81 @@ export type APIOptions = { appInfo: NormalisedAppinfo; }; export type APIInterface = { - authorisationUrlGET: undefined | ((input: { - provider: TypeProvider; - redirectURIOnProviderDashboard: string; - tenantId: string; - options: APIOptions; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - urlWithQueryParams: string; - pkceCodeVerifier?: string; - } | GeneralErrorResponse>); - signInUpPOST: undefined | ((input: { - provider: TypeProvider; - tenantId: string; - session: SessionContainerInterface | undefined; - shouldTryLinkingWithSessionUser: boolean | undefined; - options: APIOptions; - userContext: UserContext; - } & ({ - redirectURIInfo: { - redirectURIOnProviderDashboard: string; - redirectURIQueryParams: any; - pkceCodeVerifier?: string; - }; - } | { - oAuthTokens: { - [key: string]: any; - }; - })) => Promise<{ - status: "OK"; - createdNewRecipeUser: boolean; - user: User; - session: SessionContainerInterface; - oAuthTokens: { - [key: string]: any; - }; - rawUserInfoFromProvider: { - fromIdTokenPayload?: { - [key: string]: any; - }; - fromUserInfoAPI?: { - [key: string]: any; - }; - }; - } | { - status: "NO_EMAIL_GIVEN_BY_PROVIDER"; - } | { - status: "SIGN_IN_UP_NOT_ALLOWED"; - reason: string; - } | GeneralErrorResponse>); - appleRedirectHandlerPOST: undefined | ((input: { - formPostInfoFromProvider: { - [key: string]: any; - }; - options: APIOptions; - userContext: UserContext; - }) => Promise); + authorisationUrlGET: + | undefined + | ((input: { + provider: TypeProvider; + redirectURIOnProviderDashboard: string; + tenantId: string; + options: APIOptions; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + urlWithQueryParams: string; + pkceCodeVerifier?: string; + } + | GeneralErrorResponse + >); + signInUpPOST: + | undefined + | (( + input: { + provider: TypeProvider; + tenantId: string; + session: SessionContainerInterface | undefined; + shouldTryLinkingWithSessionUser: boolean | undefined; + options: APIOptions; + userContext: UserContext; + } & ( + | { + redirectURIInfo: { + redirectURIOnProviderDashboard: string; + redirectURIQueryParams: any; + pkceCodeVerifier?: string; + }; + } + | { + oAuthTokens: { + [key: string]: any; + }; + } + ) + ) => Promise< + | { + status: "OK"; + createdNewRecipeUser: boolean; + user: User; + session: SessionContainerInterface; + oAuthTokens: { + [key: string]: any; + }; + rawUserInfoFromProvider: { + fromIdTokenPayload?: { + [key: string]: any; + }; + fromUserInfoAPI?: { + [key: string]: any; + }; + }; + } + | { + status: "NO_EMAIL_GIVEN_BY_PROVIDER"; + } + | { + status: "SIGN_IN_UP_NOT_ALLOWED"; + reason: string; + } + | GeneralErrorResponse + >); + appleRedirectHandlerPOST: + | undefined + | ((input: { + formPostInfoFromProvider: { + [key: string]: any; + }; + options: APIOptions; + userContext: UserContext; + }) => Promise); }; export {}; diff --git a/lib/build/recipe/thirdparty/utils.d.ts b/lib/build/recipe/thirdparty/utils.d.ts index 7e1bebd95..e4db0684e 100644 --- a/lib/build/recipe/thirdparty/utils.d.ts +++ b/lib/build/recipe/thirdparty/utils.d.ts @@ -1,5 +1,8 @@ // @ts-nocheck import { NormalisedAppinfo } from "../../types"; import { TypeInput, TypeNormalisedInput } from "./types"; -export declare function validateAndNormaliseUserInput(appInfo: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + appInfo: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; export declare function isFakeEmail(email: string): boolean; diff --git a/lib/build/recipe/thirdparty/utils.js b/lib/build/recipe/thirdparty/utils.js index 67ed7d0f3..099b13aaf 100644 --- a/lib/build/recipe/thirdparty/utils.js +++ b/lib/build/recipe/thirdparty/utils.js @@ -17,8 +17,17 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; exports.isFakeEmail = isFakeEmail; function validateAndNormaliseUserInput(appInfo, config) { - let signInAndUpFeature = validateAndNormaliseSignInAndUpConfig(appInfo, config === null || config === void 0 ? void 0 : config.signInAndUpFeature); - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let signInAndUpFeature = validateAndNormaliseSignInAndUpConfig( + appInfo, + config === null || config === void 0 ? void 0 : config.signInAndUpFeature + ); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { signInAndUpFeature, override, diff --git a/lib/build/recipe/totp/api/createDevice.d.ts b/lib/build/recipe/totp/api/createDevice.d.ts index 9d703be7f..aaa135298 100644 --- a/lib/build/recipe/totp/api/createDevice.d.ts +++ b/lib/build/recipe/totp/api/createDevice.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function createDeviceAPI(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function createDeviceAPI( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/totp/api/createDevice.js b/lib/build/recipe/totp/api/createDevice.js index 03f55851f..3527e4448 100644 --- a/lib/build/recipe/totp/api/createDevice.js +++ b/lib/build/recipe/totp/api/createDevice.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = createDeviceAPI; const utils_1 = require("../../../utils"); @@ -24,7 +26,12 @@ async function createDeviceAPI(apiImplementation, options, userContext) { if (apiImplementation.createDevicePOST === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [], sessionRequired: true }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [], sessionRequired: true }, + userContext + ); const bodyParams = await options.req.getJSONBody(); const deviceName = bodyParams.deviceName; if (deviceName !== undefined && typeof deviceName !== "string") { diff --git a/lib/build/recipe/totp/api/implementation.js b/lib/build/recipe/totp/api/implementation.js index 2f94b0358..f2869fe9d 100644 --- a/lib/build/recipe/totp/api/implementation.js +++ b/lib/build/recipe/totp/api/implementation.js @@ -13,42 +13,63 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getAPIInterface; const multifactorauth_1 = __importStar(require("../../multifactorauth")); @@ -62,7 +83,11 @@ function getAPIInterface() { if (mfaInstance === undefined) { throw new Error("should never come here"); // If TOTP initialised, MFA is auto initialised. This should never happen. } - await multifactorauth_1.default.assertAllowedToSetupFactorElseThrowInvalidClaimError(session, "totp", userContext); + await multifactorauth_1.default.assertAllowedToSetupFactorElseThrowInvalidClaimError( + session, + "totp", + userContext + ); const createDeviceRes = await options.recipeImplementation.createDevice({ userId, deviceName: deviceName, @@ -73,8 +98,7 @@ function getAPIInterface() { type: error_1.default.UNAUTHORISED, message: "Session user not found", }); - } - else { + } else { return createDeviceRes; } }, @@ -92,7 +116,9 @@ function getAPIInterface() { userContext, }); if (deviceList.devices.some((device) => device.name === deviceName && device.verified)) { - await session.assertClaims([multifactorauth_1.MultiFactorAuthClaim.validators.hasCompletedMFARequirementsForAuth()]); + await session.assertClaims([ + multifactorauth_1.MultiFactorAuthClaim.validators.hasCompletedMFARequirementsForAuth(), + ]); } return await options.recipeImplementation.removeDevice({ userId, @@ -107,7 +133,11 @@ function getAPIInterface() { if (mfaInstance === undefined) { throw new Error("should never come here"); // If TOTP initialised, MFA is auto initialised. This should never happen. } - await multifactorauth_1.default.assertAllowedToSetupFactorElseThrowInvalidClaimError(session, "totp", userContext); + await multifactorauth_1.default.assertAllowedToSetupFactorElseThrowInvalidClaimError( + session, + "totp", + userContext + ); const res = await options.recipeImplementation.verifyDevice({ tenantId, userId, diff --git a/lib/build/recipe/totp/api/listDevices.d.ts b/lib/build/recipe/totp/api/listDevices.d.ts index ffec14f56..d6ba65d69 100644 --- a/lib/build/recipe/totp/api/listDevices.d.ts +++ b/lib/build/recipe/totp/api/listDevices.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function listDevicesAPI(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function listDevicesAPI( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/totp/api/listDevices.js b/lib/build/recipe/totp/api/listDevices.js index 8b9ea66d0..ba27614a0 100644 --- a/lib/build/recipe/totp/api/listDevices.js +++ b/lib/build/recipe/totp/api/listDevices.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = listDevicesAPI; const utils_1 = require("../../../utils"); @@ -24,7 +26,12 @@ async function listDevicesAPI(apiImplementation, options, userContext) { if (apiImplementation.listDevicesGET === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [], sessionRequired: true }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [], sessionRequired: true }, + userContext + ); let response = await apiImplementation.listDevicesGET({ options, session, diff --git a/lib/build/recipe/totp/api/removeDevice.d.ts b/lib/build/recipe/totp/api/removeDevice.d.ts index 057e4d511..047515bef 100644 --- a/lib/build/recipe/totp/api/removeDevice.d.ts +++ b/lib/build/recipe/totp/api/removeDevice.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function removeDeviceAPI(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function removeDeviceAPI( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/totp/api/removeDevice.js b/lib/build/recipe/totp/api/removeDevice.js index 3a71e16e5..7493444ac 100644 --- a/lib/build/recipe/totp/api/removeDevice.js +++ b/lib/build/recipe/totp/api/removeDevice.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = removeDeviceAPI; const utils_1 = require("../../../utils"); @@ -24,10 +26,15 @@ async function removeDeviceAPI(apiImplementation, options, userContext) { if (apiImplementation.removeDevicePOST === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { - overrideGlobalClaimValidators: () => [], - sessionRequired: true, - }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { + overrideGlobalClaimValidators: () => [], + sessionRequired: true, + }, + userContext + ); const bodyParams = await options.req.getJSONBody(); const deviceName = bodyParams.deviceName; if (deviceName === undefined || typeof deviceName !== "string" || deviceName.length === 0) { diff --git a/lib/build/recipe/totp/api/verifyDevice.d.ts b/lib/build/recipe/totp/api/verifyDevice.d.ts index 27b92b41b..d4de4bcc9 100644 --- a/lib/build/recipe/totp/api/verifyDevice.d.ts +++ b/lib/build/recipe/totp/api/verifyDevice.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function verifyDeviceAPI(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function verifyDeviceAPI( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/totp/api/verifyDevice.js b/lib/build/recipe/totp/api/verifyDevice.js index 44b79a73a..0b1e41f24 100644 --- a/lib/build/recipe/totp/api/verifyDevice.js +++ b/lib/build/recipe/totp/api/verifyDevice.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = verifyDeviceAPI; const utils_1 = require("../../../utils"); @@ -24,7 +26,12 @@ async function verifyDeviceAPI(apiImplementation, options, userContext) { if (apiImplementation.verifyDevicePOST === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [], sessionRequired: true }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [], sessionRequired: true }, + userContext + ); const bodyParams = await options.req.getJSONBody(); const deviceName = bodyParams.deviceName; const totp = bodyParams.totp; diff --git a/lib/build/recipe/totp/api/verifyTOTP.d.ts b/lib/build/recipe/totp/api/verifyTOTP.d.ts index b9e24dc4a..925a9f40a 100644 --- a/lib/build/recipe/totp/api/verifyTOTP.d.ts +++ b/lib/build/recipe/totp/api/verifyTOTP.d.ts @@ -1,4 +1,8 @@ // @ts-nocheck import { APIInterface, APIOptions } from ".."; import { UserContext } from "../../../types"; -export default function verifyTOTPAPI(apiImplementation: APIInterface, options: APIOptions, userContext: UserContext): Promise; +export default function verifyTOTPAPI( + apiImplementation: APIInterface, + options: APIOptions, + userContext: UserContext +): Promise; diff --git a/lib/build/recipe/totp/api/verifyTOTP.js b/lib/build/recipe/totp/api/verifyTOTP.js index bb325c7c2..732e0e780 100644 --- a/lib/build/recipe/totp/api/verifyTOTP.js +++ b/lib/build/recipe/totp/api/verifyTOTP.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = verifyTOTPAPI; const utils_1 = require("../../../utils"); @@ -24,7 +26,12 @@ async function verifyTOTPAPI(apiImplementation, options, userContext) { if (apiImplementation.verifyTOTPPOST === undefined) { return false; } - const session = await session_1.default.getSession(options.req, options.res, { overrideGlobalClaimValidators: () => [], sessionRequired: true }, userContext); + const session = await session_1.default.getSession( + options.req, + options.res, + { overrideGlobalClaimValidators: () => [], sessionRequired: true }, + userContext + ); const bodyParams = await options.req.getJSONBody(); const totp = bodyParams.totp; if (totp === undefined || typeof totp !== "string") { diff --git a/lib/build/recipe/totp/index.d.ts b/lib/build/recipe/totp/index.d.ts index 589bcf99a..9759cdc47 100644 --- a/lib/build/recipe/totp/index.d.ts +++ b/lib/build/recipe/totp/index.d.ts @@ -3,20 +3,39 @@ import Recipe from "./recipe"; import { RecipeInterface, APIOptions, APIInterface } from "./types"; export default class Wrapper { static init: typeof Recipe.init; - static createDevice(userId: string, userIdentifierInfo?: string, deviceName?: string, skew?: number, period?: number, userContext?: Record): Promise<{ - status: "OK"; - deviceName: string; - secret: string; - qrCodeString: string; - } | { - status: "DEVICE_ALREADY_EXISTS_ERROR"; - } | { - status: "UNKNOWN_USER_ID_ERROR"; - }>; - static updateDevice(userId: string, existingDeviceName: string, newDeviceName: string, userContext?: Record): Promise<{ + static createDevice( + userId: string, + userIdentifierInfo?: string, + deviceName?: string, + skew?: number, + period?: number, + userContext?: Record + ): Promise< + | { + status: "OK"; + deviceName: string; + secret: string; + qrCodeString: string; + } + | { + status: "DEVICE_ALREADY_EXISTS_ERROR"; + } + | { + status: "UNKNOWN_USER_ID_ERROR"; + } + >; + static updateDevice( + userId: string, + existingDeviceName: string, + newDeviceName: string, + userContext?: Record + ): Promise<{ status: "OK" | "UNKNOWN_DEVICE_ERROR" | "DEVICE_ALREADY_EXISTS_ERROR"; }>; - static listDevices(userId: string, userContext?: Record): Promise<{ + static listDevices( + userId: string, + userContext?: Record + ): Promise<{ status: "OK"; devices: { name: string; @@ -25,33 +44,57 @@ export default class Wrapper { verified: boolean; }[]; }>; - static removeDevice(userId: string, deviceName: string, userContext?: Record): Promise<{ + static removeDevice( + userId: string, + deviceName: string, + userContext?: Record + ): Promise<{ status: "OK"; didDeviceExist: boolean; }>; - static verifyDevice(tenantId: string, userId: string, deviceName: string, totp: string, userContext?: Record): Promise<{ - status: "OK"; - wasAlreadyVerified: boolean; - } | { - status: "UNKNOWN_DEVICE_ERROR"; - } | { - status: "INVALID_TOTP_ERROR"; - currentNumberOfFailedAttempts: number; - maxNumberOfFailedAttempts: number; - } | { - status: "LIMIT_REACHED_ERROR"; - retryAfterMs: number; - }>; - static verifyTOTP(tenantId: string, userId: string, totp: string, userContext?: Record): Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR"; - } | { - status: "INVALID_TOTP_ERROR"; - currentNumberOfFailedAttempts: number; - maxNumberOfFailedAttempts: number; - } | { - status: "LIMIT_REACHED_ERROR"; - retryAfterMs: number; - }>; + static verifyDevice( + tenantId: string, + userId: string, + deviceName: string, + totp: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + wasAlreadyVerified: boolean; + } + | { + status: "UNKNOWN_DEVICE_ERROR"; + } + | { + status: "INVALID_TOTP_ERROR"; + currentNumberOfFailedAttempts: number; + maxNumberOfFailedAttempts: number; + } + | { + status: "LIMIT_REACHED_ERROR"; + retryAfterMs: number; + } + >; + static verifyTOTP( + tenantId: string, + userId: string, + totp: string, + userContext?: Record + ): Promise< + | { + status: "OK" | "UNKNOWN_USER_ID_ERROR"; + } + | { + status: "INVALID_TOTP_ERROR"; + currentNumberOfFailedAttempts: number; + maxNumberOfFailedAttempts: number; + } + | { + status: "LIMIT_REACHED_ERROR"; + retryAfterMs: number; + } + >; } export declare let init: typeof Recipe.init; export declare let createDevice: typeof Wrapper.createDevice; diff --git a/lib/build/recipe/totp/index.js b/lib/build/recipe/totp/index.js index 53d357486..63603d11b 100644 --- a/lib/build/recipe/totp/index.js +++ b/lib/build/recipe/totp/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifyTOTP = exports.verifyDevice = exports.removeDevice = exports.updateDevice = exports.listDevices = exports.createDevice = exports.init = void 0; const utils_1 = require("../../utils"); diff --git a/lib/build/recipe/totp/recipe.d.ts b/lib/build/recipe/totp/recipe.d.ts index 08a0b9696..31a45bff8 100644 --- a/lib/build/recipe/totp/recipe.d.ts +++ b/lib/build/recipe/totp/recipe.d.ts @@ -18,7 +18,15 @@ export default class Recipe extends RecipeModule { static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled: () => APIHandled[]; - handleAPIRequest: (id: string, _tenantId: string, req: BaseRequest, res: BaseResponse, _: NormalisedURLPath, __: HTTPMethod, userContext: UserContext) => Promise; + handleAPIRequest: ( + id: string, + _tenantId: string, + req: BaseRequest, + res: BaseResponse, + _: NormalisedURLPath, + __: HTTPMethod, + userContext: UserContext + ) => Promise; handleError: (err: STError, _: BaseRequest, __: BaseResponse) => Promise; getAllCORSHeaders: () => string[]; isErrorFromThisRecipe: (err: any) => err is STError; diff --git a/lib/build/recipe/totp/recipe.js b/lib/build/recipe/totp/recipe.js index 551cf47a5..2fe17d28f 100644 --- a/lib/build/recipe/totp/recipe.js +++ b/lib/build/recipe/totp/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const supertokens_js_override_1 = __importDefault(require("supertokens-js-override")); const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -83,17 +85,13 @@ class Recipe extends recipeModule_1.default { }; if (id === constants_1.CREATE_TOTP_DEVICE) { return await (0, createDevice_1.default)(this.apiImpl, options, userContext); - } - else if (id === constants_1.LIST_TOTP_DEVICES) { + } else if (id === constants_1.LIST_TOTP_DEVICES) { return await (0, listDevices_1.default)(this.apiImpl, options, userContext); - } - else if (id === constants_1.REMOVE_TOTP_DEVICE) { + } else if (id === constants_1.REMOVE_TOTP_DEVICE) { return await (0, removeDevice_1.default)(this.apiImpl, options, userContext); - } - else if (id === constants_1.VERIFY_TOTP_DEVICE) { + } else if (id === constants_1.VERIFY_TOTP_DEVICE) { return await (0, verifyDevice_1.default)(this.apiImpl, options, userContext); - } - else if (id === constants_1.VERIFY_TOTP) { + } else if (id === constants_1.VERIFY_TOTP) { return await (0, verifyTOTP_1.default)(this.apiImpl, options, userContext); } throw new Error("should never come here"); @@ -110,7 +108,9 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_1.validateAndNormaliseUserInput)(appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.config)); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId), this.config) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } { @@ -150,10 +150,18 @@ class Recipe extends recipeModule_1.default { static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return Recipe.instance; - } - else { + } else { throw new Error("TOTP recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/totp/recipeImplementation.js b/lib/build/recipe/totp/recipeImplementation.js index 9680fd184..2cc839690 100644 --- a/lib/build/recipe/totp/recipeImplementation.js +++ b/lib/build/recipe/totp/recipeImplementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -29,15 +31,16 @@ function getRecipeInterface(querier, config) { status: "UNKNOWN_USER_ID_ERROR", }; } - const primaryLoginMethod = user.loginMethods.find((method) => method.recipeUserId.getAsString() === user.id); + const primaryLoginMethod = user.loginMethods.find( + (method) => method.recipeUserId.getAsString() === user.id + ); if (primaryLoginMethod !== undefined) { if (primaryLoginMethod.email !== undefined) { return { info: primaryLoginMethod.email, status: "OK", }; - } - else if (primaryLoginMethod.phoneNumber !== undefined) { + } else if (primaryLoginMethod.phoneNumber !== undefined) { return { info: primaryLoginMethod.phoneNumber, status: "OK", @@ -46,8 +49,7 @@ function getRecipeInterface(querier, config) { } if (user.emails.length > 0) { return { info: user.emails[0], status: "OK" }; - } - else if (user.phoneNumbers.length > 0) { + } else if (user.phoneNumbers.length > 0) { return { info: user.phoneNumbers[0], status: "OK" }; } return { @@ -63,55 +65,85 @@ function getRecipeInterface(querier, config) { }); if (emailOrPhoneInfo.status === "OK") { input.userIdentifierInfo = emailOrPhoneInfo.info; - } - else if (emailOrPhoneInfo.status === "UNKNOWN_USER_ID_ERROR") { + } else if (emailOrPhoneInfo.status === "UNKNOWN_USER_ID_ERROR") { return { status: "UNKNOWN_USER_ID_ERROR", }; - } - else { + } else { // Ignore since UserIdentifierInfo is optional } } - const response = await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/totp/device"), { - userId: input.userId, - deviceName: input.deviceName, - skew: (_a = input.skew) !== null && _a !== void 0 ? _a : config.defaultSkew, - period: (_b = input.period) !== null && _b !== void 0 ? _b : config.defaultPeriod, - }, input.userContext); - return Object.assign(Object.assign({}, response), { qrCodeString: `otpauth://totp/${encodeURI(config.issuer)}${input.userIdentifierInfo !== undefined ? ":" + encodeURI(input.userIdentifierInfo) : ""}` + - `?secret=${response.secret}&issuer=${encodeURI(config.issuer)}&digits=6&period=${(_c = input.period) !== null && _c !== void 0 ? _c : config.defaultPeriod}` }); + const response = await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/totp/device"), + { + userId: input.userId, + deviceName: input.deviceName, + skew: (_a = input.skew) !== null && _a !== void 0 ? _a : config.defaultSkew, + period: (_b = input.period) !== null && _b !== void 0 ? _b : config.defaultPeriod, + }, + input.userContext + ); + return Object.assign(Object.assign({}, response), { + qrCodeString: + `otpauth://totp/${encodeURI(config.issuer)}${ + input.userIdentifierInfo !== undefined ? ":" + encodeURI(input.userIdentifierInfo) : "" + }` + + `?secret=${response.secret}&issuer=${encodeURI(config.issuer)}&digits=6&period=${ + (_c = input.period) !== null && _c !== void 0 ? _c : config.defaultPeriod + }`, + }); }, updateDevice: (input) => { - return querier.sendPutRequest(new normalisedURLPath_1.default("/recipe/totp/device"), { - userId: input.userId, - existingDeviceName: input.existingDeviceName, - newDeviceName: input.newDeviceName, - }, {}, input.userContext); + return querier.sendPutRequest( + new normalisedURLPath_1.default("/recipe/totp/device"), + { + userId: input.userId, + existingDeviceName: input.existingDeviceName, + newDeviceName: input.newDeviceName, + }, + {}, + input.userContext + ); }, listDevices: (input) => { - return querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/totp/device/list"), { - userId: input.userId, - }, input.userContext); + return querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/totp/device/list"), + { + userId: input.userId, + }, + input.userContext + ); }, removeDevice: (input) => { - return querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/totp/device/remove"), { - userId: input.userId, - deviceName: input.deviceName, - }, input.userContext); + return querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/totp/device/remove"), + { + userId: input.userId, + deviceName: input.deviceName, + }, + input.userContext + ); }, verifyDevice: (input) => { - return querier.sendPostRequest(new normalisedURLPath_1.default(`${input.tenantId}/recipe/totp/device/verify`), { - userId: input.userId, - deviceName: input.deviceName, - totp: input.totp, - }, input.userContext); + return querier.sendPostRequest( + new normalisedURLPath_1.default(`${input.tenantId}/recipe/totp/device/verify`), + { + userId: input.userId, + deviceName: input.deviceName, + totp: input.totp, + }, + input.userContext + ); }, verifyTOTP: (input) => { - return querier.sendPostRequest(new normalisedURLPath_1.default(`${input.tenantId}/recipe/totp/verify`), { - userId: input.userId, - totp: input.totp, - }, input.userContext); + return querier.sendPostRequest( + new normalisedURLPath_1.default(`${input.tenantId}/recipe/totp/verify`), + { + userId: input.userId, + totp: input.totp, + }, + input.userContext + ); }, }; } diff --git a/lib/build/recipe/totp/types.d.ts b/lib/build/recipe/totp/types.d.ts index 273bb2dab..2eebe25f4 100644 --- a/lib/build/recipe/totp/types.d.ts +++ b/lib/build/recipe/totp/types.d.ts @@ -8,7 +8,10 @@ export type TypeInput = { defaultSkew?: number; defaultPeriod?: number; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -17,7 +20,10 @@ export type TypeNormalisedInput = { defaultSkew: number; defaultPeriod: number; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -25,12 +31,15 @@ export type RecipeInterface = { getUserIdentifierInfoForUserId: (input: { userId: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - info: string; - } | { - status: "UNKNOWN_USER_ID_ERROR" | "USER_IDENTIFIER_INFO_DOES_NOT_EXIST_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + info: string; + } + | { + status: "UNKNOWN_USER_ID_ERROR" | "USER_IDENTIFIER_INFO_DOES_NOT_EXIST_ERROR"; + } + >; createDevice: (input: { userId: string; userIdentifierInfo?: string; @@ -38,16 +47,20 @@ export type RecipeInterface = { skew?: number; period?: number; userContext: UserContext; - }) => Promise<{ - status: "OK"; - deviceName: string; - secret: string; - qrCodeString: string; - } | { - status: "DEVICE_ALREADY_EXISTS_ERROR"; - } | { - status: "UNKNOWN_USER_ID_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + deviceName: string; + secret: string; + qrCodeString: string; + } + | { + status: "DEVICE_ALREADY_EXISTS_ERROR"; + } + | { + status: "UNKNOWN_USER_ID_ERROR"; + } + >; updateDevice: (input: { userId: string; existingDeviceName: string; @@ -82,34 +95,43 @@ export type RecipeInterface = { deviceName: string; totp: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - wasAlreadyVerified: boolean; - } | { - status: "UNKNOWN_DEVICE_ERROR"; - } | { - status: "INVALID_TOTP_ERROR"; - currentNumberOfFailedAttempts: number; - maxNumberOfFailedAttempts: number; - } | { - status: "LIMIT_REACHED_ERROR"; - retryAfterMs: number; - }>; + }) => Promise< + | { + status: "OK"; + wasAlreadyVerified: boolean; + } + | { + status: "UNKNOWN_DEVICE_ERROR"; + } + | { + status: "INVALID_TOTP_ERROR"; + currentNumberOfFailedAttempts: number; + maxNumberOfFailedAttempts: number; + } + | { + status: "LIMIT_REACHED_ERROR"; + retryAfterMs: number; + } + >; verifyTOTP: (input: { tenantId: string; userId: string; totp: string; userContext: UserContext; - }) => Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR"; - } | { - status: "INVALID_TOTP_ERROR"; - currentNumberOfFailedAttempts: number; - maxNumberOfFailedAttempts: number; - } | { - status: "LIMIT_REACHED_ERROR"; - retryAfterMs: number; - }>; + }) => Promise< + | { + status: "OK" | "UNKNOWN_USER_ID_ERROR"; + } + | { + status: "INVALID_TOTP_ERROR"; + currentNumberOfFailedAttempts: number; + maxNumberOfFailedAttempts: number; + } + | { + status: "LIMIT_REACHED_ERROR"; + retryAfterMs: number; + } + >; }; export type APIOptions = { recipeImplementation: RecipeInterface; @@ -120,73 +142,104 @@ export type APIOptions = { res: BaseResponse; }; export type APIInterface = { - createDevicePOST: undefined | ((input: { - deviceName?: string; - options: APIOptions; - session: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - deviceName: string; - secret: string; - qrCodeString: string; - } | { - status: "DEVICE_ALREADY_EXISTS_ERROR"; - } | GeneralErrorResponse>); - listDevicesGET: undefined | ((input: { - options: APIOptions; - session: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - devices: { - name: string; - period: number; - skew: number; - verified: boolean; - }[]; - } | GeneralErrorResponse>); - removeDevicePOST: undefined | ((input: { - deviceName: string; - options: APIOptions; - session: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - didDeviceExist: boolean; - } | GeneralErrorResponse>); - verifyDevicePOST: undefined | ((input: { - deviceName: string; - totp: string; - options: APIOptions; - session: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK"; - wasAlreadyVerified: boolean; - } | { - status: "UNKNOWN_DEVICE_ERROR"; - } | { - status: "INVALID_TOTP_ERROR"; - currentNumberOfFailedAttempts: number; - maxNumberOfFailedAttempts: number; - } | { - status: "LIMIT_REACHED_ERROR"; - retryAfterMs: number; - } | GeneralErrorResponse>); - verifyTOTPPOST: undefined | ((input: { - totp: string; - options: APIOptions; - session: SessionContainerInterface; - userContext: UserContext; - }) => Promise<{ - status: "OK" | "UNKNOWN_USER_ID_ERROR"; - } | { - status: "INVALID_TOTP_ERROR"; - currentNumberOfFailedAttempts: number; - maxNumberOfFailedAttempts: number; - } | { - status: "LIMIT_REACHED_ERROR"; - retryAfterMs: number; - } | GeneralErrorResponse>); + createDevicePOST: + | undefined + | ((input: { + deviceName?: string; + options: APIOptions; + session: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + deviceName: string; + secret: string; + qrCodeString: string; + } + | { + status: "DEVICE_ALREADY_EXISTS_ERROR"; + } + | GeneralErrorResponse + >); + listDevicesGET: + | undefined + | ((input: { + options: APIOptions; + session: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + devices: { + name: string; + period: number; + skew: number; + verified: boolean; + }[]; + } + | GeneralErrorResponse + >); + removeDevicePOST: + | undefined + | ((input: { + deviceName: string; + options: APIOptions; + session: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + didDeviceExist: boolean; + } + | GeneralErrorResponse + >); + verifyDevicePOST: + | undefined + | ((input: { + deviceName: string; + totp: string; + options: APIOptions; + session: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK"; + wasAlreadyVerified: boolean; + } + | { + status: "UNKNOWN_DEVICE_ERROR"; + } + | { + status: "INVALID_TOTP_ERROR"; + currentNumberOfFailedAttempts: number; + maxNumberOfFailedAttempts: number; + } + | { + status: "LIMIT_REACHED_ERROR"; + retryAfterMs: number; + } + | GeneralErrorResponse + >); + verifyTOTPPOST: + | undefined + | ((input: { + totp: string; + options: APIOptions; + session: SessionContainerInterface; + userContext: UserContext; + }) => Promise< + | { + status: "OK" | "UNKNOWN_USER_ID_ERROR"; + } + | { + status: "INVALID_TOTP_ERROR"; + currentNumberOfFailedAttempts: number; + maxNumberOfFailedAttempts: number; + } + | { + status: "LIMIT_REACHED_ERROR"; + retryAfterMs: number; + } + | GeneralErrorResponse + >); }; diff --git a/lib/build/recipe/totp/utils.d.ts b/lib/build/recipe/totp/utils.d.ts index 69bb66884..6b5abd280 100644 --- a/lib/build/recipe/totp/utils.d.ts +++ b/lib/build/recipe/totp/utils.d.ts @@ -1,4 +1,7 @@ // @ts-nocheck import { NormalisedAppinfo } from "../../types"; import { TypeInput, TypeNormalisedInput } from "./types"; -export declare function validateAndNormaliseUserInput(appInfo: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + appInfo: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; diff --git a/lib/build/recipe/totp/utils.js b/lib/build/recipe/totp/utils.js index 023da6a2b..d5821d5d6 100644 --- a/lib/build/recipe/totp/utils.js +++ b/lib/build/recipe/totp/utils.js @@ -17,11 +17,26 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; function validateAndNormaliseUserInput(appInfo, config) { var _a, _b, _c; - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { - issuer: (_a = config === null || config === void 0 ? void 0 : config.issuer) !== null && _a !== void 0 ? _a : appInfo.appName, - defaultSkew: (_b = config === null || config === void 0 ? void 0 : config.defaultSkew) !== null && _b !== void 0 ? _b : 1, - defaultPeriod: (_c = config === null || config === void 0 ? void 0 : config.defaultPeriod) !== null && _c !== void 0 ? _c : 30, + issuer: + (_a = config === null || config === void 0 ? void 0 : config.issuer) !== null && _a !== void 0 + ? _a + : appInfo.appName, + defaultSkew: + (_b = config === null || config === void 0 ? void 0 : config.defaultSkew) !== null && _b !== void 0 + ? _b + : 1, + defaultPeriod: + (_c = config === null || config === void 0 ? void 0 : config.defaultPeriod) !== null && _c !== void 0 + ? _c + : 30, override, }; } diff --git a/lib/build/recipe/usermetadata/index.d.ts b/lib/build/recipe/usermetadata/index.d.ts index 68b6918ca..17987da81 100644 --- a/lib/build/recipe/usermetadata/index.d.ts +++ b/lib/build/recipe/usermetadata/index.d.ts @@ -4,15 +4,25 @@ import Recipe from "./recipe"; import { RecipeInterface } from "./types"; export default class Wrapper { static init: typeof Recipe.init; - static getUserMetadata(userId: string, userContext?: Record): Promise<{ + static getUserMetadata( + userId: string, + userContext?: Record + ): Promise<{ status: "OK"; metadata: any; }>; - static updateUserMetadata(userId: string, metadataUpdate: JSONObject, userContext?: Record): Promise<{ + static updateUserMetadata( + userId: string, + metadataUpdate: JSONObject, + userContext?: Record + ): Promise<{ status: "OK"; metadata: JSONObject; }>; - static clearUserMetadata(userId: string, userContext?: Record): Promise<{ + static clearUserMetadata( + userId: string, + userContext?: Record + ): Promise<{ status: "OK"; }>; } diff --git a/lib/build/recipe/usermetadata/index.js b/lib/build/recipe/usermetadata/index.js index b3c9b0a27..e0b3585c7 100644 --- a/lib/build/recipe/usermetadata/index.js +++ b/lib/build/recipe/usermetadata/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearUserMetadata = exports.updateUserMetadata = exports.getUserMetadata = exports.init = void 0; const utils_1 = require("../../utils"); diff --git a/lib/build/recipe/usermetadata/recipe.d.ts b/lib/build/recipe/usermetadata/recipe.d.ts index 8ac5a6936..a588ea3b3 100644 --- a/lib/build/recipe/usermetadata/recipe.d.ts +++ b/lib/build/recipe/usermetadata/recipe.d.ts @@ -16,7 +16,14 @@ export default class Recipe extends RecipeModule { static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled(): APIHandled[]; - handleAPIRequest: (_: string, _tenantId: string | undefined, __: BaseRequest, ___: BaseResponse, ____: normalisedURLPath, _____: HTTPMethod) => Promise; + handleAPIRequest: ( + _: string, + _tenantId: string | undefined, + __: BaseRequest, + ___: BaseResponse, + ____: normalisedURLPath, + _____: HTTPMethod + ) => Promise; handleError(error: error, _: BaseRequest, __: BaseResponse): Promise; getAllCORSHeaders(): string[]; isErrorFromThisRecipe(err: any): err is error; diff --git a/lib/build/recipe/usermetadata/recipe.js b/lib/build/recipe/usermetadata/recipe.js index 613ed098b..de33cf3ca 100644 --- a/lib/build/recipe/usermetadata/recipe.js +++ b/lib/build/recipe/usermetadata/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); const querier_1 = require("../../querier"); @@ -34,7 +36,9 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_2.validateAndNormaliseUserInput)(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId))); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId)) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } } @@ -43,15 +47,25 @@ class Recipe extends recipeModule_1.default { if (Recipe.instance !== undefined) { return Recipe.instance; } - throw new Error("Initialisation not done. Did you forget to call the UserMetadata.init or UserMetadata.init function?"); + throw new Error( + "Initialisation not done. Did you forget to call the UserMetadata.init or UserMetadata.init function?" + ); } static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_1.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_1.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return Recipe.instance; - } - else { + } else { throw new Error("UserMetadata recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/usermetadata/recipeImplementation.js b/lib/build/recipe/usermetadata/recipeImplementation.js index db9fba633..f3a2f051c 100644 --- a/lib/build/recipe/usermetadata/recipeImplementation.js +++ b/lib/build/recipe/usermetadata/recipeImplementation.js @@ -13,27 +13,42 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); function getRecipeInterface(querier) { return { getUserMetadata: function ({ userId, userContext }) { - return querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/user/metadata"), { userId }, userContext); + return querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/user/metadata"), + { userId }, + userContext + ); }, updateUserMetadata: function ({ userId, metadataUpdate, userContext }) { - return querier.sendPutRequest(new normalisedURLPath_1.default("/recipe/user/metadata"), { - userId, - metadataUpdate, - }, {}, userContext); + return querier.sendPutRequest( + new normalisedURLPath_1.default("/recipe/user/metadata"), + { + userId, + metadataUpdate, + }, + {}, + userContext + ); }, clearUserMetadata: function ({ userId, userContext }) { - return querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/user/metadata/remove"), { - userId, - }, userContext); + return querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/user/metadata/remove"), + { + userId, + }, + userContext + ); }, }; } diff --git a/lib/build/recipe/usermetadata/types.d.ts b/lib/build/recipe/usermetadata/types.d.ts index 6590f8855..69491790a 100644 --- a/lib/build/recipe/usermetadata/types.d.ts +++ b/lib/build/recipe/usermetadata/types.d.ts @@ -3,13 +3,19 @@ import OverrideableBuilder from "supertokens-js-override"; import { JSONObject, UserContext } from "../../types"; export type TypeInput = { override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; export type TypeNormalisedInput = { override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; diff --git a/lib/build/recipe/usermetadata/utils.d.ts b/lib/build/recipe/usermetadata/utils.d.ts index 133d4840f..4025b1b44 100644 --- a/lib/build/recipe/usermetadata/utils.d.ts +++ b/lib/build/recipe/usermetadata/utils.d.ts @@ -2,4 +2,8 @@ import { NormalisedAppinfo } from "../../types"; import Recipe from "./recipe"; import { TypeInput, TypeNormalisedInput } from "./types"; -export declare function validateAndNormaliseUserInput(_: Recipe, __: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + _: Recipe, + __: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; diff --git a/lib/build/recipe/usermetadata/utils.js b/lib/build/recipe/usermetadata/utils.js index 1142281c8..349fdf51d 100644 --- a/lib/build/recipe/usermetadata/utils.js +++ b/lib/build/recipe/usermetadata/utils.js @@ -16,7 +16,13 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; function validateAndNormaliseUserInput(_, __, config) { - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { override, }; diff --git a/lib/build/recipe/userroles/index.d.ts b/lib/build/recipe/userroles/index.d.ts index af8d359c2..11a803d66 100644 --- a/lib/build/recipe/userroles/index.d.ts +++ b/lib/build/recipe/userroles/index.d.ts @@ -5,50 +5,99 @@ export default class Wrapper { static init: typeof Recipe.init; static PermissionClaim: import("./permissionClaim").PermissionClaimClass; static UserRoleClaim: import("./userRoleClaim").UserRoleClaimClass; - static addRoleToUser(tenantId: string, userId: string, role: string, userContext?: Record): Promise<{ - status: "OK"; - didUserAlreadyHaveRole: boolean; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; - static removeUserRole(tenantId: string, userId: string, role: string, userContext?: Record): Promise<{ - status: "OK"; - didUserHaveRole: boolean; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; - static getRolesForUser(tenantId: string, userId: string, userContext?: Record): Promise<{ + static addRoleToUser( + tenantId: string, + userId: string, + role: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + didUserAlreadyHaveRole: boolean; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; + static removeUserRole( + tenantId: string, + userId: string, + role: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + didUserHaveRole: boolean; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; + static getRolesForUser( + tenantId: string, + userId: string, + userContext?: Record + ): Promise<{ status: "OK"; roles: string[]; }>; - static getUsersThatHaveRole(tenantId: string, role: string, userContext?: Record): Promise<{ - status: "OK"; - users: string[]; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; - static createNewRoleOrAddPermissions(role: string, permissions: string[], userContext?: Record): Promise<{ + static getUsersThatHaveRole( + tenantId: string, + role: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + users: string[]; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; + static createNewRoleOrAddPermissions( + role: string, + permissions: string[], + userContext?: Record + ): Promise<{ status: "OK"; createdNewRole: boolean; }>; - static getPermissionsForRole(role: string, userContext?: Record): Promise<{ - status: "OK"; - permissions: string[]; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; - static removePermissionsFromRole(role: string, permissions: string[], userContext?: Record): Promise<{ + static getPermissionsForRole( + role: string, + userContext?: Record + ): Promise< + | { + status: "OK"; + permissions: string[]; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; + static removePermissionsFromRole( + role: string, + permissions: string[], + userContext?: Record + ): Promise<{ status: "OK" | "UNKNOWN_ROLE_ERROR"; }>; - static getRolesThatHavePermission(permission: string, userContext?: Record): Promise<{ + static getRolesThatHavePermission( + permission: string, + userContext?: Record + ): Promise<{ status: "OK"; roles: string[]; }>; - static deleteRole(role: string, userContext?: Record): Promise<{ + static deleteRole( + role: string, + userContext?: Record + ): Promise<{ status: "OK"; didRoleExist: boolean; }>; - static getAllRoles(userContext?: Record): Promise<{ + static getAllRoles( + userContext?: Record + ): Promise<{ status: "OK"; roles: string[]; }>; diff --git a/lib/build/recipe/userroles/index.js b/lib/build/recipe/userroles/index.js index c7004dcb4..7211069f5 100644 --- a/lib/build/recipe/userroles/index.js +++ b/lib/build/recipe/userroles/index.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PermissionClaim = exports.UserRoleClaim = exports.getAllRoles = exports.deleteRole = exports.getRolesThatHavePermission = exports.removePermissionsFromRole = exports.getPermissionsForRole = exports.createNewRoleOrAddPermissions = exports.getUsersThatHaveRole = exports.getRolesForUser = exports.removeUserRole = exports.addRoleToUser = exports.init = void 0; const utils_1 = require("../../utils"); @@ -107,6 +109,16 @@ exports.getRolesThatHavePermission = Wrapper.getRolesThatHavePermission; exports.deleteRole = Wrapper.deleteRole; exports.getAllRoles = Wrapper.getAllRoles; var userRoleClaim_2 = require("./userRoleClaim"); -Object.defineProperty(exports, "UserRoleClaim", { enumerable: true, get: function () { return userRoleClaim_2.UserRoleClaim; } }); +Object.defineProperty(exports, "UserRoleClaim", { + enumerable: true, + get: function () { + return userRoleClaim_2.UserRoleClaim; + }, +}); var permissionClaim_2 = require("./permissionClaim"); -Object.defineProperty(exports, "PermissionClaim", { enumerable: true, get: function () { return permissionClaim_2.PermissionClaim; } }); +Object.defineProperty(exports, "PermissionClaim", { + enumerable: true, + get: function () { + return permissionClaim_2.PermissionClaim; + }, +}); diff --git a/lib/build/recipe/userroles/permissionClaim.js b/lib/build/recipe/userroles/permissionClaim.js index 16a5cb348..c022b4080 100644 --- a/lib/build/recipe/userroles/permissionClaim.js +++ b/lib/build/recipe/userroles/permissionClaim.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PermissionClaim = exports.PermissionClaimClass = void 0; const recipe_1 = __importDefault(require("./recipe")); diff --git a/lib/build/recipe/userroles/recipe.d.ts b/lib/build/recipe/userroles/recipe.d.ts index c03fcb524..2e0f19f0e 100644 --- a/lib/build/recipe/userroles/recipe.d.ts +++ b/lib/build/recipe/userroles/recipe.d.ts @@ -16,7 +16,14 @@ export default class Recipe extends RecipeModule { static init(config?: TypeInput): RecipeListFunction; static reset(): void; getAPIsHandled(): APIHandled[]; - handleAPIRequest: (_: string, _tenantId: string | undefined, __: BaseRequest, ___: BaseResponse, ____: normalisedURLPath, _____: HTTPMethod) => Promise; + handleAPIRequest: ( + _: string, + _tenantId: string | undefined, + __: BaseRequest, + ___: BaseResponse, + ____: normalisedURLPath, + _____: HTTPMethod + ) => Promise; handleError(error: error, _: BaseRequest, __: BaseResponse): Promise; getAllCORSHeaders(): string[]; isErrorFromThisRecipe(err: any): err is error; diff --git a/lib/build/recipe/userroles/recipe.js b/lib/build/recipe/userroles/recipe.js index bd813575c..f49939e69 100644 --- a/lib/build/recipe/userroles/recipe.js +++ b/lib/build/recipe/userroles/recipe.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const error_1 = __importDefault(require("../../error")); const querier_1 = require("../../querier"); @@ -40,7 +42,9 @@ class Recipe extends recipeModule_1.default { this.config = (0, utils_1.validateAndNormaliseUserInput)(this, appInfo, config); this.isInServerlessEnv = isInServerlessEnv; { - let builder = new supertokens_js_override_1.default((0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId))); + let builder = new supertokens_js_override_1.default( + (0, recipeImplementation_1.default)(querier_1.Querier.getNewInstanceOrThrowError(recipeId)) + ); this.recipeInterfaceImpl = builder.override(this.config.override.functions).build(); } postSuperTokensInitCallbacks_1.PostSuperTokensInitCallbacks.addPostInitCallback(() => { @@ -88,41 +92,43 @@ class Recipe extends recipeModule_1.default { }; recipe_2.default.getInstanceOrThrowError().addAccessTokenBuilderFromOtherRecipe(tokenPayloadBuilder); recipe_2.default.getInstanceOrThrowError().addIdTokenBuilderFromOtherRecipe(tokenPayloadBuilder); - recipe_2.default.getInstanceOrThrowError().addUserInfoBuilderFromOtherRecipe(async (user, _accessTokenPayload, scopes, tenantId, userContext) => { - let userInfo = {}; - let userRoles = []; - if (scopes.includes("roles") || scopes.includes("permissions")) { - const res = await this.recipeInterfaceImpl.getRolesForUser({ - userId: user.id, - tenantId, - userContext, - }); - if (res.status !== "OK") { - throw new Error("Failed to fetch roles for the user"); - } - userRoles = res.roles; - } - if (scopes.includes("roles")) { - userInfo.roles = userRoles; - } - if (scopes.includes("permissions")) { - const userPermissions = new Set(); - for (const role of userRoles) { - const rolePermissions = await this.recipeInterfaceImpl.getPermissionsForRole({ - role, + recipe_2.default + .getInstanceOrThrowError() + .addUserInfoBuilderFromOtherRecipe(async (user, _accessTokenPayload, scopes, tenantId, userContext) => { + let userInfo = {}; + let userRoles = []; + if (scopes.includes("roles") || scopes.includes("permissions")) { + const res = await this.recipeInterfaceImpl.getRolesForUser({ + userId: user.id, + tenantId, userContext, }); - if (rolePermissions.status !== "OK") { - throw new Error("Failed to fetch permissions for the role"); + if (res.status !== "OK") { + throw new Error("Failed to fetch roles for the user"); } - for (const perm of rolePermissions.permissions) { - userPermissions.add(perm); + userRoles = res.roles; + } + if (scopes.includes("roles")) { + userInfo.roles = userRoles; + } + if (scopes.includes("permissions")) { + const userPermissions = new Set(); + for (const role of userRoles) { + const rolePermissions = await this.recipeInterfaceImpl.getPermissionsForRole({ + role, + userContext, + }); + if (rolePermissions.status !== "OK") { + throw new Error("Failed to fetch permissions for the role"); + } + for (const perm of rolePermissions.permissions) { + userPermissions.add(perm); + } } + userInfo.permissions = Array.from(userPermissions); } - userInfo.permissions = Array.from(userPermissions); - } - return userInfo; - }); + return userInfo; + }); }); } /* Init functions */ @@ -130,15 +136,25 @@ class Recipe extends recipeModule_1.default { if (Recipe.instance !== undefined) { return Recipe.instance; } - throw new Error("Initialisation not done. Did you forget to call the UserRoles.init or SuperTokens.init functions?"); + throw new Error( + "Initialisation not done. Did you forget to call the UserRoles.init or SuperTokens.init functions?" + ); } static init(config) { return (appInfo, isInServerlessEnv, plugins) => { if (Recipe.instance === undefined) { - Recipe.instance = new Recipe(Recipe.RECIPE_ID, appInfo, isInServerlessEnv, (0, utils_2.applyPlugins)(Recipe.RECIPE_ID, config, plugins !== null && plugins !== void 0 ? plugins : [])); + Recipe.instance = new Recipe( + Recipe.RECIPE_ID, + appInfo, + isInServerlessEnv, + (0, utils_2.applyPlugins)( + Recipe.RECIPE_ID, + config, + plugins !== null && plugins !== void 0 ? plugins : [] + ) + ); return Recipe.instance; - } - else { + } else { throw new Error("UserRoles recipe has already been initialised. Please check your code for bugs."); } }; diff --git a/lib/build/recipe/userroles/recipeImplementation.js b/lib/build/recipe/userroles/recipeImplementation.js index 02d395050..3839661ca 100644 --- a/lib/build/recipe/userroles/recipeImplementation.js +++ b/lib/build/recipe/userroles/recipeImplementation.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getRecipeInterface; const normalisedURLPath_1 = __importDefault(require("../../normalisedURLPath")); @@ -23,34 +25,80 @@ const constants_1 = require("../multitenancy/constants"); function getRecipeInterface(querier) { return { addRoleToUser: function ({ userId, role, tenantId, userContext }) { - return querier.sendPutRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/user/role`), { userId, role }, {}, userContext); + return querier.sendPutRequest( + new normalisedURLPath_1.default( + `/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/user/role` + ), + { userId, role }, + {}, + userContext + ); }, removeUserRole: function ({ userId, role, tenantId, userContext }) { - return querier.sendPostRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/user/role/remove`), { userId, role }, userContext); + return querier.sendPostRequest( + new normalisedURLPath_1.default( + `/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/user/role/remove` + ), + { userId, role }, + userContext + ); }, getRolesForUser: function ({ userId, tenantId, userContext }) { - return querier.sendGetRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/user/roles`), { userId }, userContext); + return querier.sendGetRequest( + new normalisedURLPath_1.default( + `/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/user/roles` + ), + { userId }, + userContext + ); }, getUsersThatHaveRole: function ({ role, tenantId, userContext }) { - return querier.sendGetRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/role/users`), { role }, userContext); + return querier.sendGetRequest( + new normalisedURLPath_1.default( + `/${tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId}/recipe/role/users` + ), + { role }, + userContext + ); }, createNewRoleOrAddPermissions: function ({ role, permissions, userContext }) { - return querier.sendPutRequest(new normalisedURLPath_1.default("/recipe/role"), { role, permissions }, {}, userContext); + return querier.sendPutRequest( + new normalisedURLPath_1.default("/recipe/role"), + { role, permissions }, + {}, + userContext + ); }, getPermissionsForRole: function ({ role, userContext }) { - return querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/role/permissions"), { role }, userContext); + return querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/role/permissions"), + { role }, + userContext + ); }, removePermissionsFromRole: function ({ role, permissions, userContext }) { - return querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/role/permissions/remove"), { - role, - permissions, - }, userContext); + return querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/role/permissions/remove"), + { + role, + permissions, + }, + userContext + ); }, getRolesThatHavePermission: function ({ permission, userContext }) { - return querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/permission/roles"), { permission }, userContext); + return querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/permission/roles"), + { permission }, + userContext + ); }, deleteRole: function ({ role, userContext }) { - return querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/role/remove"), { role }, userContext); + return querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/role/remove"), + { role }, + userContext + ); }, getAllRoles: function ({ userContext }) { return querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/roles"), {}, userContext); diff --git a/lib/build/recipe/userroles/types.d.ts b/lib/build/recipe/userroles/types.d.ts index bb5047d1d..1ddd1cba1 100644 --- a/lib/build/recipe/userroles/types.d.ts +++ b/lib/build/recipe/userroles/types.d.ts @@ -5,7 +5,10 @@ export type TypeInput = { skipAddingRolesToAccessToken?: boolean; skipAddingPermissionsToAccessToken?: boolean; override?: { - functions?: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions?: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis?: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -13,7 +16,10 @@ export type TypeNormalisedInput = { skipAddingRolesToAccessToken: boolean; skipAddingPermissionsToAccessToken: boolean; override: { - functions: (originalImplementation: RecipeInterface, builder: OverrideableBuilder) => RecipeInterface; + functions: ( + originalImplementation: RecipeInterface, + builder: OverrideableBuilder + ) => RecipeInterface; apis: (originalImplementation: APIInterface, builder: OverrideableBuilder) => APIInterface; }; }; @@ -24,23 +30,29 @@ export type RecipeInterface = { role: string; tenantId: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - didUserAlreadyHaveRole: boolean; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + didUserAlreadyHaveRole: boolean; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; removeUserRole: (input: { userId: string; role: string; tenantId: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - didUserHaveRole: boolean; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + didUserHaveRole: boolean; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; getRolesForUser: (input: { userId: string; tenantId: string; @@ -53,12 +65,15 @@ export type RecipeInterface = { role: string; tenantId: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - users: string[]; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + users: string[]; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; createNewRoleOrAddPermissions: (input: { role: string; permissions: string[]; @@ -70,12 +85,15 @@ export type RecipeInterface = { getPermissionsForRole: (input: { role: string; userContext: UserContext; - }) => Promise<{ - status: "OK"; - permissions: string[]; - } | { - status: "UNKNOWN_ROLE_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + permissions: string[]; + } + | { + status: "UNKNOWN_ROLE_ERROR"; + } + >; removePermissionsFromRole: (input: { role: string; permissions: string[]; diff --git a/lib/build/recipe/userroles/userRoleClaim.js b/lib/build/recipe/userroles/userRoleClaim.js index 20254bbd7..ec8bdb305 100644 --- a/lib/build/recipe/userroles/userRoleClaim.js +++ b/lib/build/recipe/userroles/userRoleClaim.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UserRoleClaim = exports.UserRoleClaimClass = void 0; const recipe_1 = __importDefault(require("./recipe")); diff --git a/lib/build/recipe/userroles/utils.d.ts b/lib/build/recipe/userroles/utils.d.ts index 133d4840f..4025b1b44 100644 --- a/lib/build/recipe/userroles/utils.d.ts +++ b/lib/build/recipe/userroles/utils.d.ts @@ -2,4 +2,8 @@ import { NormalisedAppinfo } from "../../types"; import Recipe from "./recipe"; import { TypeInput, TypeNormalisedInput } from "./types"; -export declare function validateAndNormaliseUserInput(_: Recipe, __: NormalisedAppinfo, config?: TypeInput): TypeNormalisedInput; +export declare function validateAndNormaliseUserInput( + _: Recipe, + __: NormalisedAppinfo, + config?: TypeInput +): TypeNormalisedInput; diff --git a/lib/build/recipe/userroles/utils.js b/lib/build/recipe/userroles/utils.js index f39ac0b3e..a525e532c 100644 --- a/lib/build/recipe/userroles/utils.js +++ b/lib/build/recipe/userroles/utils.js @@ -16,10 +16,18 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.validateAndNormaliseUserInput = validateAndNormaliseUserInput; function validateAndNormaliseUserInput(_, __, config) { - let override = Object.assign({ functions: (originalImplementation) => originalImplementation, apis: (originalImplementation) => originalImplementation }, config === null || config === void 0 ? void 0 : config.override); + let override = Object.assign( + { + functions: (originalImplementation) => originalImplementation, + apis: (originalImplementation) => originalImplementation, + }, + config === null || config === void 0 ? void 0 : config.override + ); return { - skipAddingRolesToAccessToken: (config === null || config === void 0 ? void 0 : config.skipAddingRolesToAccessToken) === true, - skipAddingPermissionsToAccessToken: (config === null || config === void 0 ? void 0 : config.skipAddingPermissionsToAccessToken) === true, + skipAddingRolesToAccessToken: + (config === null || config === void 0 ? void 0 : config.skipAddingRolesToAccessToken) === true, + skipAddingPermissionsToAccessToken: + (config === null || config === void 0 ? void 0 : config.skipAddingPermissionsToAccessToken) === true, override, }; } diff --git a/lib/build/recipeModule.d.ts b/lib/build/recipeModule.d.ts index eea95cbb4..e277192a9 100644 --- a/lib/build/recipeModule.d.ts +++ b/lib/build/recipeModule.d.ts @@ -9,14 +9,34 @@ export default abstract class RecipeModule { constructor(recipeId: string, appInfo: NormalisedAppinfo); getRecipeId: () => string; getAppInfo: () => NormalisedAppinfo; - returnAPIIdIfCanHandleRequest: (path: NormalisedURLPath, method: HTTPMethod, userContext: UserContext) => Promise<{ - id: string; - tenantId: string; - exactMatch: boolean; - } | undefined>; + returnAPIIdIfCanHandleRequest: ( + path: NormalisedURLPath, + method: HTTPMethod, + userContext: UserContext + ) => Promise< + | { + id: string; + tenantId: string; + exactMatch: boolean; + } + | undefined + >; abstract getAPIsHandled(): APIHandled[]; - abstract handleAPIRequest(id: string, tenantId: string, req: BaseRequest, response: BaseResponse, path: NormalisedURLPath, method: HTTPMethod, userContext: UserContext): Promise; - abstract handleError(error: STError, request: BaseRequest, response: BaseResponse, userContext: UserContext): Promise; + abstract handleAPIRequest( + id: string, + tenantId: string, + req: BaseRequest, + response: BaseResponse, + path: NormalisedURLPath, + method: HTTPMethod, + userContext: UserContext + ): Promise; + abstract handleError( + error: STError, + request: BaseRequest, + response: BaseResponse, + userContext: UserContext + ): Promise; abstract getAllCORSHeaders(): string[]; abstract isErrorFromThisRecipe(err: any): err is STError; } diff --git a/lib/build/recipeModule.js b/lib/build/recipeModule.js index 1f3dfb145..75c3219ae 100644 --- a/lib/build/recipeModule.js +++ b/lib/build/recipeModule.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const normalisedURLPath_1 = __importDefault(require("./normalisedURLPath")); const constants_1 = require("./recipe/multitenancy/constants"); @@ -53,11 +55,12 @@ class RecipeModule { userContext, }); return { id: currAPI.id, tenantId: finalTenantId, exactMatch: true }; - } - else if (remainingPath !== undefined && + } else if ( + remainingPath !== undefined && this.appInfo.apiBasePath .appendPath(currAPI.pathWithoutApiBasePath) - .equals(this.appInfo.apiBasePath.appendPath(remainingPath))) { + .equals(this.appInfo.apiBasePath.appendPath(remainingPath)) + ) { const finalTenantId = await mtRecipe.recipeInterfaceImpl.getTenantId({ tenantIdFromFrontend: tenantId === undefined ? constants_1.DEFAULT_TENANT_ID : tenantId, userContext, diff --git a/lib/build/supertokens.d.ts b/lib/build/supertokens.d.ts index 226007f46..beb031251 100644 --- a/lib/build/supertokens.d.ts +++ b/lib/build/supertokens.d.ts @@ -17,34 +17,53 @@ export default class SuperTokens { static init(config: TypeInput): void; static reset(): void; static getInstanceOrThrowError(): SuperTokens; - handleAPI: (matchedRecipe: RecipeModule, id: string, tenantId: string, request: BaseRequest, response: BaseResponse, path: NormalisedURLPath, method: HTTPMethod, userContext: UserContext) => Promise; + handleAPI: ( + matchedRecipe: RecipeModule, + id: string, + tenantId: string, + request: BaseRequest, + response: BaseResponse, + path: NormalisedURLPath, + method: HTTPMethod, + userContext: UserContext + ) => Promise; getAllCORSHeaders: () => string[]; - getUserCount: (includeRecipeIds: string[] | undefined, tenantId: string | undefined, userContext: UserContext) => Promise; + getUserCount: ( + includeRecipeIds: string[] | undefined, + tenantId: string | undefined, + userContext: UserContext + ) => Promise; createUserIdMapping: (input: { superTokensUserId: string; externalUserId: string; externalUserIdInfo?: string; force?: boolean; userContext: UserContext; - }) => Promise<{ - status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR"; - } | { - status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR"; - doesSuperTokensUserIdExist: boolean; - doesExternalUserIdExist: boolean; - }>; + }) => Promise< + | { + status: "OK" | "UNKNOWN_SUPERTOKENS_USER_ID_ERROR"; + } + | { + status: "USER_ID_MAPPING_ALREADY_EXISTS_ERROR"; + doesSuperTokensUserIdExist: boolean; + doesExternalUserIdExist: boolean; + } + >; getUserIdMapping: (input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"; userContext: UserContext; - }) => Promise<{ - status: "OK"; - superTokensUserId: string; - externalUserId: string; - externalUserIdInfo: string | undefined; - } | { - status: "UNKNOWN_MAPPING_ERROR"; - }>; + }) => Promise< + | { + status: "OK"; + superTokensUserId: string; + externalUserId: string; + externalUserIdInfo: string | undefined; + } + | { + status: "UNKNOWN_MAPPING_ERROR"; + } + >; deleteUserIdMapping: (input: { userId: string; userIdType?: "SUPERTOKENS" | "EXTERNAL" | "ANY"; diff --git a/lib/build/supertokens.js b/lib/build/supertokens.js index 242d61e79..72c86c096 100644 --- a/lib/build/supertokens.js +++ b/lib/build/supertokens.js @@ -13,9 +13,11 @@ * License for the specific language governing permissions and limitations * under the License. */ -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("./utils"); const querier_1 = require("./querier"); @@ -27,6 +29,7 @@ const logger_1 = require("./logger"); const postSuperTokensInitCallbacks_1 = require("./postSuperTokensInitCallbacks"); const constants_2 = require("./recipe/multitenancy/constants"); const version_1 = require("./version"); +const recipe_1 = __importDefault(require("./recipe/session/recipe")); class SuperTokens { constructor(config) { var _a, _b, _c, _d, _e; @@ -49,16 +52,24 @@ class SuperTokens { let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); let apiVersion = await querier.getAPIVersion(userContext); if ((0, utils_1.maxVersion)(apiVersion, "2.7") === "2.7") { - throw new Error("Please use core version >= 3.5 to call this function. Otherwise, you can call .getUserCount() instead (for example, EmailPassword.getUserCount())"); + throw new Error( + "Please use core version >= 3.5 to call this function. Otherwise, you can call .getUserCount() instead (for example, EmailPassword.getUserCount())" + ); } let includeRecipeIdsStr = undefined; if (includeRecipeIds !== undefined) { includeRecipeIdsStr = includeRecipeIds.join(","); } - let response = await querier.sendGetRequest(new normalisedURLPath_1.default(`/${tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId}/users/count`), { - includeRecipeIds: includeRecipeIdsStr, - includeAllTenants: tenantId === undefined, - }, userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default( + `/${tenantId === undefined ? constants_2.DEFAULT_TENANT_ID : tenantId}/users/count` + ), + { + includeRecipeIds: includeRecipeIdsStr, + includeAllTenants: tenantId === undefined, + }, + userContext + ); return Number(response.count); }; this.createUserIdMapping = async function (input) { @@ -66,14 +77,17 @@ class SuperTokens { let cdiVersion = await querier.getAPIVersion(input.userContext); if ((0, utils_1.maxVersion)("2.15", cdiVersion) === cdiVersion) { // create userId mapping is only available >= CDI 2.15 - return await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/userid/map"), { - superTokensUserId: input.superTokensUserId, - externalUserId: input.externalUserId, - externalUserIdInfo: input.externalUserIdInfo, - force: input.force, - }, input.userContext); - } - else { + return await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/userid/map"), + { + superTokensUserId: input.superTokensUserId, + externalUserId: input.externalUserId, + externalUserIdInfo: input.externalUserIdInfo, + force: input.force, + }, + input.userContext + ); + } else { throw new global.Error("Please upgrade the SuperTokens core to >= 3.15.0"); } }; @@ -82,13 +96,16 @@ class SuperTokens { let cdiVersion = await querier.getAPIVersion(input.userContext); if ((0, utils_1.maxVersion)("2.15", cdiVersion) === cdiVersion) { // create userId mapping is only available >= CDI 2.15 - let response = await querier.sendGetRequest(new normalisedURLPath_1.default("/recipe/userid/map"), { - userId: input.userId, - userIdType: input.userIdType, - }, input.userContext); + let response = await querier.sendGetRequest( + new normalisedURLPath_1.default("/recipe/userid/map"), + { + userId: input.userId, + userIdType: input.userIdType, + }, + input.userContext + ); return response; - } - else { + } else { throw new global.Error("Please upgrade the SuperTokens core to >= 3.15.0"); } }; @@ -96,13 +113,16 @@ class SuperTokens { let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); let cdiVersion = await querier.getAPIVersion(input.userContext); if ((0, utils_1.maxVersion)("2.15", cdiVersion) === cdiVersion) { - return await querier.sendPostRequest(new normalisedURLPath_1.default("/recipe/userid/map/remove"), { - userId: input.userId, - userIdType: input.userIdType, - force: input.force, - }, input.userContext); - } - else { + return await querier.sendPostRequest( + new normalisedURLPath_1.default("/recipe/userid/map/remove"), + { + userId: input.userId, + userIdType: input.userIdType, + force: input.force, + }, + input.userContext + ); + } else { throw new global.Error("Please upgrade the SuperTokens core to >= 3.15.0"); } }; @@ -110,29 +130,45 @@ class SuperTokens { let querier = querier_1.Querier.getNewInstanceOrThrowError(undefined); let cdiVersion = await querier.getAPIVersion(input.userContext); if ((0, utils_1.maxVersion)("2.15", cdiVersion) === cdiVersion) { - return await querier.sendPutRequest(new normalisedURLPath_1.default("/recipe/userid/external-user-id-info"), { - userId: input.userId, - userIdType: input.userIdType, - externalUserIdInfo: input.externalUserIdInfo, - }, {}, input.userContext); - } - else { + return await querier.sendPutRequest( + new normalisedURLPath_1.default("/recipe/userid/external-user-id-info"), + { + userId: input.userId, + userIdType: input.userIdType, + externalUserIdInfo: input.externalUserIdInfo, + }, + {}, + input.userContext + ); + } else { throw new global.Error("Please upgrade the SuperTokens core to >= 3.15.0"); } }; this.middleware = async (request, response, userContext) => { (0, logger_1.logDebugMessage)("middleware: Started"); - let path = this.appInfo.apiGatewayPath.appendPath(new normalisedURLPath_1.default(request.getOriginalURL())); + let path = this.appInfo.apiGatewayPath.appendPath( + new normalisedURLPath_1.default(request.getOriginalURL()) + ); let method = (0, utils_1.normaliseHttpMethod)(request.getMethod()); - const handlerFromApis = this.pluginRouteHandlers.find((handler) => handler.path === path.getAsStringDangerous() && handler.method === method); + const handlerFromApis = this.pluginRouteHandlers.find( + (handler) => handler.path === path.getAsStringDangerous() && handler.method === method + ); if (handlerFromApis) { - handlerFromApis.handler(request, response, userContext); + let session = undefined; + if (handlerFromApis.verifySessionOptions !== undefined) { + session = await recipe_1.default + .getInstanceOrThrowError() + .verifySession(handlerFromApis.verifySessionOptions, request, response, userContext); + } + handlerFromApis.handler(request, response, session, userContext); return true; } // if the prefix of the URL doesn't match the base path, we skip if (!path.startsWith(this.appInfo.apiBasePath)) { - (0, logger_1.logDebugMessage)("middleware: Not handling because request path did not start with config path. Request path: " + - path.getAsStringDangerous()); + (0, logger_1.logDebugMessage)( + "middleware: Not handling because request path did not start with config path. Request path: " + + path.getAsStringDangerous() + ); return false; } let requestRID = (0, utils_1.getRidFromHeader)(request); @@ -144,12 +180,14 @@ class SuperTokens { async function handleWithoutRid(recipeModules) { let bestMatch = undefined; for (let i = 0; i < recipeModules.length; i++) { - (0, logger_1.logDebugMessage)("middleware: Checking recipe ID for match: " + - recipeModules[i].getRecipeId() + - " with path: " + - path.getAsStringDangerous() + - " and method: " + - method); + (0, logger_1.logDebugMessage)( + "middleware: Checking recipe ID for match: " + + recipeModules[i].getRecipeId() + + " with path: " + + path.getAsStringDangerous() + + " and method: " + + method + ); let idResult = await recipeModules[i].returnAPIIdIfCanHandleRequest(path, method, userContext); if (idResult !== undefined) { // The request path may or may not include the tenantId. `returnAPIIdIfCanHandleRequest` handles both cases. @@ -168,9 +206,19 @@ class SuperTokens { if (bestMatch !== undefined) { const { idResult, recipeModule } = bestMatch; (0, logger_1.logDebugMessage)("middleware: Request being handled by recipe. ID is: " + idResult.id); - let requestHandled = await recipeModule.handleAPIRequest(idResult.id, idResult.tenantId, request, response, path, method, userContext); + let requestHandled = await recipeModule.handleAPIRequest( + idResult.id, + idResult.tenantId, + request, + response, + path, + method, + userContext + ); if (!requestHandled) { - (0, logger_1.logDebugMessage)("middleware: Not handled because API returned requestHandled as false"); + (0, logger_1.logDebugMessage)( + "middleware: Not handled because API returned requestHandled as false" + ); return false; } (0, logger_1.logDebugMessage)("middleware: Ended"); @@ -186,19 +234,23 @@ class SuperTokens { let matchedRecipe = []; // we loop through all recipe modules to find the one with the matching rId for (let i = 0; i < this.recipeModules.length; i++) { - (0, logger_1.logDebugMessage)("middleware: Checking recipe ID for match: " + this.recipeModules[i].getRecipeId()); + (0, logger_1.logDebugMessage)( + "middleware: Checking recipe ID for match: " + this.recipeModules[i].getRecipeId() + ); if (this.recipeModules[i].getRecipeId() === requestRID) { matchedRecipe.push(this.recipeModules[i]); - } - else if (requestRID === "thirdpartyemailpassword") { - if (this.recipeModules[i].getRecipeId() === "thirdparty" || - this.recipeModules[i].getRecipeId() === "emailpassword") { + } else if (requestRID === "thirdpartyemailpassword") { + if ( + this.recipeModules[i].getRecipeId() === "thirdparty" || + this.recipeModules[i].getRecipeId() === "emailpassword" + ) { matchedRecipe.push(this.recipeModules[i]); } - } - else if (requestRID === "thirdpartypasswordless") { - if (this.recipeModules[i].getRecipeId() === "thirdparty" || - this.recipeModules[i].getRecipeId() === "passwordless") { + } else if (requestRID === "thirdpartypasswordless") { + if ( + this.recipeModules[i].getRecipeId() === "thirdparty" || + this.recipeModules[i].getRecipeId() === "passwordless" + ) { matchedRecipe.push(this.recipeModules[i]); } } @@ -208,7 +260,9 @@ class SuperTokens { return handleWithoutRid(this.recipeModules); } for (let i = 0; i < matchedRecipe.length; i++) { - (0, logger_1.logDebugMessage)("middleware: Matched with recipe IDs: " + matchedRecipe[i].getRecipeId()); + (0, logger_1.logDebugMessage)( + "middleware: Matched with recipe IDs: " + matchedRecipe[i].getRecipeId() + ); } let idResult = undefined; let finalMatchedRecipe = undefined; @@ -217,15 +271,18 @@ class SuperTokens { // the path and methods of the APIs exposed via those recipes is unique. let currIdResult = await matchedRecipe[i].returnAPIIdIfCanHandleRequest(path, method, userContext); if (currIdResult !== undefined) { - if (idResult === undefined || + if ( + idResult === undefined || // The request path may or may not include the tenantId. `returnAPIIdIfCanHandleRequest` handles both cases. // If one recipe matches with tenantId and another matches exactly, we prefer the exact match. - (currIdResult.exactMatch === true && idResult.exactMatch === false)) { + (currIdResult.exactMatch === true && idResult.exactMatch === false) + ) { finalMatchedRecipe = matchedRecipe[i]; idResult = currIdResult; - } - else { - throw new Error("Two recipes have matched the same API path and method! This is a bug in the SDK. Please contact support."); + } else { + throw new Error( + "Two recipes have matched the same API path and method! This is a bug in the SDK. Please contact support." + ); } } } @@ -234,30 +291,45 @@ class SuperTokens { } (0, logger_1.logDebugMessage)("middleware: Request being handled by recipe. ID is: " + idResult.id); // give task to the matched recipe - let requestHandled = await finalMatchedRecipe.handleAPIRequest(idResult.id, idResult.tenantId, request, response, path, method, userContext); + let requestHandled = await finalMatchedRecipe.handleAPIRequest( + idResult.id, + idResult.tenantId, + request, + response, + path, + method, + userContext + ); if (!requestHandled) { - (0, logger_1.logDebugMessage)("middleware: Not handled because API returned requestHandled as false"); + (0, logger_1.logDebugMessage)( + "middleware: Not handled because API returned requestHandled as false" + ); return false; } (0, logger_1.logDebugMessage)("middleware: Ended"); return true; - } - else { + } else { return handleWithoutRid(this.recipeModules); } }; this.errorHandler = async (err, request, response, userContext) => { (0, logger_1.logDebugMessage)("errorHandler: Started"); if (error_1.default.isErrorFromSuperTokens(err)) { - (0, logger_1.logDebugMessage)("errorHandler: Error is from SuperTokens recipe. Message: " + err.message); + (0, logger_1.logDebugMessage)( + "errorHandler: Error is from SuperTokens recipe. Message: " + err.message + ); if (err.type === error_1.default.BAD_INPUT_ERROR) { (0, logger_1.logDebugMessage)("errorHandler: Sending 400 status code response"); return (0, utils_1.sendNon200ResponseWithMessage)(response, err.message, 400); } for (let i = 0; i < this.recipeModules.length; i++) { - (0, logger_1.logDebugMessage)("errorHandler: Checking recipe for match: " + this.recipeModules[i].getRecipeId()); + (0, logger_1.logDebugMessage)( + "errorHandler: Checking recipe for match: " + this.recipeModules[i].getRecipeId() + ); if (this.recipeModules[i].isErrorFromThisRecipe(err)) { - (0, logger_1.logDebugMessage)("errorHandler: Matched with recipeID: " + this.recipeModules[i].getRecipeId()); + (0, logger_1.logDebugMessage)( + "errorHandler: Matched with recipeID: " + this.recipeModules[i].getRecipeId() + ); return await this.recipeModules[i].handleError(err, request, response, userContext); } } @@ -310,23 +382,35 @@ class SuperTokens { (0, logger_1.enableDebugLogs)(); } (0, logger_1.logDebugMessage)("Started SuperTokens with debug logging (supertokens.init called)"); - const originToPrint = config.appInfo.origin === undefined - ? undefined - : typeof config.appInfo.origin === "string" + const originToPrint = + config.appInfo.origin === undefined + ? undefined + : typeof config.appInfo.origin === "string" ? config.appInfo.origin : "function"; - (0, logger_1.logDebugMessage)("appInfo: " + - JSON.stringify(Object.assign(Object.assign({}, config.appInfo), { origin: originToPrint }))); + (0, logger_1.logDebugMessage)( + "appInfo: " + JSON.stringify(Object.assign(Object.assign({}, config.appInfo), { origin: originToPrint })) + ); this.framework = config.framework !== undefined ? config.framework : "express"; (0, logger_1.logDebugMessage)("framework: " + this.framework); this.appInfo = (0, utils_1.normaliseInputAppInfoOrThrowError)(config.appInfo); this.supertokens = config.supertokens; - querier_1.Querier.init((_b = config.supertokens) === null || _b === void 0 ? void 0 : _b.connectionURI.split(";").filter((h) => h !== "").map((h) => { - return { - domain: new normalisedURLDomain_1.default(h.trim()), - basePath: new normalisedURLPath_1.default(h.trim()), - }; - }), (_c = config.supertokens) === null || _c === void 0 ? void 0 : _c.apiKey, (_d = config.supertokens) === null || _d === void 0 ? void 0 : _d.networkInterceptor, (_e = config.supertokens) === null || _e === void 0 ? void 0 : _e.disableCoreCallCache); + querier_1.Querier.init( + (_b = config.supertokens) === null || _b === void 0 + ? void 0 + : _b.connectionURI + .split(";") + .filter((h) => h !== "") + .map((h) => { + return { + domain: new normalisedURLDomain_1.default(h.trim()), + basePath: new normalisedURLPath_1.default(h.trim()), + }; + }), + (_c = config.supertokens) === null || _c === void 0 ? void 0 : _c.apiKey, + (_d = config.supertokens) === null || _d === void 0 ? void 0 : _d.networkInterceptor, + (_e = config.supertokens) === null || _e === void 0 ? void 0 : _e.disableCoreCallCache + ); if (config.recipeList === undefined || config.recipeList.length === 0) { throw new Error("Please provide at least one recipe to the supertokens.init function call"); } @@ -353,30 +437,22 @@ class SuperTokens { let OAuth2ProviderRecipe = require("./recipe/oauth2provider/recipe").default; let OpenIdRecipe = require("./recipe/openid/recipe").default; let jwtRecipe = require("./recipe/jwt/recipe").default; - const overrideMaps = finalPluginList - .filter((p) => p.overrideMap !== undefined) - .map((p) => p.overrideMap); + const overrideMaps = finalPluginList.filter((p) => p.overrideMap !== undefined).map((p) => p.overrideMap); this.recipeModules = config.recipeList.map((func) => { const recipeModule = func(this.appInfo, this.isInServerlessEnv, overrideMaps); if (recipeModule.getRecipeId() === MultitenancyRecipe.RECIPE_ID) { multitenancyFound = true; - } - else if (recipeModule.getRecipeId() === UserMetadataRecipe.RECIPE_ID) { + } else if (recipeModule.getRecipeId() === UserMetadataRecipe.RECIPE_ID) { userMetadataFound = true; - } - else if (recipeModule.getRecipeId() === MultiFactorAuthRecipe.RECIPE_ID) { + } else if (recipeModule.getRecipeId() === MultiFactorAuthRecipe.RECIPE_ID) { multiFactorAuthFound = true; - } - else if (recipeModule.getRecipeId() === TotpRecipe.RECIPE_ID) { + } else if (recipeModule.getRecipeId() === TotpRecipe.RECIPE_ID) { totpFound = true; - } - else if (recipeModule.getRecipeId() === OAuth2ProviderRecipe.RECIPE_ID) { + } else if (recipeModule.getRecipeId() === OAuth2ProviderRecipe.RECIPE_ID) { oauth2Found = true; - } - else if (recipeModule.getRecipeId() === OpenIdRecipe.RECIPE_ID) { + } else if (recipeModule.getRecipeId() === OpenIdRecipe.RECIPE_ID) { openIdFound = true; - } - else if (recipeModule.getRecipeId() === jwtRecipe.RECIPE_ID) { + } else if (recipeModule.getRecipeId() === jwtRecipe.RECIPE_ID) { jwtFound = true; } return recipeModule; diff --git a/lib/build/thirdpartyUtils.d.ts b/lib/build/thirdpartyUtils.d.ts index 8db4b25a7..84517d5e2 100644 --- a/lib/build/thirdpartyUtils.d.ts +++ b/lib/build/thirdpartyUtils.d.ts @@ -1,22 +1,34 @@ // @ts-nocheck import * as jose from "jose"; -export declare function doGetRequest(url: string, queryParams?: { - [key: string]: string; -}, headers?: { - [key: string]: string; -}): Promise<{ +export declare function doGetRequest( + url: string, + queryParams?: { + [key: string]: string; + }, + headers?: { + [key: string]: string; + } +): Promise<{ jsonResponse: Record | undefined; status: number; stringResponse: string; }>; -export declare function doPostRequest(url: string, params: { - [key: string]: any; -}, headers?: { - [key: string]: string; -}): Promise<{ +export declare function doPostRequest( + url: string, + params: { + [key: string]: any; + }, + headers?: { + [key: string]: string; + } +): Promise<{ jsonResponse: Record | undefined; status: number; stringResponse: string; }>; -export declare function verifyIdTokenFromJWKSEndpointAndGetPayload(idToken: string, jwks: jose.JWTVerifyGetKey, otherOptions: jose.JWTVerifyOptions): Promise; +export declare function verifyIdTokenFromJWKSEndpointAndGetPayload( + idToken: string, + jwks: jose.JWTVerifyGetKey, + otherOptions: jose.JWTVerifyOptions +): Promise; export declare function getOIDCDiscoveryInfo(issuer: string): Promise; diff --git a/lib/build/thirdpartyUtils.js b/lib/build/thirdpartyUtils.js index 439f2f247..cb3344cb5 100644 --- a/lib/build/thirdpartyUtils.js +++ b/lib/build/thirdpartyUtils.js @@ -1,40 +1,61 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; +var __createBinding = + (this && this.__createBinding) || + (Object.create + ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + }, + }; + } + Object.defineProperty(o, k2, desc); + } + : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); +var __setModuleDefault = + (this && this.__setModuleDefault) || + (Object.create + ? function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } + : function (o, v) { + o["default"] = v; + }); +var __importStar = + (this && this.__importStar) || + (function () { + var ownKeys = function (o) { + ownKeys = + Object.getOwnPropertyNames || + function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) + for (var k = ownKeys(mod), i = 0; i < k.length; i++) + if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + })(); +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.doGetRequest = doGetRequest; exports.doPostRequest = doPostRequest; @@ -46,7 +67,9 @@ const utils_1 = require("./utils"); const normalisedURLDomain_1 = __importDefault(require("./normalisedURLDomain")); const normalisedURLPath_1 = __importDefault(require("./normalisedURLPath")); async function doGetRequest(url, queryParams, headers) { - (0, logger_1.logDebugMessage)(`GET request to ${url}, with query params ${JSON.stringify(queryParams)} and headers ${JSON.stringify(headers)}`); + (0, logger_1.logDebugMessage)( + `GET request to ${url}, with query params ${JSON.stringify(queryParams)} and headers ${JSON.stringify(headers)}` + ); if ((headers === null || headers === void 0 ? void 0 : headers["Accept"]) === undefined) { headers = Object.assign(Object.assign({}, headers), { Accept: "application/json" }); } @@ -73,7 +96,9 @@ async function doPostRequest(url, params, headers) { } headers["Content-Type"] = "application/x-www-form-urlencoded"; headers["Accept"] = "application/json"; - (0, logger_1.logDebugMessage)(`POST request to ${url}, with params ${JSON.stringify(params)} and headers ${JSON.stringify(headers)}`); + (0, logger_1.logDebugMessage)( + `POST request to ${url}, with params ${JSON.stringify(params)} and headers ${JSON.stringify(headers)}` + ); const body = new URLSearchParams(params).toString(); let response = await (0, utils_1.doFetch)(url, { method: "POST", @@ -104,9 +129,13 @@ async function getOIDCDiscoveryInfo(issuer) { if (oidcInfoMap[issuer] !== undefined) { return oidcInfoMap[issuer]; } - const oidcInfo = await doGetRequest(normalizedDomain.getAsStringDangerous() + normalizedPath.getAsStringDangerous()); + const oidcInfo = await doGetRequest( + normalizedDomain.getAsStringDangerous() + normalizedPath.getAsStringDangerous() + ); if (oidcInfo.status >= 400) { - (0, logger_1.logDebugMessage)(`Received response with status ${oidcInfo.status} and body ${oidcInfo.stringResponse}`); + (0, logger_1.logDebugMessage)( + `Received response with status ${oidcInfo.status} and body ${oidcInfo.stringResponse}` + ); throw new Error(`Received response with status ${oidcInfo.status} and body ${oidcInfo.stringResponse}`); } oidcInfoMap[issuer] = oidcInfo.jsonResponse; diff --git a/lib/build/types.d.ts b/lib/build/types.d.ts index 6153a8775..025ff9c61 100644 --- a/lib/build/types.d.ts +++ b/lib/build/types.d.ts @@ -15,7 +15,11 @@ import type { TypeInput as MultitenancyTypeInput } from "./recipe/multitenancy/t import type { TypeInput as OAuth2ProviderTypeInput } from "./recipe/oauth2provider/types"; import type { TypeInput as OpenIdTypeInput } from "./recipe/openid/types"; import type { TypeInput as PasswordlessTypeInput } from "./recipe/passwordless/types"; -import type { TypeInput as SessionTypeInput } from "./recipe/session/types"; +import type { + SessionContainerInterface, + TypeInput as SessionTypeInput, + VerifySessionOptions, +} from "./recipe/session/types"; import type { TypeInput as ThirdPartyTypeInput } from "./recipe/thirdparty/types"; import type { TypeInput as TotpTypeInput } from "./recipe/totp/types"; import type { TypeInput as UserMetadataTypeInput } from "./recipe/usermetadata/types"; @@ -32,10 +36,7 @@ export type UserContext = Branded, "UserContext">; export type AppInfo = { appName: string; websiteDomain?: string; - origin?: string | ((input: { - request: BaseRequest | undefined; - userContext: UserContext; - }) => string); + origin?: string | ((input: { request: BaseRequest | undefined; userContext: UserContext }) => string); websiteBasePath?: string; apiDomain: string; apiBasePath?: string; @@ -43,16 +44,10 @@ export type AppInfo = { }; export type NormalisedAppinfo = { appName: string; - getOrigin: (input: { - request: BaseRequest | undefined; - userContext: UserContext; - }) => NormalisedURLDomain; + getOrigin: (input: { request: BaseRequest | undefined; userContext: UserContext }) => NormalisedURLDomain; apiDomain: NormalisedURLDomain; topLevelAPIDomain: string; - getTopLevelWebsiteDomain: (input: { - request: BaseRequest | undefined; - userContext: UserContext; - }) => string; + getTopLevelWebsiteDomain: (input: { request: BaseRequest | undefined; userContext: UserContext }) => string; apiBasePath: NormalisedURLPath; apiGatewayPath: NormalisedURLPath; websiteBasePath: NormalisedURLPath; @@ -92,7 +87,13 @@ export type RecipePluginOverride = { export type PluginRouteHandler = { method: HTTPMethod; path: string; - handler: (req: BaseRequest, res: BaseResponse, userContext: UserContext) => Promise<{ + verifySessionOptions?: VerifySessionOptions; + handler: ( + req: BaseRequest, + res: BaseResponse, + session: SessionContainerInterface | undefined, + userContext: UserContext + ) => Promise<{ status: number; body: JSONObject; } | null>; @@ -101,13 +102,18 @@ export type SuperTokensPlugin = { id: string; version?: string; compatibleSDKVersions?: string | string[]; - dependencies?: (pluginsAbove: SuperTokensPlugin[], sdkVersion: string) => { - status: "OK"; - pluginsToAdd?: SuperTokensPlugin[]; - } | { - status: "ERROR"; - message: string; - }; + dependencies?: ( + pluginsAbove: SuperTokensPlugin[], + sdkVersion: string + ) => + | { + status: "OK"; + pluginsToAdd?: SuperTokensPlugin[]; + } + | { + status: "ERROR"; + message: string; + }; overrideMap?: { [recipeId in keyof AllRecipeConfigs]?: RecipePluginOverride & { recipeInitRequired?: boolean | ((sdkVersion: string) => boolean); @@ -135,7 +141,11 @@ export interface HttpRequest { params?: Record; body?: any; } -export type RecipeListFunction = (appInfo: NormalisedAppinfo, isInServerlessEnv: boolean, overrideMaps: NonNullable[]) => RecipeModule; +export type RecipeListFunction = ( + appInfo: NormalisedAppinfo, + isInServerlessEnv: boolean, + overrideMaps: NonNullable[] +) => RecipeModule; export type APIHandled = { pathWithoutApiBasePath: NormalisedURLPath; method: HTTPMethod; @@ -168,10 +178,7 @@ export type User = { verified: boolean; hasSameEmailAs: (email: string | undefined) => boolean; hasSamePhoneNumberAs: (phoneNumber: string | undefined) => boolean; - hasSameThirdPartyInfoAs: (thirdParty?: { - id: string; - userId: string; - }) => boolean; + hasSameThirdPartyInfoAs: (thirdParty?: { id: string; userId: string }) => boolean; toJson: () => any; })[]; toJson: () => any; diff --git a/lib/build/user.d.ts b/lib/build/user.d.ts index 2c9af724e..4b69bfc3c 100644 --- a/lib/build/user.d.ts +++ b/lib/build/user.d.ts @@ -14,10 +14,7 @@ export declare class LoginMethod implements RecipeLevelUser { constructor(loginMethod: UserWithoutHelperFunctions["loginMethods"][number]); hasSameEmailAs(email: string | undefined): boolean; hasSamePhoneNumberAs(phoneNumber: string | undefined): boolean; - hasSameThirdPartyInfoAs(thirdParty?: { - id: string; - userId: string; - }): boolean; + hasSameThirdPartyInfoAs(thirdParty?: { id: string; userId: string }): boolean; toJson(): JSONObject; } export declare class User implements UserType { diff --git a/lib/build/user.js b/lib/build/user.js index 7207280e7..b29087ffa 100644 --- a/lib/build/user.js +++ b/lib/build/user.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.User = exports.LoginMethod = void 0; const recipeUserId_1 = __importDefault(require("./recipeUserId")); @@ -34,8 +36,7 @@ class LoginMethod { // this means that the phone number is not valid according to the E.164 standard. // but we still just trim it. phoneNumber = phoneNumber.trim(); - } - else { + } else { phoneNumber = parsedPhoneNumber.format("E.164"); } return this.phoneNumber !== undefined && this.phoneNumber === phoneNumber; @@ -46,9 +47,11 @@ class LoginMethod { } thirdParty.id = thirdParty.id.trim(); thirdParty.userId = thirdParty.userId.trim(); - return (this.thirdParty !== undefined && + return ( + this.thirdParty !== undefined && this.thirdParty.id === thirdParty.id && - this.thirdParty.userId === thirdParty.userId); + this.thirdParty.userId === thirdParty.userId + ); } toJson() { return { diff --git a/lib/build/utils.d.ts b/lib/build/utils.d.ts index c16046211..30a07a6b0 100644 --- a/lib/build/utils.d.ts +++ b/lib/build/utils.d.ts @@ -1,5 +1,13 @@ // @ts-nocheck -import type { AppInfo, NormalisedAppinfo, HTTPMethod, JSONObject, UserContext, SuperTokensPlugin, AllRecipeConfigs } from "./types"; +import type { + AppInfo, + NormalisedAppinfo, + HTTPMethod, + JSONObject, + UserContext, + SuperTokensPlugin, + AllRecipeConfigs, +} from "./types"; import type { BaseRequest, BaseResponse } from "./framework"; import { User } from "./user"; import { SessionContainer } from "./recipe/session"; @@ -13,11 +21,15 @@ export declare function sendNon200Response(res: BaseResponse, statusCode: number export declare function send200Response(res: BaseResponse, responseJson: any): void; export declare function isAnIpAddress(ipaddress: string): boolean; export declare function getNormalisedShouldTryLinkingWithSessionUserFlag(req: BaseRequest, body: any): any; -export declare function getBackwardsCompatibleUserInfo(req: BaseRequest, result: { - user: User; - session: SessionContainer; - createdNewRecipeUser?: boolean; -}, userContext: UserContext): JSONObject; +export declare function getBackwardsCompatibleUserInfo( + req: BaseRequest, + result: { + user: User; + session: SessionContainer; + createdNewRecipeUser?: boolean; + }, + userContext: UserContext +): JSONObject; export declare function getLatestFDIVersionFromFDIList(fdiHeaderValue: string): string; export declare function hasGreaterThanEqualToFDI(req: BaseRequest, version: string): boolean; export declare function getRidFromHeader(req: BaseRequest): string | undefined; @@ -25,30 +37,51 @@ export declare function frontendHasInterceptor(req: BaseRequest): boolean; export declare function humaniseMilliseconds(ms: number): string; export declare function makeDefaultUserContextFromAPI(request: BaseRequest): UserContext; export declare function getUserContext(inputUserContext?: Record): UserContext; -export declare function setRequestInUserContextIfNotDefined(userContext: UserContext | undefined, request: BaseRequest): UserContext; +export declare function setRequestInUserContextIfNotDefined( + userContext: UserContext | undefined, + request: BaseRequest +): UserContext; export declare function getTopLevelDomainForSameSiteResolution(url: string): string; export declare function getFromObjectCaseInsensitive(key: string, object: Record): T | undefined; -export declare function postWithFetch(url: string, headers: Record, body: any, { successLog, errorLogHeader }: { - successLog: string; - errorLogHeader: string; -}): Promise<{ - resp: { - status: number; - body: any; - }; -} | { - error: any; -}>; +export declare function postWithFetch( + url: string, + headers: Record, + body: any, + { + successLog, + errorLogHeader, + }: { + successLog: string; + errorLogHeader: string; + } +): Promise< + | { + resp: { + status: number; + body: any; + }; + } + | { + error: any; + } +>; export declare function normaliseEmail(email: string): string; export declare function toCamelCase(str: string): string; export declare function toSnakeCase(str: string): string; -export declare function transformObjectKeys(obj: { - [key: string]: any; -}, caseType: "snake-case" | "camelCase"): T; +export declare function transformObjectKeys( + obj: { + [key: string]: any; + }, + caseType: "snake-case" | "camelCase" +): T; export declare const getProcess: () => any; export declare const getBuffer: () => any; export declare const isTestEnv: () => boolean; export declare const encodeBase64: (value: string) => string; export declare const decodeBase64: (value: string) => string; export declare const isBuffer: (obj: any) => boolean; -export declare function applyPlugins(recipeId: T, config: AllRecipeConfigs[T] | undefined, plugins: NonNullable[]): AllRecipeConfigs[T]; +export declare function applyPlugins( + recipeId: T, + config: AllRecipeConfigs[T] | undefined, + plugins: NonNullable[] +): AllRecipeConfigs[T]; diff --git a/lib/build/utils.js b/lib/build/utils.js index 5d09f5d86..452f4371a 100644 --- a/lib/build/utils.js +++ b/lib/build/utils.js @@ -1,7 +1,9 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; +var __importDefault = + (this && this.__importDefault) || + function (mod) { + return mod && mod.__esModule ? mod : { default: mod }; + }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isBuffer = exports.decodeBase64 = exports.encodeBase64 = exports.isTestEnv = exports.getBuffer = exports.getProcess = exports.doFetch = void 0; exports.getLargestVersionFromIntersection = getLargestVersionFromIntersection; @@ -41,15 +43,18 @@ const doFetch = async (input, init) => { // frameworks like nextJS cache fetch GET requests (https://nextjs.org/docs/app/building-your-application/caching#data-cache) // we don't want that because it may lead to weird behaviour when querying the core. if (init === undefined) { - processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.ADDING_NO_CACHE_HEADER_IN_FETCH); + processState_1.ProcessState.getInstance().addState( + processState_1.PROCESS_STATE.ADDING_NO_CACHE_HEADER_IN_FETCH + ); init = { cache: "no-cache", redirect: "manual", }; - } - else { + } else { if (init.cache === undefined) { - processState_1.ProcessState.getInstance().addState(processState_1.PROCESS_STATE.ADDING_NO_CACHE_HEADER_IN_FETCH); + processState_1.ProcessState.getInstance().addState( + processState_1.PROCESS_STATE.ADDING_NO_CACHE_HEADER_IN_FETCH + ); init.cache = "no-cache"; init.redirect = "manual"; } @@ -57,18 +62,17 @@ const doFetch = async (input, init) => { const fetchFunction = typeof fetch !== "undefined" ? fetch : cross_fetch_1.default; try { return await fetchFunction(input, init); - } - catch (e) { + } catch (e) { // Cloudflare Workers don't support the 'cache' field in RequestInit. // To work around this, we delete the 'cache' field and retry the fetch if the error is due to the missing 'cache' field. // Remove this workaround once the 'cache' field is supported. // More info: https://github.com/cloudflare/workerd/issues/698 - const unimplementedCacheError = e && + const unimplementedCacheError = + e && typeof e === "object" && "message" in e && e.message === "The 'cache' field on 'RequestInitializerDict' is not implemented."; - if (!unimplementedCacheError) - throw e; + if (!unimplementedCacheError) throw e; const newOpts = Object.assign({}, init); delete newOpts.cache; return await fetchFunction(input, newOpts); @@ -95,8 +99,7 @@ function maxVersion(version1, version2) { let v2 = Number(splittedv2[i]); if (v1 > v2) { return version1; - } - else if (v2 > v1) { + } else if (v2 > v1) { return version2; } } @@ -115,11 +118,14 @@ function normaliseInputAppInfoOrThrowError(appInfo) { if (appInfo.appName === undefined) { throw new Error("Please provide your appName inside the appInfo object when calling supertokens.init"); } - let apiGatewayPath = appInfo.apiGatewayPath !== undefined - ? new normalisedURLPath_1.default(appInfo.apiGatewayPath) - : new normalisedURLPath_1.default(""); + let apiGatewayPath = + appInfo.apiGatewayPath !== undefined + ? new normalisedURLPath_1.default(appInfo.apiGatewayPath) + : new normalisedURLPath_1.default(""); if (appInfo.origin === undefined && appInfo.websiteDomain === undefined) { - throw new Error("Please provide either origin or websiteDomain inside the appInfo object when calling supertokens.init"); + throw new Error( + "Please provide either origin or websiteDomain inside the appInfo object when calling supertokens.init" + ); } let websiteDomainFunction = (input) => { let origin = appInfo.origin; @@ -144,12 +150,15 @@ function normaliseInputAppInfoOrThrowError(appInfo) { appName: appInfo.appName, getOrigin: websiteDomainFunction, apiDomain, - apiBasePath: apiGatewayPath.appendPath(appInfo.apiBasePath === undefined - ? new normalisedURLPath_1.default("/auth") - : new normalisedURLPath_1.default(appInfo.apiBasePath)), - websiteBasePath: appInfo.websiteBasePath === undefined - ? new normalisedURLPath_1.default("/auth") - : new normalisedURLPath_1.default(appInfo.websiteBasePath), + apiBasePath: apiGatewayPath.appendPath( + appInfo.apiBasePath === undefined + ? new normalisedURLPath_1.default("/auth") + : new normalisedURLPath_1.default(appInfo.apiBasePath) + ), + websiteBasePath: + appInfo.websiteBasePath === undefined + ? new normalisedURLPath_1.default("/auth") + : new normalisedURLPath_1.default(appInfo.websiteBasePath), apiGatewayPath, topLevelAPIDomain, getTopLevelWebsiteDomain: topLevelWebsiteDomain, @@ -184,18 +193,18 @@ function deepTransform(obj) { let val = obj[key]; if (val && typeof val === "object" && val["toJson"] !== undefined && typeof val["toJson"] === "function") { out[key] = val.toJson(); - } - else if (val && typeof val === "object") { + } else if (val && typeof val === "object") { out[key] = deepTransform(val); - } - else { + } else { out[key] = val; } } return out; } function isAnIpAddress(ipaddress) { - return /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipaddress); + return /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test( + ipaddress + ); } function getNormalisedShouldTryLinkingWithSessionUserFlag(req, body) { var _a; @@ -208,8 +217,10 @@ function getBackwardsCompatibleUserInfo(req, result, userContext) { let resp; // (>= 1.18 && < 2.0) || >= 3.0: This is because before 1.18, and between 2 and 3, FDI does not // support account linking. - if ((hasGreaterThanEqualToFDI(req, "1.18") && !hasGreaterThanEqualToFDI(req, "2.0")) || - hasGreaterThanEqualToFDI(req, "3.0")) { + if ( + (hasGreaterThanEqualToFDI(req, "1.18") && !hasGreaterThanEqualToFDI(req, "2.0")) || + hasGreaterThanEqualToFDI(req, "3.0") + ) { resp = { user: result.user.toJson(), }; @@ -217,9 +228,10 @@ function getBackwardsCompatibleUserInfo(req, result, userContext) { resp.createdNewRecipeUser = result.createdNewRecipeUser; } return resp; - } - else { - let loginMethod = result.user.loginMethods.find((lm) => lm.recipeUserId.getAsString() === result.session.getRecipeUserId(userContext).getAsString()); + } else { + let loginMethod = result.user.loginMethods.find( + (lm) => lm.recipeUserId.getAsString() === result.session.getRecipeUserId(userContext).getAsString() + ); if (loginMethod === undefined) { // we pick the oldest login method here for the user. // this can happen in case the user is implementing something like @@ -227,8 +239,7 @@ function getBackwardsCompatibleUserInfo(req, result, userContext) { for (let i = 0; i < result.user.loginMethods.length; i++) { if (loginMethod === undefined) { loginMethod = result.user.loginMethods[i]; - } - else if (loginMethod.timeJoined > result.user.loginMethods[i].timeJoined) { + } else if (loginMethod.timeJoined > result.user.loginMethods[i].timeJoined) { loginMethod = result.user.loginMethods[i]; } } @@ -288,20 +299,15 @@ function humaniseMilliseconds(ms) { let t = Math.floor(ms / 1000); let suffix = ""; if (t < 60) { - if (t > 1) - suffix = "s"; + if (t > 1) suffix = "s"; return `${t} second${suffix}`; - } - else if (t < 3600) { + } else if (t < 3600) { const m = Math.floor(t / 60); - if (m > 1) - suffix = "s"; + if (m > 1) suffix = "s"; return `${m} minute${suffix}`; - } - else { + } else { const h = Math.floor(t / 360) / 10; - if (h > 1) - suffix = "s"; + if (h > 1) suffix = "s"; return `${h} hour${suffix}`; } } @@ -309,7 +315,7 @@ function makeDefaultUserContextFromAPI(request) { return setRequestInUserContextIfNotDefined({}, request); } function getUserContext(inputUserContext) { - return (inputUserContext !== null && inputUserContext !== void 0 ? inputUserContext : {}); + return inputUserContext !== null && inputUserContext !== void 0 ? inputUserContext : {}; } function setRequestInUserContextIfNotDefined(userContext, request) { if (userContext === undefined) { @@ -382,14 +388,12 @@ async function postWithFetch(url, headers, body, { successLog, errorLogHeader }) (0, logger_1.logDebugMessage)(errorLogHeader); (0, logger_1.logDebugMessage)(`Error status: ${fetchResp.status}`); (0, logger_1.logDebugMessage)(`Error response: ${respText}`); - } - catch (caught) { + } catch (caught) { error = caught; (0, logger_1.logDebugMessage)(errorLogHeader); if (error instanceof Error) { (0, logger_1.logDebugMessage)(`Error: ${error.message}`); - } - else { + } else { (0, logger_1.logDebugMessage)(`Error: ${JSON.stringify(error)}`); } } @@ -432,8 +436,7 @@ const getProcess = () => { * to one that is compatible where process may not be available * (like `edge` runtime). */ - if (typeof process !== "undefined") - return process; + if (typeof process !== "undefined") return process; const ponyFilledProcess = require("process"); return ponyFilledProcess; }; @@ -444,8 +447,7 @@ const getBuffer = () => { * to one that is compatible where it may not be available * (like `edge` runtime). */ - if (typeof Buffer !== "undefined") - return Buffer; + if (typeof Buffer !== "undefined") return Buffer; const ponyFilledBuffer = require("buffer").Buffer; return ponyFilledBuffer; }; @@ -499,20 +501,24 @@ function applyPlugins(recipeId, config, plugins) { functionLayers = functionLayers.reverse().filter((layer) => layer !== undefined); apiLayers = apiLayers.reverse().filter((layer) => layer !== undefined); if (recipeId !== "accountlinking" && apiLayers.length > 0) { - config.override = Object.assign(Object.assign({}, config.override), { apis: (oI, builder) => { + config.override = Object.assign(Object.assign({}, config.override), { + apis: (oI, builder) => { for (const layer of apiLayers) { builder.override(layer); } return oI; - } }); + }, + }); } if (functionLayers.length > 0) { - config.override = Object.assign(Object.assign({}, config.override), { functions: (oI, builder) => { + config.override = Object.assign(Object.assign({}, config.override), { + functions: (oI, builder) => { for (const layer of functionLayers) { builder.override(layer); } return oI; - } }); + }, + }); } return config; } diff --git a/lib/ts/supertokens.ts b/lib/ts/supertokens.ts index 0ae43660d..0cde5d019 100644 --- a/lib/ts/supertokens.ts +++ b/lib/ts/supertokens.ts @@ -42,6 +42,8 @@ import { enableDebugLogs, logDebugMessage } from "./logger"; import { PostSuperTokensInitCallbacks } from "./postSuperTokensInitCallbacks"; import { DEFAULT_TENANT_ID } from "./recipe/multitenancy/constants"; import { version } from "./version"; +import { SessionContainerInterface } from "./recipe/session/types"; +import Session from "./recipe/session/recipe"; export default class SuperTokens { private static instance: SuperTokens | undefined; @@ -428,7 +430,16 @@ export default class SuperTokens { (handler) => handler.path === path.getAsStringDangerous() && handler.method === method ); if (handlerFromApis) { - handlerFromApis.handler(request, response, userContext); + let session: SessionContainerInterface | undefined = undefined; + if (handlerFromApis.verifySessionOptions !== undefined) { + session = await Session.getInstanceOrThrowError().verifySession( + handlerFromApis.verifySessionOptions, + request, + response, + userContext + ); + } + handlerFromApis.handler(request, response, session, userContext); return true; } diff --git a/lib/ts/types.ts b/lib/ts/types.ts index a510a265d..4bcda3c7c 100644 --- a/lib/ts/types.ts +++ b/lib/ts/types.ts @@ -29,7 +29,11 @@ import type { TypeInput as MultitenancyTypeInput } from "./recipe/multitenancy/t import type { TypeInput as OAuth2ProviderTypeInput } from "./recipe/oauth2provider/types"; import type { TypeInput as OpenIdTypeInput } from "./recipe/openid/types"; import type { TypeInput as PasswordlessTypeInput } from "./recipe/passwordless/types"; -import type { TypeInput as SessionTypeInput } from "./recipe/session/types"; +import type { + SessionContainerInterface, + TypeInput as SessionTypeInput, + VerifySessionOptions, +} from "./recipe/session/types"; import type { TypeInput as ThirdPartyTypeInput } from "./recipe/thirdparty/types"; import type { TypeInput as TotpTypeInput } from "./recipe/totp/types"; import type { TypeInput as UserMetadataTypeInput } from "./recipe/usermetadata/types"; @@ -105,9 +109,11 @@ export type RecipePluginOverride = { export type PluginRouteHandler = { method: HTTPMethod; path: string; // this is appended to apiBasePath + verifySessionOptions?: VerifySessionOptions; handler: ( req: BaseRequest, res: BaseResponse, + session: SessionContainerInterface | undefined, userContext: UserContext ) => Promise<{ status: number; diff --git a/package-lock.json b/package-lock.json index b13b32f2e..4bde62250 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1183,6 +1183,74 @@ "integrity": "sha512-e7X7bbn3Z6DWnDi75UWn+REgAbLEqxI8Tq2pkFOFAMpWAWApz/YCUhtWMWn410h8Q2fYiYL7Yg5OlxMOCfFjJQ==", "dev": true }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.4.tgz", + "integrity": "sha512-ubmUkbmW65nIAOmoxT1IROZdmmJMmdYvXIe8211send9ZYJu+SqxSnJM4TrPj9wmL6g9Atvj0S/2cFmMSS99jg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.4.tgz", + "integrity": "sha512-b0Xo1ELj3u7IkZWAKcJPJEhBop117U78l70nfoQGo4xUSvv0PJSTaV4U9xQBLvZlnjsYkc8RwQN1HoH/oQmLlQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.4.tgz", + "integrity": "sha512-457G0hcLrdYA/u1O2XkRMsDKId5VKe3uKPvrKVOyuARa6nXrdhJOOYU9hkKKyQTMru1B8qEP78IAhf/1XnVqKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.4.tgz", + "integrity": "sha512-l/kMG+z6MB+fKA9KdtyprkTQ1ihlJcBh66cf0HvqGP+rXBbOXX0dpJatjZbHeunvEHoBBS69GYQG5ry78JMy3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@next/swc-linux-x64-gnu": { "version": "14.1.4", "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.4.tgz", @@ -1215,6 +1283,57 @@ "node": ">= 10" } }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.4.tgz", + "integrity": "sha512-xzxF4ErcumXjO2Pvg/wVGrtr9QQJLk3IyQX1ddAC/fi6/5jZCZ9xpuL9Tzc4KPWMFq8GGWFVDMshZOdHGdkvag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.4.tgz", + "integrity": "sha512-WZiz8OdbkpRw6/IU/lredZWKKZopUMhcI2F+XiMAcPja0uZYdMTZQRoQ0WZcvinn9xZAidimE7tN9W5v9Yyfyw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.4.tgz", + "integrity": "sha512-4Rto21sPfw555sZ/XNLqfxDUNeLhNYGO2dlPqsnuCg8N8a2a9u1ltqBOPQ4vj1Gf7eJC0W2hHG2eYUHuiXgY2w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@openapi-contrib/openapi-schema-to-json-schema": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/@openapi-contrib/openapi-schema-to-json-schema/-/openapi-schema-to-json-schema-3.3.2.tgz", @@ -1639,6 +1758,66 @@ "integrity": "sha512-i1aY7RKb6HmQIEnK0cBmUZUp1URx0riIHw/GYNoZ46Su0GWfLiDmMI8zMRmaauMnOTg2bQag0qfwcyUFC9Tn+A==", "dev": true }, + "node_modules/@wdio/logger": { + "version": "9.4.4", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-9.4.4.tgz", + "integrity": "sha512-BXx8RXFUW2M4dcO6t5Le95Hi2ZkTQBRsvBQqLekT2rZ6Xmw8ZKZBPf0FptnoftFGg6dYmwnDidYv/0+4PiHjpQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "chalk": "^5.1.2", + "loglevel": "^1.6.0", + "loglevel-plugin-prefix": "^0.8.4", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/reporter": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-9.5.0.tgz", + "integrity": "sha512-ycdbU97tDT7RCgutM+fSwbd0FIab821BAc0hYopCkB0FIooHUjIjvXmh0QichasS5a21tGe0UXfCcnn1S6V6Fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^20.1.0", + "@wdio/logger": "9.4.4", + "@wdio/types": "9.5.0", + "diff": "^7.0.0", + "object-inspect": "^1.12.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/@wdio/reporter/node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/@wdio/types": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-9.5.0.tgz", + "integrity": "sha512-sX1vH6VebVHvgdpySTOXzKNazHBu+yFr5bMvveJ2T4vKjJTJOAwO6nPftjKcgGDfhyYxM3xOCvboKICdQKFgEg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "^20.1.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, "node_modules/abstract-logging": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", @@ -1735,6 +1914,20 @@ "node": ">=6" } }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2409,6 +2602,20 @@ "node": ">=4" } }, + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/change-case": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", @@ -4894,6 +5101,29 @@ "node": ">=8" } }, + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/loglevel-plugin-prefix": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", + "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/loopback-connector": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.3.3.tgz", @@ -6512,10 +6742,11 @@ } }, "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" }, @@ -6523,6 +6754,21 @@ "node": ">=0.10.0" } }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -6685,6 +6931,17 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", "dev": true }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/scmp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", @@ -7106,6 +7363,23 @@ "node": ">=8" } }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", diff --git a/test/with-typescript/index.ts b/test/with-typescript/index.ts index 79ec3d1bd..e2e67ec2d 100644 --- a/test/with-typescript/index.ts +++ b/test/with-typescript/index.ts @@ -1,6 +1,8 @@ import * as express from "express"; import { NextApiRequest, NextApiResponse } from "next"; +import { OverrideableBuilder } from "supertokens-js-override"; import Supertokens, { RecipeUserId, User, getUser } from "../.."; +import { SuperTokensPlugin } from "../../types"; import Session, { RecipeInterface, SessionClaimValidator, VerifySessionOptions } from "../../recipe/session"; import EmailVerification from "../../recipe/emailverification"; import EmailPassword from "../../recipe/emailpassword"; @@ -949,7 +951,7 @@ Multitenancy.init({ }); import { HTTPMethod, TypeInput, UserContext } from "../../types"; -import { TypeInput as SessionTypeInput } from "../../recipe/session/types"; +import { SessionContainerInterface, TypeInput as SessionTypeInput } from "../../recipe/session/types"; import { TypeInput as EPTypeInput } from "../../recipe/emailpassword/types"; import SuperTokensError from "../../lib/build/error"; import { serialize } from "cookie"; @@ -2311,6 +2313,59 @@ OAuth2Provider.createOAuth2Client({ clientSecret: "nope!", }); +const createPluginInitFunction = < + Implementation extends Record any>, + Config, + NormalisedConfig = Config +>( + init: (implementation: Implementation, config: NormalisedConfig) => SuperTokensPlugin, + getImplementation?: Implementation | ((config: NormalisedConfig) => Implementation), + getNormalisedConfig?: (config: Config) => NormalisedConfig +): ((config: Config & { override: (oI: Implementation) => Implementation }) => SuperTokensPlugin) => { + const normalizedGetImplementation: (config: NormalisedConfig) => Implementation = + typeof getImplementation === "function" + ? getImplementation + : (_config: NormalisedConfig) => getImplementation as Implementation; + + return (inputConfig) => { + const config = getNormalisedConfig ? getNormalisedConfig(inputConfig) : (inputConfig as NormalisedConfig); + const baseImplementation = normalizedGetImplementation(config); + const overrideBuilder = new OverrideableBuilder(baseImplementation); + if (inputConfig.override) { + overrideBuilder.override(inputConfig.override); + } + const actualImplementation = overrideBuilder.build(); + return init(actualImplementation, config); + }; +}; + +const customPlugin = createPluginInitFunction<{ log: (input: any) => void }, { prefix: string }>( + (implementation, config: { prefix: string }) => { + return { + id: "asdf", + compatibleSDKVersions: "1.2.3", + overrideMap: { + emailpassword: { + functions: (oI) => ({ + ...oI, + signIn: (input) => { + implementation.log(input); + return oI.signIn(input); + }, + }), + }, + }, + }; + }, + (config) => { + return { + log: (input: any) => { + console.log(`${config.prefix} - input`); + }, + }; + } +); + Supertokens.init({ appInfo, recipeList: [OpenId.init()], @@ -2333,7 +2388,40 @@ Supertokens.init({ }, }), }, + passwordless: { + functions: (oI) => ({ + ...oI, + checkCode: (input) => { + return oI.checkCode(input); + }, + }), + }, }, + routeHandlers: [ + { + method: "get", + path: "/asdf", + verifySessionOptions: {}, + handler: async (req, res, userContext) => { + return { + status: 200, + body: {}, + }; + }, + }, + ], }, + customPlugin({ + prefix: "asdf", + override: (oI) => ({ + ...oI, + log: (input: any) => { + console.log(`in log override - before oI.log`); + const res = oI.log(input); + console.log(`in log override - after oI.log`); + return res; + }, + }), + }), ], });