feat: 2FAのバックアップコードの実装 (#121)

This commit is contained in:
まっちゃとーにゅ
2023-07-30 03:35:42 +09:00
committed by GitHub
parent 99232ed417
commit 2b941ae648
34 changed files with 91 additions and 32 deletions

View File

@@ -455,6 +455,7 @@ export class UserEntityService implements OnModuleInit {
preventAiLearning: profile!.preventAiLearning,
isExplorable: user.isExplorable,
isDeleted: user.isDeleted,
twoFactorBackupCodes: profile?.twoFactorBackupSecret?.length === 20 ? 'full' : (profile?.twoFactorBackupSecret?.length ?? 0) > 0 ? 'partial' : 'none',
hideOnlineStatus: user.hideOnlineStatus,
hasUnreadSpecifiedNotes: this.noteUnreadsRepository.count({
where: { userId: user.id, isSpecified: true },

View File

@@ -91,6 +91,11 @@ export class UserProfile {
})
public twoFactorTempSecret: string | null;
@Column('varchar', {
nullable: true, array: true,
})
public twoFactorBackupSecret: string[] | null;
@Column('varchar', {
length: 128, nullable: true,
})

View File

@@ -320,6 +320,11 @@ export const packedMeDetailedOnlySchema = {
type: 'boolean',
nullable: false, optional: false,
},
twoFactorBackupCodes: {
type: 'string',
enum: ['full', 'partial', 'none'],
nullable: false, optional: false,
},
hideOnlineStatus: {
type: 'boolean',
nullable: false, optional: false,

View File

@@ -155,6 +155,13 @@ export class SigninApiService {
});
}
if (profile.twoFactorBackupSecret?.includes(token)) {
await this.userProfilesRepository.update({ userId: profile.userId }, {
twoFactorBackupSecret: profile.twoFactorBackupSecret.filter((secret) => secret !== token),
});
return this.signinService.signin(request, reply, user);
}
const delta = OTPAuth.TOTP.validate({
secret: OTPAuth.Secret.fromBase32(profile.twoFactorSecret!),
digits: 6,

View File

@@ -54,8 +54,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
throw new Error('not verified');
}
const backupCodes = Array.from({ length: 20 }, () => {
return new OTPAuth.Secret().base32;
});
await this.userProfilesRepository.update(me.id, {
twoFactorSecret: profile.twoFactorTempSecret,
twoFactorBackupSecret: backupCodes,
twoFactorEnabled: true,
});
@@ -64,6 +69,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
detail: true,
includeSecrets: true,
}));
return {
backupCodes: backupCodes,
};
});
}
}

View File

@@ -42,6 +42,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
await this.userProfilesRepository.update(me.id, {
twoFactorSecret: null,
twoFactorBackupSecret: null,
twoFactorEnabled: false,
usePasswordLessLogin: false,
});