Recently I have been exploring Google's API to access their Drive functionality using the .NET 4.5 framework with C#. Even though the API's documentation is OK, it contains some flaws (for the .NET part at least) and gaps that might result in a less than smooth experience at first. I'd like to share a few of my findings and maybe help a few people along the way.
Even though my notes focus on accessing Google Drive, different API's could be accessed in a similar fashion.
This is one of the articles I wrote back in 2013 and which I saved from my old blog. The content is still topical for 2017, but if you find any errors, don't hesitate to contact me.
Contents
This short guide will cover the steps and source code for accessing Google Drive in enterprise applications:
- Step 1: Creating a service account
- Step 2: Grant domain-wide access to the service account
- Step 3: Accessing Google Drive via .NET
- Troubleshooting
Step 1: Creating a service account
Goal: Obtaining a Private Key File, Client ID and Email address:
- Go to the Google APIs console and select an existing project or create a new one.
- Open the Services tab and make sure the Drive API is on:
- Next, go to the API Access tab and click Create and OAuth 2.0 client ID...
- Enter a product name and specify a logo and click Next
- Select Service account and click Create client ID
- In the next dialog click Download private key as a file. Make sure to download and keep that file securely, as there will be no way to download it again from the APIs Console.
- Download the Private Key File and close the dialog.
- The APIs console will now show a service account with a Client ID and Email address
The private key file, client ID and email address will be used in later steps.
Step 2: Grant domain-wide access
Goal: Delegate domain-wide authority to the service account
- Go to the Google Apps Domain admin console. The URL will look like
https://www.google.com/a/cpanel/<mydomain>
- Open the Security control. If you can't find it, it may be under "More controls"
- Click "Advanced settings" and under Authentication click "Manage third party OAuth Client access"
- In the Client Name field enter Client ID of the service account.
- In the One or More API Scopes field enter a comma-separated list of scopes that the enterprise application should be granted access to. In this case I just used https://www.googleapis.com/auth/drive, but for a complete list of Google OAuth 2.0 scopes, I suggest going to https://developers.google.com/oauthplayground/
- Click the Authorize button
The service account made in step 1 now has domain-wide access to the Google Drive API for all users of the domain.
Step 3: Implementing the application
Goal: Connect to Google Drive via .NET
This step will only cover the most important parts as I assume you know how to create a new project in the IDE of your choosing ;)
- Go to https://code.google.com/p/google-api-dotnet-client/wiki/APIs#Drive_API and download the latest version of the Drive API library
- The image below depicts the contents of the library's archive. Make sure to also extract the contents of the google-drive-xxx-bin.zip sub-archive.
- In your project, add references to the following assemblies:
- Lib\DotNetOpenAuth.dll
- Lib\Google.Apis.dll
- Lib\Google.Apis.Authentication.OAuth2.dll
- (zip) Google.Apis.Drive.v2.dll
The following codesnippet shows how to access a list of files using the DriveService class.
private const string SERVICE_ACCOUNT_EMAIL = "[email protected]";
private const string SERVICE_ACCOUNT_PKCS12_FILE_PATH = "\\PrivateKeyFile.p12";
private const string USER_ACCOUNT_EMAIL = "[email protected]";
private DriveService _driveService;
public void InitializeService()
{
_driveService = BuildService();
}
private DriveService BuildService ()
{
var certificate = new X509Certificate2 (SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable);
var provider = new AssertionFlowClient ( GoogleAuthenticationServer.Description, certificate )
{
ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
Scope = DriveService.Scopes.Drive.GetStringValue(),
ServiceAccountUser = USER_ACCOUNT_EMAIL
};
var auth = new OAuth2Authenticator(provider, AssertionFlowClient.GetState);
return new DriveService (new BaseClientService.Initializer { Authenticator = auth });
}
public IList GetAllFiles()
{
var request = _driveService.Files.List();
var response = request.Execute();
return response.Items;
}
Important highlights:
- line 13. The password for all Google-issued private keys is the same ("notasecret"), but each key is cryptographically unique.
- line 17. Make sure to user the emailaddress created in step 1 ending with "@developer.gserviceaccount.com"
- line 19. This is the emailaddress of the user who created the serviceAccount. This address can be found in the Google APIs console - API Access tab - Branding Information - "Google account" and is different to the one specified in line 17.
- line 26. This example returns a list of type Google.Apis.Drive.v2.Data.File
Troubleshooting
-
Error: "Could not load file or assembly 'System.Net.Http.Primitives...." (occurs on line 13)
Solution: Install Microsoft Http Client Libraries (use NuGet) -
The first API-call to the service results in an error: Google.Apis.Requests.RequestError - Access Not Configured [403] ... (occurs on line 29)
Solution: Enable the used service APIs on the Services tab in the Google APIs console (see step 1) -
The request did not yield any results (occurs after evaluating the response in line 30).
Solution: Assuming there are files located on the Drive, make sure the emailaddress of the ServiceAccountUser matches emailaddress of the user that created the service. This address can be found in the Google APIs console - API Access tab - Branding Information - "Google account"