@nodefony/security 10.0.0-beta.4 → 10.0.0-beta.6

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 (74) hide show
  1. package/dist/_virtual/{_@oxc-project_runtime@0.155.0 → _@oxc-project_runtime@0.157.0}/helpers/esm/decorate.js +1 -1
  2. package/dist/index.js +60 -60
  3. package/dist/nodefony/config/config.js +13 -5
  4. package/dist/nodefony/contracts/IWebhookPayload.js +1 -0
  5. package/dist/nodefony/errors/index.js +4 -4
  6. package/dist/nodefony/keycloak/keycloakAdmin.js +3 -3
  7. package/dist/nodefony/keycloak/security-keycloak-realm.js +1 -1
  8. package/dist/nodefony/service/accessTokenVerifier.js +5 -5
  9. package/dist/nodefony/service/apiKeys.js +8 -4
  10. package/dist/nodefony/service/authFlow.js +3 -3
  11. package/dist/nodefony/service/authorization.js +1 -1
  12. package/dist/nodefony/service/firewall.js +233 -41
  13. package/dist/nodefony/service/keycloak.js +1 -1
  14. package/dist/nodefony/service/oauth2.js +8 -4
  15. package/dist/nodefony/service/securityHeaders.js +340 -47
  16. package/dist/nodefony/service/tokenService.js +8 -8
  17. package/dist/nodefony/service/totp.js +3 -3
  18. package/dist/nodefony/service/webAuthn.js +1 -1
  19. package/dist/nodefony/service/webhooks.js +11 -4
  20. package/dist/nodefony/src/admin/SecurityAdminApi.js +19 -0
  21. package/dist/nodefony/src/authenticator/ApiKeyAuthenticator.js +1 -1
  22. package/dist/nodefony/src/authenticator/ExternalSubjectResolver.js +31 -7
  23. package/dist/nodefony/src/authenticator/FirewallRealtimeAuthenticator.js +62 -20
  24. package/dist/nodefony/src/authenticator/JwtAuthenticator.js +5 -2
  25. package/dist/nodefony/src/authenticator/SessionAuthenticator.js +1 -1
  26. package/dist/nodefony/src/authenticator/authenticatorRegistry.js +1 -1
  27. package/dist/nodefony/src/csp.js +265 -10
  28. package/dist/nodefony/src/cspReports.js +307 -0
  29. package/dist/nodefony/src/oauth/clientCredentials.js +1 -1
  30. package/dist/nodefony/src/oauth/metadata.js +1 -1
  31. package/dist/nodefony/src/oauth/oauthProviderRegistry.js +17 -4
  32. package/dist/nodefony/src/oauth/providers/github.js +1 -1
  33. package/dist/nodefony/src/realtime/UserRealtimeToken.js +59 -2
  34. package/dist/nodefony/src/realtime/frameAuthorizer.js +7 -6
  35. package/dist/nodefony/src/token/RemoteJwtVerifier.js +8 -2
  36. package/dist/nodefony/src/token/tokenTimeClaims.js +34 -0
  37. package/dist/nodefony/src/totp/totpOperations.js +1 -1
  38. package/dist/nodefony/src/voter/RoleVoter.js +1 -1
  39. package/dist/nodefony/src/webhook/WebhookDispatcher.js +71 -17
  40. package/dist/nodefony/src/webhook/webhookDelivery.js +3 -3
  41. package/dist/nodefony/testing/index.js +98 -0
  42. package/dist/types/index.d.ts +1 -0
  43. package/dist/types/nodefony/config/config.d.ts +2 -0
  44. package/dist/types/nodefony/contracts/IApiKey.d.ts +8 -2
  45. package/dist/types/nodefony/contracts/IFirewall.d.ts +15 -2
  46. package/dist/types/nodefony/contracts/ITokenStore.d.ts +7 -3
  47. package/dist/types/nodefony/contracts/IWebhookEndpoint.d.ts +13 -3
  48. package/dist/types/nodefony/contracts/IWebhookPayload.d.ts +24 -0
  49. package/dist/types/nodefony/service/apiKeys.d.ts +3 -0
  50. package/dist/types/nodefony/service/firewall.d.ts +28 -7
  51. package/dist/types/nodefony/service/securityHeaders.d.ts +82 -11
  52. package/dist/types/nodefony/service/webhooks.d.ts +7 -1
  53. package/dist/types/nodefony/src/admin/SecurityAdminApi.d.ts +3 -0
  54. package/dist/types/nodefony/src/authenticator/ExternalSubjectResolver.d.ts +11 -0
  55. package/dist/types/nodefony/src/csp.d.ts +142 -0
  56. package/dist/types/nodefony/src/cspReports.d.ts +73 -0
  57. package/dist/types/nodefony/src/oauth/oauthProviderRegistry.d.ts +15 -0
  58. package/dist/types/nodefony/src/realtime/UserRealtimeToken.d.ts +35 -1
  59. package/dist/types/nodefony/src/realtime/frameAuthorizer.d.ts +2 -2
  60. package/dist/types/nodefony/src/realtime/realtimeContracts.d.ts +25 -17
  61. package/dist/types/nodefony/src/token/tokenTimeClaims.d.ts +32 -0
  62. package/dist/types/nodefony/src/webhook/WebhookDispatcher.d.ts +36 -1
  63. package/dist/types/nodefony/testing/index.d.ts +57 -0
  64. package/docs/api-keys.md +3 -1
  65. package/docs/authenticators.md +6 -4
  66. package/docs/csrf.md +3 -2
  67. package/docs/external-jwt.md +5 -1
  68. package/docs/firewall.md +3 -2
  69. package/docs/headers.md +427 -71
  70. package/docs/login-page.md +4 -3
  71. package/docs/totp.md +2 -2
  72. package/docs/webauthn.md +2 -2
  73. package/docs/webhooks.md +57 -11
  74. package/package.json +20 -14
