@nodefony/security 10.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +544 -0
- package/README.md +182 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js +9 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js +6 -0
- package/dist/index.js +151 -0
- package/dist/nodefony/command/security-secrets.js +158 -0
- package/dist/nodefony/command/security-token.js +335 -0
- package/dist/nodefony/command/security-user-add.js +131 -0
- package/dist/nodefony/command/security-user-delete.js +102 -0
- package/dist/nodefony/command/security-user-list.js +77 -0
- package/dist/nodefony/config/config.js +366 -0
- package/dist/nodefony/config/defineModuleConfig.js +35 -0
- package/dist/nodefony/contracts/IAccessVoter.js +13 -0
- package/dist/nodefony/contracts/IApiKey.js +1 -0
- package/dist/nodefony/contracts/IAuditEvent.js +1 -0
- package/dist/nodefony/contracts/IAuditStore.js +1 -0
- package/dist/nodefony/contracts/IAuthenticator.js +1 -0
- package/dist/nodefony/contracts/IAuthorizationService.js +1 -0
- package/dist/nodefony/contracts/IFirewall.js +1 -0
- package/dist/nodefony/contracts/IFirewallDescription.js +1 -0
- package/dist/nodefony/contracts/IJwtKeystore.js +1 -0
- package/dist/nodefony/contracts/IOAuthProvider.js +1 -0
- package/dist/nodefony/contracts/ISecuredArea.js +1 -0
- package/dist/nodefony/contracts/IToken.js +1 -0
- package/dist/nodefony/contracts/ITokenStore.js +1 -0
- package/dist/nodefony/contracts/ITotpSecret.js +1 -0
- package/dist/nodefony/contracts/ITotpSecretStore.js +1 -0
- package/dist/nodefony/contracts/IWebAuthnCredential.js +1 -0
- package/dist/nodefony/contracts/IWebAuthnCredentialStore.js +1 -0
- package/dist/nodefony/contracts/IWebhookEndpoint.js +1 -0
- package/dist/nodefony/contracts/IWebhookStore.js +1 -0
- package/dist/nodefony/contracts/index.js +2 -0
- package/dist/nodefony/errors/AccessDeniedError.js +14 -0
- package/dist/nodefony/errors/ApiKeyError.js +21 -0
- package/dist/nodefony/errors/AuthenticationError.js +14 -0
- package/dist/nodefony/errors/CsrfError.js +23 -0
- package/dist/nodefony/errors/InvalidTargetError.js +39 -0
- package/dist/nodefony/errors/SsrfError.js +17 -0
- package/dist/nodefony/errors/ThrottledError.js +21 -0
- package/dist/nodefony/errors/UnverifiableTokenError.js +42 -0
- package/dist/nodefony/errors/WebAuthnError.js +21 -0
- package/dist/nodefony/errors/index.js +9 -0
- package/dist/nodefony/service/accessTokenVerifier.js +77 -0
- package/dist/nodefony/service/apiKeys.js +310 -0
- package/dist/nodefony/service/auditService.js +145 -0
- package/dist/nodefony/service/authFlow.js +332 -0
- package/dist/nodefony/service/authorization.js +95 -0
- package/dist/nodefony/service/cors.js +81 -0
- package/dist/nodefony/service/csrf.js +97 -0
- package/dist/nodefony/service/firewall.js +699 -0
- package/dist/nodefony/service/oauth2.js +153 -0
- package/dist/nodefony/service/securityHeaders.js +80 -0
- package/dist/nodefony/service/tokenService.js +486 -0
- package/dist/nodefony/service/totp.js +209 -0
- package/dist/nodefony/service/webAuthn.js +343 -0
- package/dist/nodefony/service/webhooks.js +539 -0
- package/dist/nodefony/src/RoleHierarchyWalker.js +77 -0
- package/dist/nodefony/src/SecuredArea.js +51 -0
- package/dist/nodefony/src/admin/SecurityAdminApi.js +495 -0
- package/dist/nodefony/src/admin/WebhookAdminApi.js +378 -0
- package/dist/nodefony/src/admin/adminAudit.js +37 -0
- package/dist/nodefony/src/admin/userRevocationCascade.js +40 -0
- package/dist/nodefony/src/apikey/apiKeyFormat.js +107 -0
- package/dist/nodefony/src/audit/MemoryAuditStore.js +121 -0
- package/dist/nodefony/src/audit/auditBridge.js +82 -0
- package/dist/nodefony/src/audit/auditFilters.js +60 -0
- package/dist/nodefony/src/audit/auditStoreRegistry.js +25 -0
- package/dist/nodefony/src/audit/readAuditContext.js +24 -0
- package/dist/nodefony/src/audit/recordAudit.js +16 -0
- package/dist/nodefony/src/authenticator/AnonymousAuthenticator.js +36 -0
- package/dist/nodefony/src/authenticator/ApiKeyAuthenticator.js +164 -0
- package/dist/nodefony/src/authenticator/ExternalJwtAuthenticator.js +224 -0
- package/dist/nodefony/src/authenticator/FirewallRealtimeAuthenticator.js +174 -0
- package/dist/nodefony/src/authenticator/JwtAuthenticator.js +176 -0
- package/dist/nodefony/src/authenticator/SessionAuthenticator.js +92 -0
- package/dist/nodefony/src/authenticator/UserPasswordAuthenticator.js +95 -0
- package/dist/nodefony/src/authenticator/authenticatorRegistry.js +63 -0
- package/dist/nodefony/src/authenticator/bearer.js +2 -0
- package/dist/nodefony/src/authenticator/externalSubject.js +36 -0
- package/dist/nodefony/src/authenticator/peekIssuer.js +56 -0
- package/dist/nodefony/src/crypto/secretCipher.js +79 -0
- package/dist/nodefony/src/csp.js +54 -0
- package/dist/nodefony/src/csrfToken.js +65 -0
- package/dist/nodefony/src/net/ssrfGuard.js +130 -0
- package/dist/nodefony/src/oauth/oauthProviderRegistry.js +37 -0
- package/dist/nodefony/src/oauth/providers/github.js +65 -0
- package/dist/nodefony/src/oauth/providers/oidc.js +48 -0
- package/dist/nodefony/src/realtime/UserRealtimeToken.js +94 -0
- package/dist/nodefony/src/realtime/frameAuthorizer.js +279 -0
- package/dist/nodefony/src/realtime/realtimeContracts.js +1 -0
- package/dist/nodefony/src/sessionIdentity.js +35 -0
- package/dist/nodefony/src/throttle/LoginThrottler.js +97 -0
- package/dist/nodefony/src/token/AnonymousToken.js +40 -0
- package/dist/nodefony/src/token/JwtKeystore.js +160 -0
- package/dist/nodefony/src/token/MemoryTokenStore.js +236 -0
- package/dist/nodefony/src/token/RemoteJwtVerifier.js +231 -0
- package/dist/nodefony/src/token/UserToken.js +67 -0
- package/dist/nodefony/src/token/jwtRuntime.js +19 -0
- package/dist/nodefony/src/token/secretFile.js +134 -0
- package/dist/nodefony/src/token/tokenCriteria.js +35 -0
- package/dist/nodefony/src/token/tokenFilters.js +72 -0
- package/dist/nodefony/src/token/tokenSort.js +40 -0
- package/dist/nodefony/src/token/tokenStatus.js +35 -0
- package/dist/nodefony/src/token/tokenStoreRegistry.js +25 -0
- package/dist/nodefony/src/totp/MemoryTotpSecretStore.js +97 -0
- package/dist/nodefony/src/totp/totpCipher.js +30 -0
- package/dist/nodefony/src/totp/totpCrypto.js +226 -0
- package/dist/nodefony/src/totp/totpOperations.js +129 -0
- package/dist/nodefony/src/totp/totpSecretStoreRegistry.js +18 -0
- package/dist/nodefony/src/voter/RoleVoter.js +32 -0
- package/dist/nodefony/src/voter/ScopeVoter.js +52 -0
- package/dist/nodefony/src/voter/voterRegistry.js +20 -0
- package/dist/nodefony/src/webauthn/MemoryWebAuthnCredentialStore.js +121 -0
- package/dist/nodefony/src/webauthn/webAuthnCredentialStoreRegistry.js +18 -0
- package/dist/nodefony/src/webhook/MemoryWebhookStore.js +87 -0
- package/dist/nodefony/src/webhook/WebhookDispatcher.js +208 -0
- package/dist/nodefony/src/webhook/webhookCipher.js +27 -0
- package/dist/nodefony/src/webhook/webhookDelivery.js +102 -0
- package/dist/nodefony/src/webhook/webhookFilters.js +56 -0
- package/dist/nodefony/src/webhook/webhookSignature.js +51 -0
- package/dist/nodefony/src/webhook/webhookSort.js +48 -0
- package/dist/nodefony/src/webhook/webhookStoreRegistry.js +18 -0
- package/dist/types/index.d.ts +157 -0
- package/dist/types/nodefony/command/security-secrets.d.ts +24 -0
- package/dist/types/nodefony/command/security-token.d.ts +44 -0
- package/dist/types/nodefony/command/security-user-add.d.ts +28 -0
- package/dist/types/nodefony/command/security-user-delete.d.ts +25 -0
- package/dist/types/nodefony/command/security-user-list.d.ts +28 -0
- package/dist/types/nodefony/config/config.d.ts +295 -0
- package/dist/types/nodefony/config/defineModuleConfig.d.ts +27 -0
- package/dist/types/nodefony/contracts/IAccessVoter.d.ts +23 -0
- package/dist/types/nodefony/contracts/IApiKey.d.ts +75 -0
- package/dist/types/nodefony/contracts/IAuditEvent.d.ts +94 -0
- package/dist/types/nodefony/contracts/IAuditStore.d.ts +80 -0
- package/dist/types/nodefony/contracts/IAuthenticator.d.ts +66 -0
- package/dist/types/nodefony/contracts/IAuthorizationService.d.ts +28 -0
- package/dist/types/nodefony/contracts/IFirewall.d.ts +64 -0
- package/dist/types/nodefony/contracts/IFirewallDescription.d.ts +120 -0
- package/dist/types/nodefony/contracts/IJwtKeystore.d.ts +40 -0
- package/dist/types/nodefony/contracts/IOAuthProvider.d.ts +51 -0
- package/dist/types/nodefony/contracts/ISecuredArea.d.ts +57 -0
- package/dist/types/nodefony/contracts/IToken.d.ts +41 -0
- package/dist/types/nodefony/contracts/ITokenStore.d.ts +240 -0
- package/dist/types/nodefony/contracts/ITotpSecret.d.ts +41 -0
- package/dist/types/nodefony/contracts/ITotpSecretStore.d.ts +88 -0
- package/dist/types/nodefony/contracts/IWebAuthnCredential.d.ts +56 -0
- package/dist/types/nodefony/contracts/IWebAuthnCredentialStore.d.ts +118 -0
- package/dist/types/nodefony/contracts/IWebhookEndpoint.d.ts +82 -0
- package/dist/types/nodefony/contracts/IWebhookStore.d.ts +85 -0
- package/dist/types/nodefony/contracts/index.d.ts +9 -0
- package/dist/types/nodefony/errors/AccessDeniedError.d.ts +10 -0
- package/dist/types/nodefony/errors/ApiKeyError.d.ts +17 -0
- package/dist/types/nodefony/errors/AuthenticationError.d.ts +10 -0
- package/dist/types/nodefony/errors/CsrfError.d.ts +19 -0
- package/dist/types/nodefony/errors/InvalidTargetError.d.ts +34 -0
- package/dist/types/nodefony/errors/SsrfError.d.ts +13 -0
- package/dist/types/nodefony/errors/ThrottledError.d.ts +16 -0
- package/dist/types/nodefony/errors/UnverifiableTokenError.d.ts +37 -0
- package/dist/types/nodefony/errors/WebAuthnError.d.ts +17 -0
- package/dist/types/nodefony/errors/index.d.ts +8 -0
- package/dist/types/nodefony/service/accessTokenVerifier.d.ts +29 -0
- package/dist/types/nodefony/service/apiKeys.d.ts +103 -0
- package/dist/types/nodefony/service/auditService.d.ts +30 -0
- package/dist/types/nodefony/service/authFlow.d.ts +123 -0
- package/dist/types/nodefony/service/authorization.d.ts +33 -0
- package/dist/types/nodefony/service/cors.d.ts +48 -0
- package/dist/types/nodefony/service/csrf.d.ts +57 -0
- package/dist/types/nodefony/service/firewall.d.ts +148 -0
- package/dist/types/nodefony/service/oauth2.d.ts +66 -0
- package/dist/types/nodefony/service/securityHeaders.d.ts +66 -0
- package/dist/types/nodefony/service/tokenService.d.ts +103 -0
- package/dist/types/nodefony/service/totp.d.ts +58 -0
- package/dist/types/nodefony/service/webAuthn.d.ts +123 -0
- package/dist/types/nodefony/service/webhooks.d.ts +160 -0
- package/dist/types/nodefony/src/RoleHierarchyWalker.d.ts +21 -0
- package/dist/types/nodefony/src/SecuredArea.d.ts +31 -0
- package/dist/types/nodefony/src/admin/SecurityAdminApi.d.ts +82 -0
- package/dist/types/nodefony/src/admin/WebhookAdminApi.d.ts +30 -0
- package/dist/types/nodefony/src/admin/adminAudit.d.ts +27 -0
- package/dist/types/nodefony/src/admin/userRevocationCascade.d.ts +31 -0
- package/dist/types/nodefony/src/apikey/apiKeyFormat.d.ts +43 -0
- package/dist/types/nodefony/src/audit/MemoryAuditStore.d.ts +33 -0
- package/dist/types/nodefony/src/audit/auditBridge.d.ts +49 -0
- package/dist/types/nodefony/src/audit/auditFilters.d.ts +56 -0
- package/dist/types/nodefony/src/audit/auditStoreRegistry.d.ts +37 -0
- package/dist/types/nodefony/src/audit/readAuditContext.d.ts +17 -0
- package/dist/types/nodefony/src/audit/recordAudit.d.ts +13 -0
- package/dist/types/nodefony/src/authenticator/AnonymousAuthenticator.d.ts +26 -0
- package/dist/types/nodefony/src/authenticator/ApiKeyAuthenticator.d.ts +74 -0
- package/dist/types/nodefony/src/authenticator/ExternalJwtAuthenticator.d.ts +132 -0
- package/dist/types/nodefony/src/authenticator/FirewallRealtimeAuthenticator.d.ts +78 -0
- package/dist/types/nodefony/src/authenticator/JwtAuthenticator.d.ts +69 -0
- package/dist/types/nodefony/src/authenticator/SessionAuthenticator.d.ts +70 -0
- package/dist/types/nodefony/src/authenticator/UserPasswordAuthenticator.d.ts +53 -0
- package/dist/types/nodefony/src/authenticator/authenticatorRegistry.d.ts +39 -0
- package/dist/types/nodefony/src/authenticator/bearer.d.ts +22 -0
- package/dist/types/nodefony/src/authenticator/externalSubject.d.ts +27 -0
- package/dist/types/nodefony/src/authenticator/peekIssuer.d.ts +31 -0
- package/dist/types/nodefony/src/crypto/secretCipher.d.ts +31 -0
- package/dist/types/nodefony/src/csp.d.ts +39 -0
- package/dist/types/nodefony/src/csrfToken.d.ts +36 -0
- package/dist/types/nodefony/src/net/ssrfGuard.d.ts +43 -0
- package/dist/types/nodefony/src/oauth/oauthProviderRegistry.d.ts +45 -0
- package/dist/types/nodefony/src/oauth/providers/github.d.ts +9 -0
- package/dist/types/nodefony/src/oauth/providers/oidc.d.ts +35 -0
- package/dist/types/nodefony/src/realtime/UserRealtimeToken.d.ts +62 -0
- package/dist/types/nodefony/src/realtime/frameAuthorizer.d.ts +171 -0
- package/dist/types/nodefony/src/realtime/realtimeContracts.d.ts +139 -0
- package/dist/types/nodefony/src/sessionIdentity.d.ts +20 -0
- package/dist/types/nodefony/src/throttle/LoginThrottler.d.ts +68 -0
- package/dist/types/nodefony/src/token/AnonymousToken.d.ts +23 -0
- package/dist/types/nodefony/src/token/JwtKeystore.d.ts +43 -0
- package/dist/types/nodefony/src/token/MemoryTokenStore.d.ts +66 -0
- package/dist/types/nodefony/src/token/RemoteJwtVerifier.d.ts +149 -0
- package/dist/types/nodefony/src/token/UserToken.d.ts +41 -0
- package/dist/types/nodefony/src/token/jwtRuntime.d.ts +28 -0
- package/dist/types/nodefony/src/token/secretFile.d.ts +70 -0
- package/dist/types/nodefony/src/token/tokenCriteria.d.ts +20 -0
- package/dist/types/nodefony/src/token/tokenFilters.d.ts +76 -0
- package/dist/types/nodefony/src/token/tokenSort.d.ts +33 -0
- package/dist/types/nodefony/src/token/tokenStatus.d.ts +38 -0
- package/dist/types/nodefony/src/token/tokenStoreRegistry.d.ts +38 -0
- package/dist/types/nodefony/src/totp/MemoryTotpSecretStore.d.ts +43 -0
- package/dist/types/nodefony/src/totp/totpCipher.d.ts +9 -0
- package/dist/types/nodefony/src/totp/totpCrypto.d.ts +164 -0
- package/dist/types/nodefony/src/totp/totpOperations.d.ts +73 -0
- package/dist/types/nodefony/src/totp/totpSecretStoreRegistry.d.ts +27 -0
- package/dist/types/nodefony/src/voter/RoleVoter.d.ts +25 -0
- package/dist/types/nodefony/src/voter/ScopeVoter.d.ts +30 -0
- package/dist/types/nodefony/src/voter/voterRegistry.d.ts +33 -0
- package/dist/types/nodefony/src/webauthn/MemoryWebAuthnCredentialStore.d.ts +39 -0
- package/dist/types/nodefony/src/webauthn/webAuthnCredentialStoreRegistry.d.ts +26 -0
- package/dist/types/nodefony/src/webhook/MemoryWebhookStore.d.ts +37 -0
- package/dist/types/nodefony/src/webhook/WebhookDispatcher.d.ts +69 -0
- package/dist/types/nodefony/src/webhook/webhookCipher.d.ts +8 -0
- package/dist/types/nodefony/src/webhook/webhookDelivery.d.ts +28 -0
- package/dist/types/nodefony/src/webhook/webhookFilters.d.ts +64 -0
- package/dist/types/nodefony/src/webhook/webhookSignature.d.ts +20 -0
- package/dist/types/nodefony/src/webhook/webhookSort.d.ts +39 -0
- package/dist/types/nodefony/src/webhook/webhookStoreRegistry.d.ts +31 -0
- package/docs/api-keys.md +691 -0
- package/docs/audit.md +751 -0
- package/docs/authenticators.md +487 -0
- package/docs/authorization.md +497 -0
- package/docs/cors.md +497 -0
- package/docs/csrf.md +392 -0
- package/docs/external-jwt.md +181 -0
- package/docs/firewall.md +546 -0
- package/docs/headers.md +616 -0
- package/docs/index.md +207 -0
- package/docs/lexique.md +190 -0
- package/docs/oauth2.md +575 -0
- package/docs/obtenir-un-jeton.md +225 -0
- package/docs/tokens.md +520 -0
- package/docs/totp.md +804 -0
- package/docs/webauthn.md +733 -0
- package/docs/webhooks.md +1016 -0
- package/package.json +83 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Obtenir un jeton — hors bande, sans serveur ni mot de passe"
|
|
3
|
+
navTitle: Obtenir un jeton
|
|
4
|
+
lang: fr
|
|
5
|
+
module: "@nodefony/security"
|
|
6
|
+
topic: obtenir-un-jeton
|
|
7
|
+
coverageModule: security
|
|
8
|
+
coverageFiles: "security-token,tokenService,secretFile"
|
|
9
|
+
section: "Sécurité"
|
|
10
|
+
audience: [developer, devops]
|
|
11
|
+
tags:
|
|
12
|
+
[
|
|
13
|
+
security,
|
|
14
|
+
mcp,
|
|
15
|
+
token,
|
|
16
|
+
cli,
|
|
17
|
+
bearer,
|
|
18
|
+
audience,
|
|
19
|
+
rfc8707,
|
|
20
|
+
rfc6749,
|
|
21
|
+
agent,
|
|
22
|
+
secrets,
|
|
23
|
+
]
|
|
24
|
+
version: "doc"
|
|
25
|
+
status: stable
|
|
26
|
+
updated: 2026-09-06
|
|
27
|
+
source: "src/packages/@nodefony/security/docs/obtenir-un-jeton.md"
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# Obtenir un jeton — hors bande, sans serveur ni mot de passe
|
|
31
|
+
|
|
32
|
+
> [tokens](tokens.md) décrit l'**émission par la porte HTTP** : un client présente un credential,
|
|
33
|
+
> l'application répond un couple access/refresh. Cette page décrit l'autre voie, celle dont un
|
|
34
|
+
> client MCP ou un script d'exploitation a besoin : **l'application signe elle-même un jeton, en
|
|
35
|
+
> ligne de commande**, sans qu'aucun serveur n'écoute et sans qu'aucun mot de passe ne transite.
|
|
36
|
+
> Ancré sur `src/packages/@nodefony/security/nodefony/command/security-token.ts`.
|
|
37
|
+
|
|
38
|
+
📍 [Documentation](../../../../../docs/index.md) › [Sécurité](index.md) › **Obtenir un jeton**
|
|
39
|
+
|
|
40
|
+
## 🧠 Le modèle mental — qui signe, pour quelle porte, pour combien de temps
|
|
41
|
+
|
|
42
|
+
Trois questions, et une seule commande y répond.
|
|
43
|
+
|
|
44
|
+
```mermaid
|
|
45
|
+
flowchart LR
|
|
46
|
+
A["nodefony security:token"] --> B{"L'application possède<br/>sa clé de signature"}
|
|
47
|
+
B --> C["Jeton signé pour<br/>UNE audience"]
|
|
48
|
+
C --> D["--write : posé où<br/>l'agent le lit"]
|
|
49
|
+
C --> E["--json : capturé<br/>par un script"]
|
|
50
|
+
C --> F["export NF_MCP_TOKEN=…<br/>dans le shell"]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Aucun serveur n'est en marche.** La commande démarre le noyau jusqu'à `onReady` — services prêts,
|
|
54
|
+
aucune écoute réseau (`security-token.ts:36`). C'est ce qui la rend utilisable quand l'application
|
|
55
|
+
ne tourne pas, en intégration continue, ou dans un conteneur d'amorçage.
|
|
56
|
+
|
|
57
|
+
**Le jeton vise une porte, et une seule.** L'audience est celle de la porte visée — la porte MCP par
|
|
58
|
+
défaut, `/nodefony/mcp` (`src/nodefony/src/mcp/protocol.ts:95`). Un jeton d'une autre audience est
|
|
59
|
+
refusé, et c'est toute la raison d'être de la liaison d'audience
|
|
60
|
+
([RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)).
|
|
61
|
+
|
|
62
|
+
## 📖 Lexique
|
|
63
|
+
|
|
64
|
+
- **MCP** — _Model Context Protocol_ : le protocole par lequel un agent d'intelligence artificielle
|
|
65
|
+
appelle les outils d'un logiciel. Sa porte est une route de votre application, pas un processus à
|
|
66
|
+
lancer.
|
|
67
|
+
- **Hors bande** — obtenu par un canal qui n'est pas celui qu'on va ensuite utiliser. Ici : le
|
|
68
|
+
jeton s'obtient au clavier, il servira sur HTTP.
|
|
69
|
+
- **Audience** — la ressource pour laquelle un jeton est valable. Déclarée par l'émetteur ; un
|
|
70
|
+
porteur ne choisit pas la sienne.
|
|
71
|
+
- **Scope** — un pouvoir nommé, porté par le jeton. `admin:read` lit, `admin:write` mute
|
|
72
|
+
(`src/nodefony/src/kernel/adminPlane/adminCaller.ts:53`).
|
|
73
|
+
|
|
74
|
+
## Qu'est-ce que ça résout — la faille du `curl` avec mot de passe
|
|
75
|
+
|
|
76
|
+
Le jeton s'obtenait par un appel au grant : trouver l'URL, composer un JSON, y mettre un mot de
|
|
77
|
+
passe **en clair dans l'historique du shell**, et surtout avoir un serveur en marche. Trois défauts,
|
|
78
|
+
et le troisième suffit à tout bloquer : dans une application neuve, on veut le jeton **avant** que
|
|
79
|
+
quoi que ce soit ne réponde.
|
|
80
|
+
|
|
81
|
+
L'application possède sa clé de signature ; elle n'a personne à qui demander. Donc : pas de serveur,
|
|
82
|
+
pas de mot de passe, pas de réseau — et rien à effacer d'un historique.
|
|
83
|
+
|
|
84
|
+
## 🚀 Démarrage rapide
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# 1) Le jeton, pour la porte MCP de cette application
|
|
88
|
+
npx nodefony security:token
|
|
89
|
+
|
|
90
|
+
# 2) Le poser là où l'agent le lit — jamais dans un fichier suivi par git
|
|
91
|
+
npx nodefony security:token --write
|
|
92
|
+
|
|
93
|
+
# 3) Pour un script : la sortie machine
|
|
94
|
+
npx nodefony security:token --json
|
|
95
|
+
# {
|
|
96
|
+
# "access_token": "eyJ…",
|
|
97
|
+
# "resource": "http://localhost:5151/nodefony/mcp",
|
|
98
|
+
# "scopes": ["admin:read"],
|
|
99
|
+
# "requested": ["admin:read"],
|
|
100
|
+
# "expires_in": 900
|
|
101
|
+
# }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Sans `--write` et dans un terminal, la commande **propose** de poser la valeur : un jeton de quatre
|
|
105
|
+
cents caractères ne se recopie pas à la main.
|
|
106
|
+
|
|
107
|
+
### Déclarer l'audience de la porte — le préalable
|
|
108
|
+
|
|
109
|
+
Un émetteur ne signe pas pour n'importe quelle ressource : les audiences sont une **liste blanche**
|
|
110
|
+
([RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)). Sans cette déclaration, la commande
|
|
111
|
+
refuse — c'est le premier refus qu'on rencontre dans une application neuve.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// nodefony.config.ts (extrait) — la porte pour laquelle cette application signe
|
|
115
|
+
use("@nodefony/security", {
|
|
116
|
+
jwt: {
|
|
117
|
+
// L'URI COMPLÈTE de la porte, pas seulement l'hôte : c'est elle que le
|
|
118
|
+
// porteur présentera, et c'est elle qui sera comparée.
|
|
119
|
+
audiences: ["http://localhost:5151/nodefony/mcp"],
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Puis `npm run build` — le runtime lit le `dist`, pas la source.
|
|
125
|
+
|
|
126
|
+
### Les options, et ce que chacune décide
|
|
127
|
+
|
|
128
|
+
| Option | Défaut | Ce qu'elle change |
|
|
129
|
+
| ---------------------- | ----------------------------- | -------------------------------------------------------- |
|
|
130
|
+
| `[identifier]` | `admin` | le compte porteur du jeton |
|
|
131
|
+
| `-s, --scope <liste>` | `admin:read` | les pouvoirs demandés — ajouter `admin:write` pour muter |
|
|
132
|
+
| `-r, --resource <uri>` | la porte MCP de l'application | viser une **autre** audience |
|
|
133
|
+
| `-a, --agent <noms>` | ceux détectés | quels agents servir — `none` pour aucun |
|
|
134
|
+
| `-t, --ttl <minutes>` | celle de la config (15 min) | la durée de validité, **bornée à 30 jours** |
|
|
135
|
+
| `-w, --write` | proposé en terminal | poser `NF_MCP_TOKEN` chez les agents présents |
|
|
136
|
+
| `-j, --json` | — | sortie machine, sans invite |
|
|
137
|
+
|
|
138
|
+
Le plafond de `--ttl` n'est pas décoratif : un jeton posé dans un fichier **est une clé**, et une
|
|
139
|
+
clé se remplace (`security-token.ts:52`, `security-token.ts:64-79`).
|
|
140
|
+
|
|
141
|
+
### Où `--write` pose la valeur
|
|
142
|
+
|
|
143
|
+
La variable est `NF_MCP_TOKEN` (`src/nodefony/src/cli/aiMcpReport.ts:32`). La commande ne sert que
|
|
144
|
+
les agents dont la présence est **constatée** dans le projet — on ne crée pas la configuration d'un
|
|
145
|
+
outil que personne n'utilise ici. La table des cibles vit au cœur
|
|
146
|
+
(`src/nodefony/src/cli/agentTargets.ts:239`) : Claude, Gemini, Vibe, Codex.
|
|
147
|
+
|
|
148
|
+
Deux garanties qui ne se négocient pas :
|
|
149
|
+
|
|
150
|
+
- **jamais dans un fichier suivi par git** — un jeton commité est un jeton publié, et c'est la seule
|
|
151
|
+
faute de cette commande qui serait irrattrapable ;
|
|
152
|
+
- **jamais par-dessus une valeur existante** — une rotation est un geste explicite, pas un effet de
|
|
153
|
+
bord.
|
|
154
|
+
|
|
155
|
+
Si aucun agent n'est reconnu, la commande le dit et donne le geste qui vaut pour tous :
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
export NF_MCP_TOKEN=<le jeton>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Vibe et Codex prennent le **nom** de la variable, pas le secret — la porte se déclare une fois :
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
vibe mcp add nodefony --transport streamable-http \
|
|
165
|
+
--url http://localhost:5151/nodefony/mcp --api-key-env NF_MCP_TOKEN
|
|
166
|
+
codex mcp add nodefony --url http://localhost:5151/nodefony/mcp \
|
|
167
|
+
--bearer-token-env-var NF_MCP_TOKEN
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Pour câbler `.mcp.json` d'un seul geste : `npx nodefony ai:mcp --auth`. La déclaration de la porte
|
|
171
|
+
appartient à [devkit](../../devkit/docs/index.md) ; cette page ne fait qu'émettre le porteur.
|
|
172
|
+
|
|
173
|
+
## 🔄 Renouveler — c'est réémettre, pas rafraîchir
|
|
174
|
+
|
|
175
|
+
Il n'y a pas de refresh token ici : ce jeton est signé hors bande, pour une porte, avec une durée
|
|
176
|
+
courte. Le renouveler, c'est **relancer la commande**. Et comme `--write` ne remplace jamais une
|
|
177
|
+
valeur en place, une rotation se demande :
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# 1) retirer l'ancienne valeur là où elle est posée (le fichier est nommé par la commande)
|
|
181
|
+
# 2) réémettre
|
|
182
|
+
npx nodefony security:token --write --ttl 1440
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Le flux de rotation **avec détection de rejeu** est celui des refresh tokens de la porte HTTP — il
|
|
186
|
+
est décrit dans [tokens](tokens.md), pas ici.
|
|
187
|
+
|
|
188
|
+
## ⚠️ Pièges (symptôme → cause → correction)
|
|
189
|
+
|
|
190
|
+
| Symptôme | Cause | Correction |
|
|
191
|
+
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
192
|
+
| `impossible d'émettre un jeton pour cette porte ici` | **en développement** : l'audience n'est pas déclarée à l'émetteur — c'est une liste blanche, pas un défaut ouvert | `use("@nodefony/security", { jwt: { audiences: ["<la porte>"] } })`, puis `npm run build` |
|
|
193
|
+
| Le même message, mais l'environnement affiché n'est pas `development` | la porte MCP est servie par un module `policy: "dev"` : **elle n'existe pas** dans cet environnement | `NODE_ENV=development npx nodefony security:token`, ou viser une autre porte avec `--resource` |
|
|
194
|
+
| Le jeton est émis, mais avec **moins** de scopes que demandé | l'émetteur retire ceux que ce porteur ne peut pas obtenir, et il le dit ([RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) §3.3) | lire le champ `scopes` de la sortie — c'est celui qui fait foi (`security-token.ts:494`) |
|
|
195
|
+
| L'agent reçoit `401` alors que le jeton vient d'être posé | la valeur a été écrite dans un dossier que **cet** agent ne lit pas | `--agent <nom>` pour viser explicitement, ou l'`export` dans le shell qui lance l'agent |
|
|
196
|
+
| `--write` ne fait rien et n'écrit aucun fichier | aucun agent n'est **constaté** dans ce projet | la commande liste alors les emplacements connus et donne la ligne d'`export` |
|
|
197
|
+
|
|
198
|
+
> 🔴 **Le premier réflexe est faux.** Devant un refus, on cherche un serveur éteint — la commande
|
|
199
|
+
> n'en utilise aucun. Le message écarte cette fausse piste dès sa deuxième ligne
|
|
200
|
+
> (`security-token.ts:456-484`) ; il a lui-même été corrigé pour cesser d'accuser une cause unique
|
|
201
|
+
> qu'il ne constatait pas.
|
|
202
|
+
|
|
203
|
+
## 🧪 Tests & couverture
|
|
204
|
+
|
|
205
|
+
- **unit** : `securityCommands.test.ts` couvre les deux règles pures de la commande — un jeton
|
|
206
|
+
**mort-né** doit s'annoncer avant d'être copié, et `--ttl` doit s'écrire en minutes, refuser une
|
|
207
|
+
valeur aberrante et se borner à 30 jours (`ttlSeconds` est exportée pour cela).
|
|
208
|
+
- **manque assumé** : l'écriture chez les agents (`--write`) n'a pas de banc de bout en bout — sa
|
|
209
|
+
garantie la plus forte, « jamais dans un fichier suivi par git », repose sur `git check-ignore` et
|
|
210
|
+
`git ls-files`, constatés à l'exécution et non simulés.
|
|
211
|
+
|
|
212
|
+
Les chiffres exacts vivent dans la carte de l'aperçu, régénérée depuis vitest — jamais figés ici.
|
|
213
|
+
Les bancs sur serveur réel se **skippent sans leurs variables d'infra**, et un skip compte comme
|
|
214
|
+
vert : lire ce que la suite déclare ne pas avoir exercé.
|
|
215
|
+
|
|
216
|
+
## 🔗 Pour aller plus loin
|
|
217
|
+
|
|
218
|
+
- ⬆️ **Retour au hub** : [Sécurité — vue d'ensemble](index.md) · [Toute la documentation](../../../../../docs/index.md)
|
|
219
|
+
- 🧭 **Pages sœurs** : [tokens](tokens.md) · [api-keys](api-keys.md) · [oauth2](oauth2.md)
|
|
220
|
+
|
|
221
|
+
- L'émission par la porte HTTP, la rotation et la révocation → [tokens](tokens.md)
|
|
222
|
+
- Les jetons opaques pour machines, montrés une seule fois → [api-keys](api-keys.md)
|
|
223
|
+
- La vérification du porteur et les zones qui l'exigent → [authenticators](authenticators.md) · [firewall](firewall.md)
|
|
224
|
+
- Ce qu'un scope autorise → [authorization](authorization.md)
|
|
225
|
+
- Déclarer la porte MCP et lui ajouter vos outils → [devkit](../../devkit/docs/index.md)
|