Code QR
Des codes QR animés sont utilisés avec ExcelID quand l’utilisateur visite votre service sur un appareil, par exemple un ordinateur, mais utilise ExcelID sur un autre, son téléphone. Le parcours est le suivant :
- Votre service génère un code QR.
- Votre service le présente à l’utilisateur.
- L’utilisateur le scanne avec son application ExcelID.
Si le code est valide, l’application poursuit la demande.
Animation et délais
Pour renforcer la sécurité, on utilise des codes QR animés : votre service met à jour le code en continu, ce qui rend la fraude à distance plus difficile.
- Votre service doit mettre à jour le code QR chaque seconde.
- Les codes doivent être générés en continu, pas à l’avance : une génération anticipée réduirait la sécurité.
- La demande envoyée à notre serveur reste valable 180 secondes : l’utilisateur doit scanner le code dans ce délai. Pour une durée d’affichage plus longue, créez de nouvelles demandes.
- Quand l’utilisateur approche de la fin du délai, offrez-lui la possibilité de prolonger. Prolonger exige de créer une nouvelle demande.
Accessibilité
- Le code QR doit être un élément
<button>. - Appuyer sur le code doit l’ouvrir en plein écran.
- Ajoutez un texte alternatif qui indique que c’est un code QR et qu’il est cliquable.
- Vérifiez que des éléments fixes (sticky) n’empêchent pas d’interagir avec le code QR et les autres éléments.
Génération du code QR
Les codes QR sont générés chez vous. De nombreuses bibliothèques tierces existent. Pour la génération, utilisez le schéma excelid.qrStartToken.time.qrAuthCode comme contenu du code QR, où :
excelidest un préfixe fixe ;qrStartTokenvient de la réponse de/authou/sign;timeest le nombre de secondes écoulées depuis la création de la demande ;qrAuthCodevautHMACSHA256(qrStartSecret, time), en hexadécimal minuscule, oùqrStartSecretvient de la réponse de/authou/sign.
qrStartSecret ne doit pas être envoyé à votre frontend. C’est un secret partagé uniquement entre le service ExcelID et votre backend.
Conseils et recommandations
- Le code est lu sur un écran : le niveau de correction d’erreur peut être bas.
- Réduisez les couleurs au minimum ; nous recommandons le noir.
- N’inversez jamais les couleurs, y compris en mode sombre : le scan serait plus difficile.
- Laissez une marge pour renforcer le contraste.
- N’ajoutez pas d’autres informations ni de graphiques (logo superposé).
Si le code QR est trop ancien, l’application le refuse : vous devez créer une nouvelle demande et l’utilisateur doit recommencer. ExcelID accepte un code dont le temps est au plus 2 secondes en avance et 10 secondes en retard sur le temps réel de la demande.
Exemple
Si le qrStartToken est a41d8e0b-52c7-4d39-9e66-0b7c2f1a8d54 et le qrStartSecret est 0c9b7a1e-6d58-4f0b-a2b3-9d41e6c8f7a5, alors :
| Temps | Contenu du code QR |
|---|---|
| 0 s | excelid.a41d8e0b-52c7-4d39-9e66-0b7c2f1a8d54.0.2eaf777f169f8a7add2fc1c1180275de11226dfdc6ea59fe8fc4a15942b09747 |
| 1 s | excelid.a41d8e0b-52c7-4d39-9e66-0b7c2f1a8d54.1.c95bffa08846f84d2ebfe173c3e23fc04d956caff73252f6e189ad7c7a2c2fc7 |
| 2 s | excelid.a41d8e0b-52c7-4d39-9e66-0b7c2f1a8d54.2.303d9075e4ec91fb02731202942e819b0d18e6cefd92ce81400682bb2fcbde9e |
Calculer le code sur votre serveur
import { createHmac } from 'node:crypto';
// order = réponse de /auth ; startedAt = Date.now() au moment de la réponse
function qrData(order, startedAt) {
const time = Math.floor((Date.now() - startedAt) / 1000);
const code = createHmac('sha256', order.qrStartSecret).update(String(time)).digest('hex');
return `excelid.${order.qrStartToken}.${time}.${code}`;
}
// Route appelée chaque seconde par la page : elle ne renvoie que le texte du code
app.get('/login/:id/qr', (req, res) => {
const session = sessions.get(req.params.id);
if (!session) return res.sendStatus(404);
res.json({ qr: qrData(session.order, session.startedAt) });
});