emilsoftware-utilities 2.0.0-dev.76 → 2.0.0-dev.78

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.
Files changed (75) hide show
  1. package/dist/accessi/resource-server/token.js +2 -0
  2. package/dist/accessi/resource-server/token.js.map +1 -1
  3. package/dist/accessi/server/standalone.js +2 -1
  4. package/dist/accessi/server/standalone.js.map +1 -1
  5. package/dist/accessi-module/AccessiModule.d.ts +9 -0
  6. package/dist/accessi-module/AccessiModule.js.map +1 -1
  7. package/dist/accessi-module/Console/accessiFetch.d.ts +7 -0
  8. package/dist/accessi-module/Console/accessiFetch.js +45 -7
  9. package/dist/accessi-module/Console/accessiFetch.js.map +1 -1
  10. package/dist/accessi-module/Console/console.js +83 -22
  11. package/dist/accessi-module/Console/console.js.map +1 -1
  12. package/dist/accessi-module/Console/generated/model/getUserByTokenRequest.d.ts +2 -2
  13. package/dist/accessi-module/Console/generated/model/getUserByTokenRequest.js.map +1 -1
  14. package/dist/accessi-module/Console/generated/model/refreshTokenRequest.d.ts +2 -2
  15. package/dist/accessi-module/Console/generated/model/refreshTokenRequest.js.map +1 -1
  16. package/dist/accessi-module/Console/wiki.js +2 -0
  17. package/dist/accessi-module/Console/wiki.js.map +1 -1
  18. package/dist/accessi-module/Controllers/AccessiConsoleController.js +10 -2
  19. package/dist/accessi-module/Controllers/AccessiConsoleController.js.map +1 -1
  20. package/dist/accessi-module/Controllers/AccessiIntrospectionController.js +9 -0
  21. package/dist/accessi-module/Controllers/AccessiIntrospectionController.js.map +1 -1
  22. package/dist/accessi-module/Controllers/AuthController.js +102 -15
  23. package/dist/accessi-module/Controllers/AuthController.js.map +1 -1
  24. package/dist/accessi-module/Controllers/ConsoleEntryController.js +17 -0
  25. package/dist/accessi-module/Controllers/ConsoleEntryController.js.map +1 -1
  26. package/dist/accessi-module/Dtos/GetUserByTokenRequest.d.ts +1 -1
  27. package/dist/accessi-module/Dtos/GetUserByTokenRequest.js +3 -2
  28. package/dist/accessi-module/Dtos/GetUserByTokenRequest.js.map +1 -1
  29. package/dist/accessi-module/Dtos/RefreshTokenDtos.d.ts +1 -1
  30. package/dist/accessi-module/Dtos/RefreshTokenDtos.js +4 -1
  31. package/dist/accessi-module/Dtos/RefreshTokenDtos.js.map +1 -1
  32. package/dist/accessi-module/Services/AuthService/AuthService.js +8 -2
  33. package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
  34. package/dist/accessi-module/index.d.ts +6 -0
  35. package/dist/accessi-module/index.js +31 -2
  36. package/dist/accessi-module/index.js.map +1 -1
  37. package/dist/accessi-module/observability/metrics.d.ts +79 -0
  38. package/dist/accessi-module/observability/metrics.js +216 -0
  39. package/dist/accessi-module/observability/metrics.js.map +1 -0
  40. package/dist/accessi-module/observability/redisMetrics.d.ts +12 -0
  41. package/dist/accessi-module/observability/redisMetrics.js +44 -0
  42. package/dist/accessi-module/observability/redisMetrics.js.map +1 -0
  43. package/dist/accessi-module/security/accessTokenRevocation.js +5 -3
  44. package/dist/accessi-module/security/accessTokenRevocation.js.map +1 -1
  45. package/dist/accessi-module/security/authCookies.d.ts +104 -0
  46. package/dist/accessi-module/security/authCookies.js +240 -0
  47. package/dist/accessi-module/security/authCookies.js.map +1 -0
  48. package/dist/accessi-module/security/consoleEntry.js +5 -3
  49. package/dist/accessi-module/security/consoleEntry.js.map +1 -1
  50. package/dist/accessi-module/security/edgeRateLimit.js +3 -0
  51. package/dist/accessi-module/security/edgeRateLimit.js.map +1 -1
  52. package/dist/accessi-module/security/jwks.js +3 -0
  53. package/dist/accessi-module/security/jwks.js.map +1 -1
  54. package/dist/accessi-module/security/jwtTokenOptions.js +2 -0
  55. package/dist/accessi-module/security/jwtTokenOptions.js.map +1 -1
  56. package/dist/accessi-module/security/publicAuthRateLimit.js +3 -0
  57. package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
  58. package/dist/accessi-module/security/rateLimitStore.js +4 -2
  59. package/dist/accessi-module/security/rateLimitStore.js.map +1 -1
  60. package/dist/accessi-module/security/refreshTokenRotation.js +7 -5
  61. package/dist/accessi-module/security/refreshTokenRotation.js.map +1 -1
  62. package/dist/accessi-module/security/serviceTokenRateLimit.js +3 -0
  63. package/dist/accessi-module/security/serviceTokenRateLimit.js.map +1 -1
  64. package/dist/accessi-module/security/sessionRevocation.js +7 -3
  65. package/dist/accessi-module/security/sessionRevocation.js.map +1 -1
  66. package/dist/accessi-module/security/validateOptions.js +34 -0
  67. package/dist/accessi-module/security/validateOptions.js.map +1 -1
  68. package/dist/emilsoftware-utilities-2.0.0-dev.78.tgz +0 -0
  69. package/dist/initEmilsoftwareModule.js +7 -0
  70. package/dist/initEmilsoftwareModule.js.map +1 -1
  71. package/docs/auth-cookies.md +123 -0
  72. package/docs/metrics.md +153 -0
  73. package/docs/redis-load-testing.md +88 -0
  74. package/package.json +4 -3
  75. package/dist/emilsoftware-utilities-2.0.0-dev.76.tgz +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"AccessiConsoleController.js","sourceRoot":"","sources":["../../../src/accessi-module/Controllers/AccessiConsoleController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Controller, Get, Inject, Param, Res } from '@nestjs/common';\nimport { ApiExcludeController } from '@nestjs/swagger';\nimport { Response } from 'express';\nimport { randomBytes } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport type { AccessiOptions } from '../AccessiModule';\nimport {\n applyAccessiContentSecurityPolicy,\n resolveAccessiSecurityHeaders,\n} from '../security/securityHeaders';\n\n/** Serves the framework-free administrative console bundled with Accessi. API authorization remains on each API endpoint. */\n@ApiExcludeController()\n@Controller('accessi/console')\nexport class AccessiConsoleController {\n private htmlCache?: { baseUrl: string | undefined; content: string };\n\n constructor(@Inject('ACCESSI_OPTIONS') private readonly options: AccessiOptions) {}\n\n private indexHtml(): string {\n const baseUrl = this.options.consoleApiBaseUrl?.replace(/\\/+$/, '');\n if (this.htmlCache && this.htmlCache.baseUrl === baseUrl) return this.htmlCache.content;\n\n const marker = baseUrl\n ? `<script nonce=\"__ACCESSI_CSP_NONCE__\">window.__ACCESSI_API_BASE_URL__=${JSON.stringify(baseUrl)};</script>`\n : '';\n const content = readFileSync(join(__dirname, '..', 'Console', 'index.html'), 'utf8')\n .replace('</head>', `${marker}</head>`);\n this.htmlCache = { baseUrl, content };\n return content;\n }\n\n /** Origini raggiungibili dalla console: l'API puo stare su un dominio diverso. */\n private consoleConnectSrc(): string[] {\n const baseUrl = this.options.consoleApiBaseUrl?.replace(/\\/+$/, '');\n if (!baseUrl) return [];\n try {\n const url = new URL(baseUrl);\n return [`${url.protocol}//${url.host}`];\n } catch {\n return [];\n }\n }\n\n @Get()\n index(@Res() res: Response) {\n const security = resolveAccessiSecurityHeaders(this.options.http?.securityHeaders);\n res.setHeader('Cache-Control', security?.cacheControl || 'no-store, max-age=0');\n res.setHeader('Referrer-Policy', security?.referrerPolicy || 'no-referrer');\n res.setHeader('X-Content-Type-Options', 'nosniff');\n if (security) {\n if (security.frameOptions) res.setHeader('X-Frame-Options', security.frameOptions);\n if (security.permissionsPolicy) res.setHeader('Permissions-Policy', security.permissionsPolicy);\n }\n\n // Il nonce cambia a ogni risposta: la shell HTML non puo essere cacheata con il valore incorporato.\n const nonce = security?.contentSecurityPolicy ? randomBytes(16).toString('base64') : '';\n if (security) {\n applyAccessiContentSecurityPolicy(res, security, 'console', {\n ...(nonce ? { nonce } : {}),\n connectSrc: this.consoleConnectSrc(),\n });\n }\n\n const html = this.indexHtml().split('__ACCESSI_CSP_NONCE__').join(nonce);\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n return res.send(html);\n }\n\n /**\n * Percorsi SPA ammessi. Deve restare allineato a `routeSegment` (e ai padri dei\n * sottomenu) in Console/console.ts, altrimenti i deep link restituiscono 404.\n */\n private static readonly allowedViews = new Set([\n 'utenti',\n 'ruoli-e-grant',\n 'menu-e-gruppi',\n 'menu-e-gruppi/gruppi',\n 'menu-e-gruppi/menu',\n 'menu-e-gruppi/tipi-menu',\n 'filtri',\n 'filtri/utente',\n 'filtri/tipi',\n 'sso',\n 'sso/provider',\n 'sso/utenti',\n 'token-di-servizio',\n 'wiki',\n ]);\n\n // Le route statiche vanno dichiarate prima di `:view/:sub`, che altrimenti\n // catturerebbe `assets/<file>` e restituirebbe 404 per CSS e bundle.\n @Get('assets/:file')\n asset(@Param('file') file: string, @Res() res: Response) {\n const allowed = new Set(['console.css', 'console.js']);\n if (!allowed.has(file)) return res.status(404).end();\n // Keep the SPA shell, styles and bundle on the same deployed revision.\n res.setHeader('Cache-Control', 'no-store, max-age=0');\n return res.sendFile(join(__dirname, '..', 'Console', file));\n }\n\n /**\n * Serves the SPA shell for the supported console sections, allowing direct\n * navigation, bookmarks and browser back/forward without server-side state.\n */\n @Get(':view')\n section(@Param('view') view: string, @Res() res: Response) {\n if (!AccessiConsoleController.allowedViews.has(view)) return res.status(404).end();\n return this.index(res);\n }\n\n /** Serves the SPA shell for nested sections (menu, filtri, SSO). */\n @Get(':view/:sub')\n subsection(@Param('view') view: string, @Param('sub') sub: string, @Res() res: Response) {\n if (!AccessiConsoleController.allowedViews.has(`${view}/${sub}`)) return res.status(404).end();\n return this.index(res);\n }\n}\n"]}
