Ce document décrit le protocole OAuth 2.0 et indique quand l'utiliser, comment obtenir des ID client et comment l'utiliser avec la bibliothèque cliente des API Google pour .NET.
Protocole OAuth 2.0
OAuth 2.0 est le protocole d'autorisation utilisé par les API Google. Pour vous familiariser avec le protocole, consultez les liens suivants:
Obtenir des ID client et des secrets
Vous pouvez obtenir les ID et les secrets de vos clients dans la console Google APIs. Il existe différents types d'ID client. Veillez donc à obtenir le type approprié pour votre application:
- ID client d'applications Web
- ID client des applications installées
- ID client du compte de service
Dans chacun des extraits de code ci-dessous (sauf celui du compte de service), vous devez télécharger le secret client et le stocker en tant que client_secrets.json
dans votre projet.
Identifiants
Identifiants utilisateur
UserCredential
est une classe d'assistance sécurisée qui permet d'utiliser un jeton d'accès pour accéder aux ressources protégées.
Un jeton d'accès expire généralement au bout d'une heure. Passé ce délai, un message d'erreur s'affiche si vous essayez de l'utiliser.
UserCredential
et AuthorizationCodeFlow
s'occupent de l'actualisation automatique du jeton, ce qui implique simplement d'obtenir un nouveau jeton d'accès.
Pour ce faire, vous utilisez un jeton d'actualisation de longue durée, que vous recevez avec le jeton d'accès si vous utilisez le paramètre access_type=offline
lors du flux de code d'autorisation.
Dans la plupart des applications, il est conseillé de stocker le jeton d'accès et le jeton d'actualisation dans un espace de stockage persistant. Sinon, vous devrez présenter à l'utilisateur final une page d'autorisation dans le navigateur toutes les heures, car le jeton d'accès expire une heure après l'avoir reçu.
Pour vous assurer que les jetons d'accès et d'actualisation persistent, vous pouvez fournir votre propre implémentation de IDataStore
ou utiliser l'une des implémentations suivantes fournies par la bibliothèque:
-
FileDataStore
pour .NET garantit que les identifiants seront persistants dans un fichier.
ServiceAccountCredential
ServiceAccountCredential
est semblable à UserCredential
, mais il sert un objectif différent.
Google OAuth 2.0 est compatible avec les interactions de serveur à serveur telles que celles entre une application Web et Google Cloud Storage.
L'application à l'origine de la demande doit prouver sa propre identité pour accéder à une API, et l'utilisateur final n'a pas besoin de l'intervenir.
ServiceAccountCredential
stocke une clé privée, qui permet de signer une requête pour obtenir un nouveau jeton d'accès.
UserCredential
et ServiceAccountCredential
implémentent IConfigurableHttpClientInitializer
, ce qui vous permet d'enregistrer chacun de ces éléments sous la forme suivante:
- Un gestionnaire de réponses ayant échoué. Il va donc actualiser le jeton s'il reçoit un code d'état HTTP
401
. - Un intercepteur, pour intercepter l'en-tête
Authorization
à chaque requête
Applications installées
Exemple de code à l'aide de l'API Livres:
using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; using Google.Apis.Books.v1; using Google.Apis.Books.v1.Data; using Google.Apis.Services; using Google.Apis.Util.Store; namespace Books.ListMyLibrary { /// <summary> /// Sample which demonstrates how to use the Books API. /// https://developers.google.com/books/docs/v1/getting_started /// <summary> internal class Program { [STAThread] static void Main(string[] args) { Console.WriteLine("Books API Sample: List MyLibrary"); Console.WriteLine("================================"); try { new Program().Run().Wait(); } catch (AggregateException ex) { foreach (var e in ex.InnerExceptions) { Console.WriteLine("ERROR: " + e.Message); } } Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } private async Task Run() { UserCredential credential; using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read)) { credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.Load(stream).Secrets, new[] { BooksService.Scope.Books }, "user", CancellationToken.None, new FileDataStore("Books.ListMyLibrary")); } // Create the service. var service = new BooksService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "Books API Sample", }); var bookshelves = await service.Mylibrary.Bookshelves.List().ExecuteAsync(); ... } } }
-
Dans cet exemple de code, une instance
UserCredential
est créée en appelant la méthodeGoogleWebAuthorizationBroker.AuthorizeAsync
. Cette méthode statique obtient les éléments suivants:- Code secret du client (ou flux vers le code secret du client).
- Champs d'application requis.
- Identifiant de l'utilisateur.
- Jeton d'annulation pour annuler une opération.
- Un datastore facultatif. Si le datastore n'est pas spécifié, la valeur par défaut est
FileDataStore
, avec un dossierGoogle.Apis.Auth
par défaut. Le dossier est créé dansEnvironment.SpecialFolder.ApplicationData
.
-
Le
UserCredential
qui est renvoyé par cette méthode est défini en tant queHttpClientInitializer
sur leBooksService
(à l'aide de l'initialiseur). Comme expliqué ci-dessus,UserCredential
implémente un initialiseur de client HTTP. -
Notez que, dans l'exemple de code ci-dessus, les informations secrètes du client sont chargées à partir d'un fichier. Vous pouvez également procéder comme suit:
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( new ClientSecrets { ClientId = "PUT_CLIENT_ID_HERE", ClientSecret = "PUT_CLIENT_SECRETS_HERE" }, new[] { BooksService.Scope.Books }, "user", CancellationToken.None, new FileDataStore("Books.ListMyLibrary"));
Consultez notre extrait de livres.
Applications Web (ASP.NET Core 3)
Les API Google sont compatibles avec OAuth 2.0 pour les applications de serveur Web.
Google.Apis.Auth.AspNetCore3 est la bibliothèque recommandée pour la plupart des scénarios OAuth 2.0 basés sur Google dans les applications ASP.NET Core 3. Elle met en œuvre un gestionnaire d'authentification OpenIdConnect
spécifique à Google. Il est compatible avec l'authentification incrémentielle et définit un IGoogleAuthProvider
injectable qui fournit les identifiants Google pouvant être utilisés avec les API Google.
Cette section explique comment configurer et utiliser Google.Apis.Auth.AspNetCore3. Le code affiché ici est basé sur Google.Apis.Auth.AspNetCore3.IntegrationTests, une application ASP.NET Core standard entièrement opérationnelle.
Si vous souhaitez suivre cette documentation sous la forme d'un tutoriel, vous aurez besoin de votre propre application ASP.NET Core 3 et vous devrez suivre cette procédure.
Conditions préalables
- Installez le package Google.Apis.Auth.AspNetCore3.
- Comme vous utilisez l'API Google Drive, vous devez également installer le package Google.Apis.Drive.v3.
- Créez un projet Google Cloud si vous n'en avez pas déjà un. Pour ce faire, suivez ces instructions. Il s'agit du projet dans lequel votre application est identifiée.
- Veillez à activer l'API Google Drive. Pour activer les API, suivez ces instructions.
-
Créez des identifiants d'autorisation qui permettront à Google d'identifier votre application. Suivez ces instructions pour créer des identifiants d'autorisation et téléchargez le fichier
client_secrets.json
. Deux points forts :- Notez que le type credentials doit être Web application (Application Web).
- Pour exécuter cette application, le seul URI de redirection que vous devez ajouter est
https://localhost:5001/signin-oidc
.
Configurer votre application pour qu'elle utilise Google.Apis.Auth.AspNetCore3
Google.Apis.Auth.AspNetCore3 est configuré dans la classe Startup
ou une alternative similaire que vous utilisez peut-être. Les extraits suivants sont extraits de Startup.cs
dans le projet Google.Apis.Auth.AspNetCore3.IntegrationTests.
-
Ajoutez la directive d'utilisation suivante à votre fichier
Startup.cs
.using Google.Apis.Auth.AspNetCore3;
-
Dans la méthode
Startup.ConfigureServices
, ajoutez le code suivant, et modifiez les espaces réservés"ID client"et"Code secret du client"avec les valeurs contenues dans le fichierclient_secrets.json
. Vous pouvez charger ces valeurs directement à partir du fichier JSON ou les stocker de toute autre manière sécurisée. Consultez la méthodeClientInfo.Load
du projet Google.Apis.Auth.AspNetCore3.IntegrationTests pour découvrir comment charger ces valeurs directement à partir du fichier JSON.public void ConfigureServices(IServiceCollection services) { ... // This configures Google.Apis.Auth.AspNetCore3 for use in this app. services .AddAuthentication(o => { // This forces challenge results to be handled by Google OpenID Handler, so there's no // need to add an AccountController that emits challenges for Login. o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme; // This forces forbid results to be handled by Google OpenID Handler, which checks if // extra scopes are required and does automatic incremental auth. o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme; // Default scheme that will handle everything else. // Once a user is authenticated, the OAuth2 token info is stored in cookies. o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie() .AddGoogleOpenIdConnect(options => { options.ClientId = {YOUR_CLIENT_ID}; options.ClientSecret = {YOUR_CLIENT_SECRET}; }); }
-
Dans la méthode
Startup.Configure
, veillez à ajouter au pipeline des composants d'authentification et d'autorisation ASP.NET Core 3, ainsi que des redirections HTTPS :public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseHttpsRedirection(); ... app.UseAuthentication(); app.UseAuthorization(); ... }
Utiliser les identifiants utilisateur pour accéder aux API Google en leur nom
Vous êtes maintenant prêt à ajouter à vos contrôleurs des méthodes d'action qui nécessitent des identifiants utilisateur pour accéder aux API Google en leur nom. L'extrait de code suivant montre comment lister les fichiers sur le compte Google Drive de l'utilisateur authentifié. Vous remarquerez principalement deux éléments:
-
L'utilisateur doit non seulement être authentifié, mais il doit également avoir accordé le champ d'application
https://www.googleapis.com/auth/drive.readonly
à votre application, que vous spécifiez via l'attributGoogleScopedAuthorize
. -
Nous utilisons le mécanisme standard d'injection de dépendances ASP.NET Core 3 pour recevoir le
IGoogleAuthProvider
que nous utilisons pour obtenir les identifiants de l'utilisateur.
Le code:
-
Commencez par ajouter les directives d'utilisation suivantes à votre contrôleur.
using Google.Apis.Auth.AspNetCore3; using Google.Apis.Auth.OAuth2; using Google.Apis.Drive.v3; using Google.Apis.Services;
-
Ajoutez l'action du contrôleur comme suit (et associez-la à une vue simple qui reçoit un modèle
IList<string>
) :/// <summary> /// Lists the authenticated user's Google Drive files. /// Specifying the <see cref="GoogleScopedAuthorizeAttribute"> will guarantee that the code /// executes only if the user is authenticated and has granted the scope specified in the attribute /// to this application. /// </summary> /// <param name="auth">The Google authorization provider. /// This can also be injected on the controller constructor.</param> [GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)] public async Task<IActionResult> DriveFileList([FromServices] IGoogleAuthProvider auth) { GoogleCredential cred = await auth.GetCredentialAsync(); var service = new DriveService(new BaseClientService.Initializer { HttpClientInitializer = cred }); var files = await service.Files.List().ExecuteAsync(); var fileNames = files.Files.Select(x => x.Name).ToList(); return View(fileNames); }
Voilà pour les bases. Vous pouvez utiliser HomeController.cs
dans le projet Google.Apis.Auth.AspNetCore3.IntegrationTests pour découvrir comment obtenir les résultats suivants:
- Authentification des utilisateurs uniquement, sans champs d'application spécifiques
- Fonctionnalité de déconnexion
- Autorisation incrémentielle via le code. Notez que l'extrait de code ci-dessus montre une autorisation incrémentielle via des attributs.
- Examiner les champs d'application actuellement accordés
- Examiner les jetons d'accès et d'actualisation
- Forcer l'actualisation du jeton d'accès. Notez que vous n'avez pas besoin de le faire vous-même, car Google.Apis.Auth.AspNetCore3 détecte si le jeton d'accès a expiré ou est sur le point d'expirer. Il est automatiquement actualisé.
Applications Web (ASP.NET MVC)
Les API Google sont compatibles avec OAuth 2.0 pour les applications de serveur Web.
Pour pouvoir exécuter le code suivant, vous devez d'abord ajouter un URI de redirection à votre projet dans la console Google APIs.
Comme vous utiliserez FlowMetadata
et ses paramètres par défaut, définissez l'URI de redirection sur your_site/AuthCallback/IndexAsync
.
Pour trouver les URI de redirection de vos identifiants OAuth 2.0, procédez comme suit:
- Ouvrez la page Identifiants dans la console API.
- Si vous ne l'avez pas déjà fait, créez vos identifiants OAuth 2.0 en cliquant sur Créer des identifiants > ID client OAuth.
- Après avoir créé vos identifiants, affichez ou modifiez les URL de redirection en cliquant sur l'ID client (pour une application Web) dans la section ID client OAuth 2.0.
Après avoir créé un projet d'application Web dans votre IDE, ajoutez le package NuGet Google.Apis
approprié pour Drive, YouTube ou l'autre service que vous souhaitez utiliser. Ajoutez ensuite le package Google.Apis.Auth.MVC.
Le code suivant illustre une application MVC ASP.NET qui interroge un service d'API Google.
-
Ajoutez votre implémentation de
FlowMetadata
.using System; using System.Web.Mvc; using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2.Flows; using Google.Apis.Auth.OAuth2.Mvc; using Google.Apis.Drive.v2; using Google.Apis.Util.Store; namespace Google.Apis.Sample.MVC4 { public class AppFlowMetadata : FlowMetadata { private static readonly IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer { ClientSecrets = new ClientSecrets { ClientId = "PUT_CLIENT_ID_HERE", ClientSecret = "PUT_CLIENT_SECRET_HERE" }, Scopes = new[] { DriveService.Scope.Drive }, DataStore = new FileDataStore("Drive.Api.Auth.Store") }); public override string GetUserId(Controller controller) { // In this sample we use the session to store the user identifiers. // That's not the best practice, because you should have a logic to identify // a user. You might want to use "OpenID Connect". // You can read more about the protocol in the following link: // https://developers.google.com/accounts/docs/OAuth2Login. var user = controller.Session["user"]; if (user == null) { user = Guid.NewGuid(); controller.Session["user"] = user; } return user.ToString(); } public override IAuthorizationCodeFlow Flow { get { return flow; } } } }
FlowMetadata
est une classe abstraite qui contient votre propre logique de récupération de l'identifiant utilisateur et duIAuthorizationCodeFlow
que vous utilisez.Dans l'exemple de code ci-dessus, un nouveau
GoogleAuthorizationCodeFlow
est créé avec les champs d'application, les secrets client et le datastore appropriés. Pensez à ajouter votre propre mise en œuvre deIDataStore
. Par exemple, vous pouvez en écrire une qui utiliseEntityFramework
. -
Implémentez votre propre contrôleur qui utilise un service d'API Google.
L'exemple suivant utilise un élément
DriveService
:using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Web.Mvc; using Google.Apis.Auth.OAuth2.Mvc; using Google.Apis.Drive.v2; using Google.Apis.Services; using Google.Apis.Sample.MVC4; namespace Google.Apis.Sample.MVC4.Controllers { public class HomeController : Controller { public async Task<ActionResult> IndexAsync(CancellationToken cancellationToken) { var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()). AuthorizeAsync(cancellationToken); if (result.Credential != null) { var service = new DriveService(new BaseClientService.Initializer { HttpClientInitializer = result.Credential, ApplicationName = "ASP.NET MVC Sample" }); // YOUR CODE SHOULD BE HERE.. // SAMPLE CODE: var list = await service.Files.List().ExecuteAsync(); ViewBag.Message = "FILE COUNT IS: " + list.Items.Count(); return View(); } else { return new RedirectResult(result.RedirectUri); } } } }
-
Implémentez votre propre contrôleur de rappel. L'implémentation doit se présenter comme suit :
using Google.Apis.Sample.MVC4; namespace Google.Apis.Sample.MVC4.Controllers { public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController { protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData { get { return new AppFlowMetadata(); } } } }
Compte de service
Les API Google sont également compatibles avec les comptes de service. Contrairement au scénario dans lequel une application cliente demande l'accès aux données d'un utilisateur final, les comptes de service fournissent un accès aux données de l'application cliente.
Votre application cliente signe la demande de jeton d'accès à l'aide d'une clé privée téléchargée depuis la console Google APIs. Après avoir créé un ID client, vous devez choisir un type d'application "Compte de service". Vous pourrez ensuite télécharger la clé privée. Consultez cet exemple de compte de service qui utilise l'API Google Plus.
using System; using System.Security.Cryptography.X509Certificates; using Google.Apis.Auth.OAuth2; using Google.Apis.Plus.v1; using Google.Apis.Plus.v1.Data; using Google.Apis.Services; namespace Google.Apis.Samples.PlusServiceAccount { /// <summary> /// This sample demonstrates the simplest use case for a Service Account service. /// The certificate needs to be downloaded from the Google API Console /// <see cref="https://console.cloud.google.com/"> /// "Create another client ID..." -> "Service Account" -> Download the certificate, /// rename it as "key.p12" and add it to the project. Don't forget to change the Build action /// to "Content" and the Copy to Output Directory to "Copy if newer". /// </summary> public class Program { // A known public activity. private static String ACTIVITY_ID = "z12gtjhq3qn2xxl2o224exwiqruvtda0i"; public static void Main(string[] args) { Console.WriteLine("Plus API - Service Account"); Console.WriteLine("=========================="); String serviceAccountEmail = "SERVICE_ACCOUNT_EMAIL_HERE"; var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable); ServiceAccountCredential credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail) { Scopes = new[] { PlusService.Scope.PlusMe } }.FromCertificate(certificate)); // Create the service. var service = new PlusService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "Plus API Sample", }); Activity activity = service.Activities.Get(ACTIVITY_ID).Execute(); Console.WriteLine(" Activity: " + activity.Object.Content); Console.WriteLine(" Video: " + activity.Object.Attachments[0].Url); Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } } }
L'exemple de code ci-dessus crée un ServiceAccountCredential
.
Les champs d'application requis sont définis et un appel est effectué à FromCertificate
, qui charge la clé privée à partir du X509Certificate2
donné.
Comme dans tous les autres exemples de code, les identifiants sont définis sur HttpClientInitializer
.