package/docs/csrf.md CHANGED
@@ -271,8 +271,9 @@ sûres → coût nul sur le GET dominant (`csrf.ts#Csrf.enforce`). Pour une muta
271
271
  Lectures durcies côté firewall :
272
272
 
273
273
  - en-têtes lus en **première occurrence** — jamais un tableau d'en-têtes répétés (garde d'injection,
274
- `headerValue()`, `firewall.ts#headerValue`) ; cookie extrait de l'en-tête **brut**, sans dépendre du
275
- parse du contexte (`cookieValue()`, `firewall.ts#cookieValue`) ;
274
+ `headerValue()`, `firewall.ts#headerValue`) ; cookie `csrf-token` lu sur le contexte, dont
275
+ l'en-tête `Cookie` n'a qu'un lecteur (`requestCookie()`, `firewall.ts#requestCookie`) — parsé à la
276
+ construction du contexte, donc avant toute étape du pare-feu ;
276
277
  - hôte cible **brut avec port** — `:authority` en HTTP/2, `context.domain` en dernier recours
277
278
  (`firewall.ts#Firewall`) ;
278
279
  - le refus est un `CsrfError` **403 au message générique** : la politique (en-têtes inspectés,
@@ -79,7 +79,7 @@ normalisés (RFC 8414 / OpenID), et le pare-feu accepte désormais un `Authoriza
79
79
  | `issuers[].jwksUri` | découvert | Déclaré, aucune découverte n'a lieu — utile pour un émetteur sans métadonnées, ou un démarrage à froid sans requête sortante. |
80
80
  | `issuers[].algorithms` | `RS256`, `ES256`, `EdDSA` | Allowlist **serveur** : l'algorithme n'est jamais déduit de l'en-tête du jeton (RFC 8725 §3.1). À restreindre à ce que l'émetteur utilise réellement. |
81
81
  | `issuers[].typ` | non exigé | `at+jwt` pour un émetteur conforme RFC 9068. |
82
- | `issuers[].requiredClaims` | `[]` | Claims dont la présence est exigée, en plus d'`iss` et `aud`. |
82
+ | `issuers[].requiredClaims` | `[]` | Claims dont la présence est exigée, en plus d'`iss`, `aud`, `exp` et `iat` (toujours exigés, RFC 9068 §2.2 ; un `iat` daté du futur est refusé). |
83
83
  | `issuers[].subjectMapping` | `prefixed` | Comment le `sub` devient un identifiant local — **voir l'encadré ci-dessous**. |
84
84
  | `subjectPolicy` | `require` | `require` : un compte local est exigé. `ephemeral` : l'appelant vit le temps de la requête. |
85
85
  | `ephemeralRoles` | `[]` | Rôles accordés en mode `ephemeral`. Vide à dessein. |
@@ -98,6 +98,10 @@ rattaché au compte local du même nom.
98
98
  `subject` ne se déclare donc que si l'on maîtrise l'espace de noms de cet émetteur : typiquement
99
99
  parce qu'il **est** cette application, ou parce que ses sujets sont déjà des identifiants locaux.
100
100
 
101
+ `subjectMapping` ne règle que la **recherche d'un compte local** : sous `subjectPolicy: "ephemeral"`,
102
+ où aucun compte n'est cherché, l'identifiant de l'appelant est **toujours** `<issuer>#<sub>`, quel
103
+ que soit le réglage (`ExternalSubjectResolver.ts#ExternalSubjectResolver.resolve`).
104
+
101
105
  ### `subjectPolicy` — qui a le droit d'exister
102
106
 
103
107
  - **`require`** (défaut) — le sujet doit correspondre à un compte local (`loadUserByIdentifier`).
package/docs/firewall.md CHANGED
@@ -243,8 +243,9 @@ Credential = l'**identifiant** posé dans le blob de session (jamais un secret).
243
243
  régénère l'ID (anti-fixation).
244
244
  - **L'identité est re-résolue à CHAQUE requête** (`SessionAuthenticator.ts#SessionAuthenticator.authenticate`) → rôles frais,
245
245
  révocation et verrouillage effectifs immédiatement.
246
- - **Pas de `challenge()`** : session absente = 401 nu → le front redirige vers son écran de login
247
- (pas de popup Basic).
246
+ - **Pas de `challenge()`** : session absente = 401 portant le défi de repli du pare-feu,
247
+ `Session realm="nodefony"` (RFC 9110 §15.5.2) — schéma inconnu des navigateurs, donc pas de
248
+ popup ; le front redirige vers son écran de login.
248
249
 
249
250
  ### `userpassword` — HTTP Basic, avec throttle NIST
250
251