supertokens-node
Version:
NodeJS driver for SuperTokens core
401 lines (348 loc) • 17.7 kB
Markdown
## [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);
}
}
}
}
}),
```