diff --git a/server.js b/server.js index 8a2adde..1c5c429 100644 --- a/server.js +++ b/server.js @@ -7,55 +7,84 @@ const jwt = require('jsonwebtoken'); const app = express(); app.use(express.json()); +const SECRET_KEY = "votre_clé_super_secrète_et_longue"; + // BDD simulée en mémoire const db = new sqlite3.Database(':memory:'); -db.serialize(() => { +db.serialize(async () => { db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)"); db.run("CREATE TABLE notes (id INTEGER PRIMARY KEY, user_id INTEGER, content TEXT)"); - // Mot de passe stocké en clair (Faille 1) - db.run("INSERT INTO users (username, password) VALUES ('admin', 'supersecret')"); - db.run("INSERT INTO users (username, password) VALUES ('alice', 'password123')"); + const passAdmin = await bcrypt.hash('supersecret', 10); + const passAlice = await bcrypt.hash('password123', 10); + const stmt = db.prepare("INSERT INTO users (username, password) VALUES (?, ?)"); + stmt.run('admin', passAdmin); + stmt.run('alice', passAlice); + stmt.finalize(); db.run("INSERT INTO notes (user_id, content) VALUES (2, 'Mon secret personnel')"); }); +function sendResponse(res, statusCode, data = null, message = '', error = null) { + res.status(statusCode).json({ + status: statusCode < 400 ? 'success' : 'error', + message: message, + data: data, + error: error + }); +} + +function authenticateToken(req, res, next) { + const authHeader = req.headers['authorization']; + const token = authHeader && authHeader.split(' ')[1]; + if (!token) return sendResponse(res, 401, null, '', 'Forgot token'); + jwt.verify(token, SECRET_KEY, (err, user) => { + if (err) return sendResponse(res,403,null, '', 'Erreur de connexion'); + req.user = user; + next(); + }); +} + +app.get('/', (req, res) => { + return sendResponse(res, 200, null, 'Bienvenue sur mon API !') +}) + // Route de connexion app.post('/login', (req, res) => { const { username, password } = req.body; - // Faille 2 : Injection SQL (Concaténation directe) - const query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"; - - db.get(query, (err, row) => { - if (err) return res.status(500).send(err.message); - if (row) { - res.json({ message: "Connecté", userId: row.id }); + const query = "SELECT * FROM users WHERE username = ?"; + db.get(query, [username], async (err, row) => { + if (err) return sendResponse(res, 500, null, '', "Erreur serveur"); + if (!row) return sendResponse(res, 401, null, '', "Identifiants incorrects"); + const match = await bcrypt.compare(password, row.password); + if (match) { + const token = jwt.sign({ id: row.id, username: row.username }, SECRET_KEY, { expiresIn: '1h' }); + sendResponse(res, 200, token, 'Connexion réussie !') + res.json({ token }); } else { - res.status(401).send("Échec"); + sendResponse(res, 401, null, '', "Identifiants incorrects"); } }); }); -// Route pour lire une note -app.get('/notes/:id', (req, res) => { - // Faille 3 : Broken Access Control (IDOR) - // On ne vérifie pas si la note appartient à l'utilisateur qui la demande - const query = `SELECT * FROM notes WHERE id = ${req.params.id}`; - db.get(query, (err, row) => { - if (row) { - // Faille 4 : XSS Réfléchi/Stocké (Pas d'échappement de la sortie) - res.send(`