1
+ {"version":3,"file":"AccessiConsoleController.js","sourceRoot":"","sources":["../../../src/accessi-module/Controllers/AccessiConsoleController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Controller, Get, Inject, Param, Res } from '@nestjs/common';\nimport { ApiExcludeController } from '@nestjs/swagger';\nimport { Response } from 'express';\nimport { randomBytes } from 'crypto';\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport type { AccessiOptions } from '../AccessiModule';\nimport {\n applyAccessiContentSecurityPolicy,\n resolveAccessiSecurityHeaders,\n} from '../security/securityHeaders';\nimport { resolveAccessiAuthCookieOptions } from '../security/authCookies';\n\n/** Serves the framework-free administrative console bundled with Accessi. API authorization remains on each API endpoint. */\n@ApiExcludeController()\n@Controller('accessi/console')\nexport class AccessiConsoleController {\n private htmlCache?: { baseUrl: string | undefined; content: string };\n\n constructor(@Inject('ACCESSI_OPTIONS') private readonly options: AccessiOptions) {}\n\n private indexHtml(): string {\n const baseUrl = this.options.consoleApiBaseUrl?.replace(/\\/+$/, '');\n if (this.htmlCache && this.htmlCache.baseUrl === baseUrl) return this.htmlCache.content;\n\n const cookieConfig = resolveAccessiAuthCookieOptions(this.options);\n const bootstrap = [\n baseUrl ? `window.__ACCESSI_API_BASE_URL__=${JSON.stringify(baseUrl)};` : '',\n cookieConfig ? 'window.__ACCESSI_AUTH_COOKIE__=true;' : '',\n cookieConfig ? `window.__ACCESSI_CSRF_COOKIE_NAME__=${JSON.stringify(cookieConfig.csrfTokenName)};` : '',\n cookieConfig ? `window.__ACCESSI_CSRF_HEADER_NAME__=${JSON.stringify(cookieConfig.csrfHeaderName)};` : '',\n ].join('');\n const marker = bootstrap\n ? `<script nonce=\"__ACCESSI_CSP_NONCE__\">${bootstrap}</script>`\n : '';\n const content = readFileSync(join(__dirname, '..', 'Console', 'index.html'), 'utf8')\n .replace('</head>', `${marker}</head>`);\n this.htmlCache = { baseUrl, content };\n return content;\n }\n\n /** Origini raggiungibili dalla console: l'API puo stare su un dominio diverso. */\n private consoleConnectSrc(): string[] {\n const baseUrl = this.options.consoleApiBaseUrl?.replace(/\\/+$/, '');\n if (!baseUrl) return [];\n try {\n const url = new URL(baseUrl);\n return [`${url.protocol}//${url.host}`];\n } catch {\n return [];\n }\n }\n\n @Get()\n index(@Res() res: Response) {\n const security = resolveAccessiSecurityHeaders(this.options.http?.securityHeaders);\n res.setHeader('Cache-Control', security?.cacheControl || 'no-store, max-age=0');\n res.setHeader('Referrer-Policy', security?.referrerPolicy || 'no-referrer');\n res.setHeader('X-Content-Type-Options', 'nosniff');\n if (security) {\n if (security.frameOptions) res.setHeader('X-Frame-Options', security.frameOptions);\n if (security.permissionsPolicy) res.setHeader('Permissions-Policy', security.permissionsPolicy);\n }\n\n // Il nonce cambia a ogni risposta: la shell HTML non puo essere cacheata con il valore incorporato.\n const nonce = security?.contentSecurityPolicy ? randomBytes(16).toString('base64') : '';\n if (security) {\n applyAccessiContentSecurityPolicy(res, security, 'console', {\n ...(nonce ? { nonce } : {}),\n connectSrc: this.consoleConnectSrc(),\n });\n }\n\n const html = this.indexHtml().split('__ACCESSI_CSP_NONCE__').join(nonce);\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n return res.send(html);\n }\n\n /**\n * Percorsi SPA ammessi. Deve restare allineato a `routeSegment` (e ai padri dei\n * sottomenu) in Console/console.ts, altrimenti i deep link restituiscono 404.\n */\n private static readonly allowedViews = new Set([\n 'utenti',\n 'ruoli-e-grant',\n 'menu-e-gruppi',\n 'menu-e-gruppi/gruppi',\n 'menu-e-gruppi/menu',\n 'menu-e-gruppi/tipi-menu',\n 'filtri',\n 'filtri/utente',\n 'filtri/tipi',\n 'sso',\n 'sso/provider',\n 'sso/utenti',\n 'token-di-servizio',\n 'wiki',\n ]);\n\n // Le route statiche vanno dichiarate prima di `:view/:sub`, che altrimenti\n // catturerebbe `assets/<file>` e restituirebbe 404 per CSS e bundle.\n @Get('assets/:file')\n asset(@Param('file') file: string, @Res() res: Response) {\n const allowed = new Set(['console.css', 'console.js']);\n if (!allowed.has(file)) return res.status(404).end();\n // Keep the SPA shell, styles and bundle on the same deployed revision.\n res.setHeader('Cache-Control', 'no-store, max-age=0');\n return res.sendFile(join(__dirname, '..', 'Console', file));\n }\n\n /**\n * Serves the SPA shell for the supported console sections, allowing direct\n * navigation, bookmarks and browser back/forward without server-side state.\n */\n @Get(':view')\n section(@Param('view') view: string, @Res() res: Response) {\n if (!AccessiConsoleController.allowedViews.has(view)) return res.status(404).end();\n return this.index(res);\n }\n\n /** Serves the SPA shell for nested sections (menu, filtri, SSO). */\n @Get(':view/:sub')\n subsection(@Param('view') view: string, @Param('sub') sub: string, @Res() res: Response) {\n if (!AccessiConsoleController.allowedViews.has(`${view}/${sub}`)) return res.status(404).end();\n return this.index(res);\n }\n}\n"]}
@@ -30,6 +30,7 @@ const Dtos_1 = require("../Dtos");
30
30
  const PermissionService_1 = require("../Services/PermissionService/PermissionService");
31
31
  const AuthService_1 = require("../Services/AuthService/AuthService");
32
32
  const serviceTokenGuard_1 = require("../security/serviceTokenGuard");
