Loupe

Fermeture de Google+ : comment réparer l'authentification Google en ASP.NET Core

Il y a quelques mois, suite à d'importantes fuites de données, Google a décidé de fermer son réseau social Google+. Plus récemment, ils ont annoncé que les APIs Google+ seraient arrêtées le 7 mars 2019, c'est-à-dire très bientôt ! En fait, les appels à ces APIs pourraient même commencer à échouer dès le 28 janvier, soit dans moins de deux semaines. Vous vous dites peut-être que cette information ne vous affecte pas en tant que développeur ; mais si vous utilisez l'authentification Google dans une application ASP.NET Core, attention ! Le fournisseur d'authentification Google intégré à ASP.NET Core (services.AddAuthentication().AddGoogle(...)) utilise une API Google+ pour récupérer des informations sur l'utilisateur connecté, et cela ne fonctionnera bientôt plus. Pour en savoir plus, je vous renvoie vers la discussion Github à ce sujet. Notez qu'ASP.NET MVC "classique" est également affecté par ce problème.

OK, je suis concerné, comment régler le problème ?

Heureusement, ce n'est pas très difficile à corriger. Il y a déjà une pull request pour corriger le problème dans ASP.NET Core, et une mise à jour devrait être publiée prochainement. En attendant, vous pouvez:

  • soit utiliser le workaround décrit ici, qui spécifie un autre endpoint pour récupérer les infos de l'utilisateur et ajuste les mappings JSON.
  • soit utiliser le fournisseur OpenID Connect générique ; à mon avis c'est de toute façon une meilleure solution que le fournisseur Google intégré, car cela permet de récupérer toutes les informations depuis l'ID token, sans faire un appel d'API supplémentaire.

Utiliser OpenID Connect pour s'authentifier avec Google

Alors, voyons comment modifier notre application pour utiliser le fournisseur OpenID Connect à la place du fournisseur Google intégré, et comment le configurer pour obtenir les mêmes résultats qu'avant.

Pour commencer, on installe le package NuGet Microsoft.AspNetCore.Authentication.OpenIdConnect dans le projet, s'il n'est pas déjà là.

Ensuite, on va là où le fournisseur Google est ajouté (l'appel à AddGoogle, habituellement dans la classe Startup), et on supprime cet appel.

À la place, on ajoute le fournisseur OpenID Connect, on le fait pointer vers l'URL de l'autorité OpenID Connect de Google, et on définit le client id (le même qu'on utilisait avec le fournisseur Google intégré) :

services
    .AddAuthentication()
    .AddOpenIdConnect(
        authenticationScheme: "Google",
        displayName: "Google",
        options =>
        {
            options.Authority = "https://accounts.google.com/";
            options.ClientId = configuration["Authentication:Google:ClientId"];
        });

Il faut aussi ajuster le chemin de rappel pour que ce soit le même qu'avant, de façon à ce que l'URL de redirection configurée au niveau de l'app Google fonctionne toujours ; et pendant qu'on y est, on configure également les chemins de déconnexion.

options.CallbackPath = "/signin-google";
options.SignedOutCallbackPath = "/signout-callback-google";
options.RemoteSignOutPath = "/signout-google";

La configuration par défaut inclut déjà les scopes openid et profile, mais si on veut pouvoir accéder à l'adresse email de l'utilisateur comme c'était le cas avant, il faut aussi ajouter le scope email :

options.Scope.Add("email");

Et c'est tout ! Tout devrait fonctionner comme avant. Voici un Gist qui montre le code avant et après le changement.

Hey, mais où est passé le client secret?

Vous avez peut-être remarqué qu'on a pas spécifié de client secret. Comment se fait-ce?

Le fournisseur Google intégré est en fait simplement un fournisseur OAuth générique avec une configuration spécifique à Google. Il utilise le authorization code flow, qui nécessite le client secret pour échanger le code d'autorisation contre un token d'accès, qui sera ensuite utilisé pour appeler le endpoint d'informations sur l'utilisateur.

Mais par défaut, le fournisseur OpenID Connect utilise le implicit flow. Il n'y a pas de code d'autorisation : un id_token est directement fourni via l'URL de redirection, et il n'y a aucun appel d'API à faire, donc le secret n'est pas nécessaire. Si, pour une raison ou une autre, vous ne voulez pas utiliser l'implicit flow, définissez simplement options.ResponseType à code (la valeur par défaut est id_token), et affectez le client secret à la propriété options.ClientSecret. Il faut également mettre options.GetClaimsFromUserInfoEndpoint à true pour obtenir les informations de l'utilisateur (nom, email...), puisque vous n'aurez plus d'id_token contenant ces informations.

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus