feat: add permanent API keys for users

- Add api_key column to users table with auto-migration
- Modify auth middleware to accept both JWT (24h) and API keys (permanent)
- Add endpoints: GET/POST/DELETE /api/users/:id/api-key
- Update admin panel with API key management (generate, copy, regenerate, revoke)
- Update API documentation modal to show permanent API key usage

API keys use the format: nf_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Use header: X-API-Key: <your-key>
This commit is contained in:
Claude committed 2025-12-21 10:28:49 +00:00
1 parent 64ba174074
commit 239232c33c
5 files changed
+326 -28

No files matched your search

+34 -4
View File
@@ -1,6 +1,7 @@
// Middleware d'authentification JWT
// Middleware d'authentification JWT et API Key
const jwt = require('jsonwebtoken');
const logger = require('../config/logger');
const { getOne } = require('../config/database');
const JWT_SECRET = process.env.JWT_SECRET || 'change_me_in_production_please_use_strong_secret';
@@ -9,14 +10,42 @@ if (JWT_SECRET === 'change_me_in_production_please_use_strong_secret' && process
}
/**
* Middleware pour vérifier le token JWT
* Middleware pour vérifier le token JWT ou la clé API
* Supporte:
* - Header "Authorization: Bearer TOKEN" (JWT, expire après 24h)
* - Header "X-API-Key: API_KEY" (clé permanente)
*/
function authenticateToken(req, res, next) {
async function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const apiKey = req.headers['x-api-key'];
// Option 1: Clé API permanente (prioritaire)
if (apiKey) {
try {
const user = await getOne(
'SELECT id, username, is_admin FROM users WHERE api_key = $1',
[apiKey]
);
if (!user) {
logger.warn(`Tentative d'accès avec clé API invalide`);
return res.status(403).json({ error: 'Clé API invalide' });
}
req.user = user;
req.authType = 'api_key';
return next();
} catch (error) {
logger.error('Erreur lors de la vérification de la clé API:', error);
return res.status(500).json({ error: 'Erreur serveur' });
}
}
// Option 2: Token JWT
const token = authHeader && authHeader.split(' ')[1]; // Format: "Bearer TOKEN"
if (!token) {
return res.status(401).json({ error: 'Token d\'authentification manquant' });
return res.status(401).json({ error: 'Token d\'authentification ou clé API manquant' });
}
jwt.verify(token, JWT_SECRET, (err, user) => {
@@ -27,6 +56,7 @@ function authenticateToken(req, res, next) {
// Ajouter les informations utilisateur à la requête
req.user = user;
req.authType = 'jwt';
next();
});
}