emilsoftware-utilities 2.0.0-dev.75 → 2.0.0-dev.77

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 (45) hide show
  1. package/dist/accessi-module/AccessiModule.d.ts +8 -1
  2. package/dist/accessi-module/AccessiModule.js.map +1 -1
  3. package/dist/accessi-module/Console/accessiFetch.d.ts +7 -0
  4. package/dist/accessi-module/Console/accessiFetch.js +45 -7
  5. package/dist/accessi-module/Console/accessiFetch.js.map +1 -1
  6. package/dist/accessi-module/Console/console.js +84 -24
  7. package/dist/accessi-module/Console/console.js.map +1 -1
  8. package/dist/accessi-module/Console/generated/model/getUserByTokenRequest.d.ts +2 -2
  9. package/dist/accessi-module/Console/generated/model/getUserByTokenRequest.js.map +1 -1
  10. package/dist/accessi-module/Console/generated/model/refreshTokenRequest.d.ts +2 -2
  11. package/dist/accessi-module/Console/generated/model/refreshTokenRequest.js.map +1 -1
  12. package/dist/accessi-module/Console/index.html +1 -1
  13. package/dist/accessi-module/Console/wiki.js +3 -2
  14. package/dist/accessi-module/Console/wiki.js.map +1 -1
  15. package/dist/accessi-module/Controllers/AccessiConsoleController.d.ts +5 -3
  16. package/dist/accessi-module/Controllers/AccessiConsoleController.js +47 -12
  17. package/dist/accessi-module/Controllers/AccessiConsoleController.js.map +1 -1
  18. package/dist/accessi-module/Controllers/AuthController.js +35 -7
  19. package/dist/accessi-module/Controllers/AuthController.js.map +1 -1
  20. package/dist/accessi-module/Controllers/ConsoleEntryController.js +8 -0
  21. package/dist/accessi-module/Controllers/ConsoleEntryController.js.map +1 -1
  22. package/dist/accessi-module/Dtos/GetUserByTokenRequest.d.ts +1 -1
  23. package/dist/accessi-module/Dtos/GetUserByTokenRequest.js +3 -2
  24. package/dist/accessi-module/Dtos/GetUserByTokenRequest.js.map +1 -1
  25. package/dist/accessi-module/Dtos/RefreshTokenDtos.d.ts +1 -1
  26. package/dist/accessi-module/Dtos/RefreshTokenDtos.js +4 -1
  27. package/dist/accessi-module/Dtos/RefreshTokenDtos.js.map +1 -1
  28. package/dist/accessi-module/index.d.ts +4 -0
  29. package/dist/accessi-module/index.js +30 -14
  30. package/dist/accessi-module/index.js.map +1 -1
  31. package/dist/accessi-module/security/authCookies.d.ts +104 -0
  32. package/dist/accessi-module/security/authCookies.js +240 -0
  33. package/dist/accessi-module/security/authCookies.js.map +1 -0
  34. package/dist/accessi-module/security/securityHeaders.d.ts +89 -0
  35. package/dist/accessi-module/security/securityHeaders.js +155 -0
  36. package/dist/accessi-module/security/securityHeaders.js.map +1 -0
  37. package/dist/accessi-module/security/validateOptions.js +34 -0
  38. package/dist/accessi-module/security/validateOptions.js.map +1 -1
  39. package/dist/emilsoftware-utilities-2.0.0-dev.77.tgz +0 -0
  40. package/dist/initEmilsoftwareModule.js +13 -11
  41. package/dist/initEmilsoftwareModule.js.map +1 -1
  42. package/docs/auth-cookies.md +123 -0
  43. package/docs/security-headers.md +151 -0
  44. package/package.json +3 -3
  45. package/dist/emilsoftware-utilities-2.0.0-dev.75.tgz +0 -0
