lib/shared/guards/abstract-auth.guard.ts
An abstract class for creating authentication guards.
CanActivate
Properties |
|
Methods |
|
Async canActivate | ||||||||
canActivate(context: ExecutionContext)
|
||||||||
Defined in lib/shared/guards/abstract-auth.guard.ts:47
|
||||||||
Determines whether the current request is allowed to proceed based on the presence and validity of an access token.
Parameters :
Returns :
unknown
A boolean indicating whether the request is allowed to proceed. |
Private getAccessTokenFromRequest | ||||||||
getAccessTokenFromRequest(req: Request)
|
||||||||
Defined in lib/shared/guards/abstract-auth.guard.ts:83
|
||||||||
Extracts the access token from the request.
Parameters :
Returns :
any
The access token if found, otherwise null. |
Private Async validateToken | ||||||||
validateToken(token: string)
|
||||||||
Defined in lib/shared/guards/abstract-auth.guard.ts:72
|
||||||||
Validates the given access token by checking it against the store.
Parameters :
Returns :
unknown
The user identity if the token is valid, otherwise null. |
import {
CanActivate,
ExecutionContext,
ForbiddenException,
Logger,
} from "@nestjs/common";
import {
ACCESS_TOKEN_ERROR_MSG,
AUTH_ACCESS_TOKEN_PREFIX,
AUTH_JWT_CACHE_PREFIX,
} from "../../common/auth/auth.constants";
import { Request } from "express";
import { CacheService } from "../modules/cache/cache.types";
import { UserService } from "../../common/user/user.types";
import { REQUEST_PROPS } from "../constants";
/**
* An abstract class for creating authentication guards.
*/
export abstract class AbstractAuthGuard implements CanActivate {
protected abstract readonly logger: Logger;
protected abstract readonly cacheService: CacheService;
protected abstract readonly userService: UserService;
protected fetchUser = true;
/**
* Determines whether the current request is allowed to proceed based on the presence and validity of an access token.
* @param context - The execution context of the request.
* @returns A boolean indicating whether the request is allowed to proceed.
*/
async canActivate(context: ExecutionContext) {
const req = context.switchToHttp().getRequest();
const token = this.getAccessTokenFromRequest(req);
const userIdentity = await this.validateToken(token);
if (userIdentity) {
req[REQUEST_PROPS.accessToken] = token;
} else {
this.logger.warn(`Invalid token: ${token}`);
throw new ForbiddenException(ACCESS_TOKEN_ERROR_MSG);
}
if (this.fetchUser) {
const user = await this.userService.findByLogin(userIdentity);
if (!user) {
throw new ForbiddenException(ACCESS_TOKEN_ERROR_MSG);
}
req[REQUEST_PROPS.currentUser] = user;
}
return true;
}
/**
* Validates the given access token by checking it against the store.
* @param token - The access token to validate.
* @returns The user identity if the token is valid, otherwise null.
*/
private async validateToken(token: string) {
return this.cacheService.get(
`${AUTH_JWT_CACHE_PREFIX}:${AUTH_ACCESS_TOKEN_PREFIX}:${token}`,
);
}
/**
* Extracts the access token from the request.
* @param req - The request object.
* @returns The access token if found, otherwise null.
*/
private getAccessTokenFromRequest(req: Request) {
if (req.cookies?.accessToken) {
return req.cookies.accessToken;
}
if (req.headers?.authorization) {
const authorizationHeader = req.headers.authorization;
const parts = authorizationHeader.match(/Bearer\s+(\S+)\s*(.+)?/);
if (!parts.length) {
return null;
}
return parts[1];
}
return null;
}
}