-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathauth.middleware.ts
More file actions
93 lines (84 loc) · 2.84 KB
/
Copy pathauth.middleware.ts
File metadata and controls
93 lines (84 loc) · 2.84 KB
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import {
BadRequestException,
HttpException,
Injectable,
InternalServerErrorException,
NestMiddleware,
UnauthorizedException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import Sentry from '@sentry/minimal';
import { Response } from 'express';
import jwt from 'jsonwebtoken';
import { Repository } from 'typeorm';
import { LogOutEntity } from '../entities/log-out/log-out.entity.js';
import { JwtScopesEnum } from '../entities/user/enums/jwt-scopes.enum.js';
import { UserEntity } from '../entities/user/user.entity.js';
import { Messages } from '../exceptions/text/messages.js';
import { Constants } from '../helpers/constants/constants.js';
import { isObjectEmpty } from '../helpers/index.js';
import { IRequestWithCognitoInfo } from './cognito-decoded.interface.js';
@Injectable()
export class AuthMiddleware implements NestMiddleware {
public constructor(
@InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
@InjectRepository(LogOutEntity)
private readonly logOutRepository: Repository<LogOutEntity>,
) {}
async use(req: IRequestWithCognitoInfo, _res: Response, next: (err?: any, res?: any) => void): Promise<void> {
let token: string;
try {
token = req.cookies[Constants.JWT_COOKIE_KEY_NAME];
} catch (_e) {
if (process.env.NODE_ENV !== 'test') {
throw new UnauthorizedException('JWT verification failed');
}
}
if (!token) {
throw new UnauthorizedException('Token is missing');
}
const isLoggedOut = !!(await this.logOutRepository.findOne({ where: { jwtToken: token } }));
if (isLoggedOut) {
throw new UnauthorizedException('Token is invalid');
}
try {
const jwtSecret = process.env.JWT_SECRET;
const data = jwt.verify(token, jwtSecret) as jwt.JwtPayload;
const userId = data.id;
if (!userId) {
throw new UnauthorizedException('JWT verification failed');
}
const userExists = await this.userRepository.findOne({ where: { id: userId } });
if (!userExists) {
throw new UnauthorizedException('JWT verification failed');
}
if (userExists.suspended) {
throw new UnauthorizedException(Messages.ACCOUNT_SUSPENDED);
}
const addedScope: Array<JwtScopesEnum> = data.scope;
if (addedScope && addedScope.length > 0) {
if (addedScope.includes(JwtScopesEnum.TWO_FA_ENABLE)) {
throw new BadRequestException(Messages.TWO_FA_REQUIRED);
}
}
const payload = {
sub: userId,
email: data.email,
exp: data.exp,
iat: data.iat,
};
if (!payload || isObjectEmpty(payload)) {
throw new UnauthorizedException('JWT verification failed');
}
req.decoded = payload;
next();
} catch (e) {
Sentry.captureException(e);
if (e instanceof HttpException || e instanceof UnauthorizedException) {
throw e;
}
throw new InternalServerErrorException(Messages.AUTHORIZATION_REJECTED);
}
}
}