33
+ const metrics_1 = require("../observability/metrics");
33
34
  /**
34
35
  * Endpoint service-to-service per validare un access token Accessi.
35
36
  *
@@ -45,21 +46,29 @@ let AccessiIntrospectionController = AccessiIntrospectionController_1 = class Ac
45
46
  introspect(body, res) {
46
47
  return __awaiter(this, void 0, void 0, function* () {
47
48
  var _a;
49
+ const startedAt = Date.now();
48
50
  try {
49
51
  if (!(body === null || body === void 0 ? void 0 : body.token)) {
52
+ (0, metrics_1.recordAccessiMetric)('accessi_introspection_total', 1, { result: 'bad_request' });
50
53
  return Utilities_1.RestUtilities.sendErrorMessage(res, 'Token non fornito.', AccessiIntrospectionController_1.name, common_1.HttpStatus.BAD_REQUEST);
51
54
  }
52
55
  const introspection = yield this.authService.introspectAccessToken(body.token);
53
56
  if (!introspection.active || !introspection.codiceUtente) {
57
+ (0, metrics_1.recordAccessiMetric)('accessi_introspection_total', 1, { result: 'inactive' });
54
58
  return Utilities_1.RestUtilities.sendBaseResponse(res, { active: false });
55
59
  }
56
60
  const user = (_a = introspection.payload) === null || _a === void 0 ? void 0 : _a.utente;
57
61
  const grants = yield this.permissionService.getUserRolesAndGrants(introspection.codiceUtente);
62
+ (0, metrics_1.recordAccessiMetric)('accessi_introspection_total', 1, { result: 'active' });
58
63
  return Utilities_1.RestUtilities.sendBaseResponse(res, Object.assign(Object.assign({ active: true }, (user ? { user } : {})), { grants }));
59
64
  }
60
65
  catch (error) {
66
+ (0, metrics_1.recordAccessiMetric)('accessi_introspection_total', 1, { result: 'error' });
61
67
  return Utilities_1.RestUtilities.sendErrorMessage(res, error, AccessiIntrospectionController_1.name);
62
68
  }
69
+ finally {
70
+ (0, metrics_1.recordAccessiDuration)('accessi_introspection_duration_ms', Date.now() - startedAt);
71
+ }
63
72
  });
64
73
  }
65
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AccessiIntrospectionController.js","sourceRoot":"","sources":["../../../src/accessi-module/Controllers/AccessiIntrospectionController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoF;AACpF,6CAOyB;AAEzB,+CAAgD;AAChD,kCAIiB;AACjB,uFAAoF;AACpF,qEAAkE;AAClE,qEAA6F;AAE7F;;;;;;GAMG;AAKI,IAAM,8BAA8B,sCAApC,MAAM,8BAA8B;IACzC,YACmB,WAAwB,EACxB,iBAAoC;QADpC,gBAAW,GAAX,WAAW,CAAa;QACxB,sBAAiB,GAAjB,iBAAiB,CAAmB;IACpD,CAAC;IAcE,UAAU,CACN,IAAmC,EACpC,GAAa;;;YAEpB,IAAI,CAAC;gBACH,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,CAAA,EAAE,CAAC;oBACjB,OAAO,yBAAa,CAAC,gBAAgB,CACnC,GAAG,EACH,oBAAoB,EACpB,gCAA8B,CAAC,IAAI,EACnC,mBAAU,CAAC,WAAW,CACvB,CAAC;gBACJ,CAAC;gBAED,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC/E,IAAI,CAAC,aAAa,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;oBACzD,OAAO,yBAAa,CAAC,gBAAgB,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;gBAChE,CAAC;gBAED,MAAM,IAAI,GAAG,MAAC,aAAa,CAAC,OAA4C,0CAAE,MAAM,CAAC;gBACjF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;gBAC9F,OAAO,yBAAa,CAAC,gBAAgB,CAAC,GAAG,gCACvC,MAAM,EAAE,IAAI,IACT,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACzB,MAAM,IACN,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,yBAAa,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,gCAA8B,CAAC,IAAI,CAAC,CAAC;YACzF,CAAC;QACH,CAAC;KAAA;CACF,CAAA;AAhDY,wEAA8B;AAkBnC;IAZL,IAAA,aAAI,EAAC,YAAY,CAAC;IAClB,IAAA,6CAAyB,EAAC,oBAAoB,CAAC;IAC/C,IAAA,sBAAY,EAAC;QACZ,OAAO,EAAE,kCAAkC;QAC3C,WAAW,EAAE,wBAAwB;QACrC,WAAW,EACT,0IAA0I;KAC7I,CAAC;IACD,IAAA,iBAAO,EAAC,EAAE,IAAI,EAAE,oCAA6B,EAAE,CAAC;IAChD,IAAA,uBAAa,EAAC,EAAE,WAAW,EAAE,6BAA6B,EAAE,IAAI,EAAE,qCAA8B,EAAE,CAAC;IACnG,IAAA,qBAAW,EAAC,EAAE,MAAM,EAAE,mBAAU,CAAC,YAAY,EAAE,WAAW,EAAE,sCAAsC,EAAE,IAAI,EAAE,oBAAa,EAAE,CAAC;IAC1H,IAAA,qBAAW,EAAC,EAAE,MAAM,EAAE,mBAAU,CAAC,SAAS,EAAE,WAAW,EAAE,oCAAoC,EAAE,IAAI,EAAE,oBAAa,EAAE,CAAC;IAEnH,WAAA,IAAA,aAAI,GAAE,CAAA;IACN,WAAA,IAAA,YAAG,GAAE,CAAA;;qCADQ,oCAA6B;;gEA4B5C;yCA/CU,8BAA8B;IAJ1C,IAAA,iBAAO,EAAC,cAAc,CAAC;IACvB,IAAA,uBAAa,GAAE;IACf,IAAA,mBAAU,EAAC,cAAc,CAAC;IAC1B,IAAA,kBAAS,EAAC,qCAAiB,CAAC;qCAGK,yBAAW;QACL,qCAAiB;GAH5C,8BAA8B,CAgD1C","sourcesContent":["import { Body, Controller, HttpStatus, Post, Res, UseGuards } from '@nestjs/common';\nimport {\n ApiBearerAuth,\n ApiBody,\n ApiOkResponse,\n ApiOperation,\n ApiResponse,\n ApiTags,\n} from '@nestjs/swagger';\nimport { Response } from 'express';\nimport { RestUtilities } from '../../Utilities';\nimport {\n ErrorResponse,\n IntrospectAccessiTokenRequest,\n IntrospectAccessiTokenResponse,\n} from '../Dtos';\nimport { PermissionService } from '../Services/PermissionService/PermissionService';\nimport { AuthService } from '../Services/AuthService/AuthService';\nimport { RequireServiceTokenScopes, ServiceTokenGuard } from '../security/serviceTokenGuard';\n\n/**\n * Endpoint service-to-service per validare un access token Accessi.\n *\n * Non e pensato per il browser: richiede un service token con scope\n * `accessi:introspect`. I backend fratelli lo usano per autorizzare richieste\n * senza accedere al database Accessi.\n */\n@ApiTags('ServiceToken')\n@ApiBearerAuth()\n@Controller('accessi/auth')\n@UseGuards(ServiceTokenGuard)\nexport class AccessiIntrospectionController {\n constructor(\n private readonly authService: AuthService,\n private readonly permissionService: PermissionService,\n ) {}\n\n @Post('introspect')\n @RequireServiceTokenScopes('accessi:introspect')\n @ApiOperation({\n summary: 'Verifica un access token Accessi',\n operationId: 'introspectAccessiToken',\n description:\n 'Restituisce active=false per token invalido, scaduto o utente non piu abilitato. Richiede un service token con scope accessi:introspect.',\n })\n @ApiBody({ type: IntrospectAccessiTokenRequest })\n @ApiOkResponse({ description: 'Esito della verifica token.', type: IntrospectAccessiTokenResponse })\n @ApiResponse({ status: HttpStatus.UNAUTHORIZED, description: 'Service token mancante o non valido.', type: ErrorResponse })\n @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Scope accessi:introspect mancante.', type: ErrorResponse })\n async introspect(\n @Body() body: IntrospectAccessiTokenRequest,\n @Res() res: Response,\n ): Promise<Response> {\n try {\n if (!body?.token) {\n return RestUtilities.sendErrorMessage(\n res,\n 'Token non fornito.',\n AccessiIntrospectionController.name,\n HttpStatus.BAD_REQUEST,\n );\n }\n\n const introspection = await this.authService.introspectAccessToken(body.token);\n if (!introspection.active || !introspection.codiceUtente) {\n return RestUtilities.sendBaseResponse(res, { active: false });\n }\n\n const user = (introspection.payload as { utente?: unknown } | undefined)?.utente;\n const grants = await this.permissionService.getUserRolesAndGrants(introspection.codiceUtente);\n return RestUtilities.sendBaseResponse(res, {\n active: true,\n ...(user ? { user } : {}),\n grants,\n });\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AccessiIntrospectionController.name);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"AccessiIntrospectionController.js","sourceRoot":"","sources":["../../../src/accessi-module/Controllers/AccessiIntrospectionController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Body, Controller, HttpStatus, Post, Res, UseGuards } from '@nestjs/common';\nimport {\n ApiBearerAuth,\n ApiBody,\n ApiOkResponse,\n ApiOperation,\n ApiResponse,\n ApiTags,\n} from '@nestjs/swagger';\nimport { Response } from 'express';\nimport { RestUtilities } from '../../Utilities';\nimport {\n ErrorResponse,\n IntrospectAccessiTokenRequest,\n IntrospectAccessiTokenResponse,\n} from '../Dtos';\nimport { PermissionService } from '../Services/PermissionService/PermissionService';\nimport { AuthService } from '../Services/AuthService/AuthService';\nimport { RequireServiceTokenScopes, ServiceTokenGuard } from '../security/serviceTokenGuard';\nimport { recordAccessiDuration, recordAccessiMetric } from '../observability/metrics';\n\n/**\n * Endpoint service-to-service per validare un access token Accessi.\n *\n * Non e pensato per il browser: richiede un service token con scope\n * `accessi:introspect`. I backend fratelli lo usano per autorizzare richieste\n * senza accedere al database Accessi.\n */\n@ApiTags('ServiceToken')\n@ApiBearerAuth()\n@Controller('accessi/auth')\n@UseGuards(ServiceTokenGuard)\nexport class AccessiIntrospectionController {\n constructor(\n private readonly authService: AuthService,\n private readonly permissionService: PermissionService,\n ) {}\n\n @Post('introspect')\n @RequireServiceTokenScopes('accessi:introspect')\n @ApiOperation({\n summary: 'Verifica un access token Accessi',\n operationId: 'introspectAccessiToken',\n description:\n 'Restituisce active=false per token invalido, scaduto o utente non piu abilitato. Richiede un service token con scope accessi:introspect.',\n })\n @ApiBody({ type: IntrospectAccessiTokenRequest })\n @ApiOkResponse({ description: 'Esito della verifica token.', type: IntrospectAccessiTokenResponse })\n @ApiResponse({ status: HttpStatus.UNAUTHORIZED, description: 'Service token mancante o non valido.', type: ErrorResponse })\n @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Scope accessi:introspect mancante.', type: ErrorResponse })\n async introspect(\n @Body() body: IntrospectAccessiTokenRequest,\n @Res() res: Response,\n ): Promise<Response> {\n const startedAt = Date.now();\n try {\n if (!body?.token) {\n recordAccessiMetric('accessi_introspection_total', 1, { result: 'bad_request' });\n return RestUtilities.sendErrorMessage(\n res,\n 'Token non fornito.',\n AccessiIntrospectionController.name,\n HttpStatus.BAD_REQUEST,\n );\n }\n\n const introspection = await this.authService.introspectAccessToken(body.token);\n if (!introspection.active || !introspection.codiceUtente) {\n recordAccessiMetric('accessi_introspection_total', 1, { result: 'inactive' });\n return RestUtilities.sendBaseResponse(res, { active: false });\n }\n\n const user = (introspection.payload as { utente?: unknown } | undefined)?.utente;\n const grants = await this.permissionService.getUserRolesAndGrants(introspection.codiceUtente);\n recordAccessiMetric('accessi_introspection_total', 1, { result: 'active' });\n return RestUtilities.sendBaseResponse(res, {\n active: true,\n ...(user ? { user } : {}),\n grants,\n });\n } catch (error) {\n recordAccessiMetric('accessi_introspection_total', 1, { result: 'error' });\n return RestUtilities.sendErrorMessage(res, error, AccessiIntrospectionController.name);\n } finally {\n recordAccessiDuration('accessi_introspection_duration_ms', Date.now() - startedAt);\n }\n }\n}\n"]}
@@ -34,10 +34,26 @@ const AuthService_1 = require("../Services/AuthService/AuthService");
34
34
  const AdminBootstrapService_1 = require("../Services/AdminBootstrapService/AdminBootstrapService");
35
35
  const jwt_strategy_1 = require("../jwt/jwt.strategy");
36
36
  const accessControl_1 = require("../security/accessControl");
37
+ const authenticatedToken_1 = require("../security/authenticatedToken");
38
+ const authCookies_1 = require("../security/authCookies");
39
+ const metrics_1 = require("../observability/metrics");
37
40
  const sessionRevocation_1 = require("../security/sessionRevocation");
38
41
  const accessTokenRevocation_1 = require("../security/accessTokenRevocation");
39
42
  const audit_1 = require("../security/audit");
40
43
  const publicAuthRateLimit_1 = require("../security/publicAuthRateLimit");
