OAuth 2.0

This document describes OAuth 2.0, when to use it, how to acquire client IDs, and how to use it with the Google API Client Library for .NET.

OAuth 2.0 Protocol

OAuth 2.0 is the authorization protocol used by Google APIs. You should get familiar with the protocol by reading the following links:

Acquire client IDs and secrets

You can get client IDs and secrets on the Google API Console . There are different types of client IDs, so be sure to get the correct type for your application:

In each of the code snippets shown (except the Service account one), you have to download the client secret and store it as client_secrets.json in your project.

Credentials

User credentials

UserCredential is a thread-safe helper class for using an access token to access protected resources. An access token typically expires after 1 hour, after which you will get an error if you try to use it.

UserCredential and AuthorizationCodeFlow take care of automatically "refreshing" the token, which means getting a new access token. This is done using a long-lived refresh token, which you receive along with the access token if you use the access_type=offline parameter during the authorization code flow.

In most applications, it is advisable to store the credential's access token and refresh token in persistent storage. Otherwise, you will need to present the end user with an authorization page in the browser every hour, because the access token expires an hour after you've received it.

To make sure the access and refresh tokens persist, you can provide your own implementation of IDataStore , or you can use one of the following implementations provided by the library:

  • FileDataStore for .NET ensures that the credential will be persistent in a file.

ServiceAccountCredential

ServiceAccountCredential is similar to UserCredential , but it serves a different purpose. Google OAuth 2.0 supports server-to-server interactions such as those between a web application and Google Cloud Storage. The requesting application has to prove its own identity to gain access to an API, and an end user doesn't have to be involved. ServiceAccountCredential stores a private key, which is used to sign a request to get a new access token.

Both UserCredential and ServiceAccountCredential implement IConfigurableHttpClientInitializer so you can register each of these as:

  • An unsuccessful response handler, so it will refresh the token if it receives an HTTP 401 status code.
  • An interceptor, to intercept the Authorization header on every request.

Installed applications

Sample code using the Books API :

 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 
 (); 
  
 ... 
  
 } 
  
 } 
 } 
  
  • In this sample code a new UserCredential instance is created by calling the GoogleWebAuthorizationBroker.AuthorizeAsync method. This static method gets the following:

    • The client secret (or a stream to the client secret).
    • The required scopes.
    • The user identifier.
    • The cancellation token for cancelling an operation.
    • An optional datastore. If the datastore is not specified, the default is a FileDataStore with a default Google.Apis.Auth folder. The folder is created in Environment.SpecialFolder.ApplicationData .
  • The UserCredential that is returned by this method is set as a HttpClientInitializer on the BooksService (using the initializer). As explained earlier, UserCredential implements an HTTP client initializer .

  • Notice that in the sample code, the client secret information is loaded from a file, but you can also do the following:

    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"));

Take a look at our Books sample .

Web applications (ASP.NET Core 3)

Google APIs support OAuth 2.0 for Web Server Applications .

The Google.Apis.Auth.AspNetCore3 is the recommended library to use for most Google based OAuth 2.0 scenarios in ASP.NET Core 3 applications. It implements a Google-specific OpenIdConnect auth handler. It supports incremental auth, and defines an injectable IGoogleAuthProvider to supply Google credentials that can be used with Google APIs.

This section describes how to configure and use Google.Apis.Auth.AspNetCore3. The code shown here is based on Google.Apis.Auth.AspNetCore3.IntegrationTests which is a fully working, standard ASP.NET Core 3 application.

If you want to follow along this documentation as a tutorial, you will need your own ASP.NET Core 3 application and to complete these steps as a prerequisite.

Prerequisites

  • Install the Google.Apis.Auth.AspNetCore3 package.
  • We are using the Google Drive API so you'll also need to install the Google.Apis.Drive.v3 package.
  • Create a Google Cloud project if you don't have one already. Follow these instructions to do so. This will be the project your app is identified with.
  • Make sure to enable the Google Drive API. To enable APIs, follow these instructions .
  • Create authorization credentials that will identify your app to Google. Follow these instructions to create authorization credentials and download the client_secrets.json file. Two highlights:
    • Notice that the credentials' type must be Web application .
    • For running this app, the only redirect URI you need to add is https://localhost:5001/signin-oidc .

Configure your application to use Google.Apis.Auth.AspNetCore3

Google.Apis.Auth.AspNetCore3 is configured in the Startup class or similar alternative you might be using. The following snippets are extracted from Startup.cs in the Google.Apis.Auth.AspNetCore3.IntegrationTests project.

  • Add the following using directive to your Startup.cs file.
    using Google.Apis.Auth.AspNetCore3;
  • In the Startup.ConfigureServices method add the following code, changin the Client ID and Client Secret placeholders with the values contained in the client_secrets.json file. You can load these values directly from the JSON file or you can store them in any other secure manner. Take a look at the ClientInfo.Load method in the Google.Apis.Auth.AspNetCore3.IntegrationTests project for an example on how to load these values directly from the JSON file.
    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};
            });
    }
  • In the Startup.Configure method make sure to add ASP.NET Core 3 authentication and authorization middleware components to the pipeline, as well as HTTPS redirections:
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
        app.UseHttpsRedirection();
        ...
    
        app.UseAuthentication();
        app.UseAuthorization();
    
        ...
    }

Use the user credential to access Google APIs on their behalf

You are now ready to add action methods to your controllers that require the user credential to access Google APIs on their behalf. The following snippet shows how to list the files on the authenticated user's Google Drive account. Notice two things mostly:

  • The user not only needs to be authenticated, but they also need to have granted the https://www.googleapis.com/auth/drive.readonly scope to your application, which you specify using the GoogleScopedAuthorize attribute.
  • We are using ASP.NET Core 3's standard dependency injection mechanism to receive an IGoogleAuthProvider that we use to obtain the user's credentials.

The code:

  • First add the following using directives to your controller.
    using Google.Apis.Auth.AspNetCore3;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Drive.v3;
    using Google.Apis.Services;
  • Add the controller action, as follows (and accompany it with a view that receives a IList<string> model):
     /// 
      
    < 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 
     ); 
     } 
      
    

And these are the basics. You can take a look at HomeController.cs from the Google.Apis.Auth.AspNetCore3.IntegrationTests project to find out how you can achieve:

  • User authentication only, with no specific scopes
  • User logout
  • Incremental authorization with code. Notice that the sample shows incremental authorization with attributes.
  • Examine granted scopes
  • Examine access and refresh tokens
  • Force refresh the access token. Notice that you don't have to do this yourself because Google.Apis.Auth.AspNetCore3 will detect if the access token is expired or close to expiring and will automatically refresh it.
Create a Mobile Website
View Site in Mobile | Classic
Share by: