icynet-auth-server/src/modules/objects/user/user-totp-token.service.ts

70 lines
1.7 KiB
TypeScript

import { Inject, Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { UserTOTPToken } from './user-totp-token.entity';
import { User } from './user.entity';
import { TokenService } from 'src/modules/utility/services/token.service';
import { authenticator as totp } from 'otplib';
totp.options = {
window: 2,
};
@Injectable()
export class UserTOTPService {
constructor(
@Inject('USER_TOTP_TOKEN_REPOSITORY')
private userTOTPTokenRepository: Repository<UserTOTPToken>,
private token: TokenService,
) {}
/**
* Check if the user has TOTP enabled
* @param user User object
* @returns true if the user has TOTP enabled
*/
public async userHasTOTP(user: User): Promise<boolean> {
return !!(await this.getUserTOTP(user));
}
/**
* Get the TOTP token of a user
* @param user User object
* @returns TOTP token
*/
public async getUserTOTP(user: User): Promise<UserTOTPToken> {
return this.userTOTPTokenRepository.findOne({
user,
activated: true,
});
}
public validateTOTP(secret: string, token: string): boolean {
return totp.verify({ token, secret });
}
public getTOTPURL(secret: string, username: string): string {
return totp.keyuri(username, 'Icy Network', secret);
}
public createTOTPSecret(): string {
return totp.generateSecret();
}
public async activateTOTP(
user: User,
secret: string,
): Promise<UserTOTPToken> {
const totp = new UserTOTPToken();
totp.activated = true;
totp.user = user;
totp.token = secret;
totp.recovery_token = Array.from({ length: 8 }, () =>
this.token.generateString(8),
).join(' ');
await this.userTOTPTokenRepository.save(totp);
return totp;
}
}