44
+ /** Estrae il codice stabile di un errore Nest `{ code, message }`. */
45
+ function authErrorCode(error) {
46
+ if (!error || typeof error !== 'object')
47
+ return undefined;
48
+ const response = typeof error.getResponse === 'function'
49
+ ? error.getResponse()
50
+ : error.response;
51
+ if (response && typeof response === 'object') {
52
+ const code = response.code;
53
+ return typeof code === 'string' ? code : undefined;
54
+ }
55
+ return undefined;
56
+ }
41
57
  let AuthController = AuthController_1 = class AuthController {
42
58
  constructor(authService, adminBootstrapService, options) {
43
59
  this.authService = authService;
@@ -67,10 +83,13 @@ let AuthController = AuthController_1 = class AuthController {
67
83
  if (!rateLimitDecision.allowed) {
68
84
  return (0, publicAuthRateLimit_1.sendPublicAuthRateLimitExceeded)(res, rateLimitDecision.retryAfterSeconds);
69
85
  }
70
- if (!(body === null || body === void 0 ? void 0 : body.token)) {
86
+ const requestToken = typeof (body === null || body === void 0 ? void 0 : body.token) === 'string' && body.token.trim() !== ''
87
+ ? body.token
88
+ : (0, authenticatedToken_1.extractAccessiBearerToken)(request.headers.authorization);
89
+ if (!requestToken) {
71
90
  return Utilities_1.RestUtilities.sendErrorMessage(res, 'Token non fornito', AuthController_1.name, common_1.HttpStatus.BAD_REQUEST);
72
91
  }
73
- const authenticatedPayload = yield this.authService.getAuthenticatedTokenPayload(body.token);
92
+ const authenticatedPayload = yield this.authService.getAuthenticatedTokenPayload(requestToken);
74
93
  const userData = authenticatedPayload === null || authenticatedPayload === void 0 ? void 0 : authenticatedPayload.utente;
75
94
  if (!userData) {
76
95
  throw new Error('Il token non contiene un utente Accessi valido.');
@@ -95,6 +114,9 @@ let AuthController = AuthController_1 = class AuthController {
95
114
  }, common_1.HttpStatus.NOT_IMPLEMENTED);
96
115
  }
97
116
  yield (0, sessionRevocation_1.revokeAccessiUserSessions)(this.options, user.codiceUtente);
117
+ const cookieConfig = (0, authCookies_1.resolveAccessiAuthCookieOptions)(this.options);
118
+ if (cookieConfig)
119
+ (0, authCookies_1.clearAccessiAuthCookies)(res, cookieConfig);
98
120
  return Utilities_1.RestUtilities.sendOKMessage(res, 'Sessioni revocate con successo.');
99
121
  }
100
122
  catch (error) {
@@ -135,6 +157,11 @@ let AuthController = AuthController_1 = class AuthController {
135
157
  jti: targetJti,
136
158
  self: isCurrentToken,
137
159
  });
160
+ if (isCurrentToken) {
161
+ const cookieConfig = (0, authCookies_1.resolveAccessiAuthCookieOptions)(this.options);
162
+ if (cookieConfig)
163
+ (0, authCookies_1.clearAccessiAuthCookies)(res, cookieConfig);
164
+ }
138
165
  return Utilities_1.RestUtilities.sendOKMessage(res, 'Token revocato con successo.');
139
166
  }
140
167
  catch (error) {
@@ -144,13 +171,16 @@ let AuthController = AuthController_1 = class AuthController {
144
171
  }
145
172
  login(request, loginRequest, res) {
146
173
  return __awaiter(this, void 0, void 0, function* () {
174
+ const startedAt = Date.now();
147
175
  try {
148
176
  const rateLimitDecision = yield (0, publicAuthRateLimit_1.checkPublicAuthRateLimit)(this.options, 'login', request, [loginRequest === null || loginRequest === void 0 ? void 0 : loginRequest.email]);
149
177
  if (!rateLimitDecision.allowed) {
178
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_login_total', { result: 'rate_limited' });
150
179
  return (0, publicAuthRateLimit_1.sendPublicAuthRateLimitExceeded)(res, rateLimitDecision.retryAfterSeconds);
151
180
  }
152
181
  const userData = yield this.authService.login(loginRequest);
153
182
  if (!userData) {
183
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_login_total', { result: 'failure' });
154
184
  return Utilities_1.RestUtilities.sendInvalidCredentials(res);
155
185
  }
156
186
  if (!userData.challenge && !userData.passwordRequired) {
@@ -158,11 +188,25 @@ let AuthController = AuthController_1 = class AuthController {
158
188
  userData.token = tokens.access;
159
189
  if (tokens.refresh)
160
190
  userData.refreshToken = tokens.refresh;
191
+ (0, authCookies_1.applyAccessiAuthCookies)(res, (0, authCookies_1.resolveAccessiAuthCookieOptions)(this.options), userData);
161
192
  }
193
+ const result = userData.challenge
194
+ ? 'challenge'
195
+ : userData.passwordRequired
196
+ ? 'password_required'
197
+ : 'success';
198
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_login_total', { result });
162
199
  return Utilities_1.RestUtilities.sendBaseResponse(res, userData);
163
200
  }
164
201
  catch (error) {
165
- if ((error === null || error === void 0 ? void 0 : error.message) === 'PASSWORD_EXPIRED') {
202
+ const message = error === null || error === void 0 ? void 0 : error.message;
203
+ const result = message === 'PASSWORD_EXPIRED'
204
+ ? 'password_expired'
205
+ : message === AuthService_1.PASSWORD_LOGIN_DISABLED
206
+ ? 'sso_only'
207
+ : 'error';
208
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_login_total', { result });
209
+ if (message === 'PASSWORD_EXPIRED') {
166
210
  this.logger.warning('Password scaduta, cambiare password ', error);
167
211
  return Utilities_1.RestUtilities.sendPasswordExpired(res);
168
212
  }
@@ -183,51 +227,96 @@ let AuthController = AuthController_1 = class AuthController {
183
227
  }
184
228
  return Utilities_1.RestUtilities.sendInvalidCredentials(res);
185
229
  }
230
+ finally {
231
+ (0, metrics_1.observeAccessiMetric)(this.options, 'auth_login_duration_ms', Date.now() - startedAt);
232
+ }
186
233
  });
187
234
  }
188
235
  refresh(request, body, res) {
189
236
  return __awaiter(this, void 0, void 0, function* () {
237
+ const startedAt = Date.now();
190
238
  try {
191
- const tokenKey = typeof (body === null || body === void 0 ? void 0 : body.refreshToken) === 'string'
192
- ? (0, crypto_1.createHash)('sha256').update(body.refreshToken).digest('hex').slice(0, 32)
239
+ const cookieConfig = (0, authCookies_1.resolveAccessiAuthCookieOptions)(this.options);
240
+ const cookieRefreshToken = (cookieConfig === null || cookieConfig === void 0 ? void 0 : cookieConfig.refreshFromCookie)
241
+ ? (0, authCookies_1.getAccessiRefreshTokenFromCookie)(request.headers.cookie, cookieConfig)
242
+ : undefined;
243
+ const refreshToken = typeof (body === null || body === void 0 ? void 0 : body.refreshToken) === 'string' && body.refreshToken.trim() !== ''
244
+ ? body.refreshToken
245
+ : cookieRefreshToken;
246
+ const tokenKey = typeof refreshToken === 'string'
247
+ ? (0, crypto_1.createHash)('sha256').update(refreshToken).digest('hex').slice(0, 32)
193
248
  : undefined;
194
249
  const decision = yield (0, publicAuthRateLimit_1.checkPublicAuthRateLimit)(this.options, 'refresh', request, tokenKey ? [tokenKey] : []);
195
250
  if (!decision.allowed) {
251
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_refresh_total', { result: 'rate_limited' });
196
252
  return (0, publicAuthRateLimit_1.sendPublicAuthRateLimitExceeded)(res, decision.retryAfterSeconds);
197
253
  }
198
- const result = yield this.authService.refreshAccessToken(body === null || body === void 0 ? void 0 : body.refreshToken);
254
+ if (!refreshToken) {
255
+ throw new common_1.HttpException('Refresh token mancante.', common_1.HttpStatus.UNAUTHORIZED);
256
+ }
257
+ const result = yield this.authService.refreshAccessToken(refreshToken);
199
258
  if (!result.token) {
200
259
  throw new common_1.HttpException('Refresh token non valido.', common_1.HttpStatus.UNAUTHORIZED);
201
260
  }
202
- return Utilities_1.RestUtilities.sendBaseResponse(res, Object.assign({ token: result.token }, (result.refreshToken ? { refreshToken: result.refreshToken } : {})));
261
+ const response = Object.assign({ token: result.token }, (result.refreshToken ? { refreshToken: result.refreshToken } : {}));
262
+ (0, authCookies_1.applyAccessiAuthCookies)(res, cookieConfig, response);
263
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_refresh_total', { result: 'success' });
264
+ return Utilities_1.RestUtilities.sendBaseResponse(res, response);
203
265
  }
204
266
  catch (error) {
267
+ const code = authErrorCode(error);
268
+ const result = code === 'ACCESSI_REFRESH_TOKEN_REUSE'
269
+ ? 'reuse'
270
+ : code === 'ACCESSI_REFRESH_FAMILY_REVOKED'
271
+ ? 'family_revoked'
272
+ : code === 'ACCESSI_REFRESH_ROTATION_UNAVAILABLE'
273
+ ? 'store_unavailable'
274
+ : 'invalid';
275
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_refresh_total', { result });
205
276
  return Utilities_1.RestUtilities.sendErrorMessage(res, error, AuthController_1.name, error instanceof common_1.HttpException ? error.getStatus() : common_1.HttpStatus.UNAUTHORIZED);
206
277
  }
278
+ finally {
279
+ (0, metrics_1.observeAccessiMetric)(this.options, 'auth_refresh_duration_ms', Date.now() - startedAt);
280
+ }
207
281
  });
208
282
  }
209
283
  verifyTwoFactor(request, body, res) {
210
284
  return __awaiter(this, void 0, void 0, function* () {
285
+ const startedAt = Date.now();
211
286
  try {
212
287
  const limit = yield (0, publicAuthRateLimit_1.checkPublicAuthRateLimit)(this.options, 'twoFactorVerify', request, [body.challengeId]);
213
- if (!limit.allowed)
288
+ if (!limit.allowed) {
289
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_two_factor_total', { action: 'verify', result: 'rate_limited' });
214
290
  return (0, publicAuthRateLimit_1.sendPublicAuthRateLimitExceeded)(res, limit.retryAfterSeconds);
215
- return Utilities_1.RestUtilities.sendBaseResponse(res, yield this.authService.verifyTwoFactor(body.challengeId, body.code, body.scope));
291
+ }
292
+ const result = yield this.authService.verifyTwoFactor(body.challengeId, body.code, body.scope);
293
+ (0, authCookies_1.applyAccessiAuthCookies)(res, (0, authCookies_1.resolveAccessiAuthCookieOptions)(this.options), result);
294
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_two_factor_total', { action: 'verify', result: 'success' });
295
+ return Utilities_1.RestUtilities.sendBaseResponse(res, result);
216
296
  }
217
297
  catch (error) {
298
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_two_factor_total', { action: 'verify', result: 'failure' });
218
299
  return Utilities_1.RestUtilities.sendErrorMessage(res, error, AuthController_1.name, error instanceof common_1.HttpException ? error.getStatus() : 500);
219
300
  }
301
+ finally {
302
+ (0, metrics_1.observeAccessiMetric)(this.options, 'auth_two_factor_duration_ms', Date.now() - startedAt, { action: 'verify' });
303
+ }
220
304
  });
221
305
  }
222
306
  resendTwoFactor(request, body, res) {
223
307
  return __awaiter(this, void 0, void 0, function* () {
224
308
  try {
225
309
  const limit = yield (0, publicAuthRateLimit_1.checkPublicAuthRateLimit)(this.options, 'twoFactorResend', request, [body.challengeId]);
226
- if (!limit.allowed)
310
+ if (!limit.allowed) {
311
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_two_factor_total', { action: 'resend', result: 'rate_limited' });
227
312
  return (0, publicAuthRateLimit_1.sendPublicAuthRateLimitExceeded)(res, limit.retryAfterSeconds);
228
- return Utilities_1.RestUtilities.sendBaseResponse(res, yield this.authService.resendTwoFactor(body.challengeId));
313
+ }
314
+ const result = yield this.authService.resendTwoFactor(body.challengeId);
315
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_two_factor_total', { action: 'resend', result: 'success' });
316
+ return Utilities_1.RestUtilities.sendBaseResponse(res, result);
229
317
  }
230
318
  catch (error) {
319
+ (0, metrics_1.countAccessiMetric)(this.options, 'auth_two_factor_total', { action: 'resend', result: 'failure' });
231
320
  return Utilities_1.RestUtilities.sendErrorMessage(res, error, AuthController_1.name, error instanceof common_1.HttpException ? error.getStatus() : 500);
232
321
  }
233
322
  });
@@ -449,12 +538,10 @@ __decorate([
449
538
  ], AuthController.prototype, "adminBootstrapStatus", null);
450
539
  exports.AuthController = AuthController = AuthController_1 = __decorate([
451
540
  (0, swagger_1.ApiTags)('Auth'),
452
- (0, common_1.Controller)('accessi/auth')
453
- /**
541
+ (0, common_1.Controller)('accessi/auth') /**
454
542
  * Endpoint pubblici di autenticazione locale e verifica sessione.
455
543
  * Il login SSO non riceve token esterni qui: il backend validante usa `FederatedAuthService.authenticate`.
456
- */
457
- ,
544
+ */,
458
545
  __param(2, (0, common_1.Inject)('ACCESSI_OPTIONS')),
459
546
  __metadata("design:paramtypes", [AuthService_1.AuthService,
460
547
  AdminBootstrapService_1.AdminBootstrapService, Object])
@@ -1 +1 @@
1
- {"version":3,"file":"AuthController.js","sourceRoot":"","sources":["../../../src/accessi-module/Controllers/AuthController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Body, Controller, Get, HttpException, HttpStatus, Inject, Param, Post, Req, Res, UseGuards } from '@nestjs/common';\nimport { ResendTwoFactorRequest, VerifyTwoFactorRequest } from '../Dtos/TwoFactorDtos';\nimport { ApiBody, ApiOkResponse, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger';\nimport { Request, Response } from 'express';\nimport { createHash } from 'crypto';\nimport { Logger } from '../../Logger';\nimport { RestUtilities } from '../../Utilities';\nimport type { AccessiOptions } from '../AccessiModule';\nimport {\n ActionResponse,\n AdminBootstrapStatusResponse,\n BootstrapAdminRequest,\n BootstrapAdminResponse,\n ConfirmResetPasswordRequest,\n ErrorResponse,\n GetUserByTokenRequest,\n GetUserByTokenResponse,\n LoginRequest,\n LoginResponse,\n PasswordExpiredResponse,\n RefreshTokenRequest,\n RefreshTokenResponse,\n RevokeTokenRequest,\n} from '../Dtos';\nimport { AuthService, PASSWORD_LOGIN_DISABLED } from '../Services/AuthService/AuthService';\nimport { AdminBootstrapService } from '../Services/AdminBootstrapService/AdminBootstrapService';\nimport { JwtSimpleGuard } from '../jwt/jwt.strategy';\nimport { getAuthenticatedAccessiUser } from '../security/accessControl';\nimport {\n getSessionRevocationStore,\n revokeAccessiUserSessions,\n} from '../security/sessionRevocation';\nimport {\n getAccessTokenRevocationStore,\n revokeAccessiAccessToken,\n} from '../security/accessTokenRevocation';\nimport { auditAccessi } from '../security/audit';\nimport {\n checkPublicAuthRateLimit,\n sendPublicAuthRateLimitExceeded,\n} from '../security/publicAuthRateLimit';\n\n@ApiTags('Auth')\n@Controller('accessi/auth')\n/**\n * Endpoint pubblici di autenticazione locale e verifica sessione.\n * Il login SSO non riceve token esterni qui: il backend validante usa `FederatedAuthService.authenticate`.\n */\nexport class AuthController {\n logger: Logger = new Logger(AuthController.name);\n\n constructor(\n private readonly authService: AuthService,\n private readonly adminBootstrapService: AdminBootstrapService,\n @Inject('ACCESSI_OPTIONS') private readonly options: AccessiOptions,\n ) {}\n\n @ApiOperation({ summary: 'Conferma il reset della password', operationId: 'resetPassword' })\n @ApiParam({ name: 'token', description: 'Token per il reset della password', required: true })\n @ApiBody({ type: ConfirmResetPasswordRequest })\n @ApiResponse({\n status: 200,\n description: 'Password aggiornata con successo',\n type: ActionResponse,\n })\n @ApiResponse({\n status: 400,\n description: 'Errore nella richiesta o token non valido',\n type: ErrorResponse,\n })\n @Post('confirm-reset-password/:token')\n async resetPassword(\n @Req() request: Request,\n @Res() res: Response,\n @Param('token') token: string,\n @Body() body: ConfirmResetPasswordRequest,\n ) {\n try {\n const rateLimitDecision = await checkPublicAuthRateLimit(\n this.options,\n 'passwordResetConfirm',\n request,\n );\n if (!rateLimitDecision.allowed) {\n return sendPublicAuthRateLimitExceeded(res, rateLimitDecision.retryAfterSeconds);\n }\n\n await this.authService.confirmResetPassword(token, body.newPassword);\n return RestUtilities.sendOKMessage(res, 'Password aggiornata con successo!');\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, HttpStatus.BAD_REQUEST);\n }\n }\n\n @ApiOperation({\n summary: 'Recupera le informazioni utente dal token JWT',\n operationId: 'getUserByToken',\n })\n @ApiBody({ type: GetUserByTokenRequest })\n @ApiResponse({\n status: 200,\n description: 'Informazioni utente recuperate con successo',\n type: GetUserByTokenResponse,\n })\n @ApiResponse({\n status: 401,\n description: 'Token non valido o scaduto',\n type: ErrorResponse,\n })\n @Post('get-user-by-token')\n async getUserByToken(\n @Req() request: Request,\n @Body() body: GetUserByTokenRequest,\n @Res() res: Response,\n ) {\n try {\n const rateLimitDecision = await checkPublicAuthRateLimit(\n this.options,\n 'getUserByToken',\n request,\n );\n if (!rateLimitDecision.allowed) {\n return sendPublicAuthRateLimitExceeded(res, rateLimitDecision.retryAfterSeconds);\n }\n\n if (!body?.token) {\n return RestUtilities.sendErrorMessage(\n res,\n 'Token non fornito',\n AuthController.name,\n HttpStatus.BAD_REQUEST,\n );\n }\n\n const authenticatedPayload = await this.authService.getAuthenticatedTokenPayload(body.token);\n const userData = (authenticatedPayload as { utente?: unknown })?.utente;\n if (!userData) {\n throw new Error('Il token non contiene un utente Accessi valido.');\n }\n\n // Keep the runtime response aligned with GetUserByTokenResponse and Orval:\n // Result.userData contains the authenticated user directly, not a nested JWT payload.\n return RestUtilities.sendBaseResponse(res, { userData });\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, HttpStatus.UNAUTHORIZED);\n }\n }\n\n @ApiOperation({\n summary: 'Revoca tutte le sessioni dell utente corrente',\n operationId: 'revokeSessions',\n description:\n 'Invalida i token emessi prima di questa chiamata. Richiede sessionRevocation.store configurato. I token emessi dopo la revoca restano validi.',\n })\n @ApiOkResponse({ type: ActionResponse })\n @ApiResponse({ status: 401, type: ErrorResponse, description: 'Token Accessi mancante o non valido.' })\n @ApiResponse({ status: 501, type: ErrorResponse, description: 'Revoca sessioni non configurata.' })\n @UseGuards(JwtSimpleGuard)\n @Post('revoke-sessions')\n async revokeSessions(@Req() request: Request, @Res() res: Response) {\n try {\n const user = getAuthenticatedAccessiUser(request);\n if (!getSessionRevocationStore(this.options)) {\n throw new HttpException(\n {\n code: 'ACCESSI_SESSION_REVOCATION_DISABLED',\n message: 'La revoca sessioni non e configurata su questa istanza.',\n },\n HttpStatus.NOT_IMPLEMENTED,\n );\n }\n await revokeAccessiUserSessions(this.options, user.codiceUtente);\n return RestUtilities.sendOKMessage(res, 'Sessioni revocate con successo.');\n } catch (error) {\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n error instanceof HttpException ? error.getStatus() : HttpStatus.BAD_REQUEST,\n );\n }\n }\n\n @ApiOperation({\n summary: 'Revoca un singolo access token tramite jti',\n operationId: 'revokeToken',\n description:\n 'Annulla un solo token (logout del dispositivo corrente o token compromesso) senza toccare le altre sessioni. ' +\n 'Se il body non contiene jti viene revocato il token della richiesta. Richiede accessTokenRevocation.store configurato.',\n })\n @ApiBody({ type: RevokeTokenRequest })\n @ApiOkResponse({ type: ActionResponse })\n @ApiResponse({ status: 401, type: ErrorResponse, description: 'Token Accessi mancante o non valido.' })\n @ApiResponse({ status: 403, type: ErrorResponse, description: 'Non autorizzato a revocare il token indicato.' })\n @ApiResponse({ status: 501, type: ErrorResponse, description: 'Revoca token non configurata.' })\n @UseGuards(JwtSimpleGuard)\n @Post('revoke-token')\n async revokeToken(\n @Req() request: Request,\n @Body() body: RevokeTokenRequest,\n @Res() res: Response,\n ) {\n try {\n const user = getAuthenticatedAccessiUser(request);\n if (!getAccessTokenRevocationStore(this.options)) {\n throw new HttpException(\n {\n code: 'ACCESSI_ACCESS_TOKEN_REVOCATION_DISABLED',\n message: 'La revoca dei singoli token non e configurata su questa istanza.',\n },\n HttpStatus.NOT_IMPLEMENTED,\n );\n }\n\n const payload = ((request as Request & { user?: unknown }).user ?? {}) as Record<string, unknown>;\n const currentJti = typeof payload.jti === 'string' ? payload.jti : undefined;\n const requestedJti = typeof body?.jti === 'string' ? body.jti.trim() : '';\n const targetJti = requestedJti !== '' ? requestedJti : currentJti;\n\n if (!targetJti) {\n throw new HttpException(\n { code: 'ACCESSI_TOKEN_JTI_MISSING', message: 'Il token non contiene un jti revocabile.' },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n const isCurrentToken = targetJti === currentJti;\n if (!isCurrentToken && !user.flagAdmin && !user.flagSuper) {\n throw new HttpException(\n {\n code: 'ACCESSI_TOKEN_REVOKE_FORBIDDEN',\n message: 'Solo gli amministratori possono revocare il token di un altro utente.',\n },\n HttpStatus.FORBIDDEN,\n );\n }\n\n const expiresAt = Number(payload.exp);\n await revokeAccessiAccessToken(\n this.options,\n targetJti,\n isCurrentToken && Number.isFinite(expiresAt) ? expiresAt * 1000 : undefined,\n );\n auditAccessi('access_token_revoked', {\n codiceUtente: user.codiceUtente,\n actor: user.codiceUtente,\n jti: targetJti,\n self: isCurrentToken,\n });\n return RestUtilities.sendOKMessage(res, 'Token revocato con successo.');\n } catch (error) {\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n error instanceof HttpException ? error.getStatus() : HttpStatus.BAD_REQUEST,\n );\n }\n }\n\n @ApiOperation({\n summary: 'Effettua il login utente',\n description:\n \"Con sola email restituisce passwordRequired oppure avvia il codice per utenti passwordless. Con password valida restituisce il login completo o challenge se la 2FA e attiva. Nessun JWT viene emesso prima della verifica del codice.\",\n operationId: 'login',\n })\n @ApiBody({ type: LoginRequest })\n @ApiResponse({\n status: 200,\n description: 'Login effettuato con successo',\n type: LoginResponse,\n })\n @ApiResponse({\n status: 401,\n description: 'Credenziali non valide',\n type: ErrorResponse,\n })\n @ApiResponse({\n status: 403,\n description: 'Password scaduta, e necessario aggiornarla.',\n type: PasswordExpiredResponse,\n })\n @ApiResponse({ status: 403, description: 'Utente abilitato solo a SSO.', type: ErrorResponse })\n @Post('login')\n async login(@Req() request: Request, @Body() loginRequest: LoginRequest, @Res() res: Response) {\n try {\n const rateLimitDecision = await checkPublicAuthRateLimit(\n this.options,\n 'login',\n request,\n [loginRequest?.email],\n );\n if (!rateLimitDecision.allowed) {\n return sendPublicAuthRateLimitExceeded(res, rateLimitDecision.retryAfterSeconds);\n }\n\n const userData = await this.authService.login(loginRequest);\n if (!userData) {\n return RestUtilities.sendInvalidCredentials(res);\n }\n\n if (!userData.challenge && !userData.passwordRequired) {\n const tokens = this.authService.createTokenPair(userData.utente, ['password']);\n userData.token = tokens.access;\n if (tokens.refresh) userData.refreshToken = tokens.refresh;\n }\n\n return RestUtilities.sendBaseResponse(res, userData);\n } catch (error) {\n if ((error as Error)?.message === 'PASSWORD_EXPIRED') {\n this.logger.warning('Password scaduta, cambiare password ', error);\n return RestUtilities.sendPasswordExpired(res);\n }\n\n if (error instanceof HttpException) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error.getStatus());\n }\n\n if ((error as Error)?.message === PASSWORD_LOGIN_DISABLED) {\n return res.status(HttpStatus.FORBIDDEN).json({\n severity: 'error', status: HttpStatus.FORBIDDEN, statusCode: 2,\n code: PASSWORD_LOGIN_DISABLED,\n error: PASSWORD_LOGIN_DISABLED,\n message: 'Questo utente e abilitato solo tramite SSO. Accedi con un provider collegato.',\n });\n }\n\n this.logger.error('Errore durante il login', error);\n if (RestUtilities.isDatabaseSchemaError(error)) {\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n HttpStatus.SERVICE_UNAVAILABLE,\n );\n }\n return RestUtilities.sendInvalidCredentials(res);\n }\n }\n\n @ApiOperation({\n summary: 'Scambia un refresh token con un nuovo access token',\n operationId: 'refreshAccessToken',\n description:\n 'Richiede jwtOptions.refreshExpiresIn. Il refresh token ha typ=refresh e non e accettato dai guard API.',\n })\n @ApiBody({ type: RefreshTokenRequest })\n @ApiOkResponse({ type: RefreshTokenResponse })\n @ApiResponse({ status: 401, description: 'Refresh token non valido, scaduto o revocato.', type: ErrorResponse })\n @ApiResponse({ status: 429, description: 'Troppi tentativi.', type: ErrorResponse })\n @Post('refresh')\n async refresh(\n @Req() request: Request,\n @Body() body: RefreshTokenRequest,\n @Res() res: Response,\n ) {\n try {\n const tokenKey = typeof body?.refreshToken === 'string'\n ? createHash('sha256').update(body.refreshToken).digest('hex').slice(0, 32)\n : undefined;\n const decision = await checkPublicAuthRateLimit(\n this.options,\n 'refresh',\n request,\n tokenKey ? [tokenKey] : [],\n );\n if (!decision.allowed) {\n return sendPublicAuthRateLimitExceeded(res, decision.retryAfterSeconds);\n }\n\n const result = await this.authService.refreshAccessToken(body?.refreshToken);\n if (!result.token) {\n throw new HttpException('Refresh token non valido.', HttpStatus.UNAUTHORIZED);\n }\n return RestUtilities.sendBaseResponse(res, {\n token: result.token,\n ...(result.refreshToken ? { refreshToken: result.refreshToken } : {}),\n });\n } catch (error) {\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n error instanceof HttpException ? error.getStatus() : HttpStatus.UNAUTHORIZED,\n );\n }\n }\n\n @Post('two-factor/verify')\n @ApiOperation({ summary: 'Verifica il codice e completa il login', operationId: 'verifyTwoFactor' })\n @ApiBody({ type: VerifyTwoFactorRequest })\n @ApiResponse({ status: 200, type: LoginResponse })\n @ApiResponse({ status: 401, type: ErrorResponse })\n @ApiResponse({ status: 429, type: ErrorResponse })\n async verifyTwoFactor(@Req() request: Request, @Body() body: VerifyTwoFactorRequest, @Res() res: Response) {\n try {\n const limit = await checkPublicAuthRateLimit(this.options, 'twoFactorVerify', request, [body.challengeId]);\n if (!limit.allowed) return sendPublicAuthRateLimitExceeded(res, limit.retryAfterSeconds);\n return RestUtilities.sendBaseResponse(res, await this.authService.verifyTwoFactor(body.challengeId, body.code, body.scope));\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error instanceof HttpException ? error.getStatus() : 500);\n }\n }\n\n @Post('two-factor/resend')\n @ApiOperation({ summary: 'Reinvia il codice, invalidando il precedente', operationId: 'resendTwoFactor' })\n @ApiBody({ type: ResendTwoFactorRequest })\n @ApiResponse({ status: 200, type: LoginResponse })\n @ApiResponse({ status: 401, type: ErrorResponse })\n @ApiResponse({ status: 429, type: ErrorResponse })\n async resendTwoFactor(@Req() request: Request, @Body() body: ResendTwoFactorRequest, @Res() res: Response) {\n try {\n const limit = await checkPublicAuthRateLimit(this.options, 'twoFactorResend', request, [body.challengeId]);\n if (!limit.allowed) return sendPublicAuthRateLimitExceeded(res, limit.retryAfterSeconds);\n return RestUtilities.sendBaseResponse(res, await this.authService.resendTwoFactor(body.challengeId));\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error instanceof HttpException ? error.getStatus() : 500);\n }\n }\n\n @Post('bootstrap-admin')\n @ApiOperation({\n summary: 'Crea il primo utente admin (bootstrap)',\n operationId: 'bootstrapAdmin',\n description:\n 'Endpoint pubblico ma protetto dal token di avvio: attivo solo con adminBootstrap.enabled. ' +\n 'Crea un utente in stato confermato senza email, con flag admin (e super opzionale) e password fornita o generata.',\n })\n @ApiBody({ type: BootstrapAdminRequest })\n @ApiResponse({ status: 200, type: BootstrapAdminResponse })\n @ApiResponse({ status: 401, description: 'Token di bootstrap non valido', type: ErrorResponse })\n @ApiResponse({ status: 403, description: 'Bootstrap admin non abilitato', type: ErrorResponse })\n @ApiResponse({ status: 429, description: 'Troppi tentativi', type: ErrorResponse })\n async bootstrapAdmin(@Req() request: Request, @Body() body: BootstrapAdminRequest, @Res() res: Response) {\n try {\n const limit = await checkPublicAuthRateLimit(this.options, 'adminBootstrap', request);\n if (!limit.allowed) return sendPublicAuthRateLimitExceeded(res, limit.retryAfterSeconds);\n return RestUtilities.sendBaseResponse(res, await this.adminBootstrapService.bootstrap(body));\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error instanceof HttpException ? error.getStatus() : 500);\n }\n }\n\n @Get('bootstrap-admin/status')\n @ApiOperation({\n summary: 'Indica se il bootstrap admin e abilitato',\n operationId: 'getAdminBootstrapStatus',\n description:\n 'Endpoint pubblico: la console mostra la sezione \"Crea utente admin\" solo quando enabled e true.',\n })\n @ApiResponse({ status: 200, type: AdminBootstrapStatusResponse })\n async adminBootstrapStatus(@Res() res: Response) {\n return RestUtilities.sendBaseResponse(res, { enabled: this.adminBootstrapService.isEnabled() });\n }\n}\n"]}
1
+ {"version":3,"file":"AuthController.js","sourceRoot":"","sources":["../../../src/accessi-module/Controllers/AuthController.ts"],"names":[],"mappings":"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","sourcesContent":["import { Body, Controller, Get, HttpException, HttpStatus, Inject, Param, Post, Req, Res, UseGuards } from '@nestjs/common';\nimport { ResendTwoFactorRequest, VerifyTwoFactorRequest } from '../Dtos/TwoFactorDtos';\nimport { ApiBody, ApiOkResponse, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger';\nimport { Request, Response } from 'express';\nimport { createHash } from 'crypto';\nimport { Logger } from '../../Logger';\nimport { RestUtilities } from '../../Utilities';\nimport type { AccessiOptions } from '../AccessiModule';\nimport {\n ActionResponse,\n AdminBootstrapStatusResponse,\n BootstrapAdminRequest,\n BootstrapAdminResponse,\n ConfirmResetPasswordRequest,\n ErrorResponse,\n GetUserByTokenRequest,\n GetUserByTokenResponse,\n LoginRequest,\n LoginResponse,\n PasswordExpiredResponse,\n RefreshTokenRequest,\n RefreshTokenResponse,\n RevokeTokenRequest,\n} from '../Dtos';\nimport { AuthService, PASSWORD_LOGIN_DISABLED } from '../Services/AuthService/AuthService';\nimport { AdminBootstrapService } from '../Services/AdminBootstrapService/AdminBootstrapService';\nimport { JwtSimpleGuard } from '../jwt/jwt.strategy';\nimport { getAuthenticatedAccessiUser } from '../security/accessControl';\nimport { extractAccessiBearerToken } from '../security/authenticatedToken';\nimport {\n applyAccessiAuthCookies,\n clearAccessiAuthCookies,\n getAccessiRefreshTokenFromCookie,\n resolveAccessiAuthCookieOptions,\n} from '../security/authCookies';\nimport {\n countAccessiMetric,\n observeAccessiMetric,\n} from '../observability/metrics';\nimport {\n getSessionRevocationStore,\n revokeAccessiUserSessions,\n} from '../security/sessionRevocation';\nimport {\n getAccessTokenRevocationStore,\n revokeAccessiAccessToken,\n} from '../security/accessTokenRevocation';\nimport { auditAccessi } from '../security/audit';\nimport {\n checkPublicAuthRateLimit,\n sendPublicAuthRateLimitExceeded,\n} from '../security/publicAuthRateLimit';\n\n/** Estrae il codice stabile di un errore Nest `{ code, message }`. */\nfunction authErrorCode(error: unknown): string | undefined {\n if (!error || typeof error !== 'object') return undefined;\n const response = typeof (error as { getResponse?: unknown }).getResponse === 'function'\n ? (error as { getResponse: () => unknown }).getResponse()\n : (error as { response?: unknown }).response;\n if (response && typeof response === 'object') {\n const code = (response as { code?: unknown }).code;\n return typeof code === 'string' ? code : undefined;\n }\n return undefined;\n}\n\n@ApiTags('Auth')\n@Controller('accessi/auth')/**\n * Endpoint pubblici di autenticazione locale e verifica sessione.\n * Il login SSO non riceve token esterni qui: il backend validante usa `FederatedAuthService.authenticate`.\n */\nexport class AuthController {\n logger: Logger = new Logger(AuthController.name);\n\n constructor(\n private readonly authService: AuthService,\n private readonly adminBootstrapService: AdminBootstrapService,\n @Inject('ACCESSI_OPTIONS') private readonly options: AccessiOptions,\n ) {}\n\n @ApiOperation({ summary: 'Conferma il reset della password', operationId: 'resetPassword' })\n @ApiParam({ name: 'token', description: 'Token per il reset della password', required: true })\n @ApiBody({ type: ConfirmResetPasswordRequest })\n @ApiResponse({\n status: 200,\n description: 'Password aggiornata con successo',\n type: ActionResponse,\n })\n @ApiResponse({\n status: 400,\n description: 'Errore nella richiesta o token non valido',\n type: ErrorResponse,\n })\n @Post('confirm-reset-password/:token')\n async resetPassword(\n @Req() request: Request,\n @Res() res: Response,\n @Param('token') token: string,\n @Body() body: ConfirmResetPasswordRequest,\n ) {\n try {\n const rateLimitDecision = await checkPublicAuthRateLimit(\n this.options,\n 'passwordResetConfirm',\n request,\n );\n if (!rateLimitDecision.allowed) {\n return sendPublicAuthRateLimitExceeded(res, rateLimitDecision.retryAfterSeconds);\n }\n\n await this.authService.confirmResetPassword(token, body.newPassword);\n return RestUtilities.sendOKMessage(res, 'Password aggiornata con successo!');\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, HttpStatus.BAD_REQUEST);\n }\n }\n\n @ApiOperation({\n summary: 'Recupera le informazioni utente dal token JWT',\n operationId: 'getUserByToken',\n })\n @ApiBody({ type: GetUserByTokenRequest })\n @ApiResponse({\n status: 200,\n description: 'Informazioni utente recuperate con successo',\n type: GetUserByTokenResponse,\n })\n @ApiResponse({\n status: 401,\n description: 'Token non valido o scaduto',\n type: ErrorResponse,\n })\n @Post('get-user-by-token')\n async getUserByToken(\n @Req() request: Request,\n @Body() body: GetUserByTokenRequest,\n @Res() res: Response,\n ) {\n try {\n const rateLimitDecision = await checkPublicAuthRateLimit(\n this.options,\n 'getUserByToken',\n request,\n );\n if (!rateLimitDecision.allowed) {\n return sendPublicAuthRateLimitExceeded(res, rateLimitDecision.retryAfterSeconds);\n }\n\n const requestToken = typeof body?.token === 'string' && body.token.trim() !== ''\n ? body.token\n : extractAccessiBearerToken(request.headers.authorization);\n if (!requestToken) {\n return RestUtilities.sendErrorMessage(\n res,\n 'Token non fornito',\n AuthController.name,\n HttpStatus.BAD_REQUEST,\n );\n }\n\n const authenticatedPayload = await this.authService.getAuthenticatedTokenPayload(requestToken);\n const userData = (authenticatedPayload as { utente?: unknown })?.utente;\n if (!userData) {\n throw new Error('Il token non contiene un utente Accessi valido.');\n }\n\n // Keep the runtime response aligned with GetUserByTokenResponse and Orval:\n // Result.userData contains the authenticated user directly, not a nested JWT payload.\n return RestUtilities.sendBaseResponse(res, { userData });\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, HttpStatus.UNAUTHORIZED);\n }\n }\n\n @ApiOperation({\n summary: 'Revoca tutte le sessioni dell utente corrente',\n operationId: 'revokeSessions',\n description:\n 'Invalida i token emessi prima di questa chiamata. Richiede sessionRevocation.store configurato. I token emessi dopo la revoca restano validi.',\n })\n @ApiOkResponse({ type: ActionResponse })\n @ApiResponse({ status: 401, type: ErrorResponse, description: 'Token Accessi mancante o non valido.' })\n @ApiResponse({ status: 501, type: ErrorResponse, description: 'Revoca sessioni non configurata.' })\n @UseGuards(JwtSimpleGuard)\n @Post('revoke-sessions')\n async revokeSessions(@Req() request: Request, @Res() res: Response) {\n try {\n const user = getAuthenticatedAccessiUser(request);\n if (!getSessionRevocationStore(this.options)) {\n throw new HttpException(\n {\n code: 'ACCESSI_SESSION_REVOCATION_DISABLED',\n message: 'La revoca sessioni non e configurata su questa istanza.',\n },\n HttpStatus.NOT_IMPLEMENTED,\n );\n }\n await revokeAccessiUserSessions(this.options, user.codiceUtente);\n const cookieConfig = resolveAccessiAuthCookieOptions(this.options);\n if (cookieConfig) clearAccessiAuthCookies(res, cookieConfig);\n return RestUtilities.sendOKMessage(res, 'Sessioni revocate con successo.');\n } catch (error) {\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n error instanceof HttpException ? error.getStatus() : HttpStatus.BAD_REQUEST,\n );\n }\n }\n\n @ApiOperation({\n summary: 'Revoca un singolo access token tramite jti',\n operationId: 'revokeToken',\n description:\n 'Annulla un solo token (logout del dispositivo corrente o token compromesso) senza toccare le altre sessioni. ' +\n 'Se il body non contiene jti viene revocato il token della richiesta. Richiede accessTokenRevocation.store configurato.',\n })\n @ApiBody({ type: RevokeTokenRequest })\n @ApiOkResponse({ type: ActionResponse })\n @ApiResponse({ status: 401, type: ErrorResponse, description: 'Token Accessi mancante o non valido.' })\n @ApiResponse({ status: 403, type: ErrorResponse, description: 'Non autorizzato a revocare il token indicato.' })\n @ApiResponse({ status: 501, type: ErrorResponse, description: 'Revoca token non configurata.' })\n @UseGuards(JwtSimpleGuard)\n @Post('revoke-token')\n async revokeToken(\n @Req() request: Request,\n @Body() body: RevokeTokenRequest,\n @Res() res: Response,\n ) {\n try {\n const user = getAuthenticatedAccessiUser(request);\n if (!getAccessTokenRevocationStore(this.options)) {\n throw new HttpException(\n {\n code: 'ACCESSI_ACCESS_TOKEN_REVOCATION_DISABLED',\n message: 'La revoca dei singoli token non e configurata su questa istanza.',\n },\n HttpStatus.NOT_IMPLEMENTED,\n );\n }\n\n const payload = ((request as Request & { user?: unknown }).user ?? {}) as Record<string, unknown>;\n const currentJti = typeof payload.jti === 'string' ? payload.jti : undefined;\n const requestedJti = typeof body?.jti === 'string' ? body.jti.trim() : '';\n const targetJti = requestedJti !== '' ? requestedJti : currentJti;\n\n if (!targetJti) {\n throw new HttpException(\n { code: 'ACCESSI_TOKEN_JTI_MISSING', message: 'Il token non contiene un jti revocabile.' },\n HttpStatus.BAD_REQUEST,\n );\n }\n\n const isCurrentToken = targetJti === currentJti;\n if (!isCurrentToken && !user.flagAdmin && !user.flagSuper) {\n throw new HttpException(\n {\n code: 'ACCESSI_TOKEN_REVOKE_FORBIDDEN',\n message: 'Solo gli amministratori possono revocare il token di un altro utente.',\n },\n HttpStatus.FORBIDDEN,\n );\n }\n\n const expiresAt = Number(payload.exp);\n await revokeAccessiAccessToken(\n this.options,\n targetJti,\n isCurrentToken && Number.isFinite(expiresAt) ? expiresAt * 1000 : undefined,\n );\n auditAccessi('access_token_revoked', {\n codiceUtente: user.codiceUtente,\n actor: user.codiceUtente,\n jti: targetJti,\n self: isCurrentToken,\n });\n if (isCurrentToken) {\n const cookieConfig = resolveAccessiAuthCookieOptions(this.options);\n if (cookieConfig) clearAccessiAuthCookies(res, cookieConfig);\n }\n return RestUtilities.sendOKMessage(res, 'Token revocato con successo.');\n } catch (error) {\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n error instanceof HttpException ? error.getStatus() : HttpStatus.BAD_REQUEST,\n );\n }\n }\n\n @ApiOperation({\n summary: 'Effettua il login utente',\n description:\n \"Con sola email restituisce passwordRequired oppure avvia il codice per utenti passwordless. Con password valida restituisce il login completo o challenge se la 2FA e attiva. Nessun JWT viene emesso prima della verifica del codice.\",\n operationId: 'login',\n })\n @ApiBody({ type: LoginRequest })\n @ApiResponse({\n status: 200,\n description: 'Login effettuato con successo',\n type: LoginResponse,\n })\n @ApiResponse({\n status: 401,\n description: 'Credenziali non valide',\n type: ErrorResponse,\n })\n @ApiResponse({\n status: 403,\n description: 'Password scaduta, e necessario aggiornarla.',\n type: PasswordExpiredResponse,\n })\n @ApiResponse({ status: 403, description: 'Utente abilitato solo a SSO.', type: ErrorResponse })\n @Post('login')\n async login(@Req() request: Request, @Body() loginRequest: LoginRequest, @Res() res: Response) {\n const startedAt = Date.now();\n try {\n const rateLimitDecision = await checkPublicAuthRateLimit(\n this.options,\n 'login',\n request,\n [loginRequest?.email],\n );\n if (!rateLimitDecision.allowed) {\n countAccessiMetric(this.options, 'auth_login_total', { result: 'rate_limited' });\n return sendPublicAuthRateLimitExceeded(res, rateLimitDecision.retryAfterSeconds);\n }\n\n const userData = await this.authService.login(loginRequest);\n if (!userData) {\n countAccessiMetric(this.options, 'auth_login_total', { result: 'failure' });\n return RestUtilities.sendInvalidCredentials(res);\n }\n\n if (!userData.challenge && !userData.passwordRequired) {\n const tokens = this.authService.createTokenPair(userData.utente, ['password']);\n userData.token = tokens.access;\n if (tokens.refresh) userData.refreshToken = tokens.refresh;\n applyAccessiAuthCookies(res, resolveAccessiAuthCookieOptions(this.options), userData);\n }\n\n const result = userData.challenge\n ? 'challenge'\n : userData.passwordRequired\n ? 'password_required'\n : 'success';\n countAccessiMetric(this.options, 'auth_login_total', { result });\n return RestUtilities.sendBaseResponse(res, userData);\n } catch (error) {\n const message = (error as Error)?.message;\n const result = message === 'PASSWORD_EXPIRED'\n ? 'password_expired'\n : message === PASSWORD_LOGIN_DISABLED\n ? 'sso_only'\n : 'error';\n countAccessiMetric(this.options, 'auth_login_total', { result });\n if (message === 'PASSWORD_EXPIRED') {\n this.logger.warning('Password scaduta, cambiare password ', error);\n return RestUtilities.sendPasswordExpired(res);\n }\n\n if (error instanceof HttpException) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error.getStatus());\n }\n\n if ((error as Error)?.message === PASSWORD_LOGIN_DISABLED) {\n return res.status(HttpStatus.FORBIDDEN).json({\n severity: 'error', status: HttpStatus.FORBIDDEN, statusCode: 2,\n code: PASSWORD_LOGIN_DISABLED,\n error: PASSWORD_LOGIN_DISABLED,\n message: 'Questo utente e abilitato solo tramite SSO. Accedi con un provider collegato.',\n });\n }\n\n this.logger.error('Errore durante il login', error);\n if (RestUtilities.isDatabaseSchemaError(error)) {\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n HttpStatus.SERVICE_UNAVAILABLE,\n );\n }\n return RestUtilities.sendInvalidCredentials(res);\n } finally {\n observeAccessiMetric(this.options, 'auth_login_duration_ms', Date.now() - startedAt);\n }\n }\n\n @ApiOperation({\n summary: 'Scambia un refresh token con un nuovo access token',\n operationId: 'refreshAccessToken',\n description:\n 'Richiede jwtOptions.refreshExpiresIn. Il refresh token ha typ=refresh e non e accettato dai guard API.',\n })\n @ApiBody({ type: RefreshTokenRequest })\n @ApiOkResponse({ type: RefreshTokenResponse })\n @ApiResponse({ status: 401, description: 'Refresh token non valido, scaduto o revocato.', type: ErrorResponse })\n @ApiResponse({ status: 429, description: 'Troppi tentativi.', type: ErrorResponse })\n @Post('refresh')\n async refresh(\n @Req() request: Request,\n @Body() body: RefreshTokenRequest,\n @Res() res: Response,\n ) {\n const startedAt = Date.now();\n try {\n const cookieConfig = resolveAccessiAuthCookieOptions(this.options);\n const cookieRefreshToken = cookieConfig?.refreshFromCookie\n ? getAccessiRefreshTokenFromCookie(request.headers.cookie, cookieConfig)\n : undefined;\n const refreshToken = typeof body?.refreshToken === 'string' && body.refreshToken.trim() !== ''\n ? body.refreshToken\n : cookieRefreshToken;\n const tokenKey = typeof refreshToken === 'string'\n ? createHash('sha256').update(refreshToken).digest('hex').slice(0, 32)\n : undefined;\n const decision = await checkPublicAuthRateLimit(\n this.options,\n 'refresh',\n request,\n tokenKey ? [tokenKey] : [],\n );\n if (!decision.allowed) {\n countAccessiMetric(this.options, 'auth_refresh_total', { result: 'rate_limited' });\n return sendPublicAuthRateLimitExceeded(res, decision.retryAfterSeconds);\n }\n\n if (!refreshToken) {\n throw new HttpException('Refresh token mancante.', HttpStatus.UNAUTHORIZED);\n }\n\n const result = await this.authService.refreshAccessToken(refreshToken);\n if (!result.token) {\n throw new HttpException('Refresh token non valido.', HttpStatus.UNAUTHORIZED);\n }\n const response = {\n token: result.token,\n ...(result.refreshToken ? { refreshToken: result.refreshToken } : {}),\n };\n applyAccessiAuthCookies(res, cookieConfig, response);\n countAccessiMetric(this.options, 'auth_refresh_total', { result: 'success' });\n return RestUtilities.sendBaseResponse(res, response);\n } catch (error) {\n const code = authErrorCode(error);\n const result = code === 'ACCESSI_REFRESH_TOKEN_REUSE'\n ? 'reuse'\n : code === 'ACCESSI_REFRESH_FAMILY_REVOKED'\n ? 'family_revoked'\n : code === 'ACCESSI_REFRESH_ROTATION_UNAVAILABLE'\n ? 'store_unavailable'\n : 'invalid';\n countAccessiMetric(this.options, 'auth_refresh_total', { result });\n return RestUtilities.sendErrorMessage(\n res,\n error,\n AuthController.name,\n error instanceof HttpException ? error.getStatus() : HttpStatus.UNAUTHORIZED,\n );\n } finally {\n observeAccessiMetric(this.options, 'auth_refresh_duration_ms', Date.now() - startedAt);\n }\n }\n\n @Post('two-factor/verify')\n @ApiOperation({ summary: 'Verifica il codice e completa il login', operationId: 'verifyTwoFactor' })\n @ApiBody({ type: VerifyTwoFactorRequest })\n @ApiResponse({ status: 200, type: LoginResponse })\n @ApiResponse({ status: 401, type: ErrorResponse })\n @ApiResponse({ status: 429, type: ErrorResponse })\n async verifyTwoFactor(@Req() request: Request, @Body() body: VerifyTwoFactorRequest, @Res() res: Response) {\n const startedAt = Date.now();\n try {\n const limit = await checkPublicAuthRateLimit(this.options, 'twoFactorVerify', request, [body.challengeId]);\n if (!limit.allowed) {\n countAccessiMetric(this.options, 'auth_two_factor_total', { action: 'verify', result: 'rate_limited' });\n return sendPublicAuthRateLimitExceeded(res, limit.retryAfterSeconds);\n }\n const result = await this.authService.verifyTwoFactor(body.challengeId, body.code, body.scope);\n applyAccessiAuthCookies(res, resolveAccessiAuthCookieOptions(this.options), result);\n countAccessiMetric(this.options, 'auth_two_factor_total', { action: 'verify', result: 'success' });\n return RestUtilities.sendBaseResponse(res, result);\n } catch (error) {\n countAccessiMetric(this.options, 'auth_two_factor_total', { action: 'verify', result: 'failure' });\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error instanceof HttpException ? error.getStatus() : 500);\n } finally {\n observeAccessiMetric(this.options, 'auth_two_factor_duration_ms', Date.now() - startedAt, { action: 'verify' });\n }\n }\n\n @Post('two-factor/resend')\n @ApiOperation({ summary: 'Reinvia il codice, invalidando il precedente', operationId: 'resendTwoFactor' })\n @ApiBody({ type: ResendTwoFactorRequest })\n @ApiResponse({ status: 200, type: LoginResponse })\n @ApiResponse({ status: 401, type: ErrorResponse })\n @ApiResponse({ status: 429, type: ErrorResponse })\n async resendTwoFactor(@Req() request: Request, @Body() body: ResendTwoFactorRequest, @Res() res: Response) {\n try {\n const limit = await checkPublicAuthRateLimit(this.options, 'twoFactorResend', request, [body.challengeId]);\n if (!limit.allowed) {\n countAccessiMetric(this.options, 'auth_two_factor_total', { action: 'resend', result: 'rate_limited' });\n return sendPublicAuthRateLimitExceeded(res, limit.retryAfterSeconds);\n }\n const result = await this.authService.resendTwoFactor(body.challengeId);\n countAccessiMetric(this.options, 'auth_two_factor_total', { action: 'resend', result: 'success' });\n return RestUtilities.sendBaseResponse(res, result);\n } catch (error) {\n countAccessiMetric(this.options, 'auth_two_factor_total', { action: 'resend', result: 'failure' });\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error instanceof HttpException ? error.getStatus() : 500);\n }\n }\n\n @Post('bootstrap-admin')\n @ApiOperation({\n summary: 'Crea il primo utente admin (bootstrap)',\n operationId: 'bootstrapAdmin',\n description:\n 'Endpoint pubblico ma protetto dal token di avvio: attivo solo con adminBootstrap.enabled. ' +\n 'Crea un utente in stato confermato senza email, con flag admin (e super opzionale) e password fornita o generata.',\n })\n @ApiBody({ type: BootstrapAdminRequest })\n @ApiResponse({ status: 200, type: BootstrapAdminResponse })\n @ApiResponse({ status: 401, description: 'Token di bootstrap non valido', type: ErrorResponse })\n @ApiResponse({ status: 403, description: 'Bootstrap admin non abilitato', type: ErrorResponse })\n @ApiResponse({ status: 429, description: 'Troppi tentativi', type: ErrorResponse })\n async bootstrapAdmin(@Req() request: Request, @Body() body: BootstrapAdminRequest, @Res() res: Response) {\n try {\n const limit = await checkPublicAuthRateLimit(this.options, 'adminBootstrap', request);\n if (!limit.allowed) return sendPublicAuthRateLimitExceeded(res, limit.retryAfterSeconds);\n return RestUtilities.sendBaseResponse(res, await this.adminBootstrapService.bootstrap(body));\n } catch (error) {\n return RestUtilities.sendErrorMessage(res, error, AuthController.name, error instanceof HttpException ? error.getStatus() : 500);\n }\n }\n\n @Get('bootstrap-admin/status')\n @ApiOperation({\n summary: 'Indica se il bootstrap admin e abilitato',\n operationId: 'getAdminBootstrapStatus',\n description:\n 'Endpoint pubblico: la console mostra la sezione \"Crea utente admin\" solo quando enabled e true.',\n })\n @ApiResponse({ status: 200, type: AdminBootstrapStatusResponse })\n async adminBootstrapStatus(@Res() res: Response) {\n return RestUtilities.sendBaseResponse(res, { enabled: this.adminBootstrapService.isEnabled() });\n }\n}\n"]}
@@ -33,6 +33,8 @@ const accessControl_1 = require("../security/accessControl");
33
33
  const authenticatedToken_1 = require("../security/authenticatedToken");
34
34
  const consoleEntry_1 = require("../security/consoleEntry");
35
35
  const publicAuthRateLimit_1 = require("../security/publicAuthRateLimit");
36
+ const authCookies_1 = require("../security/authCookies");
37
+ const metrics_1 = require("../observability/metrics");
36
38
  /**
37
39
  * Auto-ingresso alla console amministrativa da un frontend gia autenticato.
38
40
  * Il frontend scambia la propria sessione Accessi con un ticket monouso, poi apre
@@ -60,9 +62,11 @@ let ConsoleEntryController = ConsoleEntryController_1 = class ConsoleEntryContro
60
62
  throw new common_1.UnauthorizedException({ code: 'ACCESSI_CONSOLE_ENTRY_TOKEN_MISSING', message: 'Token Accessi mancante.' });
61
63
  }
62
64
  const issued = yield this.store.issue({ token: tokenValue, codiceUtente: user.codiceUtente }, this.ttlMs);
65
+ (0, metrics_1.countAccessiMetric)(this.options, 'console_ticket_total', { action: 'create', result: 'issued' });
63
66
  return Utilities_1.RestUtilities.sendBaseResponse(res, issued);
64
67
  }
65
68
  catch (error) {
69
+ (0, metrics_1.countAccessiMetric)(this.options, 'console_ticket_total', { action: 'create', result: 'error' });
66
70
  return Utilities_1.RestUtilities.sendErrorMessage(res, error, ConsoleEntryController_1.name, error instanceof common_1.HttpException ? error.getStatus() : common_1.HttpStatus.UNAUTHORIZED);
67
71
  }
68
72
  });
@@ -73,6 +77,7 @@ let ConsoleEntryController = ConsoleEntryController_1 = class ConsoleEntryContro
73
77
  try {
74
78
  const decision = yield (0, publicAuthRateLimit_1.checkPublicAuthRateLimit)(this.options, 'consoleEntry', request, [(_a = body === null || body === void 0 ? void 0 : body.ticket) !== null && _a !== void 0 ? _a : '']);
75
79
  if (!decision.allowed) {
80
+ (0, metrics_1.countAccessiMetric)(this.options, 'console_ticket_total', { action: 'exchange', result: 'rate_limited' });
76
81
  return (0, publicAuthRateLimit_1.sendPublicAuthRateLimitExceeded)(res, decision.retryAfterSeconds);
77
82
  }
78
83
  const entry = yield this.store.consume(body === null || body === void 0 ? void 0 : body.ticket);
@@ -82,9 +87,21 @@ let ConsoleEntryController = ConsoleEntryController_1 = class ConsoleEntryContro
82
87
  message: 'Ticket di ingresso console non valido o scaduto. Riapri la console dal frontend.',
83
88
  });
84
89
  }
90
+ (0, metrics_1.countAccessiMetric)(this.options, 'console_ticket_total', { action: 'exchange', result: 'consumed' });
91
+ const cookieConfig = (0, authCookies_1.resolveAccessiAuthCookieOptions)(this.options);
92
+ if (cookieConfig) {
93
+ (0, authCookies_1.setAccessiAuthCookies)(res, cookieConfig, { access: entry.token });
94
+ if (!cookieConfig.exposeTokens) {
95
+ return Utilities_1.RestUtilities.sendBaseResponse(res, {});
96
+ }
97
+ }
85
98
  return Utilities_1.RestUtilities.sendBaseResponse(res, { token: { value: entry.token, type: 'Bearer' } });
86
99
  }
87
100
  catch (error) {
101
+ (0, metrics_1.countAccessiMetric)(this.options, 'console_ticket_total', {
102
+ action: 'exchange',
103
+ result: error instanceof common_1.UnauthorizedException ? 'invalid' : 'error',
104
+ });
88
105
  return Utilities_1.RestUtilities.sendErrorMessage(res, error, ConsoleEntryController_1.name, error instanceof common_1.HttpException ? error.getStatus() : common_1.HttpStatus.UNAUTHORIZED);
89
106
  }
90
107
  });