UNPKG

@citrineos/util

Version:

The OCPP util module which supplies helpful utilities like cache and queue connectors, etc.

142 lines 6.31 kB
"use strict"; /* * // Copyright Contributors to the CitrineOS Project * */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const tslog_1 = require("tslog"); const fastify_plugin_1 = __importDefault(require("fastify-plugin")); const base_1 = require("@citrineos/base"); /** * Authentication plugin for Fastify * This plugin adds authentication and authorization capabilities to Fastify * using the provided auth provider * * @param fastify Fastify instance * @param provider Auth provider instance * @param options Plugin options */ const apiAuthPlugin = (fastify_1, _a) => __awaiter(void 0, [fastify_1, _a], void 0, function* (fastify, { provider, options = {}, logger }) { //TODO add logger instance ? const _logger = logger ? logger.getSubLogger({ name: 'AuthPlugin' }) : new tslog_1.Logger({ name: 'AuthPlugin' }); // Register the auth provider fastify.decorate('authProvider', provider); // Helper to check if a route is excluded from authentication function isExcludedRoute(url) { var _a; // Always exclude health check if (url === '/health') { return true; } const isExcluded = !!((_a = options.excludedRoutes) === null || _a === void 0 ? void 0 : _a.some((route) => url === route || url.startsWith(`${route}/`))); if (isExcluded && options.debug) { _logger.debug(`Skipping authentication for excluded route: ${url}`); } return isExcluded; } // Authentication decorator - validates token from Authorization header fastify.decorate('authenticate', function (request, reply) { return __awaiter(this, void 0, void 0, function* () { try { // Extract token const token = yield provider.extractToken(request); if (!token) { reply.code(base_1.HttpStatus.UNAUTHORIZED).send({ error: 'Unauthorized', message: 'Missing or invalid authorization header', }); return; } // Authenticate token const authResult = yield provider.authenticateToken(token); if (!authResult.isAuthenticated || !authResult.user) { reply.code(base_1.HttpStatus.UNAUTHORIZED).send({ error: 'Unauthorized', message: authResult.error || 'Invalid token', }); return; } // Store user info in request request.user = authResult.user; if (options.debug) { _logger.debug(`Authenticated user: ${authResult.user.id} (${authResult.user.name})`); _logger.debug(`Roles: ${authResult.user.roles.join(', ')}`); } } catch (error) { _logger.error('Authentication error:', error); reply.code(base_1.HttpStatus.UNAUTHORIZED).send({ error: 'Unauthorized', message: 'Authentication failed', }); } }); }); // Authorization decorator - authorizes user for the requested resource fastify.decorate('authorize', function (request, reply) { return __awaiter(this, void 0, void 0, function* () { try { // Check if user is authenticated if (!request.user) { reply.code(base_1.HttpStatus.UNAUTHORIZED).send({ error: 'Unauthorized', message: 'Authentication required', }); return; } // Authorize user for this request const authzResult = yield provider.authorizeUser(request.user, request); if (!authzResult.isAuthorized) { reply.code(base_1.HttpStatus.FORBIDDEN).send({ error: 'Forbidden', message: authzResult.error || 'Insufficient permissions', }); return; } if (options.debug) { _logger.debug(`Authorized user ${request.user.id} for ${request.method} ${request.url}`); } } catch (error) { _logger.error('Authorization error:', error); reply.code(base_1.HttpStatus.FORBIDDEN).send({ error: 'Forbidden', message: 'Authorization failed', }); } }); }); // Add global authentication hook for all routes fastify.addHook('onRequest', (request, reply) => __awaiter(void 0, void 0, void 0, function* () { // Skip authentication for excluded routes if (isExcludedRoute(request.url)) { if (options.debug) { _logger.trace(`Skipping authentication for excluded route: ${request.url}`); } return; } // Authenticate and authorize the request yield fastify.authenticate(request, reply); yield fastify.authorize(request, reply); })); _logger.info('Authentication plugin registered'); }); exports.default = (0, fastify_plugin_1.default)(apiAuthPlugin, { name: 'apiAuth', fastify: '5.x', }); //# sourceMappingURL=ApiAuthPlugin.js.map