import { ContentPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp"; import { IUser, IUserAuthFactor, UserAuthFactor } from "../../../../model/model"; import InjectProperty from "@web-atoms/core/dist/core/InjectProperty"; import UserService from "../services/UserService"; import XNode from "@web-atoms/core/dist/core/XNode"; import Form from "@web-atoms/web-controls/dist/basic/Form"; import FormField from "@web-atoms/web-controls/dist/basic/FormField"; import Bind from "@web-atoms/core/dist/core/Bind"; import Action from "@web-atoms/core/dist/view-model/Action"; import AtomRepeater from "@web-atoms/web-controls/dist/basic/AtomRepeater"; import { DateFormats } from "../../../../common/date/DateFormats"; import { AddIconTextButton, DeleteIconTextButton, SaveIconTextButton } from "../../../../controls/buttons/IconButton"; export default class MultiFactorSetupPage extends ContentPage { model: IUser; @InjectProperty userService: UserService; authFactor: IUserAuthFactor; async init() { this.model = await this.userService.getCurrent(); const { multiFactor } = this.model; this.title = "Setup Multi Factor Authentication"; if (!this.model.authFactors?.length) { await this.notSetup(); return; } if (multiFactor) { this.renderer =
this.renderAuthFactor(item)} /> { !multiFactor &&
this.addAuthenticator()} text="Add Authenticator" /> this.generateOTP()} text="Generate OTP" />
}
Multi factor authentication is enabled.
; return; } const disable = !this.model.authFactors?.length || !this.model.authFactors.some((i) => i.method === "totp" && i.verified) || this.model.authFactors.filter((i) => i.method === "one-time").length < 8; this.renderer =
this.renderAuthFactor(item)} /> { !multiFactor &&
this.addAuthenticator()} text="Add Authenticator" /> this.generateOTP()} text="Generate OTP" />
} { disable &&
You must add at least one authenticator and generate 8 OTPs (one time passwords) to enable Multi factor authentication.
} { !multiFactor &&
} { multiFactor &&
}
; } renderAuthFactor(item: IUserAuthFactor): XNode { if (item.method === "totp") { return Authenticator {item.hint} {DateFormats.relative.short(item.dateUpdated)} ; } if (item.method === "one-time") { return OTP {item.hint}***************** {DateFormats.relative.short(item.dateUpdated)} ; } return {item.method} {item.hint} {DateFormats.relative.short(item.dateUpdated)} ; } async notSetup() { this.renderer =

You account is not secure, please setup multi factor authentication.

this.addAuthenticator()} text="Add Authenticator" />
; } async addAuthenticator() { const authFactor = await this.userService.createAuthFactor(this.model); this.authFactor = authFactor; this.renderer =
Scan following QR Code in any compatible Authenticator App. Enter the generated code and hit the verify button.
this.authFactor.token ? "" : "Code is required")} > this.authFactor.token)}/>
; } async generateOTP() { const authList = (this.model.authFactors ??= []) as IUserAuthFactor[]; for (let index = 0; index < 8; index++) { authList.push(UserAuthFactor.create({ method: "one-time" })); } await this.userService.save(this.model); let text = ""; for (const iterator of authList) { if (!iterator?.displaySecret) { continue; } text += "\r\n" + iterator.displaySecret; } text += "\r\n"; this.renderer =
Please copy and save these passwords somewhere safe. You can use them if you cannot access Authenticator app.