Skip to content

Commit

Permalink
Merge pull request #794 from Lehoczky/master
Browse files Browse the repository at this point in the history
refactor: use ENUM values for MFA factors
  • Loading branch information
rishabhpoddar authored May 13, 2024
2 parents 01c4ebb + 068b5d2 commit b6f5b7d
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 82 deletions.
65 changes: 46 additions & 19 deletions v2/mfa/backend-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ supertokens.init({
flowType: "USER_INPUT_CODE"
}),
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"]
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
})
// highlight-end
]
Expand Down Expand Up @@ -164,7 +167,7 @@ async function createNewTenant() {
let resp = await Multitenancy.createOrUpdateTenant("customer1", {
emailPasswordEnabled: true,
passwordlessEnabled: true,
firstFactors: ["emailpassword"]
firstFactors: [MultiFactorAuth.FactorIds.EMAILPASSWORD]
});

if (resp.createdNew) {
Expand Down Expand Up @@ -262,14 +265,17 @@ SuperTokens.init({
}),
totp.init(),
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
],
// highlight-start
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
getMFARequirementsForAuth: async function (input) {
return ["totp"]
return [MultiFactorAuth.FactorIds.TOTP]
}
}
}
Expand Down Expand Up @@ -324,15 +330,21 @@ supertokens.init({
recipeList: [
// ...
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
],
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
getMFARequirementsForAuth: async function (input) {
// highlight-start
return [{
oneOf: ["totp", "otp-email"]
oneOf: [
MultiFactorAuth.FactorIds.TOTP,
MultiFactorAuth.FactorIds.OTP_EMAIL
]
}]
// highlight-end
}
Expand Down Expand Up @@ -382,15 +394,21 @@ supertokens.init({
recipeList: [
// ...
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
],
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
getMFARequirementsForAuth: async function (input) {
// highlight-start
return [{
allOfInAnyOrder: ["totp", "otp-email"]
allOfInAnyOrder: [
MultiFactorAuth.FactorIds.TOTP,
MultiFactorAuth.FactorIds.OTP_EMAIL
]
}]
// highlight-end
}
Expand Down Expand Up @@ -442,21 +460,24 @@ supertokens.init({
recipeList: [
// ...
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
],
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
getMFARequirementsForAuth: async function (input) {
// highlight-start
let currentCompletedFactors = MultiFactorAuth.MultiFactorAuthClaim.getValueFromPayload(input.accessTokenPayload)
if ("totp" in currentCompletedFactors) {
if (MultiFactorAuth.FactorIds.TOTP in currentCompletedFactors) {
// this means the totp factor is completed
return ["otp-email"]
return [MultiFactorAuth.FactorIds.OTP_EMAIL]
} else {
// this means we have not finished totp yet, and we want
// to do that right after first factor login
return ["totp"]
return [MultiFactorAuth.FactorIds.TOTP]
}
// highlight-end
}
Expand Down Expand Up @@ -516,8 +537,8 @@ async function createNewTenant() {
let resp = await Multitenancy.createOrUpdateTenant("customer1", {
emailPasswordEnabled: true,
passwordlessEnabled: true,
firstFactors: ["emailpassword"],
requiredSecondaryFactors: ["otp-email"]
firstFactors: [MultiFactorAuth.FactorIds.EMAILPASSWORD],
requiredSecondaryFactors: [MultiFactorAuth.FactorIds.OTP_EMAIL]
});

if (resp.createdNew) {
Expand Down Expand Up @@ -592,7 +613,10 @@ supertokens.init({
recipeList: [
// ...
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
],
override: {
functions: (originalImplementation) => {
return {
Expand Down Expand Up @@ -650,7 +674,7 @@ You want to start by creating an API that does [session verification](/docs/sess
import MultiFactorAuth from "supertokens-node/recipe/multifactorauth";

async function enableMFAForUser(userId: string) {
await MultiFactorAuth.addToRequiredSecondaryFactorsForUser(userId, "totp")
await MultiFactorAuth.addToRequiredSecondaryFactorsForUser(userId, MultiFactorAuth.FactorIds.TOTP)
}
```

Expand Down Expand Up @@ -697,7 +721,10 @@ supertokens.init({
recipeList: [
// ...
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
],
override: {
functions: (originalImplementation) => {
return {
Expand Down Expand Up @@ -760,7 +787,7 @@ import MultiFactorAuth from "supertokens-node/recipe/multifactorauth";

async function isTotpEnabledForUser(userId: string) {
let factors = await MultiFactorAuth.getRequiredSecondaryFactorsForUser(userId)
return factors.includes("totp")
return factors.includes(MultiFactorAuth.FactorIds.TOTP)
}
```

Expand Down Expand Up @@ -795,7 +822,7 @@ import MultiFactorAuth from "supertokens-node/recipe/multifactorauth";

async function isTotpSetupForUser(userId: string) {
let factors = await MultiFactorAuth.getFactorsSetupForUser(userId)
return factors.includes("totp")
return factors.includes(MultiFactorAuth.FactorIds.TOTP)
}
```

Expand Down
18 changes: 14 additions & 4 deletions v2/mfa/email-sms-otp/otp-for-all-users.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ supertokens.init({
}),
// highlight-end
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
// highlight-start
override: {
functions: (originalImplementation) => {
Expand Down Expand Up @@ -193,7 +196,10 @@ supertokens.init({
contactMethod: "EMAIL"
}),
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"]
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
})
// highlight-end
]
Expand Down Expand Up @@ -482,14 +488,18 @@ To configure otp-email requirement for a tenant, we can call the following API:

```tsx
import Multitenancy from "supertokens-node/recipe/multitenancy";
import MultiFactorAuth from "supertokens-node/recipe/multifactorauth"

async function createNewTenant() {
let resp = await Multitenancy.createOrUpdateTenant("customer1", {
emailPasswordEnabled: true,
thirdPartyEnabled: true,
passwordlessEnabled: true,
firstFactors: ["emailpassword", "thirdparty"],
requiredSecondaryFactors: ["otp-email"]
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
requiredSecondaryFactors: [MultiFactorAuth.FactorIds.OTP_EMAIL]
});

if (resp.createdNew) {
Expand Down
38 changes: 25 additions & 13 deletions v2/mfa/email-sms-otp/otp-for-opt-in-users.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ supertokens.init({
}),
// highlight-end
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
// highlight-start
override: {
functions: (originalImplementation) => {
Expand All @@ -102,7 +105,7 @@ supertokens.init({
let roles = await UserRoles.getRolesForUser(input.tenantId, (await input.user).id)
if (roles.roles.includes("admin")) {
// we only want otp-email for admins
return ["otp-email"]
return [MultiFactorAuth.FactorIds.OTP_EMAIL]
} else {
// no MFA for non admin users.
return []
Expand Down Expand Up @@ -210,7 +213,10 @@ supertokens.init({
}
}),
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
})
// highlight-end
]
Expand Down Expand Up @@ -297,7 +303,7 @@ import MultiFactorAuth from "supertokens-node/recipe/multifactorauth";

async function isOTPEmailEnabledForUser(userId: string) {
let factors = await MultiFactorAuth.getRequiredSecondaryFactorsForUser(userId)
return factors.includes("otp-email")
return factors.includes(MultiFactorAuth.FactorIds.OTP_EMAIL)
}
```

Expand Down Expand Up @@ -327,11 +333,11 @@ If the user wants to enable or disable otp-email for them, you can make an API o
import MultiFactorAuth from "supertokens-node/recipe/multifactorauth";

async function enableMFAForUser(userId: string) {
await MultiFactorAuth.addToRequiredSecondaryFactorsForUser(userId, "otp-email")
await MultiFactorAuth.addToRequiredSecondaryFactorsForUser(userId, MultiFactorAuth.FactorIds.OTP_EMAIL)
}

async function disableMFAForUser(userId: string) {
await MultiFactorAuth.removeFromRequiredSecondaryFactorsForUser(userId, "otp-email")
await MultiFactorAuth.removeFromRequiredSecondaryFactorsForUser(userId, MultiFactorAuth.FactorIds.OTP_EMAIL)
}
```

Expand Down Expand Up @@ -416,17 +422,20 @@ supertokens.init({
}
}),
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
getMFARequirementsForAuth: async function (input) {
let roles = await UserRoles.getRolesForUser(input.tenantId, (await input.user).id)
// highlight-next-line
if (roles.roles.includes("admin") && (await input.requiredSecondaryFactorsForTenant).includes("otp-email")) {
if (roles.roles.includes("admin") && (await input.requiredSecondaryFactorsForTenant).includes(MultiFactorAuth.FactorIds.OTP_EMAIL)) {
// we only want otp-email for admins
return ["otp-email"]
return [MultiFactorAuth.FactorIds.OTP_EMAIL]
} else {
// no MFA for non admin users.
return []
Expand Down Expand Up @@ -529,16 +538,19 @@ supertokens.init({
}
}),
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"],
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
// highlight-start
override: {
functions: (originalImplementation) => {
return {
...originalImplementation,
getMFARequirementsForAuth: async function (input) {
if ((await input.requiredSecondaryFactorsForUser).includes("otp-email")) {
if ((await input.requiredSecondaryFactorsForTenant).includes("otp-email")) {
return ["otp-email"]
if ((await input.requiredSecondaryFactorsForUser).includes(MultiFactorAuth.FactorIds.OTP_EMAIL)) {
if ((await input.requiredSecondaryFactorsForTenant).includes(MultiFactorAuth.FactorIds.OTP_EMAIL)) {
return [MultiFactorAuth.FactorIds.OTP_EMAIL]
}
}
// no otp-email required for input.user, with the input.tenant.
Expand Down
5 changes: 4 additions & 1 deletion v2/mfa/frontend-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ supertokens.init({
}),
// highlight-start
MultiFactorAuth.init({
firstFactors: ["emailpassword", "thirdparty"]
firstFactors: [
MultiFactorAuth.FactorIds.EMAILPASSWORD,
MultiFactorAuth.FactorIds.THIRDPARTY
]
})
// highlight-end
]
Expand Down
Loading

0 comments on commit b6f5b7d

Please sign in to comment.