Bonjour,

Je construis des applications qui demandent un système d'authentification. Cette authentification s'effectue bien sur côté serveur via une API dédiée, avec des endpoints login, me, et logout.

Le problème que je rencontre est le suivant : la connexion à mon application 1 se passe normalement avec le passage d'un cookie httponly, la connexion à mon application 2 se passe normalement, même process. La déconnexion de l'application 2 entraine la déconnexion de l'application 1 et inversement. Je pense que le cookie n'est pas assez discriminant, il possède un nom trop générique, du coup si j'utilise le même navigateur, il se passe ce que je décris plus haut.

Merci pour votre aide,

Sylvain

Je partage mon code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    static async login(req, res) {
        const userAgent = req.headers['user-agent'] || '';
        const ipAddress = req.ip || req.connection.remoteAddress || 'inconnue';
        const { identifiant, password } = req.body;
 
        const loginSchema = Joi.object({
            identifiant: Joi.string().trim().required(),
            password: Joi.string().required()
        });
 
        // Validation Joi
        const { error } = loginSchema.validate({ identifiant, password });
        if (error) {
            return res.status(400).json({ message: "Identifiant ou mot de passe manquant" });
        }
 
        try {
            // 1. Récupération de l'utilisateur
            const query = `
            SELECT 
                c.id_contributeur,
                c.nom_contributeur,
                c.identifiant,
                c.email,
                c.password,
                c.id_role
            FROM api_projet.contributeur c
            WHERE c.identifiant = $1
            `;
 
            const result = await pool.query(query, [identifiant]);
            if (result.rowCount === 0) {
            return res.status(401).json({ message: "Identifiant ou mot de passe incorrect" });
            }
 
            const utilisateur = result.rows[0];
 
            // 2. Vérification du mot de passe
            const passwordValid = await bcrypt.compare(password, utilisateur.password);
            if (!passwordValid) {
            return res.status(401).json({ message: "Identifiant ou mot de passe incorrect" });
            }
 
            // 3. Vérification de session existante pour ce user-agent
            const sessionCheck = await pool.query(
            `SELECT id_session FROM api_projet.sessions
            WHERE id_contributeur = $1 AND user_agent = $2`,
            [utilisateur.id_contributeur, userAgent]
            );
 
            if (sessionCheck.rowCount > 0) {
            return res.status(200).json({ message: "Déjà connecté sur ce navigateur." });
            }
 
            // 4. Création de la session
            const sessionId = crypto.randomUUID();
 
            await pool.query(
            `INSERT INTO api_projet.sessions (id_session, id_contributeur, ip_address, user_agent, expires_at)
            VALUES ($1, $2, $3, $4, NOW() + interval '7 days')`,
            [sessionId, utilisateur.id_contributeur, ipAddress, userAgent]
            );
 
            // 5. Cookie spécifique (évite collisions si plusieurs comptes connectés)
           const cookieName = `session_id_${utilisateur.id_contributeur}`;
 
            res.cookie(cookieName, sessionId, {
            httpOnly: true,
            secure: true,
            sameSite: "none",
            maxAge: 3 * 60 * 60 * 1000, // 3 heures
            path: "/"
            });
 
            return res.status(200).json({ message: "Connexion réussie" });
 
        } catch (err) {
            console.error("Erreur login :", err);
            return res.status(500).json({ message: "Erreur serveur lors de la connexion" });
        }
    };