Résumé

  • Publié en août 2026 comme Best Current Practice de l’IETF, le RFC 10017 recommande fortement le Backend for Frontend aux applications professionnelles, sensibles ou traitant des données personnelles, car les jetons d’accès et de rafraîchissement ne sont pas exposés au code du navigateur.
  • Cette architecture neutralise plusieurs vols de jetons et l’obtention d’un nouveau jeu de jetons, mais elle n’isole pas un JavaScript malveillant qui partage l’origine de l’application. L’absence d’exfiltration ne prouve pas l’absence d’action indue.

Une compromission sans secret dérobé

La scène d’ouverture est un cas analytique tiré du modèle de menace, pas un incident rapporté. Elle sépare deux questions que les tableaux de sécurité réunissent trop vite : l’attaquant a-t-il obtenu une valeur transportable, et a-t-il pu faire agir le contexte actif de l’utilisateur ?

Dans le RFC 10017, un JavaScript malveillant entré dans l’environnement d’exécution n’est pas un locataire inférieur. Il possède les privilèges du code légitime : lecture de la page, accès aux stockages liés à l’origine, interaction avec les contextes de même origine et émission de requêtes vers les services de l’application.

Le texte distingue quatre scénarios. Un attaquant peut voler une fois les jetons présents, organiser leur vol continu, lancer un nouveau flux pour obtenir ses propres jetons, ou faire transiter ses requêtes par le navigateur de la victime. Dans le dernier cas, aucun secret ne doit sortir. Les requêtes légitimes et malveillantes proviennent du même contexte ; si un composant externe ajoute le jeton, il peut également l’ajouter à la requête induite.

« Aucun jeton volé » répond donc à la garde et à la réutilisation hors du poste. Cette conclusion ne dit pas quelle requête a consommé la session, si la route du BFF était trop large, ni si le serveur de ressources devait autoriser l’effet métier.

Le BFF réduit l’attaque sans assainir l’origine

Un BFF remplit trois fonctions : il agit comme client OAuth confidentiel, conserve les jetons dans un contexte serveur associé à une session par cookie, puis relaie les appels en ajoutant le bon jeton d’accès. Le navigateur manipule une interface de session, pas le matériau d’autorisation.

Le gain est substantiel. Il n’existe pas de jeton disponible pour un vol ponctuel ou persistant. Même si le code compromis récupère un code d’autorisation, il ne dispose pas des identifiants confidentiels du BFF pour l’échanger. PKCE apporte une protection supplémentaire à cet échange.

Mais le risque résiduel est explicite. Le code hostile tourne toujours dans l’origine et peut envoyer une requête au BFF depuis le navigateur. HttpOnly empêche de lire le cookie ; il n’empêche pas le navigateur de joindre ce cookie à un appel permis. Le BFF peut alors sélectionner le jeton et relayer la requête sans exposer le secret.

Il s’agit d’un détournement du client. L’attaquant reste limité aux opérations admises par l’application, la session, les routes du BFF et les politiques de la ressource. Il ne gagne pas nécessairement un jeton réutilisable partout. Limiter la conséquence est précieux, mais ne transforme pas le code de l’origine en code digne de confiance.

C’est pourquoi le BCP peut recommander fortement le BFF pour les applications à risque tout en conservant cette attaque. Un choix d’architecture compare des conséquences : supprimer la forme durable et portable de l’abus ne supprime pas l’abus du contexte utilisateur actif.

Un cookie illisible reste opérant

Le RFC exige Secure et HttpOnly pour le cookie de session du BFF. Il recommande aussi SameSite=Strict, le chemin /, l’absence d’attribut Domain et un préfixe limité à l’hôte, sauf justification propre au déploiement. Ces propriétés protègent contre l’exposition réseau, la lecture par script et un partage excessif entre sous-domaines.

Elles ne prouvent pas l’intention de la requête. Puisque le cookie authentifie les échanges avec le BFF, une défense CSRF correcte reste obligatoire. SameSite=Strict peut suffire pour un site isolé ; des sous-domaines frères sont toutefois same-site même s’ils sont cross-origin. La prise de contrôle d’un sous-domaine peut alors contourner une hypothèse trop générale.

CORS doit aussi être testé au niveau de chaque requête. Certaines requêtes safelisted partent sans preflight ; le navigateur se contente de ne pas rendre la réponse au script. Un BFF qui s’appuie sur le preflight peut imposer un en-tête personnalisé et rejeter toute absence. La preuve utile n’est pas « CORS activé », mais l’application uniforme de cette condition aux opérations qui modifient l’état.

