boredgame/src/lib/server/api/services/totp.service.ts

58 lines
1.6 KiB
TypeScript
Raw Normal View History

import { inject, injectable } from "tsyringe";
import { HMAC } from 'oslo/crypto';
2024-08-31 00:36:22 +00:00
import { decodeHex, encodeHex } from 'oslo/encoding';
import {CredentialsRepository} from "$lib/server/api/repositories/credentials.repository";
2024-08-31 00:36:22 +00:00
import { TOTPController } from "oslo/otp";
import type { CredentialsType } from "$db/tables";
@injectable()
export class TotpService {
constructor(
@inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository
) {
}
async findOneByUserId(userId: string) {
return this.credentialsRepository.findTOTPCredentialsByUserId(userId);
}
2024-08-31 00:36:22 +00:00
async findOneByUserIdOrThrow(userId: string) {
const credential = await this.findOneByUserId(userId);
if (!credential) {
throw new Error('TOTP credential not found');
}
return credential;
}
async create(userId: string) {
const twoFactorSecret = await new HMAC('SHA-1').generateKey();
try {
return await this.credentialsRepository.create({
user_id: userId,
secret_data: encodeHex(twoFactorSecret),
type: 'totp'
});
} catch (e) {
console.error(e);
return null;
}
}
async deleteOneByUserId(userId: string) {
return this.credentialsRepository.deleteByUserId(userId);
}
2024-08-31 00:36:22 +00:00
async deleteOneByUserIdAndType(userId: string, type: CredentialsType) {
return this.credentialsRepository.deleteByUserIdAndType(userId, type)
}
async verify(userId: string, code: string) {
const credential = await this.credentialsRepository.findTOTPCredentialsByUserId(userId);
if (!credential) {
throw new Error('TOTP credential not found');
}
return await new TOTPController().verify(code, decodeHex(credential.secret_data))
}
}