Skip to main content

Setting up the 1st factor

caution
  • SuperTokens is not yet optimised for 2FA implementation, so you have to add a lot of customisations for it to work. We are working on improving the development experience for 2FA as well as adding more factors like TOTP. Stay tuned.
  • A demo app that uses the pre built UI can be found on our GitHub.

1) Initialisation#

Start by following the recipe guide for the first factor. In this guide, we will take the example of thirdpartyemailpassword recipe as being the first factor.

After following the backend quick setup section (or any of the framework specific integration guides), you should have all the auth APIs exposed to the frontend via the SuperTokens middleware. The supertokens.init code on the server would look like this:

import supertokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import UserMetadata from "supertokens-node/recipe/usermetadata";
import ThirdPartyEmailPassword from"supertokens-node/recipe/thirdpartyemailpassword";

supertokens.init({
framework: "express",
supertokens: {
connectionURI: "",
apiKey: "",
},
appInfo: {
// learn more about this on https://supertokens.com/docs/thirdpartyemailpassword/appinfo
appName: "<YOUR_APP_NAME>",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth"
},
recipeList: [
ThirdPartyEmailPassword.init({/*...*/}),
Session.init(), // initializes session features
UserMetadata.init() // initializes the user metadata feature
]
});
important

You should have also added the SuperTokens middleware and errorHandler (depending on your framework) to your application. We are not showing it in the above code snippet for brevity, but it is explained in the ThirdPartyEmailPassword recipe guide.

2) Adding SecondFactorClaim#

After sign up or sign in of the first factor, the existence of the session signifies the completion of the first factor, but we want to explicitly mark the second factor as incomplete. This can be done by overriding the createNewSession function in the Session.init config:

import Session from "supertokens-node/recipe/session";
import UserMetadata from "supertokens-node/recipe/usermetadata";
import Passwordless from "supertokens-node/recipe/passwordless";
import { BooleanClaim } from "supertokens-node/recipe/session/claims";

/*
This will be used to modify the session's access token payload
to add {"2fa-completed": false} into it.
*/
export const SecondFactorClaim = new BooleanClaim({
fetchValue: () => false,
key: "2fa-completed",
});

Session.init({
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
/* This function is called after signing in or signing up via the first factor */
createNewSession: async function (input) {
return originalImplementation.createNewSession({
...input,
accessTokenPayload: {
...input.accessTokenPayload,
...(await SecondFactorClaim.build(input.userId, input.tenantId, input.userContext)),
},
});
},
};
},
},
})

We add SecondFactorClaim into the access token payload. This will be set to false on session creation (see fetchValue in the claim definition).

Which UI do you use?
Custom UI
Pre built UI