0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-24 22:41:28 -05:00

refactor(core): extract isNewMfaVerification property (#6338)

extract isNewMfaVerifrication property
This commit is contained in:
simeng-li 2024-07-26 15:08:03 +08:00 committed by GitHub
parent 58a5004aa2
commit 34c8bedef6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 35 additions and 25 deletions

View file

@ -36,24 +36,6 @@ const isMfaVerificationRecord = (
return mfaVerificationTypes.includes(verification.type);
};
/**
* Check if the MFA verification record is a new bind MFA verification.
* New bind MFA verification can only be used for binding new MFA factors.
*/
const isNewBindMfaVerification = (verification: MfaVerificationRecord) => {
switch (verification.type) {
case VerificationType.TOTP: {
return Boolean(verification.secret);
}
case VerificationType.WebAuthn: {
return Boolean(verification.registrationInfo);
}
case VerificationType.BackupCode: {
return false;
}
}
};
export class MfaValidator {
constructor(
private readonly mfaSettings: Mfa,
@ -137,7 +119,7 @@ export class MfaValidator {
isMfaVerificationRecord(verification) &&
verification.isVerified &&
// New bind MFA verification can not be used for verification
!isNewBindMfaVerification(verification) &&
!verification.isNewBindMfaVerification &&
// Check if the verification type is enabled in the user's MFA settings
this.userEnabledMfaVerifications.some(
(factor) => factor.type === mfaVerificationTypeToMfaFactorMap[verification.type]

View file

@ -7,7 +7,7 @@ import type Libraries from '#src/tenants/Libraries.js';
import type Queries from '#src/tenants/Queries.js';
import assertThat from '#src/utils/assert-that.js';
import { type VerificationRecord } from './verification-record.js';
import { type MfaVerificationRecord } from './verification-record.js';
export type BackupCodeVerificationRecordData = {
id: string;
@ -24,7 +24,7 @@ export const backupCodeVerificationRecordDataGuard = z.object({
code: z.string().optional(),
}) satisfies ToZodObject<BackupCodeVerificationRecordData>;
export class BackupCodeVerification implements VerificationRecord<VerificationType.BackupCode> {
export class BackupCodeVerification implements MfaVerificationRecord<VerificationType.BackupCode> {
/**
* Factory method to create a new BackupCodeVerification instance
*
@ -60,6 +60,10 @@ export class BackupCodeVerification implements VerificationRecord<VerificationTy
return Boolean(this.code);
}
get isNewBindMfaVerification() {
return false;
}
async verify(code: string) {
const {
users: { findUserById, updateUserById },

View file

@ -20,7 +20,7 @@ import type Libraries from '#src/tenants/Libraries.js';
import type Queries from '#src/tenants/Queries.js';
import assertThat from '#src/utils/assert-that.js';
import { type VerificationRecord } from './verification-record.js';
import { type MfaVerificationRecord } from './verification-record.js';
const defaultDisplayName = 'Unnamed User';
@ -47,7 +47,7 @@ export const totpVerificationRecordDataGuard = z.object({
verified: z.boolean(),
}) satisfies ToZodObject<TotpVerificationRecordData>;
export class TotpVerification implements VerificationRecord<VerificationType.TOTP> {
export class TotpVerification implements MfaVerificationRecord<VerificationType.TOTP> {
/**
* Factory method to create a new TotpVerification instance
*
@ -90,6 +90,10 @@ export class TotpVerification implements VerificationRecord<VerificationType.TOT
return this.#secret;
}
get isNewBindMfaVerification() {
return Boolean(this.#secret);
}
/**
* Create a new TOTP secret and QR code for the user.
* The secret will be stored in the instance and can be used for verifying the TOTP.

View file

@ -37,3 +37,19 @@ export abstract class IdentifierVerificationRecord<
/** Identify the user associated with the verification record. */
abstract identifyUser(): Promise<User>;
}
type MfaVerificationType =
| VerificationType.TOTP
| VerificationType.BackupCode
| VerificationType.WebAuthn;
export abstract class MfaVerificationRecord<
T extends MfaVerificationType = MfaVerificationType,
Json extends Data<T> = Data<T>,
> extends VerificationRecord<T, Json> {
/**
* Indicates if the verification record is for a new bind MFA verification.
* A new bind MFA verification record can not be used for existing user's interaction verification.
**/
abstract get isNewBindMfaVerification(): boolean;
}

View file

@ -25,7 +25,7 @@ import type Libraries from '#src/tenants/Libraries.js';
import type Queries from '#src/tenants/Queries.js';
import assertThat from '#src/utils/assert-that.js';
import { type VerificationRecord } from './verification-record.js';
import { type MfaVerificationRecord } from './verification-record.js';
export type WebAuthnVerificationRecordData = {
id: string;
@ -50,7 +50,7 @@ export const webAuthnVerificationRecordDataGuard = z.object({
registrationInfo: bindWebAuthnGuard.optional(),
}) satisfies ToZodObject<WebAuthnVerificationRecordData>;
export class WebAuthnVerification implements VerificationRecord<VerificationType.WebAuthn> {
export class WebAuthnVerification implements MfaVerificationRecord<VerificationType.WebAuthn> {
/**
* Factory method to create a new WebAuthnVerification instance
*
@ -104,6 +104,10 @@ export class WebAuthnVerification implements VerificationRecord<VerificationType
return this.#registrationInfo;
}
get isNewBindMfaVerification() {
return Boolean(this.#registrationInfo ?? this.registrationChallenge);
}
/**
* @remarks
* This method is used to generate the WebAuthn registration options for the user.