TW3 — Technologies du Web 3

🔒 ActivitĂ© Pratique : Mise en Place d’un SystĂšme d’Authentification BasĂ© sur des JWT

Dans cette activitĂ©, nous allons implĂ©menter un systĂšme d’authentification utilisant des JSON Web Tokens (JWT) avec Node.js et Express. Ce systĂšme permettra aux utilisateurs de s'inscrire, de se connecter et d'accĂ©der Ă  des routes protĂ©gĂ©es uniquement s'ils sont authentifiĂ©s via un JWT.

Objectif de l'activité

Nous allons construire une authentification JWT complÚte avec Node.js et Express : inscription, connexion, et protection de routes. Les utilisateurs accÚdent aux routes sécurisées uniquement s'ils présentent un JWT valide.


🔐 Étapes à Suivre

🔐 1. Initialisation du Projet

  1. Créer un nouveau projet Node.js :

    mkdir jwt-auth
    cd jwt-auth
    npm init -y
    npm install express bcrypt jsonwebtoken body-parser dotenv
  2. Configurer l’environnement :
    Créez un fichier .env à la racine pour y stocker des variables sensibles :

    JWT_SECRET=votre_secret_jwt
    PORT=3000

🔐 2. Structure des Fichiers

Organisez les fichiers comme suit :

jwt-auth/
├── app.js
├── .env
└── package.json

🔐 3. Écriture du Code

Fichier app.js :

const express = require('express');
const bodyParser = require('body-parser');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
require('dotenv').config();

const app = express();
app.use(bodyParser.json());

// Simuler une base de données
const users = [];

// Middleware pour vérifier les JWT
function authenticateToken(req, res, next) {
    const token = req.headers['authorization'] && req.headers['authorization'].split(' ')[1];
    if (!token) return res.status(401).send('AccÚs non autorisé : Aucun token fourni.');
    
    jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
        if (err) return res.status(403).send('Token invalide.');
        req.user = user;
        next();
    });
}

// Route d'inscription
app.post('/register', async (req, res) => {
    const { username, password } = req.body;
    if (!username || !password) return res.status(400).send('Nom d’utilisateur et mot de passe requis.');

    // Vérifier si l'utilisateur existe déjà
    const existingUser = users.find(user => user.username === username);
    if (existingUser) return res.status(400).send('Utilisateur déjà existant.');

    // Hacher le mot de passe
    const hashedPassword = await bcrypt.hash(password, 10);
    users.push({ username, password: hashedPassword });
    res.status(201).send('Utilisateur enregistré avec succÚs.');
});

// Route de connexion
app.post('/login', async (req, res) => {
    const { username, password } = req.body;
    const user = users.find(user => user.username === username);
    if (!user) return res.status(400).send('Nom d’utilisateur ou mot de passe incorrect.');

    // Vérifier le mot de passe
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) return res.status(400).send('Nom d’utilisateur ou mot de passe incorrect.');

    // Générer un JWT
    const token = jwt.sign({ username: user.username }, process.env.JWT_SECRET, { expiresIn: '1h' });
    res.json({ token });
});

// Route protégée
app.get('/protected', authenticateToken, (req, res) => {
    res.send(`Bienvenue ${req.user.username}, vous ĂȘtes authentifiĂ©.`);
});

// Démarrer le serveur
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Serveur en cours d’exĂ©cution sur http://localhost:${PORT}`);
});

🔐 4. Tester l’Application

  1. Démarrer le serveur :

    node app.js
  2. Inscription (POST /register) :
    Utilisez Postman ou curl pour envoyer une requĂȘte :

    POST http://localhost:3000/register
    Content-Type: application/json
    
    {
        "username": "testuser",
        "password": "password123"
    }

    Réponse attendue :

    Utilisateur enregistré avec succÚs.
  3. Connexion (POST /login) :
    Envoyez une requĂȘte pour obtenir un token JWT :

    POST http://localhost:3000/login
    Content-Type: application/json
    
    {
        "username": "testuser",
        "password": "password123"
    }

    Réponse attendue :

        {
        "token": "<votre_jwt>"
    }
  4. Accéder à une route protégée (GET /protected) :
    Ajoutez le token dans les headers de la requĂȘte :

    Authorization: Bearer <votre_jwt>

    Réponse attendue :

    Bienvenue testuser, vous ĂȘtes authentifiĂ©.
  5. Tester un Token Invalide :
    Remplacez le token par un faux ou un expiré, et observez la réponse 401 ou 403.


🔐 Explications Techniques

  1. bcrypt :
    UtilisĂ© pour hacher et vĂ©rifier les mots de passe afin qu’ils ne soient jamais stockĂ©s en clair.

  2. jsonwebtoken :

    • jwt.sign gĂ©nĂšre un token avec un payload (donnĂ©es utilisateur).
    • jwt.verify vĂ©rifie si un token est valide et non expirĂ©.
  3. Middleware authenticateToken :
    ProtĂšge les routes sensibles en exigeant un JWT valide dans les headers.

  4. Expiration du Token :
    Le token est configurĂ© pour expirer aprĂšs 1 heure (expiresIn: '1h'). Cela rĂ©duit le risque d’abus en cas de vol du token.


🔐 AmĂ©liorations Futures

  • Ajouter une base de donnĂ©es rĂ©elle (MongoDB, MySQL) pour stocker les utilisateurs.
  • GĂ©rer la rĂ©vocation de tokens via une liste noire.
  • Chiffrer les donnĂ©es sensibles dans les payloads JWT si nĂ©cessaire.
  • Utiliser HttpOnly et Secure pour transporter les JWT dans des cookies sĂ©curisĂ©s.

Ce systÚme vous donne une base solide pour implémenter un mécanisme d'authentification moderne basé sur des JWT, adaptable aux APIs REST ou aux microservices.

Vérification rapide

Quiz du chapitre

2 questions
0 / 2 répondue0%
  1. 1Dans cette activité, pourquoi le JWT_SECRET est-il stocké dans un fichier .env plutÎt que directement dans le code ?
  2. 2Dans cette activité JWT, quel rÎle joue le middleware de vérification appliqué aux routes protégées ?
Répondez à toutes les questions pour valider.

Authentification

Terminez le quiz du chapitre pour le marquer comme complété.

Tableau de bord

On this page