Skip to main content
Paid Feature

This is a paid feature.

For self hosted users, Sign up to get a license key and follow the instructions sent to you by email. Using the dev license key is free. We only start charging you once you enable the feature in production using the provided production license key.

For managed service users, you can click on the "enable paid features" button on our dashboard, and follow the steps from there on. Once enabled, this feature is free on the provided development environment.

Migration to SuperTokens from another auth solution

This section covers migration of secondary factors from your existing auth solution to SuperTokens. To see how to migrate the first factor, refer to our migration docs for the recipe you have setup as the first factor:

After you have completed the first factor migration, you can focus on the secondary factor migration for the user. We will cover migration steps for each of the support secondary factors we have.

important

Before reading further, make sure you have understood how MFA works with SuperTokens based on the docs above in this guide.

TOTP#

From the migration step above (for the first factor), you should have the user's user ID generated by SuperTokens. Call the following API to create a new TOTP device for the user with their user ID and extisting TOTP secret:

curl --location --request POST '/recipe/totp/device/import' \
--header 'api-key: ' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"userId": "<FROM FIRST FACTOR MIGRATION>",
"skew": 1,
"period": 30,
"secretKey": "...."
}'

The above API call will create a new TOTP device for the user. The secretKey field should be fetched from your existing auth provider (we expect it to be in base32 format). You can also provide an optional deviceName as a prop in the body which will help identify the TOTP device for future operations like if you want to delete this device. If you do not provide a deviceName, SuperTokens will generate a device name for this user like TOTP Device X, where X is 1, 2, 3 and so on depending on how many devices this user already has.

caution
  • If you have mapped the SuperTokens user ID to an external user ID, then you should use the external user ID in the above API call instead of the SuperTokens user ID.
  • The secretKey field must be base32 encoded. If your existing auth provider provides the key encoded in any other format, you must decode their key and then encode it in base32 format. For example, if the provided key is in base64 format, then you must do base32encode(base64decode(secretKeyFromAuthProvider))

Email / SMS OTP#

SuperTokens relies on the passwordless recipe to complete this type of factor. The overall process here is to:

  • Create a new passwordless user with the email of the first factor, or with a phone number.
  • Make the first factor user a primary user for account linking purposes.
  • Link the passwordless user to the first factor user.

Generate passwordless code#

With Email

curl --location --request POST '/recipe/signinup/code' \
--header 'api-key: ' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"email": "johndoe@example.com"
}'

With Phone Number


curl --location --request POST '/recipe/signinup/code' \
--header 'api-key: ' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"phoneNumber": "+14155552671"
}'

On successfully generating the passwordless code you should see the following response

{
"status": "OK",
"preAuthSessionId": "d3Zpa9eoyV2Wr7uN5DLr6H1clzbwwGTc_0wIIXJT55M=",
"codeId": "4fe93f8e-a5da-4588-82e2-314c6993b345",
"deviceId": "+cWm1Y2EFxEPyHM7CAwYyAdkakBeoEDm6IOGT3xfa1U=",
"userInputCode": "463152",
"linkCode": "UlEb3-gbIYow61ce6RNzghkGN8qcHkpRwbhHbvMEjxY=",
"timeCreated": 1664283193059,
"codeLifetime": 900000
}

Consume the passwordless code to create the passwordless user#

Retrieve the preAuthSessionId and linkCode from the previous response and set them as request body parameters for the consume code request.

curl --location --request POST '/recipe/signinup/code/consume' \
--header 'api-key: ' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"preAuthSessionId": "d3Zpa9eoyV2Wr7uN5DLr6H1clzbwwGTc_0wIIXJT55M=",
"linkCode": "UlEb3-gbIYow61ce6RNzghkGN8qcHkpRwbhHbvMEjxY="
}'

If the user has both email and password associated with them, then you can call the update user API to associate the missing information

curl --location --request PUT '/recipe/user' \
--header 'api-key: ' \
--header 'rid: passwordless' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"userId": "fa7a0841-b533-4478-95533-0fde890c3483",
"email": "johndoe@gmail.com",
"phoneNumber": "+14155552671"
}'

Make the first factor user a primary user#

The user ID returned from the first factor migration should be made a primary user with the following API call:

curl --location --request POST '/recipe/accountlinking/user/primary' \
--header 'api-key: ' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"recipeUserId": "<FROM FIRST FACTOR MIGRATION>"
}'

This will allow another recipe user to be linked to this user.

caution

If you have mapped the first factor's SuperTokens user ID to an external user ID, then you should use the external user ID in the above API call (for the recipeUserId field) instead of the SuperTokens user ID.

Link the passwordless user to the first factor user#

Then we link the newly created passwordless user to the first factor user with the following API call:

curl --location --request POST '/recipe/accountlinking/user/link' \
--header 'api-key: ' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"primaryUserId": "<FROM FIRST FACTOR MIGRATION>",
"recipeUserId": "<FROM PASSWORDLESS API CALL ABOVE>"
}'
caution

If you have mapped the first factor's SuperTokens user ID to an external user ID, then you should use the external user ID in the above API call (for the primaryUserId field) instead of the SuperTokens user ID.