La durée de la session doit suivre celle du jeton de rafraîchissement. Maintenir une session apparemment active après invalidation crée une divergence. Révoquer le jeton sans conserver son lien avec la session laisse également l’équipe incapable de dire quelles actions du navigateur ont été arrêtées.

La table de proxy distribue une autorité

Le BFF n’est pas seulement un coffre. Il traduit une requête entrante appuyée sur un cookie en appel sortant muni d’un bearer token. Cette traduction est une surface de contrôle.

Le RFC impose des restrictions sortantes strictes : liste explicite d’hôtes, validation des chemins dynamiques et, lorsque cela convient, limitation des méthodes HTTP par point d’entrée. Sans elles, une session légitime peut devenir un proxy ouvert, envoyer un jeton vers un hôte imprévu ou atteindre une opération que le frontend n’entendait pas exposer.

Une route comme /bff/orders/{id} n’est donc pas de la simple plomberie. Elle décide quelle ressource, quel chemin et quelle méthode la session peut dépenser. Le serveur de ressources doit encore vérifier l’audience, la portée, le sujet et la politique de l’action. Une bonne route ne suffit pas à autoriser un remboursement, un transfert ou une modification administrative.

La réponse HTTP ne clôt pas la preuve. Le service peut rejeter l’effet plus tard, le BFF peut réessayer, et l’agrégation de nombreux utilisateurs derrière une adresse sortante peut perturber les limites de débit. Il faut relier session, identifiant de requête, route, portée, décision de la ressource et état métier final.

La concentration est aussi privée. Le BFF voit toutes les requêtes et réponses. Lorsqu’un tiers l’héberge, la protection des jetons dans le navigateur s’améliore, tandis que la visibilité de cet intermédiaire augmente. Garde des secrets et minimisation des données sont deux décisions.

Trois architectures, trois contrats de preuve

Le BCP compare trois modèles. Le BFF complet conserve les deux types de jetons et relaie tous les appels. Le token-mediating backend reste un client confidentiel et protège le jeton de rafraîchissement, mais remet le jeton d’accès au navigateur. Le client purement navigateur gère lui-même OAuth et les jetons.

Le modèle intermédiaire laisse possible le vol ou l’usage du jeton d’accès par un code compromis, tout en protégeant normalement le rafraîchissement et les identifiants du backend. Ce n’est pas seulement un niveau moyen : ses preuves de garde, de rejeu et d’action sont différentes.

Le client navigateur reste exposé aux quatre scénarios. Authorization Code avec PKCE est obligatoire ; les jetons de rafraîchissement doivent tourner ou être liés à un expéditeur et avoir une durée maximale ou d’inactivité. Ces contrôles réduisent interception et persistance, sans isoler le code déjà présent dans l’origine.

DPoP a la même discipline. Une clé non exportable rend un jeton volé plus difficile à employer ailleurs. Elle n’arrête pas les requêtes relayées par le navigateur. Si le code compromis peut lancer un nouveau flux, il peut parfois associer les nouveaux jetons à sa propre clé. Il faut donc préciser quel contexte est l’« expéditeur ».

Enfin, une application et son API sur un domaine commun n’ont pas toujours besoin d’OAuth entre elles. Après une authentification fédérée, une session applicative peut suffire. Ajouter OAuth sans partie ressource indépendante peut créer des surfaces de jeton et de proxy sans nouvelle frontière de confiance.

Ne pas élargir la promesse

Le RFC 10017 est utile précisément parce qu’il ne promet pas une enclave dans le navigateur. Le BFF est une réponse forte et locale à l’exposition des jetons. Il n’approuve ni tout code de l’origine, ni chaque requête relayée, ni son effet métier.

Le dossier opérationnel doit distinguer provenance du code et des dépendances, origine, création et expiration de session, attributs du cookie, heure, méthode, chemin, classe du corps, résultat CSRF, route BFF, audience et portée, décision de la ressource, réponse, effet et responsable du retour arrière. Chaque élément a son horloge et son propriétaire.

C’est une coordination minimale : le BCP fixe des pratiques communes, tandis que les limites d’application, listes de routes, seuils d’anomalie et mécanismes de réversibilité restent locaux. Le comportement observé prime sur l’étiquette d’architecture. Celui qui supporte la fraude, l’atteinte à la vie privée ou l’indisponibilité garde l’autorité finale d’admettre, observer, arrêter et annuler.

Sources