@@ -0,0 +1,151 @@
1
+ # Header di sicurezza e CSP
2
+
3
+ Accessi applica header di sicurezza alle proprie rotte (`/api/accessi/*`, JWKS e
4
+ documentazione OpenAPI). La configurazione avviene in `http.securityHeaders`:
5
+
6
+ ```ts
7
+ const accessiOptions: AccessiOptions = {
8
+ // ...
9
+ http: {
10
+ securityHeaders: {
11
+ frameOptions: 'SAMEORIGIN',
12
+ referrerPolicy: 'no-referrer',
13
+ permissionsPolicy: 'camera=(), microphone=(), geolocation=()',
14
+ cacheControl: 'no-store, max-age=0',
15
+ contentSecurityPolicy: {
16
+ reportOnly: false,
17
+ connectSrc: ['https://api.example.com'],
18
+ reportUri: 'https://csp.example.com/report',
19
+ directives: {
20
+ 'img-src': ["'self'", 'data:', 'https:'],
21
+ },
22
+ },
23
+ },
24
+ },
25
+ };
26
+ ```
27
+
28
+ `securityHeaders: false` disabilita tutto; `securityHeaders: true` (o l'omissione)
29
+ usa i default. La forma storica booleana resta valida.
30
+
31
+ ## Default
32
+
33
+ | Header | Valore | Note |
34
+ | --- | --- | --- |
35
+ | `X-Content-Type-Options` | `nosniff` | sempre presente |
36
+ | `X-Frame-Options` | `SAMEORIGIN` | `false` per non inviarlo |
37
+ | `Referrer-Policy` | `no-referrer` | `false` per non inviarla |
38
+ | `Permissions-Policy` | `camera=(), microphone=(), geolocation=()` | `false` per non inviarla |
39
+ | `Cache-Control` (shell console) | `no-store, max-age=0` | `false` per non inviarlo |
40
+ | `Content-Security-Policy` | vedi sotto | `false` per disabilitarla |
41
+
42
+ La shell della console risponde sempre con `Cache-Control: no-store`,
43
+ `Referrer-Policy: no-referrer` e `X-Content-Type-Options: nosniff`, anche con
44
+ `securityHeaders: false`, per non regredire rispetto alle versioni precedenti.
45
+
46
+ ## Content Security Policy
47
+
48
+ Direttive di base:
49
+
50
+ ```
51
+ default-src 'self'
52
+ base-uri 'none'
53
+ object-src 'none'
54
+ frame-ancestors 'self'
55
+ form-action 'self'
56
+ img-src 'self' data:
57
+ font-src 'self'
58
+ style-src 'self'
59
+ script-src 'self'
60
+ connect-src 'self'
61
+ ```
62
+
63
+ La policy cambia per superficie:
64
+
65
+ - **Console** (`/api/accessi/console*`): i due script inline della shell ricevono
66
+ un nonce casuale per richiesta (`script-src 'self' 'nonce-...'`). Non viene mai
67
+ usato `'unsafe-inline'`. Se la console chiama l'API su un'altra origine, quella
68
+ origine viene aggiunta automaticamente a `connect-src` da
69
+ `consoleApiBaseUrl`.
70
+ - **OpenAPI** (`/accessi/openapi*`): la UI Swagger genera script e stili inline a
71
+ runtime, quindi la policy include `'unsafe-inline'` per `script-src` e
72
+ `style-src`. È l'unica eccezione documentata; per rimuoverla impostare
73
+ `contentSecurityPolicy.swaggerUnsafeInline: false` e servire una UI Swagger
74
+ compatibile con nonce/hash.
75
+ - **API e JWKS**: policy stretta, senza `'unsafe-inline'`.
76
+
77
+ `directives` vince sui default: una direttiva impostata a `false` viene rimossa,
78
+ altrimenti i valori sostituiscono quelli predefiniti. `connectSrc` aggiunge
79
+ origini a `connect-src`; `reportUri` aggiunge `report-uri`.
80
+
81
+ ### Rollout con Report-Only
82
+
83
+ 1. Imposta `contentSecurityPolicy.reportOnly: true` e un `reportUri`.
84
+ 2. Raccogli le violazioni per almeno un ciclo di utilizzo della console.
85
+ 3. Aggiungi le origini legittime a `connectSrc` o alle direttive.
86
+ 4. Passa a `reportOnly: false`.
87
+
88
+ ## Reverse proxy
89
+
90
+ Accessi non imposta HSTS: va configurato sul terminatore TLS insieme ai
91
+ redirect HTTP→HTTPS.
92
+
93
+ ### Nginx
94
+
95
+ ```nginx
96
+ location / {
97
+ proxy_pass http://accessi_upstream;
98
+ proxy_set_header Host $host;
99
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
100
+ proxy_set_header X-Forwarded-Proto $scheme;
101
+
102
+ # Non rimuovere gli header CSP inviati da Accessi.
103
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
104
+ }
105
+ ```
106
+
107
+ `add_header` di Nginx si aggiunge solo se la risposta non ha già un header con
108
+ lo stesso nome: non duplicare `Content-Security-Policy` a questo livello. Se il
109
+ proxy deve imporre una policy propria, disattiva quella di Accessi
110
+ (`contentSecurityPolicy: false`) e mantieni una sola policy, consapevole che la
111
+ console richiede il nonce (il proxy non può generarlo al posto dell'app).
112
+
113
+ ### Traefik
114
+
115
+ ```yaml
116
+ http:
117
+ middlewares:
118
+ accessi-headers:
119
+ headers:
120
+ stsSeconds: 31536000
121
+ stsIncludeSubdomains: true
122
+ contentTypeNosniff: true
123
+ referrerPolicy: no-referrer
124
+ customResponseHeaders:
125
+ Permissions-Policy: "camera=(), microphone=(), geolocation=()"
126
+ ```
127
+
128
+ Non aggiungere `Content-Security-Policy` in `customResponseHeaders` se Accessi la
129
+ invia già: due header CSP vengono applicati come intersezione e la console
130
+ smetterebbe di funzionare. Per una policy unica, gestiscila in un solo punto.
131
+
132
+ ### Cloudflare
133
+
134
+ - Abilita "Always Use HTTPS" e HSTS nelle impostazioni TLS/Edge.
135
+ - Se usi Transform Rules per aggiungere header, escludi
136
+ `Content-Security-Policy`: Cloudflare non può generare il nonce della console.
137
+ - Verifica che "Email Obfuscation" o altre feature che iniettano script inline
138
+ siano disattivate sulle pagine della console, altrimenti violano la CSP.
139
+ - Con Cloudflare davanti alla JWKS, mantieni il TTL della cache allineato a
140
+ `jwt.jwks.cacheTtlMs` (default 300 s): un TTL più alto ritarda la rotazione
141
+ delle chiavi.
142
+
143
+ ## Verifica
144
+
145
+ ```bash
146
+ curl -sSI https://accessi.example.com/api/accessi/console | grep -i -E 'content-security|x-frame|referrer|permissions'
147
+ ```
148
+
149
+ La CSP della console cambia a ogni risposta per via del nonce: due richieste
150
+ consecutive devono restituire policy diverse. Il nonce nell'header deve
151
+ coincidere con quello dei due script inline nella pagina.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emilsoftware-utilities",
3
- "version": "2.0.0-dev.75",
3
+ "version": "2.0.0-dev.77",
4
4
  "description": "Utilities for EmilSoftware",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -139,8 +139,8 @@
139
139
  "typecheck": "tsc --noEmit",
140
140
  "lint": "node scripts/lint.cjs",
141
141
  "test": "npm run typecheck && npm run lint && npm run test:unit",
142
- "test:unit": "node --test test/angular-components.cjs test/menus-catalog.mjs test/menu-scopes.cjs test/accessi-regressions.cjs test/password-reset-regressions.cjs test/two-factor.cjs test/accessi-schema.cjs test/utilities-regressions.cjs test/service-token-regressions.cjs test/accessi-email-config.cjs test/accessi-catalog-scripts.cjs test/openapi-config.cjs test/resource-server.cjs test/accessi-security-standards.cjs test/accessi-service.cjs test/refresh-token.cjs test/token-revocation.cjs test/accessi-client.cjs test/accessi-client-scopes.cjs test/openapi-semantic-diff.cjs test/proxy-ip.cjs test/readiness.cjs test/jwt-key-rotation.cjs",
143
- "test:coverage": "node --experimental-test-coverage --test-coverage-lines=50 --test-coverage-functions=60 --test-coverage-branches=60 --test test/angular-components.cjs test/menus-catalog.mjs test/menu-scopes.cjs test/accessi-regressions.cjs test/password-reset-regressions.cjs test/two-factor.cjs test/accessi-schema.cjs test/utilities-regressions.cjs test/service-token-regressions.cjs test/accessi-email-config.cjs test/accessi-catalog-scripts.cjs test/openapi-config.cjs test/resource-server.cjs test/accessi-security-standards.cjs test/accessi-service.cjs test/refresh-token.cjs test/token-revocation.cjs test/accessi-client.cjs test/accessi-client-scopes.cjs test/openapi-semantic-diff.cjs test/proxy-ip.cjs test/readiness.cjs test/jwt-key-rotation.cjs",
142
+ "test:unit": "node --test test/angular-components.cjs test/menus-catalog.mjs test/menu-scopes.cjs test/accessi-regressions.cjs test/password-reset-regressions.cjs test/two-factor.cjs test/accessi-schema.cjs test/utilities-regressions.cjs test/service-token-regressions.cjs test/accessi-email-config.cjs test/accessi-catalog-scripts.cjs test/openapi-config.cjs test/resource-server.cjs test/accessi-security-standards.cjs test/accessi-service.cjs test/refresh-token.cjs test/token-revocation.cjs test/accessi-client.cjs test/accessi-client-scopes.cjs test/openapi-semantic-diff.cjs test/proxy-ip.cjs test/readiness.cjs test/jwt-key-rotation.cjs test/security-headers.cjs test/auth-cookies.cjs",
143
+ "test:coverage": "node --experimental-test-coverage --test-coverage-lines=50 --test-coverage-functions=60 --test-coverage-branches=60 --test test/angular-components.cjs test/menus-catalog.mjs test/menu-scopes.cjs test/accessi-regressions.cjs test/password-reset-regressions.cjs test/two-factor.cjs test/accessi-schema.cjs test/utilities-regressions.cjs test/service-token-regressions.cjs test/accessi-email-config.cjs test/accessi-catalog-scripts.cjs test/openapi-config.cjs test/resource-server.cjs test/accessi-security-standards.cjs test/accessi-service.cjs test/refresh-token.cjs test/token-revocation.cjs test/accessi-client.cjs test/accessi-client-scopes.cjs test/openapi-semantic-diff.cjs test/proxy-ip.cjs test/readiness.cjs test/jwt-key-rotation.cjs test/security-headers.cjs test/auth-cookies.cjs",
144
144
  "test:accessi": "npm run test:unit",
145
145
  "test:all": "npm test && npm run test:integration && npm run test:integration:redis",
146
146
  "test:integration": "node test/integration/run-firebird.cjs 5",