bb-inspired
Version:
Core library for BB-inspired NestJS backend
145 lines • 6.73 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var AuthMiddleware_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthMiddleware = void 0;
const common_1 = require("@nestjs/common");
const jwt_service_1 = require("../jwt.service");
const auth_service_1 = require("../auth.service");
const external_auth_service_1 = require("./external-auth.service");
const logger_1 = require("../../../utils/logger");
let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
constructor(options, middlewareOptions, jwtService, authService, externalAuthService) {
this.options = options;
this.middlewareOptions = middlewareOptions;
this.jwtService = jwtService;
this.authService = authService;
this.externalAuthService = externalAuthService;
this.logger = new logger_1.AppLogger(AuthMiddleware_1.name);
this.excludePaths = middlewareOptions.excludePaths || [
'/api/auth/login',
'/api/auth/refresh',
'/api/health',
'/docs',
'/api-docs',
];
}
async use(req, res, next) {
if (this.shouldSkipAuth(req.path)) {
return next();
}
try {
const token = this.extractTokenFromHeader(req);
if (!token) {
this.logger.debug(`No token provided for ${req.path}`);
return this.handleUnauthorized(req, res, next, 'No token provided');
}
try {
const payload = await this.jwtService.verifyToken(token);
const user = await this.authService.validateUserByJwt(payload);
if (!user) {
this.logger.warn(`User validation failed for token in request to ${req.path}`);
return this.handleUnauthorized(req, res, next, 'Invalid user');
}
req.user = user;
if (this.middlewareOptions.externalAuth) {
this.validateWithExternalService(token, user)
.catch(error => {
this.logger.error(`Error validating with external auth service: ${error.message}`, error.stack);
});
}
return next();
}
catch (jwtError) {
if (this.middlewareOptions.externalAuth) {
try {
const validationResult = await this.externalAuthService.validateToken(token);
if (validationResult.isValid && validationResult.user) {
req.user = validationResult.user;
return next();
}
this.logger.warn(`External auth validation failed for ${req.path}: ${validationResult.error}`);
return this.handleUnauthorized(req, res, next, validationResult.error || 'Invalid token');
}
catch (externalError) {
this.logger.error(`External auth service error: ${externalError.message}`, externalError.stack);
return this.handleUnauthorized(req, res, next, 'Authentication service error');
}
}
else {
this.logger.warn(`JWT validation failed for ${req.path}: ${jwtError.message}`);
return this.handleUnauthorized(req, res, next, 'Invalid token');
}
}
}
catch (error) {
this.logger.error(`Auth middleware error: ${error.message}`, error.stack);
return this.handleUnauthorized(req, res, next, 'Authentication error');
}
}
extractTokenFromHeader(req) {
const authHeader = req.headers.authorization;
if (!authHeader) {
return null;
}
const [type, token] = authHeader.split(' ');
return type === 'Bearer' ? token : null;
}
shouldSkipAuth(path) {
return this.excludePaths.some(excludePath => {
if (excludePath === path) {
return true;
}
if (excludePath.endsWith('*')) {
const prefix = excludePath.slice(0, -1);
return path.startsWith(prefix);
}
return false;
});
}
handleUnauthorized(req, res, next, message) {
var _a;
if (((_a = this.middlewareOptions.errorHandling) === null || _a === void 0 ? void 0 : _a.throwUnauthorized) === false) {
req.user = null;
return next();
}
res.status(401).json({
statusCode: 401,
message: message || 'Unauthorized',
timestamp: new Date().toISOString(),
path: req.url,
});
}
async validateWithExternalService(token, user) {
try {
const validationResult = await this.externalAuthService.validateToken(token);
if (!validationResult.isValid) {
this.logger.warn(`Background validation with external auth service failed for user ${user.id}: ${validationResult.error}`);
}
}
catch (error) {
this.logger.error(`Background validation with external auth service error: ${error.message}`, error.stack);
}
}
};
exports.AuthMiddleware = AuthMiddleware;
exports.AuthMiddleware = AuthMiddleware = AuthMiddleware_1 = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, common_1.Inject)('AUTH_OPTIONS')),
__param(1, (0, common_1.Inject)('AUTH_MIDDLEWARE_OPTIONS')),
__metadata("design:paramtypes", [Object, Object, jwt_service_1.JwtService,
auth_service_1.AuthService,
external_auth_service_1.ExternalAuthService])
], AuthMiddleware);
//# sourceMappingURL=auth.middleware.js.map