UNPKG

supertokens-node

Version:
401 lines (348 loc) 17.7 kB
## [17.0.0] - 2024-03-08 ### Changes - Enable smooth switching between `useDynamicAccessTokenSigningKey` settings by allowing refresh calls to change the signing key type of a session - Added a core call cache that should reduce traffic to your SuperTokens core instances - Refactored sign in/up API codes to reduce code duplication - Added MFA related information to dashboard APIs - Added a cache to reduce the number of requests made to the core. This can be disabled using the `disableCoreCallCache: true`, in the config. - Added new `overwriteSessionDuringSignInUp` configuration option to the Session recipe - Added new function: `checkCode` to Passwordless and ThirdPartyPasswordless recipes - Added new function: `verifyCredentials` to EmailPassword and ThirdPartyEmailPassword recipes - Added the `MultiFactorAuth` and `TOTP` recipes. To start using them you'll need compatible versions: - Core>=8.0.0 - supertokens-node>=17.0.0 - supertokens-website>=18.0.0 - supertokens-web-js>=0.10.0 - supertokens-auth-react>=0.39.0 ### Breaking changes - Now only supporting CDI 5.0. Compatible with core version >= 8.0 - Account linking now takes the active session into account. - Account linking now also happens in sign in function calls (instead of sign ups and sign in API calls) - Fixed the typing of the `userContext`: - All functions now take `Record<string, any>` instead of `any` as `userContext`. This means that primitives (strings, numbers) are no longer allowed as `userContext`. - All functions overrides that take a `userContext` parameter now get a well typed `userContext` parameter ensuring that the right object is passed to the original implementation calls - Calling sign in/up APIs with a session will now skip creating a new session by default. This is overrideable through by passing `overwriteSessionDuringSignInUp: true` to the Session recipe config. - Added new support codes to sign in/up APIs. This means that there are new possible values coming from the default implementation for the `reason` strings of `SIGN_IN_NOT_ALLOWED`, `SIGN_UP_NOT_ALLOWED` and `SIGN_IN_UP_NOT_ALLOWED` responses. - `Session` recipe: - The sign out API new returns a 401 instead of 200 in case the input access token has expired or is missing. - `AccountLinking` recipe: - Changed the signature of the following functions, each taking a new (optional) `session` parameter: - `createPrimaryUserIdOrLinkAccounts` - `isSignUpAllowed` - `isSignInAllowed` - `isEmailChangeAllowed` - Changed the signature of the `shouldDoAutomaticAccountLinking` callback: it now takes a new (optional) session parameter. - `EmailPassword`: - Changed the signature of the following overrideable functions: - `signUp` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `signIn` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - Changed the signature of overrideable APIs, adding a new (optional) session parameter: - `signInPOST` - `signUpPOST` - Changed the signature of functions: - `signUp` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `signIn` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED" - `Multitenancy`: - Changed the signature of the following functions: - `createOrUpdateTenant`: Added optional `firstFactors` and `requiredSecondaryFactors` parameters. - `getTenant`: Added `firstFactors` and `requiredSecondaryFactors` to the return type - `listAllTenants`: Added `firstFactors` and `requiredSecondaryFactors` to the returned tenants - Changed the signature of the following overrideable functions: - `createOrUpdateTenant`: Now gets optional `firstFactors` and `requiredSecondaryFactors` in the input. - `getTenant`: Added `firstFactors` and `requiredSecondaryFactors` to the return type - `listAllTenants`: Added `firstFactors` and `requiredSecondaryFactors` to the returned tenants - Changed the signature of the overrideable apis: - `loginMethodsGET`: Now returns `firstFactors` - `Passwordless`: - `revokeCode` (and the related overrideable func) can now be called with either `preAuthSessionId` or `codeId` instead of only `codeId`. - Added new email and sms type for MFA - Changed the signature of the following functions: - `signInUp`, `createCode`: Takes a new (optional) `session` parameter - `consumeCode`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - It now also returns `consumedDevice` if the code was successfully consumed - Changed the signature of the following overrideable functions: - `createCode`: Takes a new (optional) `session` parameter - `consumeCode`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - It now also returns `consumedDevice` if the code was successfully consumed - Changed the signature of overrideable APIs, adding a new (optional) session parameter: - `createCodePOST` - `resendCodePOST` - `consumeCodePOST` - Session claims: - The `build` function and the `fetchValue` callback of session claims now take a new `currentPayload` param. - This affects built-in claims: `EmailVerificationClaim`, `UserRoleClaim`, `PermissionClaim`, `AllowedDomainsClaim`. - This will affect all custom claims as well built on our base classes. - `ThirdParty`: - Changed the signature of the following functions: - `manuallyCreateOrUpdateUser`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - Changed the signature of the following overrideable functions: - `signInUp`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `manuallyCreateOrUpdateUser` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - Changed the signature of overrideable APIs, adding a new (optional) session parameter: - `signInUpPOST` - `ThirdPartyEmailPassword`: - Added new function: `emailPasswordVerifyCredentials` - Changed the signature of the following functions: - `thirdPartyManuallyCreateOrUpdateUser`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `emailPasswordSignUp` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - Changed the signature of the following overrideable functions: - `thirdPartySignInUp`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `thirdPartyManuallyCreateOrUpdateUser` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `emailPasswordSignUp` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - Changed the signature of overrideable APIs, adding a new (optional) session parameter: - `emailPasswordSignInPOST` - `emailPasswordSignUpPOST` - `thirdPartySignInUpPOST` - `ThirdPartyPasswordless`: - `revokeCode` (and the related overrideable func) can now be called with either `preAuthSessionId` or `codeId` instead of only `codeId`. - Changed the signature of the following functions: - `thirdPartyManuallyCreateOrUpdateUser`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `passwordlessSignInUp`, `createCode`: Takes a new (optional) `session` parameter - `consumeCode`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - It now also returns `consumedDevice` if the code was successfully consumed - Changed the signature of the following overrideable functions: - `thirdPartySignInUp`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `thirdPartyManuallyCreateOrUpdateUser` - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - `createCode`: Takes a new (optional) `session` parameter - `consumeCode`: - Takes a new (optional) `session` parameter - Can now return with `status: "LINKING_TO_SESSION_USER_FAILED"` - It now also returns `consumedDevice` if the code was successfully consumed - Changed the signature of overrideable APIs, adding a new (optional) session parameter: - `thirdPartySignInUpPOST` - `createCodePOST` - `resendCodePOST` - `consumeCodePOST` #### Migration guide ##### shouldDoAutomaticAccountLinking signature change If you use the `userContext` or `tenantId` parameters passed to `shouldDoAutomaticAccountLinking`, please update your implementation to account for the new parameter. Before: ```ts AccountLinking.init({ shouldDoAutomaticAccountLinking: async (newAccountInfo, user, tenantId, userContext) => { return { shouldAutomaticallyLink: true, shouldRequireVerification: true, }; }, }); ``` After: ```ts AccountLinking.init({ shouldDoAutomaticAccountLinking: async (newAccountInfo, user, session, tenantId, userContext) => { return { shouldAutomaticallyLink: true, shouldRequireVerification: true, }; }, }); ``` ##### Optional `session` parameter added to public functions We've added a new optional `session` parameter to many function calls. In all cases, these have been added as the last parameter before `userContext`, so this should only affect you if you are using that. You only need to pass a session as a parameter if you are using account linking and want to try and link the user signing in/up to the session user. You can get the necessary session object using `verifySession` in an API call. Here we use the example of `EmailPassword.signIn` but this fits other functions with changed signatures. Before: ```ts const signInResp = await EmailPassword.signIn("public", "asdf@asdf.asfd", "testpw", { myContextVar: true }); ``` After: ```ts const signInResp = await EmailPassword.signIn("public", "asdf@asdf.asfd", "testpw", undefined, { myContextVar: true }); ``` ##### `fetchValue` signature change If you use the `userContext` parameter passed to `fetchValue`, please update your implementation to account for the new parameter. Before: ```ts const boolClaim = new BooleanClaim({ key: "asdf", fetchValue: (userId, recipeUserId, tenantId, userContext) => { return userContext.claimValue; }, }); ``` After: ```ts const boolClaim = new BooleanClaim({ key: "asdf", fetchValue: (userId, recipeUserId, tenantId, currentPayload, userContext) => { return userContext.claimValue; }, }); ``` ##### `build` signature change If you were using the `build` function for custom or built-in session claims, you should update the call signature to also pass the new parameter. Before: ```ts Session.init({ override: { functions: (originalImplementation) => { return { ...originalImplementation, createNewSession: async function (input) { input.accessTokenPayload = { ...input.accessTokenPayload, ...(await UserRoleClaim.build( input.userId, input.recipeUserId, input.tenantId, input.userContext )), }; return originalImplementation.createNewSession(input); }, }; }, }, }); ``` After: ```ts Session.init({ override: { functions: (originalImplementation) => { return { ...originalImplementation, createNewSession: async function (input) { input.accessTokenPayload = { ...input.accessTokenPayload, ...(await UserRoleClaim.build( input.userId, input.recipeUserId, input.tenantId, input.accessTokenPayload, input.userContext )), }; return originalImplementation.createNewSession(input); }, }; }, }, }); ``` ##### Post sign-in/up actions Since now sign in/up APIs and functions can be called with a session (e.g.: during MFA flows), you may need to add an extra check to your overrides to account for that: Before: ```ts // While this example uses Passwordless, all recipes require a very similar change Passwordless.init({ contactMethod: "EMAIL", // This example will work with any contactMethod flowType: "USER_INPUT_CODE_AND_MAGIC_LINK", // This example will work with any flowType override: { functions: (originalImplementation) => { return { ...originalImplementation, consumeCode: async (input) => { // First we call the original implementation of consumeCode. let response = await originalImplementation.consumeCode(input); // Post sign up response, we check if it was successful if (response.status === "OK") { if (response.createdNewRecipeUser && response.user.loginMethods.length === 1) { // TODO: post sign up logic } else { // TODO: post sign in logic } } return response; } } } } }), ``` After: ```ts // While this example uses Passwordless, all recipes require a very similar change Passwordless.init({ contactMethod: "EMAIL", // This example will work with any contactMethod flowType: "USER_INPUT_CODE_AND_MAGIC_LINK", // This example will work with any flowType override: { functions: (originalImplementation) => { return { ...originalImplementation, consumeCode: async (input) => { // First we call the original implementation of consumeCode. let response = await originalImplementation.consumeCode(input); // Post sign up response, we check if it was successful if (response.status === "OK") { if (input.session === undefined) { if (response.createdNewRecipeUser && response.user.loginMethods.length === 1) { // TODO: post sign up logic } else { // TODO: post sign in logic } } } return response; } } } } }), ``` ##### Sign-in/up linking to the session user Sign in/up APIs and functions will now attempt to link the authenticating user to the session user if a session is available (depending on AccountLinking settings). You can disable this and get the old behaviour by: Before: ```ts // While this example uses Passwordless, all recipes require a very similar change Passwordless.init({ contactMethod: "EMAIL", // This example will work with any contactMethod flowType: "USER_INPUT_CODE_AND_MAGIC_LINK", // This example will work with any flowType }), ``` After: ```ts // While this example uses Passwordless, all recipes require a very similar change Passwordless.init({ contactMethod: "EMAIL", // This example will work with any contactMethod flowType: "USER_INPUT_CODE_AND_MAGIC_LINK", // This example will work with any flowType override: { functions: (originalImplementation) => { return { ...originalImplementation, consumeCode: async (input) => { input.session = undefined; return originalImplementation.consumeCode(input); } } } } }), ```