Blog
Feature
6 février 20269 min

Auth QR code : le pattern WhatsApp Web avec Supabase

Pour connecter le site web à l'app mobile, je voulais quelque chose d'instantané. Pas de formulaire, pas de mot de passe à retaper. Le pattern WhatsApp Web : scanner un QR code et boom, connecté. Voici comment j'ai implémenté ce système dans TAMSIV avec Supabase Realtime, un fallback polling, et une UX qui impressionne.

Points clés à retenir :
- Le QR code encode un UUID de session unique — le site s'abonne en temps réel via Supabase Realtime.
- Un fallback polling HTTP (toutes les 2s) prend le relais si le Realtime échoue après 3 secondes.
- Le QR code expire après 5 minutes et se régénère automatiquement à 4min30 avec countdown visuel.
- L'ensemble du système tient en 300 lignes côté web et 150 côté mobile.

Pourquoi choisir l'authentification par QR code plutôt qu'un formulaire classique ?

L'authentification classique — email + mot de passe — fonctionne. Mais elle crée de la friction. L'utilisateur a déjà un compte sur l'app mobile. Lui demander de retaper ses identifiants sur le web, c'est l'obliger à se souvenir d'un mot de passe, potentiellement chercher dans son gestionnaire, et risquer un échec.

Le QR code élimine cette friction. L'utilisateur est déjà authentifié sur son téléphone. Scanner un code prend 2 secondes. C'est le pattern popularisé par WhatsApp Web, Telegram et Discord. Les utilisateurs le connaissent et l'attendent.

Pour TAMSIV, c'est d'autant plus pertinent que le site web sert de complément à l'app mobile — pas de remplacement. Le QR code matérialise ce lien entre les deux plateformes.

Personne scannant un QR code affiché sur un écran de laptop avec son smartphone pour se connecter
Scanner un QR code prend 2 secondes — contre 30 secondes pour un formulaire email/mot de passe.

Comment fonctionne le flux d'authentification QR code ?

Du point de vue de l'utilisateur, c'est magique : je scanne, je suis connecté. Du point de vue technique, c'est un ballet précis de tokens et de channels temps réel. Voici les étapes :

  1. Génération : l'utilisateur ouvre tamsiv.com. Le site génère un UUID de session unique et crée une entrée dans Supabase avec le statut "pending".
  2. Affichage : le QR code encode cet UUID. Le site s'abonne au channel Supabase Realtime pour cette session.
  3. Scan : l'utilisateur scanne le QR code avec l'app mobile TAMSIV. L'app décode l'UUID.
  4. Confirmation : l'app envoie son JWT existant + l'UUID au backend. Le backend vérifie le JWT, génère un token d'auth web, et met à jour la session en "confirmed".
  5. Connexion : le site reçoit la mise à jour via Realtime, récupère le token, et l'utilisateur est connecté.

Ce flux garantit que seul un utilisateur déjà authentifié sur l'app mobile peut confirmer la session. Le token généré pour le web a une durée de vie limitée et est indépendant du token mobile — les deux sessions sont séparées.

Comment Supabase Realtime permet-il la connexion instantanée ?

Supabase Realtime est le composant qui rend l'expérience instantanée. Quand l'app mobile confirme la session, le changement en base de données est détecté par le channel Realtime et poussé vers le navigateur — en quelques millisecondes.

Techniquement, le site s'abonne à un channel spécifique filtrant sur l'UUID de session :

supabase.channel('qr-auth-SESSION_UUID')
  .on('postgres_changes', { event: 'UPDATE', filter: `id=eq.SESSION_UUID` }, callback)
  .subscribe()

Le callback est déclenché dès que le statut passe de "pending" à "confirmed". Le token d'auth est inclus dans la mise à jour. L'utilisateur voit la page de connexion se transformer en dashboard — sans aucune action supplémentaire.

C'est le même mécanisme Realtime que j'utilise pour le cache de contenu et les mises à jour en direct dans les groupes collaboratifs.

Diagramme architectural montrant le flux d'authentification temps réel entre une app mobile et un navigateur web
Le flux complet : génération du QR, scan mobile, confirmation via JWT, connexion web via Realtime.

Pourquoi un fallback polling est-il indispensable ?

Supabase Realtime fonctionne très bien dans la majorité des cas. Mais "la majorité" ne suffit pas pour une feature d'authentification. Certains réseaux d'entreprise bloquent les WebSockets. Certains proxies les interrompent. Certains navigateurs ont des bugs spécifiques.

J'ai implémenté un fallback polling HTTP qui prend le relais automatiquement :

  • Le site tente la connexion Realtime pendant 3 secondes
  • Si la connexion échoue, il bascule silencieusement sur un polling HTTP toutes les 2 secondes
  • Le polling interroge directement la base : "est-ce que la session UUID est confirmée ?"
  • L'utilisateur ne sait jamais quel mécanisme est utilisé — l'expérience est identique

Le délai de 3 secondes est un compromis entre réactivité et fiabilité. Plus court, on passerait trop vite au polling (moins efficace). Plus long, l'utilisateur attendrait sans feedback.

Ce pattern dual (Realtime + polling) est une bonne pratique pour toute fonctionnalité critique. Ne jamais dépendre d'un seul canal de communication.

Comment sécuriser le système de QR code ?

