emilsoftware-utilities 2.0.0-dev.68 → 2.0.0-dev.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessi/resource-server/errors.d.ts +1 -1
- package/dist/accessi/resource-server/errors.js.map +1 -1
- package/dist/accessi/resource-server/express.js +21 -0
- package/dist/accessi/resource-server/express.js.map +1 -1
- package/dist/accessi/resource-server/nest.js +13 -0
- package/dist/accessi/resource-server/nest.js.map +1 -1
- package/dist/accessi/resource-server/runtime.js +11 -1
- package/dist/accessi/resource-server/runtime.js.map +1 -1
- package/dist/accessi/resource-server/types.d.ts +7 -0
- package/dist/accessi/resource-server/types.js.map +1 -1
- package/dist/accessi/server/index.d.ts +1 -0
- package/dist/accessi/server/index.js +1 -0
- package/dist/accessi/server/index.js.map +1 -1
- package/dist/accessi/server/standalone.d.ts +41 -0
- package/dist/accessi/server/standalone.js +264 -0
- package/dist/accessi/server/standalone.js.map +1 -0
- package/dist/accessi-module/AccessiModule.d.ts +26 -1
- package/dist/accessi-module/AccessiModule.js +5 -2
- package/dist/accessi-module/AccessiModule.js.map +1 -1
- package/dist/accessi-module/Console/accessiFetch.d.ts +5 -0
- package/dist/accessi-module/Console/accessiFetch.js +7 -4
- package/dist/accessi-module/Console/accessiFetch.js.map +1 -1
- package/dist/accessi-module/Console/console.js +12 -4
- package/dist/accessi-module/Console/generated/emilsoftware-utilities.d.ts +31 -1
- package/dist/accessi-module/Console/generated/emilsoftware-utilities.js +28 -3
- package/dist/accessi-module/Console/generated/emilsoftware-utilities.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/exchangeFederatedIdentityRequest.d.ts +12 -0
- package/dist/accessi-module/Console/generated/model/exchangeFederatedIdentityRequest.js +9 -0
- package/dist/accessi-module/Console/generated/model/exchangeFederatedIdentityRequest.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/federatedAuthenticationResultDto.d.ts +15 -0
- package/dist/accessi-module/Console/generated/model/federatedAuthenticationResultDto.js +3 -0
- package/dist/accessi-module/Console/generated/model/federatedAuthenticationResultDto.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/federatedExchangeResponse.d.ts +14 -0
- package/dist/accessi-module/Console/generated/model/federatedExchangeResponse.js +3 -0
- package/dist/accessi-module/Console/generated/model/federatedExchangeResponse.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/index.d.ts +6 -0
- package/dist/accessi-module/Console/generated/model/index.js +6 -0
- package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/loginResult.d.ts +2 -0
- package/dist/accessi-module/Console/generated/model/loginResult.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/refreshTokenRequest.d.ts +10 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenRequest.js +9 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenRequest.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResponse.d.ts +14 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResponse.js +3 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResponse.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResult.d.ts +13 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResult.js +3 -0
- package/dist/accessi-module/Console/generated/model/refreshTokenResult.js.map +1 -0
- package/dist/accessi-module/Console/wiki.js +8 -1
- package/dist/accessi-module/Console/wiki.js.map +1 -1
- package/dist/accessi-module/Controllers/AccessiConsoleController.d.ts +6 -1
- package/dist/accessi-module/Controllers/AccessiConsoleController.js +24 -1
- package/dist/accessi-module/Controllers/AccessiConsoleController.js.map +1 -1
- package/dist/accessi-module/Controllers/AuthController.d.ts +3 -1
- package/dist/accessi-module/Controllers/AuthController.js +84 -2
- package/dist/accessi-module/Controllers/AuthController.js.map +1 -1
- package/dist/accessi-module/Dtos/FederatedExchangeDtos.d.ts +21 -0
- package/dist/accessi-module/Dtos/FederatedExchangeDtos.js +74 -0
- package/dist/accessi-module/Dtos/FederatedExchangeDtos.js.map +1 -0
- package/dist/accessi-module/Dtos/LoginResponse.d.ts +1 -0
- package/dist/accessi-module/Dtos/LoginResponse.js +6 -0
- package/dist/accessi-module/Dtos/LoginResponse.js.map +1 -1
- package/dist/accessi-module/Dtos/RefreshTokenDtos.d.ts +12 -0
- package/dist/accessi-module/Dtos/RefreshTokenDtos.js +50 -0
- package/dist/accessi-module/Dtos/RefreshTokenDtos.js.map +1 -0
- package/dist/accessi-module/Dtos/index.d.ts +2 -0
- package/dist/accessi-module/Dtos/index.js +2 -0
- package/dist/accessi-module/Dtos/index.js.map +1 -1
- package/dist/accessi-module/Services/AuthService/AuthService.d.ts +14 -0
- package/dist/accessi-module/Services/AuthService/AuthService.js +99 -6
- package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
- package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js +1 -1
- package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js.map +1 -1
- package/dist/accessi-module/federated-auth/FederatedAuthExchangeController.d.ts +15 -0
- package/dist/accessi-module/federated-auth/FederatedAuthExchangeController.js +85 -0
- package/dist/accessi-module/federated-auth/FederatedAuthExchangeController.js.map +1 -0
- package/dist/accessi-module/federated-auth/FederatedAuthService.js +7 -1
- package/dist/accessi-module/federated-auth/FederatedAuthService.js.map +1 -1
- package/dist/accessi-module/index.d.ts +8 -0
- package/dist/accessi-module/index.js +40 -4
- package/dist/accessi-module/index.js.map +1 -1
- package/dist/accessi-module/jwt/jwt.strategy.js +4 -0
- package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
- package/dist/accessi-module/middleware/authenticateGen.js +4 -0
- package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
- package/dist/accessi-module/security/audit.d.ts +7 -0
- package/dist/accessi-module/security/audit.js +14 -0
- package/dist/accessi-module/security/audit.js.map +1 -0
- package/dist/accessi-module/security/authenticatedToken.d.ts +1 -1
- package/dist/accessi-module/security/authenticatedToken.js +3 -3
- package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
- package/dist/accessi-module/security/consoleEntry.d.ts +2 -0
- package/dist/accessi-module/security/consoleEntry.js +16 -0
- package/dist/accessi-module/security/consoleEntry.js.map +1 -1
- package/dist/accessi-module/security/edgeRateLimit.d.ts +2 -0
- package/dist/accessi-module/security/edgeRateLimit.js +11 -0
- package/dist/accessi-module/security/edgeRateLimit.js.map +1 -1
- package/dist/accessi-module/security/jwksBootstrap.d.ts +15 -0
- package/dist/accessi-module/security/jwksBootstrap.js +44 -0
- package/dist/accessi-module/security/jwksBootstrap.js.map +1 -0
- package/dist/accessi-module/security/jwtTokenOptions.d.ts +9 -2
- package/dist/accessi-module/security/jwtTokenOptions.js +18 -4
- package/dist/accessi-module/security/jwtTokenOptions.js.map +1 -1
- package/dist/accessi-module/security/passwordResetToken.d.ts +1 -1
- package/dist/accessi-module/security/passwordResetToken.js.map +1 -1
- package/dist/accessi-module/security/publicAuthRateLimit.d.ts +1 -1
- package/dist/accessi-module/security/publicAuthRateLimit.js +1 -0
- package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
- package/dist/accessi-module/security/rateLimitStore.d.ts +2 -0
- package/dist/accessi-module/security/rateLimitStore.js +16 -0
- package/dist/accessi-module/security/rateLimitStore.js.map +1 -1
- package/dist/accessi-module/security/refreshTokenRotation.d.ts +40 -0
- package/dist/accessi-module/security/refreshTokenRotation.js +91 -0
- package/dist/accessi-module/security/refreshTokenRotation.js.map +1 -0
- package/dist/accessi-module/security/sessionRevocation.d.ts +52 -0
- package/dist/accessi-module/security/sessionRevocation.js +124 -0
- package/dist/accessi-module/security/sessionRevocation.js.map +1 -0
- package/dist/accessi-module/security/validateOptions.d.ts +19 -0
- package/dist/accessi-module/security/validateOptions.js +115 -0
- package/dist/accessi-module/security/validateOptions.js.map +1 -0
- package/dist/emilsoftware-utilities-2.0.0-dev.69.tgz +0 -0
- package/dist/initEmilsoftwareModule.js +22 -4
- package/dist/initEmilsoftwareModule.js.map +1 -1
- package/dist/scripts/startAccessiService.d.ts +1 -0
- package/dist/scripts/startAccessiService.js +11 -0
- package/dist/scripts/startAccessiService.js.map +1 -0
- package/docs/accessi-openapi-fingerprint.json +190 -0
- package/docs/standalone-service.md +176 -0
- package/integration-prompt.md +160 -0
- package/package.json +9 -4
- package/dist/emilsoftware-utilities-2.0.0-dev.68.tgz +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initEmilsoftwareModule.js","sourceRoot":"","sources":["../src/initEmilsoftwareModule.ts"],"names":[],"mappings":"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","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport type { INestApplication } from \"@nestjs/common\";\nimport type { OpenAPIObject } from \"@nestjs/swagger\";\nimport {\n buildOpenApiExcludePaths,\n isOpenApiRequestPath,\n resolveAccessiOpenApiOptions,\n setupOpenApi\n} from \"./openapi/OpenApiConfig\";\nimport { Logger } from \"./Logger\";\nimport { EmilsoftwareModule, EmilsoftwareOptions } from \"./EmilsoftwareModule\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./accessi-module/middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessi-module/accessiRuntime\";\nimport { logAccessiStartup } from \"./accessi-module/startupLog\";\nimport { createAccessiValidationPipe } from './accessi-module/security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './accessi-module/security/AccessiHttpExceptionFilter';\nimport { getAccessiJwksPath, setupAccessiJwks } from './accessi-module/security/jwks';\nimport { createAccessiEdgeRateLimitMiddleware } from './accessi-module/security/edgeRateLimit';\n\n/** Esito del bootstrap del modulo unificato. */\nexport interface EmilsoftwareModuleInitializationResult {\n /** Sotto-app Nest che serve Accessi, Allegati e la documentazione. */\n nestApp: INestApplication;\n /** Documento OpenAPI generato, mergiabile nel documento unico dell'host. */\n document: OpenAPIObject;\n}\n\n/**\n * Initializes the unified module that combines Accessi and Allegati functionality\n * @param app Express application instance\n * @param options Configuration options for both modules\n * @returns Il sotto-app Nest e il documento OpenAPI generato.\n */\nexport async function initEmilsoftwareModule(\n app: Application,\n options: EmilsoftwareOptions\n): Promise<EmilsoftwareModuleInitializationResult> {\n const logger: Logger = new Logger(initEmilsoftwareModule.name);\n if (options?.accessiOptions) {\n beginAccessiAuthInitialization();\n }\n\n try {\n // Isolate Nest on a dedicated Express instance and dispatch only module routes.\n // This keeps pre-existing routes/middlewares on the host app untouched.\n // Prefisso OpenAPI configurabile (default `accessi/openapi`), cosi' piu'\n // documentazioni possono convivere (backend su `/openapi`, moduli sotto\n // `/<modulo>/openapi`).\n // Precedenza: EmilsoftwareOptions.openapi > AccessiOptions.openapi > default.\n const resolvedOpenApi = resolveAccessiOpenApiOptions(\n options?.accessiOptions?.openapi,\n options?.openapi\n );\n\n const nestHostApp = express();\n const jwksPath = options?.accessiOptions\n ? getAccessiJwksPath(options.accessiOptions)\n : undefined;\n const isNestRoute = (path: string) =>\n path === \"/api\" ||\n path.startsWith(\"/api/\") ||\n isOpenApiRequestPath(path, resolvedOpenApi) ||\n (jwksPath !== undefined && path === jwksPath);\n const edgeRateLimit = options?.accessiOptions?.edgeRateLimit\n ? createAccessiEdgeRateLimitMiddleware({\n ...options.accessiOptions.edgeRateLimit,\n match: options.accessiOptions.edgeRateLimit.match ?? ((path) => isNestRoute(path)),\n })\n : undefined;\n if (edgeRateLimit) {\n app.use(edgeRateLimit);\n }\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n return nestHostApp(req, res, next);\n });\n\n if (options?.accessiOptions) {\n setupAccessiJwks(app, options.accessiOptions);\n if (jwksPath) {\n logger.info(`JWKS accessi disponibile su: ${jwksPath}`);\n }\n }\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n const nestApp = await NestFactory.create(EmilsoftwareModule.forRoot(options), nestExpressInstance, {\n bufferLogs: options?.bufferLogs !== false,\n ...(options?.logger ? { logger: options.logger } : {})\n });\n\n nestApp.enableCors();\n if (options?.accessiOptions) {\n // Keep the Accessi API contract identical for standalone and unified bootstraps.\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n }\n\n nestApp.setGlobalPrefix('api', {\n exclude: buildOpenApiExcludePaths(resolvedOpenApi)\n });\n\n // Documentazione OpenAPI del modulo unificato (Accessi + Allegati).\n const document = setupOpenApi(nestApp, resolvedOpenApi);\n\n await nestApp.init();\n if (options?.accessiOptions) {\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n logAccessiStartup(options.accessiOptions, resolvedOpenApi);\n }\n\n logger.info(\"Emilsoftware module initialized successfully\");\n\n return { nestApp, document };\n } catch (error) {\n if (options?.accessiOptions) {\n failAccessiAuthInitialization(error);\n }\n logger.error(\"Error initializing Emilsoftware Module:\", error);\n throw error;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"initEmilsoftwareModule.js","sourceRoot":"","sources":["../src/initEmilsoftwareModule.ts"],"names":[],"mappings":"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","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport type { INestApplication } from \"@nestjs/common\";\nimport type { OpenAPIObject } from \"@nestjs/swagger\";\nimport {\n buildOpenApiExcludePaths,\n isOpenApiRequestPath,\n resolveAccessiOpenApiOptions,\n setupOpenApi\n} from \"./openapi/OpenApiConfig\";\nimport { Logger } from \"./Logger\";\nimport { EmilsoftwareModule, EmilsoftwareOptions } from \"./EmilsoftwareModule\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./accessi-module/middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessi-module/accessiRuntime\";\nimport { logAccessiStartup } from \"./accessi-module/startupLog\";\nimport { createAccessiValidationPipe } from './accessi-module/security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './accessi-module/security/AccessiHttpExceptionFilter';\nimport { getAccessiJwksPath, setupAccessiJwks } from './accessi-module/security/jwks';\nimport { createAccessiEdgeRateLimitMiddleware } from './accessi-module/security/edgeRateLimit';\n\n/** Esito del bootstrap del modulo unificato. */\nexport interface EmilsoftwareModuleInitializationResult {\n /** Sotto-app Nest che serve Accessi, Allegati e la documentazione. */\n nestApp: INestApplication;\n /** Documento OpenAPI generato, mergiabile nel documento unico dell'host. */\n document: OpenAPIObject;\n}\n\n/**\n * Initializes the unified module that combines Accessi and Allegati functionality\n * @param app Express application instance\n * @param options Configuration options for both modules\n * @returns Il sotto-app Nest e il documento OpenAPI generato.\n */\nexport async function initEmilsoftwareModule(\n app: Application,\n options: EmilsoftwareOptions\n): Promise<EmilsoftwareModuleInitializationResult> {\n const logger: Logger = new Logger(initEmilsoftwareModule.name);\n if (options?.accessiOptions) {\n beginAccessiAuthInitialization();\n }\n\n try {\n // Isolate Nest on a dedicated Express instance and dispatch only module routes.\n // This keeps pre-existing routes/middlewares on the host app untouched.\n // Prefisso OpenAPI configurabile (default `accessi/openapi`), cosi' piu'\n // documentazioni possono convivere (backend su `/openapi`, moduli sotto\n // `/<modulo>/openapi`).\n // Precedenza: EmilsoftwareOptions.openapi > AccessiOptions.openapi > default.\n const resolvedOpenApi = resolveAccessiOpenApiOptions(\n options?.accessiOptions?.openapi,\n options?.openapi\n );\n\n const nestHostApp = express();\n if (options?.accessiOptions?.http?.trustProxy !== undefined) {\n app.set('trust proxy', options.accessiOptions.http.trustProxy);\n nestHostApp.set('trust proxy', options.accessiOptions.http.trustProxy);\n }\n const jwksPath = options?.accessiOptions\n ? getAccessiJwksPath(options.accessiOptions)\n : undefined;\n const isNestRoute = (path: string) =>\n path === \"/api\" ||\n path.startsWith(\"/api/\") ||\n isOpenApiRequestPath(path, resolvedOpenApi) ||\n (jwksPath !== undefined && path === jwksPath);\n const edgeRateLimit = options?.accessiOptions?.edgeRateLimit\n ? createAccessiEdgeRateLimitMiddleware({\n ...options.accessiOptions.edgeRateLimit,\n match: options.accessiOptions.edgeRateLimit.match ?? ((path) => isNestRoute(path)),\n })\n : undefined;\n if (edgeRateLimit) {\n app.use(edgeRateLimit);\n }\n if (options?.accessiOptions?.http?.securityHeaders !== false) {\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.setHeader('X-Frame-Options', 'SAMEORIGIN');\n res.setHeader('Referrer-Policy', 'no-referrer');\n res.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');\n return next();\n });\n }\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n return nestHostApp(req, res, next);\n });\n\n if (options?.accessiOptions) {\n setupAccessiJwks(app, options.accessiOptions);\n if (jwksPath) {\n logger.info(`JWKS accessi disponibile su: ${jwksPath}`);\n }\n }\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n const nestApp = await NestFactory.create(EmilsoftwareModule.forRoot(options), nestExpressInstance, {\n bufferLogs: options?.bufferLogs !== false,\n ...(options?.logger ? { logger: options.logger } : {})\n });\n\n if (options?.accessiOptions?.http?.cors !== false) {\n nestApp.enableCors(options?.accessiOptions?.http?.cors);\n }\n if (options?.accessiOptions) {\n // Keep the Accessi API contract identical for standalone and unified bootstraps.\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n }\n\n nestApp.setGlobalPrefix('api', {\n exclude: buildOpenApiExcludePaths(resolvedOpenApi)\n });\n\n // Documentazione OpenAPI del modulo unificato (Accessi + Allegati).\n const document = setupOpenApi(nestApp, resolvedOpenApi);\n\n await nestApp.init();\n if (options?.accessiOptions) {\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n logAccessiStartup(options.accessiOptions, resolvedOpenApi);\n }\n\n logger.info(\"Emilsoftware module initialized successfully\");\n\n return { nestApp, document };\n } catch (error) {\n if (options?.accessiOptions) {\n failAccessiAuthInitialization(error);\n }\n logger.error(\"Error initializing Emilsoftware Module:\", error);\n throw error;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const server_1 = require("../accessi/server");
|
|
4
|
+
const Logger_1 = require("../Logger");
|
|
5
|
+
(0, server_1.startAccessiService)().catch((error) => {
|
|
6
|
+
new Logger_1.Logger('startAccessiService').error('Avvio Accessi Service fallito:', error instanceof Error
|
|
7
|
+
? { name: error.name, message: error.message, stack: error.stack }
|
|
8
|
+
: { error: String(error) });
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=startAccessiService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startAccessiService.js","sourceRoot":"","sources":["../../src/scripts/startAccessiService.ts"],"names":[],"mappings":";;AAAA,8CAAwD;AACxD,sCAAmC;AAEnC,IAAA,4BAAmB,GAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC7C,IAAI,eAAM,CAAC,qBAAqB,CAAC,CAAC,KAAK,CACrC,gCAAgC,EAChC,KAAK,YAAY,KAAK;QACpB,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;QAClE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAC7B,CAAC;IACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC","sourcesContent":["import { startAccessiService } from '../accessi/server';\nimport { Logger } from '../Logger';\n\nstartAccessiService().catch((error: unknown) => {\n new Logger('startAccessiService').error(\n 'Avvio Accessi Service fallito:',\n error instanceof Error\n ? { name: error.name, message: error.message, stack: error.stack }\n : { error: String(error) },\n );\n process.exitCode = 1;\n});\n"]}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
{
|
|
2
|
+
"paths": [
|
|
3
|
+
"DELETE /api/accessi/federated-auth/identities/{identityKey} disableFederatedIdentity",
|
|
4
|
+
"DELETE /api/accessi/federated-auth/providers/{provider} deleteFederatedProvider",
|
|
5
|
+
"DELETE /api/accessi/federated-auth/users/{codiceUtente}/identities/{identityKey} deleteFederatedIdentityPermanently",
|
|
6
|
+
"DELETE /api/accessi/filtri/tipi/{tipFil} deleteTipoFiltro",
|
|
7
|
+
"DELETE /api/accessi/permission/delete-role/{codiceRuolo} deleteRole",
|
|
8
|
+
"DELETE /api/accessi/permission/menu-groups/{codiceGruppo} deleteMenuGroup",
|
|
9
|
+
"DELETE /api/accessi/permission/menu-types/{codiceTipo} deleteMenuType",
|
|
10
|
+
"DELETE /api/accessi/permission/menus/{codiceMenu} deleteMenu",
|
|
11
|
+
"DELETE /api/accessi/permission/scopes/{codiceScope} deleteScope",
|
|
12
|
+
"DELETE /api/accessi/service-token/{tokenId} revokeServiceToken",
|
|
13
|
+
"DELETE /api/accessi/user/delete-user-permanent/{codiceUtente} deleteUserPermanently",
|
|
14
|
+
"DELETE /api/accessi/user/delete-user/{codiceUtente} deleteUser",
|
|
15
|
+
"GET /api/accessi/auth/bootstrap-admin/status getAdminBootstrapStatus",
|
|
16
|
+
"GET /api/accessi/email/reset-password-page/{token} serveResetPasswordPage",
|
|
17
|
+
"GET /api/accessi/federated-auth/providers getFederatedProviders",
|
|
18
|
+
"GET /api/accessi/federated-auth/users/{codiceUtente}/identities getFederatedIdentities",
|
|
19
|
+
"GET /api/accessi/filtri/tipi getTipiFiltro",
|
|
20
|
+
"GET /api/accessi/filtri/utente getFiltriUtente",
|
|
21
|
+
"GET /api/accessi/permission/grants/{codiceUtente} getUserRolesAndGrants",
|
|
22
|
+
"GET /api/accessi/permission/groups-with-menus getGroupsWithMenus",
|
|
23
|
+
"GET /api/accessi/permission/menu-types getMenuTypes",
|
|
24
|
+
"GET /api/accessi/permission/menus getMenus",
|
|
25
|
+
"GET /api/accessi/permission/menus/{codiceMenu}/scopes getMenuScopes",
|
|
26
|
+
"GET /api/accessi/permission/roles getRoles",
|
|
27
|
+
"GET /api/accessi/permission/scopes getScopes",
|
|
28
|
+
"GET /api/accessi/schema getSchema",
|
|
29
|
+
"GET /api/accessi/service-token getServiceTokens",
|
|
30
|
+
"GET /api/accessi/user/get-users getUsers",
|
|
31
|
+
"GET /api/accessi/user/reset-password/{token} serveResetPasswordPageUser",
|
|
32
|
+
"PATCH /api/accessi/configurator/groups/{codiceGruppo}/enabled setGroupEnabled",
|
|
33
|
+
"PATCH /api/accessi/configurator/menus/{codiceMenu}/enabled setMenuEnabled",
|
|
34
|
+
"PATCH /api/accessi/federated-auth/identities/{identityKey} updateFederatedIdentity",
|
|
35
|
+
"PATCH /api/accessi/federated-auth/providers/{provider} updateFederatedProvider",
|
|
36
|
+
"PATCH /api/accessi/federated-auth/users/{codiceUtente}/password-login setPasswordLoginPolicy",
|
|
37
|
+
"PATCH /api/accessi/user/set-gdpr/{codiceUtente} setGdpr",
|
|
38
|
+
"POST /api/accessi/auth/bootstrap-admin bootstrapAdmin",
|
|
39
|
+
"POST /api/accessi/auth/confirm-reset-password/{token} resetPassword",
|
|
40
|
+
"POST /api/accessi/auth/get-user-by-token getUserByToken",
|
|
41
|
+
"POST /api/accessi/auth/introspect introspectAccessiToken",
|
|
42
|
+
"POST /api/accessi/auth/login login",
|
|
43
|
+
"POST /api/accessi/auth/refresh refreshAccessToken",
|
|
44
|
+
"POST /api/accessi/auth/revoke-sessions revokeSessions",
|
|
45
|
+
"POST /api/accessi/auth/two-factor/resend resendTwoFactor",
|
|
46
|
+
"POST /api/accessi/auth/two-factor/verify verifyTwoFactor",
|
|
47
|
+
"POST /api/accessi/console/entry createConsoleEntryTicket",
|
|
48
|
+
"POST /api/accessi/console/entry/exchange exchangeConsoleEntryTicket",
|
|
49
|
+
"POST /api/accessi/email/send-reset-password-email sendPasswordResetEmail",
|
|
50
|
+
"POST /api/accessi/federated-auth/exchange exchangeFederatedIdentity",
|
|
51
|
+
"POST /api/accessi/federated-auth/providers createFederatedProvider",
|
|
52
|
+
"POST /api/accessi/federated-auth/users createFederatedUser",
|
|
53
|
+
"POST /api/accessi/federated-auth/users/{codiceUtente}/identities linkFederatedIdentity",
|
|
54
|
+
"POST /api/accessi/filtri/tipi createTipoFiltro",
|
|
55
|
+
"POST /api/accessi/filtri/utente saveFiltriUtente",
|
|
56
|
+
"POST /api/accessi/permission/assign-permissions/{codiceUtente} assignPermissionsToUser",
|
|
57
|
+
"POST /api/accessi/permission/assign-roles/{codiceUtente} assignRolesToUser",
|
|
58
|
+
"POST /api/accessi/permission/create-role createRole",
|
|
59
|
+
"POST /api/accessi/permission/menu-groups createMenuGroup",
|
|
60
|
+
"POST /api/accessi/permission/menu-types createMenuType",
|
|
61
|
+
"POST /api/accessi/permission/menus createMenu",
|
|
62
|
+
"POST /api/accessi/permission/scopes createScope",
|
|
63
|
+
"POST /api/accessi/service-token createServiceToken",
|
|
64
|
+
"POST /api/accessi/service-token/{tokenId}/rotate rotateServiceToken",
|
|
65
|
+
"POST /api/accessi/user/create-managed-user createManagedUser",
|
|
66
|
+
"POST /api/accessi/user/force-password-reset-legacy forcePasswordResetLegacy",
|
|
67
|
+
"POST /api/accessi/user/force-password-reset/{codiceUtente} forcePasswordReset",
|
|
68
|
+
"POST /api/accessi/user/login-as/{codiceUtente} createLoginAsUrl",
|
|
69
|
+
"POST /api/accessi/user/register register",
|
|
70
|
+
"POST /api/accessi/user/set-password/{codiceUtente} setUserPassword",
|
|
71
|
+
"POST /api/accessi/user/set-stato setStatoRegistrazione",
|
|
72
|
+
"PUT /api/accessi/filtri/tipi/{tipFil} updateTipoFiltro",
|
|
73
|
+
"PUT /api/accessi/permission/menu-groups/{codiceGruppo} updateMenuGroup",
|
|
74
|
+
"PUT /api/accessi/permission/menu-types/{codiceTipo} updateMenuType",
|
|
75
|
+
"PUT /api/accessi/permission/menus/{codiceMenu} updateMenu",
|
|
76
|
+
"PUT /api/accessi/permission/menus/{codiceMenu}/scopes setMenuScopes",
|
|
77
|
+
"PUT /api/accessi/permission/scopes/{codiceScope} updateScope",
|
|
78
|
+
"PUT /api/accessi/permission/scopes/{codiceScope}/menus setScopeMenus",
|
|
79
|
+
"PUT /api/accessi/permission/update-role/{codiceRuolo} updateRole",
|
|
80
|
+
"PUT /api/accessi/user/update-user/{codiceUtente} updateUtente"
|
|
81
|
+
],
|
|
82
|
+
"schemas": [
|
|
83
|
+
"AbilitazioneMenu",
|
|
84
|
+
"AccessiIntrospectionResultDto",
|
|
85
|
+
"ActionResponse",
|
|
86
|
+
"AdminBootstrapStatusResponse",
|
|
87
|
+
"AdminBootstrapStatusResult",
|
|
88
|
+
"AssignPermissionsToUserRequest",
|
|
89
|
+
"AssignRolesToUserRequest",
|
|
90
|
+
"AuthenticatedTokenPayloadDto",
|
|
91
|
+
"AuthenticatedUserPayloadDto",
|
|
92
|
+
"BootstrapAdminRequest",
|
|
93
|
+
"BootstrapAdminResponse",
|
|
94
|
+
"BootstrapAdminResultDto",
|
|
95
|
+
"ConfirmResetPasswordRequest",
|
|
96
|
+
"ConsoleEntryExchangeRequest",
|
|
97
|
+
"ConsoleEntrySessionResponse",
|
|
98
|
+
"ConsoleEntrySessionResult",
|
|
99
|
+
"ConsoleEntryTicketResponse",
|
|
100
|
+
"ConsoleEntryTicketResult",
|
|
101
|
+
"ConsoleEntryTokenResult",
|
|
102
|
+
"CreateFederatedIdentityRequest",
|
|
103
|
+
"CreateFederatedProviderRequest",
|
|
104
|
+
"CreateFederatedUserRequest",
|
|
105
|
+
"CreateFilterTypeRequest",
|
|
106
|
+
"CreateMenuGroupRequest",
|
|
107
|
+
"CreateMenuRequest",
|
|
108
|
+
"CreateMenuTypeRequest",
|
|
109
|
+
"CreateScopeRequest",
|
|
110
|
+
"CreateServiceTokenRequest",
|
|
111
|
+
"CreateServiceTokenResponse",
|
|
112
|
+
"ErrorResponse",
|
|
113
|
+
"ExchangeFederatedIdentityRequest",
|
|
114
|
+
"FederatedAuthenticationResultDto",
|
|
115
|
+
"FederatedExchangeResponse",
|
|
116
|
+
"FederatedIdentityListResponse",
|
|
117
|
+
"FederatedIdentityResponse",
|
|
118
|
+
"FederatedIdentityResponseDto",
|
|
119
|
+
"FederatedProviderListResponse",
|
|
120
|
+
"FederatedProviderResponse",
|
|
121
|
+
"FederatedProviderResponseDto",
|
|
122
|
+
"FiltriUtente",
|
|
123
|
+
"GetFiltriResponse",
|
|
124
|
+
"GetFiltriUtenteResponse",
|
|
125
|
+
"GetGroupsWithMenusResponse",
|
|
126
|
+
"GetMenuScopesResponse",
|
|
127
|
+
"GetMenuTypesResponse",
|
|
128
|
+
"GetMenusResponse",
|
|
129
|
+
"GetRolesResponse",
|
|
130
|
+
"GetSchemaResponse",
|
|
131
|
+
"GetScopesResponse",
|
|
132
|
+
"GetServiceTokensResponse",
|
|
133
|
+
"GetUserByTokenRequest",
|
|
134
|
+
"GetUserByTokenResponse",
|
|
135
|
+
"GetUsersResponse",
|
|
136
|
+
"GetUsersResult",
|
|
137
|
+
"GroupWithMenusEntity",
|
|
138
|
+
"IntrospectAccessiTokenRequest",
|
|
139
|
+
"IntrospectAccessiTokenResponse",
|
|
140
|
+
"IssuedServiceTokenDto",
|
|
141
|
+
"LoginAsRequest",
|
|
142
|
+
"LoginAsResponse",
|
|
143
|
+
"LoginAsResult",
|
|
144
|
+
"LoginRequest",
|
|
145
|
+
"LoginResponse",
|
|
146
|
+
"LoginResult",
|
|
147
|
+
"MenuEntity",
|
|
148
|
+
"MenuTypeEntity",
|
|
149
|
+
"PasswordExpiredResponse",
|
|
150
|
+
"Permission",
|
|
151
|
+
"PublicRegisterRequest",
|
|
152
|
+
"RefreshTokenRequest",
|
|
153
|
+
"RefreshTokenResponse",
|
|
154
|
+
"RefreshTokenResult",
|
|
155
|
+
"RegisterRequest",
|
|
156
|
+
"RegisterResponse",
|
|
157
|
+
"ResendTwoFactorRequest",
|
|
158
|
+
"Role",
|
|
159
|
+
"RuoliMenu",
|
|
160
|
+
"SchemaDdlResult",
|
|
161
|
+
"SchemaDdlSection",
|
|
162
|
+
"ScopeEntity",
|
|
163
|
+
"SendResetPasswordEmailRequest",
|
|
164
|
+
"ServiceTokenDto",
|
|
165
|
+
"SetMenuScopesRequest",
|
|
166
|
+
"SetPasswordLoginPolicyRequest",
|
|
167
|
+
"SetScopeMenusRequest",
|
|
168
|
+
"SetStatoRegistrazioneDto",
|
|
169
|
+
"SetUserPasswordRequest",
|
|
170
|
+
"Status",
|
|
171
|
+
"TipoFiltro",
|
|
172
|
+
"TokenResult",
|
|
173
|
+
"TwoFactorChallengeDto",
|
|
174
|
+
"UpdateEnabledStatusRequest",
|
|
175
|
+
"UpdateFederatedIdentityRequest",
|
|
176
|
+
"UpdateFederatedProviderRequest",
|
|
177
|
+
"UpdateFilterTypeRequest",
|
|
178
|
+
"UpdateMenuGroupRequest",
|
|
179
|
+
"UpdateMenuRequest",
|
|
180
|
+
"UpdateMenuTypeRequest",
|
|
181
|
+
"UpdateScopeRequest",
|
|
182
|
+
"UserDto",
|
|
183
|
+
"UserGrantsDto",
|
|
184
|
+
"UserGrantsResponse",
|
|
185
|
+
"VerifyTwoFactorRequest"
|
|
186
|
+
],
|
|
187
|
+
"securitySchemes": [
|
|
188
|
+
"bearer"
|
|
189
|
+
]
|
|
190
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Accessi Service standalone
|
|
2
|
+
|
|
3
|
+
Accessi puo girare come servizio autonomo, senza un backend ospitante.
|
|
4
|
+
|
|
5
|
+
## Avvio da codice
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { startAccessiService } from "emilsoftware-utilities/accessi/server";
|
|
9
|
+
|
|
10
|
+
await startAccessiService({
|
|
11
|
+
port: Number(process.env.PORT ?? 3000),
|
|
12
|
+
healthPath: "/health",
|
|
13
|
+
metrics: true,
|
|
14
|
+
});
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`startAccessiService`:
|
|
18
|
+
|
|
19
|
+
- valida `AccessiOptions` con `assertValidAccessiOptions`
|
|
20
|
+
- crea l'app Express
|
|
21
|
+
- monta `/health/live`, `/health/ready`, `/health/metrics`
|
|
22
|
+
- inizializza Accessi
|
|
23
|
+
- avvia il server
|
|
24
|
+
- registra `SIGTERM`/`SIGINT` per lo shutdown graceful
|
|
25
|
+
- chiude Nest e i pool Firebird
|
|
26
|
+
|
|
27
|
+
Per un controllo manuale usare `createAccessiService`, che restituisce `start()` e `stop()`.
|
|
28
|
+
|
|
29
|
+
## Avvio da CLI
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm run accessi:serve
|
|
33
|
+
npm run accessi:serve:dist
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
La configurazione viene letta da `createAccessiOptionsFromEnv()`.
|
|
37
|
+
|
|
38
|
+
## Health
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
GET /health/live -> 200 se il processo e vivo
|
|
42
|
+
GET /health/ready -> 200 se DB e store configurati sono pronti
|
|
43
|
+
GET /health/metrics -> metriche Prometheus testuali
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`/health/ready` controlla:
|
|
47
|
+
|
|
48
|
+
- bootstrap completato
|
|
49
|
+
- database Accessi raggiungibile e schema inizializzato
|
|
50
|
+
- `healthCheck()` degli store Redis configurati
|
|
51
|
+
- `readinessChecks` aggiuntivi passati dal chiamante
|
|
52
|
+
|
|
53
|
+
## Esecuzione come processo
|
|
54
|
+
|
|
55
|
+
In produzione il servizio viene eseguito come processo Node gestito da systemd, PM2 o dal supervisor del cliente:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm run accessi:serve:dist
|
|
59
|
+
# oppure
|
|
60
|
+
node dist/scripts/startAccessiService.js
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Esempio systemd minimale:
|
|
64
|
+
|
|
65
|
+
```ini
|
|
66
|
+
[Unit]
|
|
67
|
+
Description=Accessi Service
|
|
68
|
+
After=network.target
|
|
69
|
+
|
|
70
|
+
[Service]
|
|
71
|
+
WorkingDirectory=/opt/accessi-service
|
|
72
|
+
EnvironmentFile=/etc/accessi/accessi.env
|
|
73
|
+
ExecStart=/usr/bin/node dist/scripts/startAccessiService.js
|
|
74
|
+
Restart=on-failure
|
|
75
|
+
RestartSec=5
|
|
76
|
+
KillSignal=SIGTERM
|
|
77
|
+
TimeoutStopSec=15
|
|
78
|
+
|
|
79
|
+
[Install]
|
|
80
|
+
WantedBy=multi-user.target
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Il readiness endpoint `/health/ready` va usato dal load balancer o dal supervisore per decidere quando inviare traffico.
|
|
84
|
+
|
|
85
|
+
## Configurazione consigliata
|
|
86
|
+
|
|
87
|
+
- `ACCESSI_DB_*`
|
|
88
|
+
- `ACCESSI_ENCRYPTION_KEY`
|
|
89
|
+
- `ACCESSI_JWT_SECRET`
|
|
90
|
+
- `ACCESSI_JWT_ISSUER`
|
|
91
|
+
- `ACCESSI_JWT_AUDIENCE`
|
|
92
|
+
- `ACCESSI_JWT_ALGORITHM`, `ACCESSI_JWT_PRIVATE_KEY`, `ACCESSI_JWT_PUBLIC_KEY`, `ACCESSI_JWT_KEY_ID` per RS/ES
|
|
93
|
+
- `ACCESSI_JWKS_PATH`
|
|
94
|
+
- SMTP
|
|
95
|
+
- `PORT`
|
|
96
|
+
|
|
97
|
+
Per Redis, passare gli store nel bootstrap applicativo:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { createRedisRateLimitStore, createRedisConsoleEntryStore } from "emilsoftware-utilities/accessi/server";
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Generazione chiavi JWT
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npm run accessi:generate-jwt-keys -- --algorithm RS256 --out ./keys
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Genera:
|
|
110
|
+
|
|
111
|
+
- `jwt-private.pem`
|
|
112
|
+
- `jwt-public.pem`
|
|
113
|
+
- `jwks.json`
|
|
114
|
+
- `jwt-keys.json` con `algorithm` e `keyId`
|
|
115
|
+
|
|
116
|
+
Configurare poi:
|
|
117
|
+
|
|
118
|
+
```env
|
|
119
|
+
ACCESSI_JWT_ALGORITHM=RS256
|
|
120
|
+
ACCESSI_JWT_PRIVATE_KEY=<contenuto jwt-private.pem>
|
|
121
|
+
ACCESSI_JWT_PUBLIC_KEY=<contenuto jwt-public.pem>
|
|
122
|
+
ACCESSI_JWT_KEY_ID=<keyId>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Revoca sessioni
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { createRedisSessionRevocationStore } from "emilsoftware-utilities/accessi/server";
|
|
129
|
+
|
|
130
|
+
sessionRevocation: {
|
|
131
|
+
store: createRedisSessionRevocationStore({
|
|
132
|
+
client: redis,
|
|
133
|
+
ttlMs: 30 * 24 * 60 * 60 * 1000, // maggiore della durata massima dei token
|
|
134
|
+
}),
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Endpoint utente:
|
|
139
|
+
|
|
140
|
+
```http
|
|
141
|
+
POST /api/accessi/auth/revoke-sessions
|
|
142
|
+
Authorization: Bearer <access-token>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
I resource server fratelli devono ricevere lo stesso store in `revocation.store`.
|
|
146
|
+
|
|
147
|
+
## Console su dominio separato
|
|
148
|
+
|
|
149
|
+
Se la console è servita da un dominio diverso dall’API:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
accessiOptions: {
|
|
153
|
+
...options,
|
|
154
|
+
consoleApiBaseUrl: "https://accessi.example.com",
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Accessi inietta `window.__ACCESSI_API_BASE_URL__` nella pagina della console.
|
|
159
|
+
|
|
160
|
+
## CORS e proxy
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
accessiOptions: {
|
|
164
|
+
...options,
|
|
165
|
+
http: {
|
|
166
|
+
cors: {
|
|
167
|
+
origin: ["https://app.example.com"],
|
|
168
|
+
credentials: false,
|
|
169
|
+
},
|
|
170
|
+
trustProxy: 1, // load balancer/reverse proxy
|
|
171
|
+
securityHeaders: true,
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Con Bearer token non serve CSRF. Se in futuro si passasse a cookie httpOnly, aggiungere CSRF e configurazione cookie same-site.
|
package/integration-prompt.md
CHANGED
|
@@ -74,6 +74,60 @@ const { nestApp, document } = await initializeAccessiModule(app, options);
|
|
|
74
74
|
|
|
75
75
|
Aprire la porta HTTP solo dopo l'await.
|
|
76
76
|
|
|
77
|
+
### Avvio standalone
|
|
78
|
+
|
|
79
|
+
Per un servizio Accessi autonomo:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { startAccessiService } from "emilsoftware-utilities/accessi/server";
|
|
83
|
+
|
|
84
|
+
await startAccessiService({
|
|
85
|
+
port: Number(process.env.PORT ?? 3000),
|
|
86
|
+
healthPath: "/health",
|
|
87
|
+
metrics: true,
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Oppure:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm run accessi:serve
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Endpoint:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
GET /health/live
|
|
101
|
+
GET /health/ready
|
|
102
|
+
GET /health/metrics
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`/health/ready` controlla bootstrap, database, schema, store Redis configurati e `readinessChecks` custom. `startAccessiService` registra SIGTERM/SIGINT e chiude Nest e i pool Firebird.
|
|
106
|
+
|
|
107
|
+
In produzione il servizio viene eseguito come processo Node con systemd/PM2/supervisor:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm run accessi:serve:dist
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Dettagli e esempio systemd: `docs/standalone-service.md`.
|
|
114
|
+
|
|
115
|
+
### Validazione configurazione
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import {
|
|
119
|
+
assertValidAccessiOptions,
|
|
120
|
+
validateAccessiOptions,
|
|
121
|
+
} from "emilsoftware-utilities/accessi/server";
|
|
122
|
+
|
|
123
|
+
const validation = validateAccessiOptions(options);
|
|
124
|
+
// validation.errors / validation.warnings
|
|
125
|
+
|
|
126
|
+
assertValidAccessiOptions(options); // fail-fast
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`createAccessiService` la applica automaticamente. Controlla JWT/key, DB, encryption key, URL email, rate limit, console entry e `http`.
|
|
130
|
+
|
|
77
131
|
### Bootstrap Nest
|
|
78
132
|
|
|
79
133
|
```ts
|
|
@@ -150,6 +204,24 @@ const merged = mergeOpenApiDocuments(hostDocument, accessiDocument, {
|
|
|
150
204
|
});
|
|
151
205
|
```
|
|
152
206
|
|
|
207
|
+
### HTTP, CORS e proxy
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
http: {
|
|
211
|
+
cors: {
|
|
212
|
+
origin: ["https://app.example.com"],
|
|
213
|
+
credentials: false,
|
|
214
|
+
},
|
|
215
|
+
trustProxy: 1, // load balancer/reverse proxy
|
|
216
|
+
securityHeaders: true,
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- `cors: false` disabilita CORS.
|
|
221
|
+
- `trustProxy` e obbligatorio per rate limit corretti dietro proxy.
|
|
222
|
+
- `securityHeaders` aggiunge `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Permissions-Policy`.
|
|
223
|
+
- Con Bearer token non serve CSRF. Se usi cookie httpOnly, aggiungi CSRF e cookie same-site.
|
|
224
|
+
|
|
153
225
|
### JWKS e rotazione chiavi
|
|
154
226
|
|
|
155
227
|
Con RS256/ES256 Accessi pubblica automaticamente:
|
|
@@ -271,6 +343,12 @@ Il gateway/API gateway resta consigliato per:
|
|
|
271
343
|
|
|
272
344
|
Configurazioni di riferimento: `docs/gateway-rate-limit.md`.
|
|
273
345
|
|
|
346
|
+
### Audit
|
|
347
|
+
|
|
348
|
+
Resource server ed edge rate limit producono eventi strutturati tramite `auditAccessi`. I campi sensibili vengono redatti dal Logger. Disattivabile con `audit: false` nelle rispettive opzioni.
|
|
349
|
+
|
|
350
|
+
Nel servizio standalone le metriche Prometheus sono su `/health/metrics`.
|
|
351
|
+
|
|
274
352
|
---
|
|
275
353
|
|
|
276
354
|
## 4. Backend fratello — Express
|
|
@@ -397,6 +475,60 @@ Risposta:
|
|
|
397
475
|
- Il resource server cachea i risultati attivi per `cacheTtlMs` (default 30s). I risultati inattivi non sono cachati.
|
|
398
476
|
- Fail closed: se Accessi Service non risponde, la richiesta non viene autorizzata.
|
|
399
477
|
|
|
478
|
+
### SSO exchange service-to-service
|
|
479
|
+
|
|
480
|
+
Se un backend fratello valida un provider SSO proprio, non deve duplicare utenti o grant. Dopo aver verificato firma, issuer, audience e subject del provider, chiama:
|
|
481
|
+
|
|
482
|
+
```http
|
|
483
|
+
POST /api/accessi/federated-auth/exchange
|
|
484
|
+
Authorization: Bearer <service-token>
|
|
485
|
+
Content-Type: application/json
|
|
486
|
+
|
|
487
|
+
{ "provider": "azure-ad-acme-produzione", "subject": "<oid o sub>" }
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Scope richiesto: `accessi:federated:exchange`.
|
|
491
|
+
|
|
492
|
+
La risposta contiene:
|
|
493
|
+
|
|
494
|
+
- `codiceUtente`
|
|
495
|
+
- `login` con profilo, grant e token
|
|
496
|
+
- `token` assente quando è richiesta la verifica 2FA
|
|
497
|
+
|
|
498
|
+
Accessi non riceve il token del provider: riceve solo l'identità esterna già verificata.
|
|
499
|
+
|
|
500
|
+
### Revoca sessioni
|
|
501
|
+
|
|
502
|
+
Configurazione:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
import { createRedisSessionRevocationStore } from "emilsoftware-utilities/accessi/server";
|
|
506
|
+
|
|
507
|
+
sessionRevocation: {
|
|
508
|
+
store: createRedisSessionRevocationStore({
|
|
509
|
+
client: redis,
|
|
510
|
+
ttlMs: 30 * 24 * 60 * 60 * 1000, // maggiore della durata massima dei token
|
|
511
|
+
}),
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Endpoint utente:
|
|
516
|
+
|
|
517
|
+
```http
|
|
518
|
+
POST /api/accessi/auth/revoke-sessions
|
|
519
|
+
Authorization: Bearer <access-token>
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Invalida i token emessi prima della chiamata. I token emessi dopo restano validi. Per i backend fratelli configurare lo stesso store anche nel resource server:
|
|
523
|
+
|
|
524
|
+
```ts
|
|
525
|
+
revocation: {
|
|
526
|
+
store: revocationStore,
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Senza store condiviso la revoca vale solo nel processo che la esegue.
|
|
531
|
+
|
|
400
532
|
---
|
|
401
533
|
|
|
402
534
|
## 7. Frontend
|
|
@@ -426,6 +558,29 @@ configureAccessiClient({
|
|
|
426
558
|
});
|
|
427
559
|
```
|
|
428
560
|
|
|
561
|
+
Se `jwtOptions.refreshExpiresIn` è configurato, la risposta contiene anche `refreshToken`. Conservarlo separatamente dall’access token e usarlo su:
|
|
562
|
+
|
|
563
|
+
```http
|
|
564
|
+
POST /api/accessi/auth/refresh
|
|
565
|
+
Content-Type: application/json
|
|
566
|
+
|
|
567
|
+
{ "refreshToken": "<refresh-token>" }
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
La risposta contiene un nuovo `token` e un nuovo `refreshToken`. Il refresh token ha `typ: "refresh"` e non va mai usato come Bearer sulle API.
|
|
571
|
+
|
|
572
|
+
Per rendere il refresh token monouso anche in multi-istanza:
|
|
573
|
+
|
|
574
|
+
```ts
|
|
575
|
+
import { createRedisRefreshTokenRotationStore } from "emilsoftware-utilities/accessi/server";
|
|
576
|
+
|
|
577
|
+
refreshTokenRotation: {
|
|
578
|
+
store: createRedisRefreshTokenRotationStore({ client: redis }),
|
|
579
|
+
}
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
Ogni refresh consuma il vecchio `jti` in modo atomico. Due refresh concorrenti dello stesso token producono un solo successo.
|
|
583
|
+
|
|
429
584
|
Per token che cambiano nel tempo:
|
|
430
585
|
|
|
431
586
|
```ts
|
|
@@ -455,6 +610,7 @@ const consoleUrl = buildAccessiConsoleUrl("https://accessi.example.com", {
|
|
|
455
610
|
- Il ticket e monouso, dura 60 secondi.
|
|
456
611
|
- Per il 2FA handoff usare `twoFactorChallengeId`.
|
|
457
612
|
- Se la console deve stare sullo stesso dominio, fare reverse proxy di `/api/accessi/*` verso Accessi Service, non copiare gli asset.
|
|
613
|
+
- Se la UI della console è su un dominio diverso dall’API, configurare `consoleApiBaseUrl`: Accessi inietta `window.__ACCESSI_API_BASE_URL__` nella pagina servita.
|
|
458
614
|
|
|
459
615
|
### Web component
|
|
460
616
|
|
|
@@ -485,6 +641,7 @@ Per chiamare l'introspection o API tecniche:
|
|
|
485
641
|
2. Creare un token dalla console o con `POST /api/accessi/service-token`.
|
|
486
642
|
3. Assegnare lo scope minimo necessario:
|
|
487
643
|
- `accessi:introspect` per l'introspection
|
|
644
|
+
- `accessi:federated:exchange` per scambiare un'identita SSO verificata
|
|
488
645
|
- altri scope applicativi secondo necessita
|
|
489
646
|
4. Conservarlo come secret nel backend fratello.
|
|
490
647
|
5. Ruotarlo periodicamente; il segreto e mostrato una sola volta.
|
|
@@ -520,6 +677,7 @@ ACCESSI_DB_PASSWORD=
|
|
|
520
677
|
ACCESSI_ENCRYPTION_KEY=
|
|
521
678
|
ACCESSI_JWT_SECRET=
|
|
522
679
|
ACCESSI_JWT_EXPIRES=24h
|
|
680
|
+
ACCESSI_JWT_REFRESH_EXPIRES=30d
|
|
523
681
|
ACCESSI_JWT_ISSUER=accessi
|
|
524
682
|
ACCESSI_JWT_AUDIENCE=backend-app
|
|
525
683
|
# Opzionale RS256
|
|
@@ -584,6 +742,8 @@ Checklist:
|
|
|
584
742
|
- rotazione JWKS con vecchia chiave ancora valida
|
|
585
743
|
11. Aggiornare CORS se i frontend cambiano dominio.
|
|
586
744
|
12. Aggiornare monitoraggio e log senza includere token.
|
|
745
|
+
13. Eseguire `npm run check:accessi-openapi` e `npm run typecheck` prima del rilascio.
|
|
746
|
+
14. Dopo una modifica intenzionale al contratto, aggiornare il fingerprint con `npm run accessi:update-openapi-fingerprint` e includerlo nel commit.
|
|
587
747
|
|
|
588
748
|
---
|
|
589
749
|
|