@aventii/security (1.1.0)
Installation
@aventii:registry=npm install @aventii/security@1.1.0"@aventii/security": "1.1.0"About this package
@aventii/security
Primitives de sécurité communes aux services Aventii.
Ce package regroupe des mécanismes génériques de sécurité destinés à être partagés entre plusieurs microservices et plusieurs produits. Il ne contient aucune logique métier et ne dépend ni d'une base de données particulière, ni d'une topologie réseau, ni d'un service Aventii spécifique.
Installation
Le package est distribué sur le registre npm privé Aventii.
npm install @aventii/security
L'accès au registre nécessite une configuration npm Aventii valide.
Principes
Le package fournit des primitives configurables. Le service consommateur reste responsable de sa politique de sécurité et injecte les dépendances propres à son environnement.
Ainsi, @aventii/security peut connaître le mécanisme de vérification
d'un token sans connaître MongoDB, ou vérifier un Proof of Work sans
connaître les routes sur lesquelles celui-ci doit être exigé.
Tokens internes
createInternalTokenUtils fournit les mécanismes utilisés pour
authentifier les communications internes entre services.
const {
createInternalTokenUtils
} = require('@aventii/security');
const {
getAuthToken,
isValidToken,
checkAuthTokenValidity
} = createInternalTokenUtils({
secret: process.env.AUTH_TOKEN
});
Le secret est fourni par le consommateur.
Le token est dérivé par HMAC-SHA256 à partir du secret et d'une période temporelle. Une tolérance horaire peut être configurée afin d'accepter les périodes adjacentes.
const tokens = createInternalTokenUtils({
secret: process.env.AUTH_TOKEN,
toleranceHours: 1
});
Tokens utilisateur
createUserTokenVerifier vérifie les tokens utilisateur sans dépendre
de leur mécanisme de stockage.
const {
createUserTokenVerifier
} = require('@aventii/security');
const { verifyToken } = createUserTokenVerifier({
secret: process.env.HMAC_SECRET,
findToken: async payload => {
return tokenRepository.findById(payload._id);
}
});
Le package prend en charge :
- le format du token ;
- le décodage du payload ;
- la signature HMAC-SHA256 ;
- l'expiration ;
- la recherche du token persistant via une fonction injectée ;
- le contrôle optionnel du fingerprint ;
- l'instrumentation optionnelle des erreurs.
Le package ne connaît pas la base de données utilisée par le consommateur.
Fingerprint utilisateur
Le contrôle du fingerprint est optionnel.
const { verifyToken } = createUserTokenVerifier({
secret,
findToken,
enforceFingerprint: true,
generateFingerprint: req =>
generateFingerprintFromRequest(req)
});
Lorsque enforceFingerprint vaut true, generateFingerprint doit
être fourni.
Fingerprint
generateDeviceFingerprint génère une empreinte SHA-256 à partir de
données explicites.
const {
generateDeviceFingerprint
} = require('@aventii/security');
const fingerprint = generateDeviceFingerprint({
userAgent: 'Mozilla/5.0',
ip: '127.0.0.1',
timezone: 'Europe/Paris'
});
generateFingerprintFromRequest fournit un adaptateur pratique pour une
requête HTTP.
const {
generateFingerprintFromRequest
} = require('@aventii/security');
const fingerprint =
generateFingerprintFromRequest(req);
Le nom du header contenant le fuseau horaire peut être configuré.
generateFingerprintFromRequest(req, {
timezoneHeader: 'x-timezone'
});
Proof of Work
createProofOfWork fournit un mécanisme générique de vérification de
Proof of Work HTTP.
const {
createProofOfWork
} = require('@aventii/security');
const {
verifyProof,
proofOfWorkMiddleware,
maybePow
} = createProofOfWork({
difficulty: 3,
timestampToleranceMs: 15000
});
La difficulté peut être une valeur fixe :
difficulty: 3
ou une fonction :
difficulty: () => getCurrentPowLevel()
Le package ne décide pas quand le PoW doit être activé. Une fonction
skip peut être injectée par le consommateur.
createProofOfWork({
difficulty: 3,
skip: req =>
req.path.startsWith('/public/')
});
verifyProof permet de tester le mécanisme indépendamment d'Express.
Whitelist IP
createIpWhitelistMiddleware crée un middleware de restriction par
adresse IP.
const {
createIpWhitelistMiddleware
} = require('@aventii/security');
const ipWhitelist =
createIpWhitelistMiddleware({
allowedIps: [
'127.0.0.1',
'10.0.0.10'
]
});
Une fonction de normalisation peut être injectée :
createIpWhitelistMiddleware({
allowedIps,
normalizeIp: ip =>
ip.replace(/^::ffff:/, '')
});
Instrumentation
Les mécanismes qui peuvent produire des erreurs acceptent une instrumentation optionnelle.
createUserTokenVerifier({
secret,
findToken,
recordError,
incrementIpError
});
ou :
createProofOfWork({
recordError,
incrementIpError
});
L'absence d'instrumentation n'empêche pas le fonctionnement du package.
API
Le package expose :
createInternalTokenUtils
createUserTokenVerifier
generateDeviceFingerprint
generateFingerprintFromRequest
createProofOfWork
createIpWhitelistMiddleware
Les fonctions de création retournent des instances configurées pour le service consommateur.
Hors périmètre
@aventii/security ne décide pas :
- quelles routes sont publiques ou privées ;
- quelles routes nécessitent une authentification utilisateur ;
- quelles routes sont réservées aux administrateurs ;
- où sont stockés les tokens ;
- comment sont obtenus ou renouvelés les secrets ;
- quels microservices sont exposés sur le réseau ;
- quand une politique de PoW doit être activée ;
- comment les événements de sécurité sont persistés.
Ces décisions appartiennent au produit ou au service consommateur.
Tests
npm test
Les tests couvrent séparément les contrats des différentes primitives :
- tokens internes ;
- tokens utilisateur ;
- fingerprints ;
- Proof of Work ;
- whitelist IP.
Les dépendances propres aux applications consommatrices sont injectées et testées dans les applications concernées.
Dependencies
Development Dependencies
| ID | Version |
|---|---|
| jest | ^30.0.0 |