Toutes les applications web qui utilisent le protocole OAuth 2.0 pour l’authentification sont confrontĂ©es Ă  de nombreuses failles de sĂ©curitĂ©. Parmis les solutions pour faire bouclier Ă  ses attaques, c’est le pattern Backend For Frontend (BFF).

DĂ©finition du pattern BFF

Le pattern Backend for Frontend consiste à créer des passerelles conformes aux besoins spécifiques de chaque client. Le pattern BFF est considéré aussi comme une variante du pattern API Gateway.

Pour donner un exemple, nous pouvons crĂ©er un BFF dans le cas oĂč nous avons une application web qui communique avec des services comme la solution Algolia qui utilise l’intelligence artificielle pour optimiser la recherche pour votre site ou une solution de paiement comme Stripe qui permet aux clients d’effectuer des achats en ligne. Le Pattern BFF peut Ă©galement ĂȘtre utilisĂ© dans l’authentification si nous communiquons par exemple avec un serveur de dĂ©lĂ©gation d’authentification comme Auth0.

L’image ci-dessous reprĂ©sente l’acheminement d’une application web serverless avec des services externes sans l’utilisation d’un BFF.

Avec cette architecture, les services se comportent comme suit  : 

    • Stripe : l’achat des articles se fait uniquement dans la partie frontend ( risque de fraude vu qu’il n’y a pas un serveur backend qui vĂ©rifie derriĂšre l’intĂ©gritĂ© de l’achat )
    • Algolia : L’alimentation de nouvelles entrĂ©es pour la recherche se fait en front ( risque de compromettre la base de donnĂ©es des mots clĂ©s )
    • Auth0 : L’authentification se fait uniquement en frontend ( risque d’usurpation d’identitĂ© )

L’image ci-dessous reprĂ©sente le mĂȘme schĂ©ma prĂ©cĂ©dent mais avec l’utilisation d’un BFF.

Comme l’image ci-dessus le montre, le BFF est une API intermĂ©diaire entre une application web et le reste des services. Cela permet de faire abstraction de toute la complexitĂ© de la communication avec les services externes et laisser le frontend se concentrer pour offrir une bonne expĂ©rience utilisateur.

Par ailleurs, le fait de sortir toute la gestion de connexion avec les services en dehors du frontend, cela rĂ©duira la taille du bundle finale de l’application web, ce qui en rĂ©sulte Ă  un chargement trĂšs rapide dans les navigateurs web.

Maintenant que le BFF est mis en place, voilà comment les services se comportent : 

    • Stripe : La validation de l’achat se fait cĂŽtĂ© BFF, ce qui permet au dĂ©veloppeur d’ajouter des couches de sĂ©curitĂ©.
    • Algolia : L’alimentation des mots clĂ©s se fait cĂŽtĂ© BFF, ce qui permet de vĂ©rifier l’identitĂ© du client avant d’enrichir la base de donnĂ©es.
    • Auth0: La gĂ©nĂ©ration du jeton d’authentification se fait cĂŽtĂ© BFF, ce qui permet de cacher le token aux clients publiques.

Les risques de gĂ©rer l’authentification cĂŽtĂ© frontend

Les applications basĂ©es sur les navigateurs web prĂ©sentent une surface d’attaque relativement large. Les risques de sĂ©curitĂ© proviennent non seulement du code de l’application elle-mĂȘme, qui doit ĂȘtre protĂ©gĂ© contre les scripts intersites ( cross site ), la falsification des requĂȘtes intersites et d’autres vulnĂ©rabilitĂ©s, mais aussi des frameworks, bibliothĂšques et autres paquets NPM qu’elle utilise, ainsi que de toutes leurs dĂ©pendances transitives.

En outre, les autres applications fonctionnant sur le mĂȘme site doivent Ă©galement ĂȘtre sĂ©curisĂ©es. Les rĂ©centes attaques Spectre contre les navigateurs nous rappellent que de nouvelles menaces apparaissent constamment. Compte tenu de tous ces risques, il n’est pas recommandĂ© de stocker des jetons d’accĂšs ou des jetons de rafraĂźchissement de grande valeur dans des emplacements accessibles par JavaScript.

De ce fait, en utilisant un BFF, les jetons d’authentification ne sont accessibles que cĂŽtĂ© serveur et les sessions sont gĂ©rĂ©es Ă  l’aide de cookies HTTP cryptĂ©s et signĂ©s. Cela simplifie considĂ©rablement les menaces et rĂ©duit les risques. Bien que les attaques par injection de contenu soient toujours possibles, le BFF limite la capacitĂ© de l’attaquant Ă  abuser des API en limitant l’accĂšs par une interface bien dĂ©finie au backend, ce qui Ă©limine la possibilitĂ© d’appels d’API arbitraires.