L'authentification par QR code introduit des vecteurs d'attaque spécifiques. Voici les mesures implémentées dans TAMSIV :

  • Expiration à 5 minutes : un QR code non utilisé devient invalide. Ça empêche la réutilisation de screenshots ou de QR codes partagés.
  • Usage unique : une session ne peut être confirmée qu'une seule fois. Toute tentative subséquente est rejetée.
  • Auth requise côté mobile : seul un utilisateur connecté à l'app peut confirmer. Le JWT est vérifié côté backend comme pour les WebSockets.
  • Token éphémère : le token généré pour le web est à usage unique et à durée limitée. Il sert uniquement à initier la session web, pas comme token permanent.
  • UUID v4 imprévisible : l'UUID utilisé pour la session est généré avec un CSPRNG (Cryptographically Secure Pseudo-Random Number Generator). Impossible à deviner.

Ces mesures sont alignées avec les recommandations OWASP pour l'authentification.

Double écran montrant un countdown timer sur un navigateur web et un viewfinder de caméra scannant un QR code sur smartphone
Le QR code se régénère automatiquement à 4min30 avec un countdown visuel pour guider l'utilisateur.

Quelle est l'expérience utilisateur finale ?

L'UX a été soignée dans les moindres détails :

  1. Auto-régénération du QR : à 4min30, le QR code se régénère automatiquement avec un nouveau UUID. Un countdown visuel indique le temps restant. L'utilisateur n'a jamais à rafraîchir la page.
  2. Animation de connexion : quand le scan est confirmé, une animation smooth transitionne entre la page de login et le dashboard. Pas de rechargement de page.
  3. Options alternatives : email/password et Magic Link sont disponibles en dessous du QR code. Aucun utilisateur n'est bloqué si le scan ne fonctionne pas.
  4. Responsive : sur mobile (quand le QR n'a pas de sens), l'interface privilégie email/password et Magic Link. Le QR est affiché uniquement sur desktop/tablet.

Le système d'onboarding guide les nouveaux utilisateurs web vers le QR code en premier, avec un fallback naturel vers les méthodes classiques.

Combien de code représente cette feature ?

Environ 300 lignes côté web (composant QR, logique Realtime/polling, gestion des tokens) et 150 lignes côté mobile (scanner, vérification, appel API de confirmation). C'est compact.

La raison : Supabase fait le gros du travail. La base de données stocke les sessions, Realtime pousse les updates, Auth gère les tokens. Le code applicatif se concentre sur l'orchestration et l'UX.

C'est typique de l'approche architecture Supabase de TAMSIV : maximiser ce que la plateforme offre nativement, minimiser le code custom. Le même principe qui guide la stratégie d'internationalisation et le système de gamification.

Quelles alternatives au QR code existent pour le cross-device auth ?

D'autres approches sont possibles pour l'authentification cross-device :

  • Deep links : envoyer un lien cliquable à l'utilisateur qui ouvre l'app et confirme. Marche bien mais nécessite que l'utilisateur soit sur le même appareil — ce qui n'est pas le cas ici.
  • Code numérique : afficher un code à 6 chiffres que l'utilisateur tape dans l'app. Plus universel mais plus lent (6 secondes vs 2 secondes pour un scan).
  • Push notification : envoyer une notification push avec un bouton "Confirmer". Nécessite que les notifications soient activées et que le système FCM soit configuré.
  • WebAuthn/Passkeys : la solution moderne mais pas encore universellement supportée sur tous les devices.

Le QR code offre le meilleur compromis entre rapidité, universalité et "effet wahou". C'est le genre de feature qui fait dire "c'est bien pensé" — et c'est exactement l'impression que TAMSIV veut laisser.

FAQ

Que se passe-t-il si je ferme le navigateur après avoir scanné le QR code ?

Le token généré pour la session web est stocké en local storage. À la prochaine visite, le site vérifie ce token et te reconnecte automatiquement si le token est encore valide. Tu n'as pas besoin de rescanner le QR code à chaque visite.

Peut-on avoir plusieurs sessions web en même temps ?

Oui, chaque scan crée une session indépendante. Tu peux être connecté sur ton ordinateur de bureau et ton laptop simultanément. Chaque session a son propre token et peut être révoquée individuellement depuis les paramètres de l'app.

Le QR code fonctionne-t-il sans connexion internet ?

Non, le QR code nécessite une connexion internet active des deux côtés (mobile et web). Le scan décode un UUID qui doit être vérifié en ligne via Supabase. Pour une utilisation hors ligne, les méthodes email/password restent disponibles.

Comment TAMSIV protège-t-il contre le QR code phishing ?

Le QR code encode uniquement un UUID de session — pas de données sensibles. La confirmation se fait via l'app officielle TAMSIV qui vérifie le domaine et la validité de la session. Un QR code forgé redirigerait vers un UUID inexistant en base et échouerait immédiatement.

Pourquoi le QR code expire-t-il après 5 minutes seulement ?

Cinq minutes est un compromis sécurité/UX. C'est assez long pour que l'utilisateur ait le temps de prendre son téléphone et scanner. C'est assez court pour limiter la fenêtre d'attaque si le QR est intercepté. La régénération automatique à 4min30 garantit un QR toujours frais sans action de l'utilisateur.