UNPKG

@gov-cy/govcy-express-services

Version:

An Express-based system that dynamically renders services using @gov-cy/govcy-frontend-renderer and posts data to a submission API.

131 lines (120 loc) 4.97 kB
/** * @fileoverview This module provides middleware functions for authentication and authorization in an Express application. * It includes functions to check if a user is logged in, handle login and logout routes, and enforce natural person policy. * * @module cyLoginAuth */ import { getLoginUrl, handleCallback, getLogoutUrl } from '../auth/cyLoginAuth.mjs'; import { logger } from "../utils/govcyLogger.mjs"; import { handleMiddlewareError } from "../utils/govcyUtils.mjs"; /** * Middleware to check if the user is authenticated. If not, redirect to the login page. * * @param {object} req The request object * @param {object} res The response object * @param {object} next The next middleware function */ export function requireAuth(req, res, next) { if (!req.session.user) { // Store the original URL before redirecting to login req.session.redirectAfterLogin = req.originalUrl; return res.redirect('/login'); } next(); } /** * Middleware to enforce natural person policy. If the user is not a natural person, return a 403 error. * * @param {object} req The request object * @param {object} res The response object * @param {object} next The next middleware function */ export function naturalPersonPolicy(req, res, next) { // // allow only natural persons with approved profiles // if (req.session.user.profile_type == 'Individual' && req.session.user.unique_identifier) { // next(); // } else { // return handleMiddlewareError("🚨 Access Denied: natural person policy not met.", 403, next); // } // https://dev.azure.com/cyprus-gov-cds/Documentation/_wiki/wikis/Documentation/42/For-Cyprus-Natural-or-Legal-person const { profile_type, unique_identifier } = req.session.user || {}; // Allow only natural persons with approved profiles if (profile_type === 'Individual' && unique_identifier) { // Validate Cypriot Citizen (starts with "00" and is 10 characters long) if (unique_identifier.startsWith('00') && unique_identifier.length === 10) { return next(); } // Validate Foreigner with ARN (starts with "05" and is 10 characters long) if (unique_identifier.startsWith('05') && unique_identifier.length === 10) { return next(); } } // Deny access if validation fails return handleMiddlewareError("🚨 Access Denied: natural person policy not met.", 403, next); } /** * Middleware to handle the login route. Redirects the user to the login URL. * * @param {object} req The request object * @param {object} res The response object * @param {object} next The next middleware function */ export function handleLoginRoute() { return async (req, res, next) => { try { let loginUrl = await getLoginUrl(req); res.redirect(loginUrl); } catch (error) { next(error); // Pass any errors to Express error handler } }; } /** * Middleware to handle the sign-in callback from the authentication provider. * * @param {object} req The request object * @param {object} res The response object * @param {object} next The next middleware function */ export function handleSigninOidc() { return async (req, res, next) => { try { const { tokens, claims, userInfo } = await handleCallback(req); // Store user information in session req.session.user = { ...userInfo, id_token: tokens.id_token, access_token: tokens.access_token, refresh_token: tokens.refresh_token || null, }; // Redirect to the stored URL after login or fallback to '/' const redirectUrl = req.session.redirectAfterLogin || '/'; // Clean up session for redirect after login delete req.session.redirectAfterLogin; // Redirect to the stored URL res.redirect(redirectUrl); } catch (error) { logger.debug('Token exchange failed:', error,req); res.status(500).send('Authentication failed'); } } } /** * Middleware to handle the logout route. Destroys the session and redirects the user to the logout URL. * * @param {object} req The request object * @param {object} res The response object * @param {object} next The next middleware function */ export function handleLogout() { return (req, res, next) => { if (!req.session.user) { return res.redirect('/'); // Redirect if not logged in } const id_token_hint = req.session.user.id_token; // Retrieve ID token req.session.destroy(() => { const logoutUrl = getLogoutUrl(id_token_hint); res.redirect(logoutUrl); }); }; }