GĂ©nĂ©ration de jeton đŸ—ïž d’authentification sans BFF :

GĂ©nĂ©ration de jeton đŸ—ïž d’authentification avec BFF :

Mise en place d’un BFF

Nous pouvons implĂ©menter un BFF avec n’importe quel framework backend qui permet de mettre en place une authentification HTTP par Cookie pour protĂ©ger les endpoints ( entrĂ©es ) de l’API. Mais dans cet article, nous allons utiliser ASP.NET, et comme nous sommes fainĂ©ants, nous allons utiliser un framework qui va nous permettre d’aller encore plus vite s’appelant Duende – BFF Security Framework.

Étapes de mise en place :

1. Installation du framework
> dotnet add package Duende.BFF

2. Dans le fichier program.cs ajouter l’authentification par cookie et par openId dans les services :

services.AddAuthentication(options =>
  {
    options.DefaultScheme = "cookie";
    options.DefaultChallengeScheme = "oidc";
    options.DefaultSignOutScheme = "oidc";
  })
  .AddCookie("cookie", options =>
  {
    options.ExpireTimeSpan = TimeSpan.FromHours(8);
    options.SlidingExpiration = false;
    options.Cookie.Name = "__Host-spa";
    options.Cookie.SameSite = SameSiteMode.Strict;
  })
  .AddOpenIdConnect("oidc", options =>
  {
    options.Authority = "https://demo.duendesoftware.com";
    options.ClientId = "spa";
    options.ClientSecret = "secret";
    options.ResponseType = "code";
    options.ResponseMode = "query";
    options.GetClaimsFromUserInfoEndpoint = true;
    options.SaveTokens = true;
    options.Scope.Clear();
    options.Scope.Add("openid profile api");
    options.Scope.Add("offline_access");
  });

3. Ajouter l’intĂ©gration du BFF dans les services

services.AddBff(options =>
  {
    options.ManagementBasePath = "/bff";
  };

4. Ajouter les routes de la gestion du BFF dans les routes du serveur

 app.UseEndpoints(endpoints =>
  {
    endpoints.MapBffManagementEndpoints();
  });

5. Ajouter le BFF dans les middlewares ( intercepteurs )

 app.UseAutentication();  
  app.UseBff();
  app.UseAuthorization();

NB: La ligne “app.UseBff()” doit ĂȘtre entre le middle d’authentification et d’autorisation.

6. Considérer que tous les contrÎleurs sont des entrées BFF ( donc sécurisés )  

app.MapControllers()
     .RequireAuthorization()
     .AsBffApiEndpoint();

 

7. CĂŽtĂ© FrontEnd, il faut ajouter dans les entĂȘtes ( headers ) des requĂȘtes HTTP l’entĂȘte “x-csrf: 1″, La valeur de l’en-tĂȘte n’est pas importante, mais sa prĂ©sence, combinĂ©e Ă  l’exigence d’un cookie, dĂ©clenche une demande de contrĂŽle prĂ©alable CORS pour les appels inter-origines. Cela permet d’isoler efficacement l’appelant Ă  la mĂȘme origine que le BackEnd, ce qui offre une garantie de sĂ©curitĂ© solide. 

DĂ©clencher l’authentification 

Pour dĂ©clencher l’authentification, il suffit d’appeler la ressource : “/bff/login” du BFF, cette derniĂšre redirige le client vers la page d’authentification.

Une fois l’utilisateur connectĂ©, un jeton est gĂ©nĂ©rĂ© signĂ© et cryptĂ© cĂŽtĂ© BFF et sera attachĂ© et rĂ©gĂ©nĂ©rĂ© Ă  chaque interaction avec le BFF.

Nous pouvons avoir les informations publiques du client en appelant la ressource “/bff/user”.

Enfin, La dĂ©connexion se fait en appelant la ressource “/bff/logout” avec l’url de dĂ©connexion contenant l’ID de la session rĂ©cupĂ©rĂ© des claims ( informations publiques du client ). 

Conclusion

L’utilisation d’un BFF n’est pas toujours utile, notamment s’il n’y a pas d’authentification ou l’inexistence des services externes. En revanche, le pattern BFF est fortement recommandĂ© pour assurer la sĂ©curitĂ© minimale au sein d’une application web.

 

GHEMID Mohamed
DĂ©veloppeur Full Stack Senior chez Devoteam
Créateur de contenu
Site Web · YouTube · LinkedIn

Partager
Faire suivre