-
Notifications
You must be signed in to change notification settings - Fork 70
/
google-authenticator-verify.provider.ts
72 lines (67 loc) · 2.22 KB
/
google-authenticator-verify.provider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Copyright (c) 2023 Sourcefuse Technologies
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
import {inject, Provider} from '@loopback/context';
import {repository} from '@loopback/repository';
import {HttpErrors} from '@loopback/rest';
import {ILogger, LOGGER} from '@sourceloop/core';
import {AuthErrorKeys, VerifyFunction} from 'loopback4-authentication';
import {authenticator} from 'otplib';
import {UserCredentials} from '../../../models';
import {
OtpCacheRepository,
UserCredentialsRepository,
UserRepository,
} from '../../../repositories';
export class GoogleAuthenticatorVerifyProvider
implements Provider<VerifyFunction.OtpAuthFn>
{
constructor(
@repository(UserRepository)
public userRepository: UserRepository,
@repository(UserCredentialsRepository)
public userCredsRepository: UserCredentialsRepository,
@repository(OtpCacheRepository)
public otpCacheRepo: OtpCacheRepository,
@inject(LOGGER.LOGGER_INJECT) private readonly logger: ILogger,
) {}
value(): VerifyFunction.OtpAuthFn {
return async (username: string, otp: string) => {
const user = await this.userRepository.findOne({
where: {
username: username,
},
});
if (!user) {
this.logger.error('Invalid Username');
throw new HttpErrors.Unauthorized(AuthErrorKeys.InvalidCredentials);
}
const authenticatorSecret: Pick<UserCredentials, 'secretKey'> | null =
await this.userCredsRepository.findOne({
where: {
userId: user.id,
},
fields: {
secretKey: true,
},
});
if (!authenticatorSecret?.secretKey) {
throw new HttpErrors.Unauthorized(AuthErrorKeys.InvalidCredentials);
}
let isValid = false;
try {
isValid = authenticator
.create(authenticator.allOptions())
.verify({token: otp, secret: authenticatorSecret.secretKey});
} catch (err) {
this.logger.error(err);
throw new HttpErrors.Unauthorized(AuthErrorKeys.InvalidCredentials);
}
if (!isValid) {
throw new HttpErrors.Unauthorized(AuthErrorKeys.OtpExpired);
}
return user;
};
}
}