@falandyjean/lockbox-auth
v2.0.1
Published
🔐 Bibliothèque d'authentification complète avec système de rôles avancé (RBAC) pour Node.js/Express
Downloads
6
Maintainers
Readme
🔐 @falandy/lockbox-auth
Bibliothèque d'authentification moderne avec système de rôles basé sur des modèles pour Node.js/Express
🎯 Comment ça marche ? (Explication Complète)
🏗️ Architecture du Système
Lockbox-auth est un système d'authentification complet qui s'intègre dans votre application web comme une couche de sécurité intelligente. Voici comment ça fonctionne dans la vraie vie :
1. Dans votre site web
- Un utilisateur arrive sur votre site
- Il essaie d'accéder à une page protégée (ex:
/admin,/write-article) - Lockbox-auth intercepte la requête AVANT qu'elle n'atteigne votre code
- Il vérifie : "Est-ce que cet utilisateur a le bon rôle ?"
- ✅ Autorisé → L'utilisateur voit la page
- ❌ Refusé → Erreur 403 ou redirection vers login
2. Cycle de vie complet d'un utilisateur
👤 VISITEUR
↓ S'inscrit sur /auth/register
👤 UTILISATEUR CONNECTÉ (role: USER)
↓ Admin lui donne le rôle BLOG_WRITER
👤 RÉDACTEUR (peut écrire des articles)
↓ Promotion → rôle BLOG_EDITOR
👤 ÉDITEUR (peut écrire + modifier + supprimer)
↓ Promotion → rôle BLOG_CHIEF_EDITOR
👤 RÉDACTEUR EN CHEF (contrôle total du blog)3. Système de hiérarchie automatique
BLOG_CHIEF_EDITOR (niveau 15)
↓ peut faire tout ce que fait...
BLOG_EDITOR (niveau 10)
↓ peut faire tout ce que fait...
BLOG_WRITER (niveau 5)
↓ peut faire tout ce que fait...
BLOG_READER (niveau 1)💡 Magie de lockbox-auth : Si quelqu'un a le rôle BLOG_EDITOR, il peut automatiquement accéder aux pages BLOG_WRITER et BLOG_READER !
🔄 Workflow typique dans une vraie application
Étape 1 : Inscription
Utilisateur remplit un formulaire → POST /auth/register
↓
Lockbox-auth crée le compte + hash le mot de passe
↓
Utilisateur reçoit un email de confirmation (optionnel)
↓
Utilisateur peut se connecterÉtape 2 : Connexion
Utilisateur remplit login/password → POST /auth/login
↓
Lockbox-auth vérifie les identifiants
↓
Si OK : génère un JWT token (expire dans 1h)
↓
Renvoie { accessToken, refreshToken, user: {...} }
↓
Frontend stocke le token (localStorage/cookie)Étape 3 : Navigation protégée
Utilisateur clique sur "Écrire un article"
↓
Frontend fait GET /write-article
↓
Lockbox-auth intercepte et lit le token JWT
↓
Vérifie : "A-t-il le rôle BLOG_WRITER ou supérieur ?"
↓
OUI → Page s'affiche | NON → Erreur 403Étape 4 : Renouvellement automatique
Token expire (1h) → Frontend reçoit erreur 401
↓
Frontend utilise automatiquement le refreshToken
↓
POST /auth/refresh avec le refreshToken
↓
Lockbox-auth génère un nouveau accessToken
↓
Navigation continue sans interruption🎯 Pourquoi Choisir lockbox-auth ?
✅ Révolutionnaire : Système de Modèles
- Fini les centaines de rôles ! Choisissez seulement les modèles dont vous avez besoin
- Package plus léger : Importez uniquement ce que vous utilisez
- Plus simple à comprendre : Logique claire et modèles sectoriels
- Totalement modulaire : Créez vos propres modèles facilement
� Sécurité de niveau entreprise
- Hachage Argon2 (résistant aux GPU/ASIC)
- JWT + Refresh Tokens avec expiration automatique
- Protection CSRF intégrée
- Rate limiting sur les tentatives de connexion
- Mots de passe temporaires sécurisés
- Validation stricte des entrées utilisateur
⚡ Performance optimisée
- Middleware ultra-rapide (< 1ms de latence)
- Cache intelligent des rôles en mémoire
- Base de données optimisée avec Prisma
- Lazy loading des modèles de rôles
🎯 Utilisé dans la vraie vie
- Sites e-commerce : Gérer clients, vendeurs, admins
- Plateformes de contenu : Lecteurs, rédacteurs, éditeurs
- Applications SaaS : Utilisateurs gratuits, premium, support
- Intranets d'entreprise : Employés, managers, direction
�🔥 Comparaison : Ancien vs Nouveau
❌ Ancien système (statique) :
// Vous étiez forcé d'avoir TOUS ces rôles même si vous n'en utilisiez que 5
import { USER_ROLES } from 'lockbox-auth'; // 500+ rôles importés !
// BLOG_READER, HOSPITAL_SURGEON, BANK_TRADER, SCHOOL_STUDENT, etc.✅ Nouveau système (modèles) :
// Vous choisissez EXACTEMENT ce dont vous avez besoin
import { deployTemplate, BLOG_TEMPLATE } from 'lockbox-auth';
// En une ligne, vous déployez seulement les rôles blog
deployTemplate('BLOG', BLOG_TEMPLATE);🚀 Installation Ultra-Rapide
npm install @falandy/lockbox-auth
npx lockbox-init🏗️ Implémentation complète dans un site réel
Étape 1 : Configuration de base (2 minutes)
// server.js - Configuration Express + Lockbox
import express from 'express';
import {
deployTemplate,
BLOG_TEMPLATE,
createAuthRouter,
requireAuth,
requireRole
} from '@falandy/lockbox-auth';
const app = express();
app.use(express.json());
// 1. Déployer vos modèles de rôles
deployTemplate('BLOG', BLOG_TEMPLATE);
// 2. Configuration auth
const authConfig = {
jwtSecret: process.env.JWT_SECRET || 'your-secret-key',
refreshTTL: 7, // 7 jours
temporaryPassword: {
enabled: true,
length: 12,
expiryHours: 24,
},
};
// 3. Routes d'authentification automatiques
app.use('/auth', createAuthRouter(authConfig));
// Crée automatiquement : /auth/register, /auth/login, /auth/refresh, /auth/logout
app.listen(3000);Étape 2 : Pages frontend avec protection (5 minutes)
<!-- login.html - Page de connexion -->
<!DOCTYPE html>
<html>
<head>
<title>Connexion</title>
</head>
<body>
<form id="loginForm">
<input type="email" placeholder="Email" required>
<input type="password" placeholder="Mot de passe" required>
<button type="submit">Se connecter</button>
</form>
<script>
document.getElementById('loginForm').onsubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
try {
const response = await fetch('/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: formData.get('email'),
password: formData.get('password')
})
});
const data = await response.json();
if (response.ok) {
// Stocker les tokens
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
// Rediriger selon le rôle
if (data.user.role.includes('BLOG_WRITER')) {
window.location.href = '/write-article';
} else {
window.location.href = '/dashboard';
}
} else {
alert('Erreur: ' + data.message);
}
} catch (error) {
alert('Erreur de connexion');
}
};
</script>
</body>
</html>Étape 3 : Routes protégées par rôle
// server.js - Ajout des routes protégées
// 🌍 Pages publiques (accessibles à tous)
app.get('/', (req, res) => {
res.send('<h1>Accueil</h1><a href="/login.html">Se connecter</a>');
});
// 🔒 Pages protégées (connexion requise)
app.get('/dashboard', requireAuth(authConfig.jwtSecret), (req, res) => {
res.json({
message: `Bienvenue ${req.user.email}`,
role: req.user.role,
canWrite: req.user.role.includes('BLOG_WRITER')
});
});
// ✍️ Zone rédaction (rôle BLOG_WRITER minimum)
app.get('/write-article', requireRole('BLOG_WRITER'), (req, res) => {
res.send(`
<h1>Zone de rédaction</h1>
<p>Bonjour ${req.user.email}, vous pouvez écrire des articles</p>
<form method="POST" action="/api/articles">
<textarea name="content" placeholder="Votre article..."></textarea>
<button type="submit">Publier</button>
</form>
`);
});
// 🛠️ Zone d'édition (rôle BLOG_EDITOR minimum)
app.get('/manage-articles', requireRole('BLOG_EDITOR'), (req, res) => {
res.send(`
<h1>Gestion des articles</h1>
<p>Vous pouvez modifier et supprimer tous les articles</p>
<ul>
<li>Article 1 <button onclick="deleteArticle(1)">Supprimer</button></li>
<li>Article 2 <button onclick="deleteArticle(2)">Supprimer</button></li>
</ul>
`);
});
// 👑 Zone admin (rôle BLOG_CHIEF_EDITOR)
app.get('/admin', requireRole('BLOG_CHIEF_EDITOR'), (req, res) => {
res.send(`
<h1>Administration</h1>
<p>Contrôle total du système</p>
<button onclick="promoteUser()">Promouvoir un utilisateur</button>
<button onclick="viewStats()">Voir les statistiques</button>
`);
});
// 📝 API pour créer des articles
app.post('/api/articles', requireRole('BLOG_WRITER'), async (req, res) => {
// req.user contient automatiquement les infos de l'utilisateur connecté
const article = {
title: req.body.title,
content: req.body.content,
authorId: req.user.id,
authorEmail: req.user.email, createdAt: new Date()
};
res.json({ message: 'Article créé !', article });
});Étape 4 : Middleware JavaScript pour le frontend
// auth.js - Middleware côté client
class AuthManager {
constructor() {
this.token = localStorage.getItem('accessToken');
this.refreshToken = localStorage.getItem('refreshToken');
}
// Faire une requête authentifiée
async fetch(url, options = {}) {
const headers = {
'Content-Type': 'application/json',
...options.headers
};
if (this.token) {
headers['Authorization'] = `Bearer ${this.token}`;
}
let response = await fetch(url, { ...options, headers });
if (response.status === 401 && this.refreshToken) {
const renewed = await this.renewToken();
if (renewed) {
headers['Authorization'] = `Bearer ${this.token}`;
response = await fetch(url, { ...options, headers });
}
}
return response;
}
// Renouveler le token automatiquement
async renewToken() {
try {
const response = await fetch('/auth/refresh', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken: this.refreshToken })
});
if (response.ok) {
const data = await response.json();
this.token = data.accessToken;
localStorage.setItem('accessToken', data.accessToken);
return true;
}
} catch (error) { console.error('Erreur renouvellement token:', error);
}
this.logout();
return false;
}
// Déconnexion
logout() {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
window.location.href = '/login.html';
}
// Vérifier si l'utilisateur a un rôle
async hasRole(role) {
try {
const response = await this.fetch('/auth/me');
if (response.ok) {
const user = await response.json();
return user.role.includes(role);
}
} catch (error) {
console.error('Erreur vérification rôle:', error);
}
return false;
}
}
// Instance globale
const auth = new AuthManager();
// Utilisation dans vos pages
document.addEventListener('DOMContentLoaded', async () => {
// Cacher/afficher des éléments selon le rôle
if (await auth.hasRole('BLOG_WRITER')) {
document.getElementById('writeButton').style.display = 'block';
}
if (await auth.hasRole('BLOG_EDITOR')) {
document.getElementById('adminPanel').style.display = 'block';
}
});Étape 5 : Gestion avancée des utilisateurs
// admin-routes.js - Routes pour gérer les utilisateurs
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Promouvoir un utilisateur
app.post('/admin/promote-user', requireRole('BLOG_CHIEF_EDITOR'), async (req, res) => {
try {
const { userId, newRole } = req.body;
const updatedUser = await prisma.user.update({
where: { id: userId },
data: { role: newRole }
});
res.json({
message: `Utilisateur promu au rôle ${newRole}`,
user: updatedUser
});
} catch (error) {
res.status(500).json({ error: 'Erreur promotion utilisateur' });
}
});
// Lister tous les utilisateurs avec leurs rôles
app.get('/admin/users', requireRole('BLOG_EDITOR'), async (req, res) => {
try {
const users = await prisma.user.findMany({
select: {
id: true,
email: true,
role: true,
createdAt: true,
lastLoginAt: true
}
});
res.json({ users });
} catch (error) {
res.status(500).json({ error: 'Erreur récupération utilisateurs' });
}
});
// Statistiques du site
app.get('/admin/stats', requireRole('BLOG_CHIEF_EDITOR'), async (req, res) => {
try {
const stats = {
totalUsers: await prisma.user.count(),
usersByRole: await prisma.user.groupBy({
by: ['role'],
_count: { role: true }
}),
totalArticles: await prisma.article?.count() || 0,
recentLogins: await prisma.user.count({
where: {
lastLoginAt: {
gte: new Date(Date.now() - 24 * 60 * 60 * 1000) // 24h
}
}
})
};
res.json({ stats });
} catch (error) {
res.status(500).json({ error: 'Erreur récupération statistiques' });
}
});🎨 Usage par Secteur
📝 Blog/Média
import { deployTemplate, BLOG_TEMPLATE, requireAuth } from '@falandy/lockbox-auth';
// Déployer le modèle blog
deployTemplate('BLOG', BLOG_TEMPLATE);
// Utiliser les rôles
app.get('/write-article', requireRole('BLOG_WRITER'), (req, res) => {
// Seuls les rédacteurs peuvent écrire
});🛒 E-commerce
import { deployTemplate, ECOMMERCE_TEMPLATE } from '@falandy/lockbox-auth';
// Déployer le modèle e-commerce
deployTemplate('SHOP', ECOMMERCE_TEMPLATE);🏥 Hôpital
import { deployTemplate, HOSPITAL_TEMPLATE } from '@falandy/lockbox-auth';
deployTemplate('HOSPITAL', HOSPITAL_TEMPLATE);🎓 École/Université
import { deployTemplate, SCHOOL_TEMPLATE } from '@falandy/lockbox-auth';
deployTemplate('SCHOOL', SCHOOL_TEMPLATE);📦 Modèles Disponibles
| Secteur | Modèle | Rôles Inclus |
|---------|--------|--------------|
| 📝 Média | BLOG_TEMPLATE | READER, WRITER, EDITOR, CHIEF_EDITOR |
| 📺 Journalisme | JOURNALISM_TEMPLATE | READER, JOURNALIST, PHOTOGRAPHER, EDITOR_IN_CHIEF |
| 🎥 Streaming | STREAMING_TEMPLATE | VIEWER, STREAMER, MODERATOR, PLATFORM_ADMIN |
| 🛒 E-commerce | ECOMMERCE_TEMPLATE | CUSTOMER, VENDOR, STORE_MANAGER, MARKETPLACE_ADMIN |
| 🏪 Marketplace | MARKETPLACE_TEMPLATE | BUYER, SELLER, AFFILIATE, PLATFORM_OWNER |
| 🎓 École | SCHOOL_TEMPLATE | STUDENT, TEACHER, PRINCIPAL, SUPERINTENDENT |
| 🏛️ Université | UNIVERSITY_TEMPLATE | STUDENT, PROFESSOR, DEAN, CHANCELLOR |
| 🏥 Hôpital | HOSPITAL_TEMPLATE | PATIENT, NURSE, DOCTOR, MEDICAL_DIRECTOR |
| 🍽️ Restaurant | RESTAURANT_TEMPLATE | CUSTOMER, SERVER, CHEF, OWNER |
| 🏨 Hôtel | HOTEL_TEMPLATE | GUEST, RECEPTIONIST, MANAGER, OWNER |
| 🚚 Livraison | DELIVERY_TEMPLATE | CUSTOMER, DRIVER, DISPATCHER, OPERATIONS_MANAGER |
| 💻 SaaS | SAAS_TEMPLATE | FREE_USER, PREMIUM_USER, SUPPORT_AGENT, PLATFORM_ADMIN |
| 🎮 Gaming | GAMING_TEMPLATE | PLAYER, STREAMER, MODERATOR, GAME_MASTER |
| 🏦 Banque | BANK_TEMPLATE | CUSTOMER, ADVISOR, MANAGER, DIRECTOR |
| 🏛️ Gouvernement | GOVERNMENT_TEMPLATE | CITIZEN, EMPLOYEE, MANAGER, DIRECTOR |
💡 Utilisation Avancée
🔧 Créer un Modèle Personnalisé
import { CustomRole, deployTemplate } from '@falandy/lockbox-auth';
// Définir vos rôles personnalisés
const myCustomRoles: CustomRole[] = [
{ key: 'VISITOR', value: 'VISITOR', level: 1, description: 'Visiteur' },
{ key: 'MEMBER', value: 'MEMBER', level: 5, description: 'Membre' },
{ key: 'PREMIUM', value: 'PREMIUM', level: 8, description: 'Membre premium' },
{ key: 'ADMIN', value: 'ADMIN', level: 15, description: 'Administrateur' },
];
// Déployer votre modèle
deployTemplate('MYAPP', myCustomRoles);🔄 Combiner Plusieurs Modèles
// Déployer plusieurs modèles pour une app complexe
deployTemplate('BLOG', BLOG_TEMPLATE);
deployTemplate('SHOP', ECOMMERCE_TEMPLATE);
deployTemplate('SUPPORT', SAAS_TEMPLATE);
// Maintenant vous avez tous ces rôles :
// BLOG_WRITER, SHOP_VENDOR, SUPPORT_AGENT, etc.📊 Gestion Avancée des Rôles
import {
getDeployedRoles,
getActiveTemplates,
getRoleStats,
hasRolePermission
} from '@falandy/lockbox-auth';
// Voir tous les rôles déployés
console.log(getDeployedRoles());
// Voir les modèles actifs
console.log(getActiveTemplates());
console.log(getRoleStats());
const canEdit = hasRolePermission('BLOG_WRITER', 'BLOG_READER');🔐 Authentification Complète
import express from 'express';
import {
createAuthRouter,
requireAuth,
requireRole,
deployTemplate,
BLOG_TEMPLATE,
} from '@falandy/lockbox-auth';
const app = express();
// 1. Déployer vos modèles
deployTemplate('BLOG', BLOG_TEMPLATE);
// 2. Configuration auth
const authConfig = {
jwtSecret: process.env.JWT_SECRET!,
refreshTTL: 7, // 7 jours
temporaryPassword: {
enabled: true,
length: 12,
expiryHours: 24,
},
};
// 3. Routes d'authentification
app.use('/auth', createAuthRouter(authConfig));
// 4. Routes protégées
app.get('/profile', requireAuth(authConfig.jwtSecret), (req, res) => {
res.json({ user: req.user });
});
app.get('/write', requireRole('BLOG_WRITER'), (req, res) => {
res.json({ message: 'Zone de rédaction' });
});
app.get('/admin', requireRole('BLOG_CHIEF_EDITOR'), (req, res) => {
res.json({ message: 'Zone d\'administration' });
});⚡ Configuration Rapide
📋 Variables d'Environnement
# .env
JWT_SECRET=your-super-secret-key
LOCKBOX_COMPANY_NAME="Mon Entreprise"
LOCKBOX_EMAIL_FROM="[email protected]"
# Email (optionnel)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
[email protected]
SMTP_PASSWORD=your-app-password🗄️ Base de Données (Prisma)
# Initialiser Prisma
npx prisma init
npx prisma migrate dev�️ Interface CLI
Lockbox Auth inclut un CLI puissant pour gérer vos modèles et configurations depuis le terminal :
# Voir l'état de vos rôles
lockbox-auth status
# Afficher les informations du package
lockbox-auth info
# Exporter votre configuration
lockbox-auth export ./backup-roles.json
# Synchroniser la base de données
lockbox-auth db-sync
# Réinitialiser tous les rôles
lockbox-auth reset-all🎯 Avantages du CLI
- Surveillance en temps réel de vos rôles déployés
- Sauvegarde/restauration facile de vos configurations
- Debug rapide pour voir l'état du système
- Synchronisation DB en une commande
�📚 Documentation Complète
- 🚀 Guide de Démarrage Rapide
- 🎨 Modèles Sectoriels
- 🔧 Rôles Personnalisés
- 🖥️ Utilisation du CLI
- 📧 Configuration Email
- 🔑 Mots de Passe Temporaires
- 🚀 Déploiement
- 📖 Référence Rapide
🌟 Avantages du Système de Modèles
✅ Avant lockbox-auth
- ❌ Créer un système de rôles from scratch
- ❌ Gérer manuellement les hiérarchies
- ❌ Coder les middlewares d'autorisation
- ❌ Écrire les fonctions de validation
- ❌ Temps : 2-3 semaines
🚀 Avec lockbox-auth
- ✅
deployTemplate('BLOG', BLOG_TEMPLATE)- 1 ligne - ✅ Hiérarchies automatiques
- ✅ Middlewares inclus
- ✅ Validation intégrée
- ✅ Temps : 5 minutes
🛠️ Migration depuis l'Ancien Système
Si vous utilisiez l'ancienne version avec USER_ROLES statique :
// ❌ Ancien (ne marche plus)
import { USER_ROLES } from '@falandy/lockbox-auth';
// ✅ Nouveau (recommandé)
import { deployTemplate, BLOG_TEMPLATE } from '@falandy/lockbox-auth';
deployTemplate('BLOG', BLOG_TEMPLATE);🤝 Contribuer
git clone https://github.com/falandy/lockbox-auth
cd lockbox-auth
npm install
npm run dev📄 Licence
MIT © Falandy
🎉 Application Blog Complète - Configuration Rapide
import express from 'express';
import { deployTemplate, BLOG_TEMPLATE, createAuthRouter, requireRole } from '@falandy/lockbox-auth';
const app = express();
app.use(express.json());
// 1. Déployer le modèle blog
deployTemplate('BLOG', BLOG_TEMPLATE);
// 2. Configuration
const authConfig = { jwtSecret: 'secret', refreshTTL: 7 };
// 3. Routes
app.use('/auth', createAuthRouter(authConfig));
// 4. Routes protégées
app.get('/articles', requireRole('BLOG_READER'), (req, res) => {
res.json({ articles: ['Article 1', 'Article 2'] });
});
app.post('/articles', requireRole('BLOG_WRITER'), (req, res) => {
res.json({ message: 'Article créé !' });
});
app.delete('/articles/:id', requireRole('BLOG_EDITOR'), (req, res) => {
res.json({ message: 'Article supprimé !' });
});
app.listen(3000);
console.log('🚀 App blog avec système de rôles en quelques lignes !');Vous obtenez une authentification complète avec système de rôles hiérarchiques rapidement et efficacement. 🎉
