feat!: reset password with email
This commit is contained in:
@@ -6,10 +6,8 @@ import {
|
||||
} from "@nestjs/common";
|
||||
import { User } from "@prisma/client";
|
||||
import * as argon from "argon2";
|
||||
import * as crypto from "crypto";
|
||||
import { authenticator, totp } from "otplib";
|
||||
import * as qrcode from "qrcode-svg";
|
||||
import { ConfigService } from "src/config/config.service";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
import { AuthService } from "./auth.service";
|
||||
import { AuthSignInTotpDTO } from "./dto/authSignInTotp.dto";
|
||||
@@ -17,7 +15,6 @@ import { AuthSignInTotpDTO } from "./dto/authSignInTotp.dto";
|
||||
@Injectable()
|
||||
export class AuthTotpService {
|
||||
constructor(
|
||||
private config: ConfigService,
|
||||
private prisma: PrismaService,
|
||||
private authService: AuthService
|
||||
) {}
|
||||
@@ -57,9 +54,7 @@ export class AuthTotpService {
|
||||
throw new BadRequestException("TOTP is not enabled");
|
||||
}
|
||||
|
||||
const decryptedSecret = this.decryptTotpSecret(totpSecret, dto.password);
|
||||
|
||||
const expected = authenticator.generate(decryptedSecret);
|
||||
const expected = authenticator.generate(totpSecret);
|
||||
|
||||
if (dto.totp !== expected) {
|
||||
throw new BadRequestException("Invalid code");
|
||||
@@ -81,41 +76,6 @@ export class AuthTotpService {
|
||||
return { accessToken, refreshToken };
|
||||
}
|
||||
|
||||
encryptTotpSecret(totpSecret: string, password: string) {
|
||||
let iv = this.config.get("TOTP_SECRET");
|
||||
iv = Buffer.from(iv, "base64");
|
||||
const key = crypto
|
||||
.createHash("sha256")
|
||||
.update(String(password))
|
||||
.digest("base64")
|
||||
.substr(0, 32);
|
||||
|
||||
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
|
||||
|
||||
let encrypted = cipher.update(totpSecret);
|
||||
|
||||
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
||||
|
||||
return encrypted.toString("base64");
|
||||
}
|
||||
|
||||
decryptTotpSecret(encryptedTotpSecret: string, password: string) {
|
||||
let iv = this.config.get("TOTP_SECRET");
|
||||
iv = Buffer.from(iv, "base64");
|
||||
const key = crypto
|
||||
.createHash("sha256")
|
||||
.update(String(password))
|
||||
.digest("base64")
|
||||
.substr(0, 32);
|
||||
|
||||
const encryptedText = Buffer.from(encryptedTotpSecret, "base64");
|
||||
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
||||
let decrypted = decipher.update(encryptedText);
|
||||
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
||||
|
||||
return decrypted.toString();
|
||||
}
|
||||
|
||||
async enableTotp(user: User, password: string) {
|
||||
if (!(await argon.verify(user.password, password)))
|
||||
throw new ForbiddenException("Invalid password");
|
||||
@@ -132,7 +92,6 @@ export class AuthTotpService {
|
||||
|
||||
// TODO: Maybe make the issuer configurable with env vars?
|
||||
const secret = authenticator.generateSecret();
|
||||
const encryptedSecret = this.encryptTotpSecret(secret, password);
|
||||
|
||||
const otpURL = totp.keyuri(
|
||||
user.username || user.email,
|
||||
@@ -144,7 +103,7 @@ export class AuthTotpService {
|
||||
where: { id: user.id },
|
||||
data: {
|
||||
totpEnabled: true,
|
||||
totpSecret: encryptedSecret,
|
||||
totpSecret: secret,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -177,9 +136,7 @@ export class AuthTotpService {
|
||||
throw new BadRequestException("TOTP is not in progress");
|
||||
}
|
||||
|
||||
const decryptedSecret = this.decryptTotpSecret(totpSecret, password);
|
||||
|
||||
const expected = authenticator.generate(decryptedSecret);
|
||||
const expected = authenticator.generate(totpSecret);
|
||||
|
||||
if (code !== expected) {
|
||||
throw new BadRequestException("Invalid code");
|
||||
@@ -208,9 +165,7 @@ export class AuthTotpService {
|
||||
throw new BadRequestException("TOTP is not enabled");
|
||||
}
|
||||
|
||||
const decryptedSecret = this.decryptTotpSecret(totpSecret, password);
|
||||
|
||||
const expected = authenticator.generate(decryptedSecret);
|
||||
const expected = authenticator.generate(totpSecret);
|
||||
|
||||
if (code !== expected) {
|
||||
throw new BadRequestException("Invalid code");
|
||||
|
||||
Reference in New Issue
Block a user