UNPKG

@sphereon/ssi-express-support

Version:

944 lines (933 loc) • 30.5 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { EntraIDAuth: () => EntraIDAuth, ExpressBuilder: () => ExpressBuilder, ExpressCorsConfigurer: () => ExpressCorsConfigurer, MapBasedStaticBearerUserProvider: () => MapBasedStaticBearerUserProvider, OpenIDConnectAuthApi: () => OpenIDConnectAuthApi, StaticBearerAuth: () => StaticBearerAuth, checkAuth: () => checkAuth, checkAuthenticationOnly: () => checkAuthenticationOnly, checkAuthorizationOnly: () => checkAuthorizationOnly, checkUserIsInRole: () => checkUserIsInRole, copyGlobalAuthToEndpoint: () => copyGlobalAuthToEndpoint, copyGlobalAuthToEndpoints: () => copyGlobalAuthToEndpoints, env: () => env, getAuthenticatedUserEndpoint: () => getAuthenticatedUserEndpoint, getIdTokenEndpoint: () => getIdTokenEndpoint, getLoginCallbackEndpoint: () => getLoginCallbackEndpoint, getLoginEndpoint: () => getLoginEndpoint, getLogoutCallbackEndpoint: () => getLogoutCallbackEndpoint, getLogoutEndpoint: () => getLogoutEndpoint, hasEndpointOpts: () => hasEndpointOpts, isUserAuthenticated: () => isUserAuthenticated, isUserNotAuthenticated: () => isUserNotAuthenticated, jsonErrorHandler: () => jsonErrorHandler, oidcDiscoverIssuer: () => oidcDiscoverIssuer, oidcGetClient: () => oidcGetClient, sendErrorResponse: () => sendErrorResponse }); module.exports = __toCommonJS(index_exports); // src/entra-id-auth.ts var import_passport = __toESM(require("passport"), 1); var EntraIDAuth = class _EntraIDAuth { static { __name(this, "EntraIDAuth"); } strategy; options; static init(strategy) { return new _EntraIDAuth(strategy); } constructor(strategy) { this.strategy = strategy; } withOptions(options) { this.options = { ...options, passReqToCallback: "passReqToCallback" in options ? options.passReqToCallback : false }; return this; } connectPassport() { const _options = this.options; if (!_options) { throw Error("No options supplied for EntraID"); } import("passport-azure-ad").then((entraID) => import_passport.default.use(this.strategy, new entraID.BearerStrategy(_options, function(token, cb) { if (token) { return cb(null, token); } return cb("bearer token not found or incorrect", null); }))).catch((reason) => { console.log(reason); throw Error('Could not create bearer strategy. Did you include the "passport-azure-ad/bearer-strategy" dependency in package.json?'); }); } }; // src/static-bearer-auth.ts var import_passport2 = __toESM(require("passport"), 1); var import_to_string = require("uint8arrays/to-string"); var StaticBearerAuth = class _StaticBearerAuth { static { __name(this, "StaticBearerAuth"); } strategy; static providers = /* @__PURE__ */ new Map(); static verifyOptions = /* @__PURE__ */ new Map(); hashTokens = false; static init(strategy, provider) { return new _StaticBearerAuth(strategy ?? "bearer", provider ?? new MapBasedStaticBearerUserProvider(strategy)); } constructor(strategy, provider) { this.strategy = strategy; if (_StaticBearerAuth.providers.has(strategy)) { if (_StaticBearerAuth.providers.get(strategy) !== provider) { throw Error("Cannot register another user provider for strategy: " + strategy); } } else { _StaticBearerAuth.providers.set(strategy, provider); } } get provider() { const provider = _StaticBearerAuth.providers.get(this.strategy); if (!provider) { throw Error("Could not get user provider for " + this.strategy); } return provider; } withHashTokens(hashTokens) { this.hashTokens = hashTokens; return this; } withUsers(users) { this.addUser(users); return this; } addUser(user) { this.provider.addUser(user); return this; } withVerifyOptions(options) { _StaticBearerAuth.verifyOptions.set(this.strategy, options); return this; } connectPassport() { const _provider = this.provider; function findUser(token, cb) { const user = _provider.getUser(token); if (user) { return cb(null, user); } return cb("bearer token not found or incorrect", false); } __name(findUser, "findUser"); import("passport-http-bearer").then((httpBearer) => { const hashTokens = this.hashTokens ?? false; import_passport2.default.use(this.strategy, new httpBearer.Strategy({ passReqToCallback: false }, function(token, cb) { if (hashTokens) { import("@noble/hashes/sha256").then((hash) => { findUser((0, import_to_string.toString)(hash.sha256(token)), cb); }).catch((error) => { console.log(`hash problem: ${error}`); throw Error("Did you include @noble/hashes in package.json?"); }); } else { findUser(token, cb); } })); }).catch((error) => { console.log(`passport-http-bearer package problem: ${error}`); throw Error("Did you include passport-http-bearer in package.json?"); }); } }; var MapBasedStaticBearerUserProvider = class { static { __name(this, "MapBasedStaticBearerUserProvider"); } _strategy; _users = []; _hashedTokens; constructor(strategy, hashedTokens) { this._strategy = strategy; this._hashedTokens = hashedTokens ?? false; } get users() { return this._users; } get hashedTokens() { return this._hashedTokens; } get strategy() { return this._strategy; } getUser(token) { return this.users.find((user) => user.token === token); } addUser(user, hashToken) { const users = Array.isArray(user) ? user : [ user ]; if (hashToken) { if (!this.hashedTokens) { throw Error("Cannot hash token, when hashed tokens is not enabled on the user provider for strategy " + this.strategy); } import("@noble/hashes/sha256").then((hash) => { users.forEach((user2) => user2.token = (0, import_to_string.toString)(hash.sha256(user2.token))); }).catch((error) => { console.log(`hash problem: ${error}`); throw Error("Did you include @noble/hashes in package.json?"); }); } this._users.push(...users); } getUsers() { return this._users; } }; // src/auth-utils.ts var import_passport3 = __toESM(require("passport"), 1); // src/express-utils.ts function sendErrorResponse(response, statusCode, message, error) { let msg = message; if (!msg) { console.error("Message was null when calling sendErrorResponse. This should not happen"); msg = "An unexpected error occurred"; statusCode = 500; } else { console.error(`sendErrorResponse (${statusCode}): ${typeof msg === "string" ? msg : JSON.stringify(msg)}`); } if (error) { if (error instanceof Error) { console.error(`error message: ${error.message}`); } console.error(`error object: ${JSON.stringify(error)}`); } if (statusCode >= 500) { console.error("Original error stack (if any) and REST API error stack:"); console.error(error?.stack); console.error(Error().stack); } if (response.headersSent) { console.error(`sendErrorResponse headers already sent`); return response; } response.statusCode = statusCode; if (typeof msg === "string" && !msg.startsWith("{")) { msg = { error: msg }; } if (typeof msg === "string" && msg.startsWith("{")) { response.header("Content-Type", "application/json"); return response.status(statusCode).end(msg); } return response.status(statusCode).json(msg); } __name(sendErrorResponse, "sendErrorResponse"); var jsonErrorHandler = /* @__PURE__ */ __name((err, req, res, next) => { const statusCode = "statusCode" in err ? err.statusCode : 500; let errorMsg = typeof err === "string" ? err : err.message ?? err; if (typeof errorMsg !== "string") { errorMsg = JSON.stringify(errorMsg); } if (res.headersSent) { console.log("Headers already sent, when calling error handler. Will defer to next error handler"); console.log(`Error was: ${JSON.stringify(err)}`); return next(err); } return sendErrorResponse(res, statusCode, errorMsg, err); }, "jsonErrorHandler"); // src/types.ts function hasEndpointOpts(opts) { return "endpointOpts" in opts && opts.endpointOpts; } __name(hasEndpointOpts, "hasEndpointOpts"); // src/auth-utils.ts var checkUserIsInRole = /* @__PURE__ */ __name((opts) => (req, res, next) => { if (!opts?.roles || opts.roles.length === 0) { return next(); } const roles = Array.isArray(opts.roles) ? opts.roles : [ opts.roles ]; if (!req?.user || !("role" in req.user)) { return res.status(401).end(); } const hasRole = roles.find((role) => req.user.role.toLowerCase() === role.toLowerCase()); if (!hasRole) { return res.status(403).end(); } return next(); }, "checkUserIsInRole"); var checkAuthenticationImpl = /* @__PURE__ */ __name((req, res, next, opts) => { const defaultCallback = /* @__PURE__ */ __name((err, user, _info, _status) => { if (err) { const message = "message" in err ? err.message : err; console.log("Authentication failed, error: " + JSON.stringify(message)); return next({ statusCode: 403, message }); } else if (!user) { console.log("Authentication failed, no user object present in request. Redirecting to /login"); return res.redirect("/authentication/login"); } if (options.session) { req.logIn(user, function(err2) { if (err2) { return next(err2); } }); } return next(); }, "defaultCallback"); if (!opts || !opts.authentication || opts.authentication.enabled === false) { return next(); } if (!opts.authentication.strategy) { console.log(`Authentication enabled, but no strategy configured. All auth request will be denied!`); return res.status(401).end(); } const options = { ...opts?.authentication?.strategyOptions, authInfo: opts?.authentication?.authInfo !== false, session: opts?.authentication?.session !== false }; const callback = opts?.authentication?.callback ?? (opts?.authentication?.useDefaultCallback ? defaultCallback : void 0); import_passport3.default.authenticate(opts.authentication.strategy, options, callback).call(void 0, req, res, next); }, "checkAuthenticationImpl"); var checkAuthorizationImpl = /* @__PURE__ */ __name((req, res, next, opts) => { if (!opts || !opts.authentication || !opts.authorization || opts.authentication.enabled === false || opts?.authorization.enabled === false) { return next(); } const authorization = opts.authorization; if (!authorization.enforcer && (!authorization.requireUserInRoles || authorization.requireUserInRoles.length === 0)) { console.log(`Authorization enabled for endpoint, but no enforcer or roles supplied`); return res.status(401).end(); } if (authorization.requireUserInRoles && authorization.requireUserInRoles.length > 0) { checkUserIsInRole({ roles: authorization.requireUserInRoles }); } if (authorization.enforcer) { const enforcer = authorization.enforcer; const permitted = enforcer.enforceSync(req.user, opts.resource, opts.operation); if (!permitted) { console.log(`Access to ${opts.resource} and op ${opts.operation} not allowed for ${req.user}`); return res.status(403).end(); } } return next(); }, "checkAuthorizationImpl"); var checkAuthenticationOnly = /* @__PURE__ */ __name((opts) => (req, res, next) => { return checkAuthenticationImpl(req, res, next, opts); }, "checkAuthenticationOnly"); var checkAuthorizationOnly = /* @__PURE__ */ __name((opts) => (req, res, next) => { return checkAuthorizationImpl(req, res, next, opts); }, "checkAuthorizationOnly"); var isUserNotAuthenticated = /* @__PURE__ */ __name((req, res, next) => { if (!req.user) { next(); } }, "isUserNotAuthenticated"); var isUserAuthenticated = /* @__PURE__ */ __name((req, res, next) => { if (!req.user) { return sendErrorResponse(res, 401, "Authentication required"); } else { return next(); } }, "isUserAuthenticated"); var checkAuth = /* @__PURE__ */ __name((opts) => { const handlers = []; handlers.push(checkAuthenticationOnly(opts)); handlers.push(checkAuthorizationOnly(opts)); opts?.handlers && handlers.push(...opts.handlers); return handlers; }, "checkAuth"); function copyGlobalAuthToEndpoint(args) { const opts = args?.opts; const key = args?.key; if (!opts || !key || !hasEndpointOpts(opts)) { return; } if (key === "basePath") { return; } if (opts.endpointOpts?.globalAuth) { if (opts.endpointOpts[key]?.disableGlobalAuth === true) { return; } opts.endpointOpts[key] = { ...opts.endpointOpts[key], endpoint: { ...opts.endpointOpts.globalAuth, ...opts.endpointOpts[key]?.endpoint } }; } } __name(copyGlobalAuthToEndpoint, "copyGlobalAuthToEndpoint"); function copyGlobalAuthToEndpoints(args) { args?.keys.forEach((key) => copyGlobalAuthToEndpoint({ opts: args?.opts, key })); } __name(copyGlobalAuthToEndpoints, "copyGlobalAuthToEndpoints"); // src/express-builders.ts var import_body_parser = __toESM(require("body-parser"), 1); var import_cors = __toESM(require("cors"), 1); var import_express = __toESM(require("express"), 1); var import_express_session = __toESM(require("express-session"), 1); var import_http_terminator = require("http-terminator"); var import_morgan = __toESM(require("morgan"), 1); var import_passport4 = __toESM(require("passport"), 1); // src/functions.ts function env(key, prefix) { if (!key) { return void 0; } return process.env[`${prefix ? prefix.trim() : ""}${key}`]; } __name(env, "env"); // src/express-builders.ts var ExpressBuilder = class _ExpressBuilder { static { __name(this, "ExpressBuilder"); } existingExpress; hostnameOrIP; port; _handlers = []; listenCallback; _startListen = void 0; envVarPrefix; _corsConfigurer; _sessionOpts; _usePassportAuth = false; _passportInitOpts; _userIsInRole; _enforcer; _server; _terminator; _morgan; constructor(opts) { const { existingExpress, envVarPrefix } = opts ?? {}; if (existingExpress) { this.withExpress(existingExpress); } this.envVarPrefix = envVarPrefix ?? ""; } static fromExistingExpress(opts) { return new _ExpressBuilder(opts ?? {}); } static fromServerOpts(opts) { const builder = new _ExpressBuilder({ existingExpress: opts?.existingExpress, envVarPrefix: opts?.envVarPrefix }); return builder.withEnableListenOpts({ ...opts, hostnameOrIP: opts.hostname, startOnBuild: opts.startListening ?? false }); } enableListen(startOnBuild) { if (startOnBuild !== void 0) { this._startListen = startOnBuild; } return this; } withMorganLogging(opts) { if (opts?.existingMorgan && (opts.format || opts.options)) { throw Error("Cannot using an existing morgan with either a format or options"); } this._morgan = opts?.existingMorgan ?? (0, import_morgan.default)(opts?.format ?? "dev", opts?.options); return this; } withEnableListenOpts({ port, hostnameOrIP, callback, startOnBuild }) { port && this.withPort(port); hostnameOrIP && this.withHostname(hostnameOrIP); if (typeof callback === "function") { this.withListenCallback(callback); } this._startListen = startOnBuild === true; return this; } withPort(port) { this.port = port; return this; } withHostname(hostnameOrIP) { this.hostnameOrIP = hostnameOrIP; return this; } withListenCallback(callback) { this.listenCallback = callback; return this; } withExpress(existingExpress) { this.existingExpress = existingExpress; this._startListen = false; return this; } withCorsConfigurer(configurer) { this._corsConfigurer = configurer; return this; } withPassportAuth(usePassport, initializeOptions) { this._usePassportAuth = usePassport; this._passportInitOpts = initializeOptions; return this; } withGlobalUserIsInRole(userIsInRole) { this._userIsInRole = userIsInRole; return this; } withEnforcer(enforcer) { this._enforcer = enforcer; return this; } startListening(express3) { this._server = express3.listen(this.getPort(), this.getHostname(), this.listenCallback); this._terminator = (0, import_http_terminator.createHttpTerminator)({ server: this._server }); return { server: this._server, terminator: this._terminator }; } getHostname() { return this.hostnameOrIP ?? env("HOSTNAME", this.envVarPrefix) ?? "0.0.0.0"; } getPort() { return this.port ?? env("PORT", this.envVarPrefix) ?? 5e3; } setHandlers(handlers) { if (Array.isArray(handlers)) { this._handlers = handlers; } else if (handlers) { if (!this._handlers) { this._handlers = []; } this._handlers.push(handlers); } else { this._handlers = []; } return this; } addHandler(handler) { if (!this._handlers) { this._handlers = []; } this._handlers.push(handler); return this; } withSessionOptions(sessionOpts) { this._sessionOpts = sessionOpts; return this; } build(opts) { const express3 = this.buildExpress(opts); const startListening = opts?.startListening === void 0 ? this._startListen !== true : opts.startListening; let started = this._server !== void 0; if (startListening && !started) { this.startListening(express3); started = true; } return { express: express3, port: this.getPort(), hostname: this.getHostname(), userIsInRole: this._userIsInRole, startListening, enforcer: this._enforcer, start: /* @__PURE__ */ __name((opts2) => { if (opts2?.doNotStartListening) { console.log("Express will not start listening. You will have to start it yourself"); } else { if (!started) { this.startListening(express3); started = true; } } if (opts2?.disableErrorHandler !== true) { express3.use(jsonErrorHandler); } return { server: this._server, terminator: this._terminator }; }, "start"), stop: /* @__PURE__ */ __name(async (terminator) => { const term = terminator ?? this._terminator; if (!term) { return false; } return await term.terminate().then(() => true); }, "stop") }; } buildExpress(opts) { const app = opts?.express ?? this.existingExpress ?? (0, import_express.default)(); if (this._morgan) { app.use(this._morgan); } if (this._sessionOpts) { const store = this._sessionOpts.store ?? new import_express_session.default.MemoryStore(); this._sessionOpts.store = store; app.use((0, import_express_session.default)(this._sessionOpts)); } if (this._usePassportAuth) { app.use(import_passport4.default.initialize(this._passportInitOpts)); if (this._sessionOpts) { app.use(import_passport4.default.session()); } } if (this._userIsInRole) { app.use(checkUserIsInRole({ roles: this._userIsInRole })); } if (this._corsConfigurer) { this._corsConfigurer.configure({ existingExpress: app }); } this._handlers && this._handlers.length > 0 && app.use(this._handlers); opts?.handlers && app.use(opts.handlers); app.use(import_body_parser.default.urlencoded({ extended: true })); app.use(import_body_parser.default.json({ limit: "5mb" })); return app; } }; var ExpressCorsConfigurer = class { static { __name(this, "ExpressCorsConfigurer"); } _disableCors; _enablePreflightOptions; _allowOrigin; _allowMethods; _allowedHeaders; _allowCredentials; _express; _envVarPrefix; constructor(args) { const { existingExpress, envVarPrefix } = args ?? {}; this._express = existingExpress; this._envVarPrefix = envVarPrefix; } allowOrigin(value) { this._allowOrigin = value; return this; } disableCors(value) { this._disableCors = value; return this; } allowMethods(value) { this._allowMethods = value; return this; } allowedHeaders(value) { this._allowedHeaders = value; return this; } allowCredentials(value) { this._allowCredentials = value; return this; } configure({ existingExpress }) { const express3 = existingExpress ?? this._express; if (!express3) { throw Error("No express passed in during construction or configure"); } const disableCorsEnv = env("CORS_DISABLE", this._envVarPrefix); const corsDisabled = this._disableCors ?? (disableCorsEnv ? /true/.test(disableCorsEnv) : false); if (corsDisabled) { return; } const envAllowOriginStr = env("CORS_ALLOW_ORIGIN", this._envVarPrefix) ?? "*"; let envAllowOrigin; if (envAllowOriginStr.includes(",")) { envAllowOrigin = envAllowOriginStr.split(","); } else if (envAllowOriginStr.includes(" ")) { envAllowOrigin = envAllowOriginStr.split(" "); } else { envAllowOrigin = envAllowOriginStr; } if (Array.isArray(envAllowOrigin) && envAllowOrigin.length === 1) { envAllowOrigin = envAllowOrigin[0]; } const corsOptions = { origin: this._allowOrigin ?? envAllowOrigin, // todo: env vars ...this._allowMethods && { methods: this._allowMethods }, ...this._allowedHeaders && { allowedHeaders: this._allowedHeaders }, ...this._allowCredentials !== void 0 && { credentials: this._allowCredentials }, optionsSuccessStatus: 204 }; if (this._enablePreflightOptions) { express3.options("*", (0, import_cors.default)(corsOptions)); } express3.use((0, import_cors.default)(corsOptions)); } }; // src/openid-connect-rp.ts var import_express2 = __toESM(require("express"), 1); var import_openid_client = require("openid-client"); var import_passport5 = __toESM(require("passport"), 1); var PREFIX = process.env.PREFIX ?? ""; async function oidcDiscoverIssuer(opts) { const issuerUrl = opts?.issuerUrl ?? env("OIDC_ISSUER", PREFIX) ?? "https://auth01.test.sphereon.com/auth/realms/energy-shr"; const issuer = await import_openid_client.Issuer.discover(issuerUrl); console.log("Discovered issuer %s %O", issuer.issuer, issuer.metadata); return { issuer, issuerUrl }; } __name(oidcDiscoverIssuer, "oidcDiscoverIssuer"); async function oidcGetClient(issuer, metadata, opts) { return new issuer.Client(metadata, opts?.jwks, opts?.options); } __name(oidcGetClient, "oidcGetClient"); function getLoginEndpoint(router, opts) { if (opts?.enabled === false) { console.log(`Login endpoint is disabled`); return; } const strategy = opts?.endpoint?.authentication?.strategy; if (!strategy) { throw Error("strategy needs to be provided"); } const path = opts?.path ?? "/authentication/login"; router.get(path, (req, res, next) => { const redirectPage = req.get("referer") ?? "/"; req.session.redirectPage = redirectPage; next(); }, import_passport5.default.authenticate(strategy, { ...opts.authentication?.strategyOptions, ...opts.endpoint?.authentication?.strategyOptions, keepSessionInfo: false }, void 0)); } __name(getLoginEndpoint, "getLoginEndpoint"); function getLoginCallbackEndpoint(router, opts) { if (opts?.enabled === false) { console.log(`Auth callback endpoint is disabled`); return; } const strategy = opts?.endpoint?.authentication?.strategy; if (!strategy) { throw Error("strategy needs to be provided"); } const path = opts?.path ?? "/authentication/callback"; router.get(path, import_passport5.default.authenticate(strategy, { ...opts.authentication?.strategyOptions, ...opts.endpoint?.authentication?.strategyOptions, keepSessionInfo: true }, void 0), (req, res, next) => { if (req.user) { console.log("User authenticated", req.user?.name); const redirectPage = req.session.redirectPage ?? "/search"; delete req.session.redirectPage; return res.redirect(redirectPage); } else { return res.redirect(env("OIDC_FRONTEND_LOGIN_URL", PREFIX) ?? "http://localhost:3001/authentication/login"); } }); } __name(getLoginCallbackEndpoint, "getLoginCallbackEndpoint"); function getLogoutEndpoint(router, client, opts) { if (opts?.enabled === false) { console.log(`Logout endpoint is disabled`); return; } const path = opts?.path ?? "/authentication/logout"; router.get(path, (req, res) => { try { if (client.endSessionUrl()) { return res.redirect(client.endSessionUrl()); } else { console.log("IDP does not support end session url"); return res.redirect("/authentication/logout-callback"); } } catch (error) { console.log(error); return res.redirect("/authentication/logout-callback"); } }); } __name(getLogoutEndpoint, "getLogoutEndpoint"); function getLogoutCallbackEndpoint(router, opts) { if (opts?.enabled === false) { console.log(`Logout callback endpoint is disabled`); return; } const path = opts?.path ?? "/authentication/logout-callback"; router.get(path, (req, res, next) => { try { req.logout((err) => { if (err) { console.log(`Error during calling logout-callback: ${JSON.stringify(err)}`); } }); return res.redirect(env("OIDC_FRONTEND_LOGOUT_REDIRECT_URL", PREFIX) ?? "/"); } catch (e) { return sendErrorResponse(res, 500, "An unexpected error occurred during logout callback", e); } }); } __name(getLogoutCallbackEndpoint, "getLogoutCallbackEndpoint"); function getIdTokenEndpoint(router, client, opts) { if (opts?.enabled === false) { console.log(`ID Token endpoint is disabled`); return; } const path = opts.path ?? "/authentication/tokens/id"; router.get(path, isUserAuthenticated, (req, res) => { if (req.session.tokens.id_token) { return res.json({ id_token: req.session.tokens.id_token }); } else { return sendErrorResponse(res, 401, "Authentication required"); } }); } __name(getIdTokenEndpoint, "getIdTokenEndpoint"); function getAuthenticatedUserEndpoint(router, opts) { if (opts?.enabled === false) { console.log(`Authenticated User endpoint is disabled`); return; } const path = opts?.path ?? "/authentication/user"; router.get(path, isUserAuthenticated, (req, res, next) => { if (!req.user) { return sendErrorResponse(res, 401, "Authentication required"); } let user = req.user; return res.json(user); }); } __name(getAuthenticatedUserEndpoint, "getAuthenticatedUserEndpoint"); var OpenIDConnectAuthApi = class { static { __name(this, "OpenIDConnectAuthApi"); } get router() { return this._router; } _express; _agent; _opts; _router; constructor(args) { const { agent, opts } = args; this._agent = agent; copyGlobalAuthToEndpoints({ opts, keys: [ "getLogin" ] }); copyGlobalAuthToEndpoints({ opts, keys: [ "getIdToken" ] }); copyGlobalAuthToEndpoints({ opts, keys: [ "getAuthenticatedUser" ] }); this._opts = opts; this._express = args.expressSupport.express; this._router = import_express2.default.Router(); const features = opts?.enabledFeatures ?? [ "login", "logout", "id-token", "authenticated-user" ]; console.log(`Authentication API enabled`); if (features.includes("login")) { getLoginEndpoint(this.router, opts?.endpointOpts?.getLogin); getLoginCallbackEndpoint(this.router, opts?.endpointOpts?.getLogin); } if (features.includes("logout")) { getLogoutEndpoint(this.router, args.client, opts?.endpointOpts?.getLogout); getLogoutCallbackEndpoint(this.router, opts?.endpointOpts?.getLogout); } if (features.includes("id-token")) { if (opts.endpointOpts?.getIdToken === void 0) { throw Error("Cannot enable id-token endpoint without providing id-token endpoint options"); } getIdTokenEndpoint(this.router, args.client, opts?.endpointOpts?.getIdToken); } if (features.includes("authenticated-user")) { getAuthenticatedUserEndpoint(this.router, opts?.endpointOpts?.getAuthenticatedUser); } this._express.use(opts?.endpointOpts?.basePath ?? "", this.router); } get agent() { return this._agent; } get opts() { return this._opts; } get express() { return this._express; } }; //# sourceMappingURL=index.cjs.map