5
votes

I've tried creating a DriveService using service account acting on behalf of another user.

I've copied this code from google documentation found here https://developers.google.com/drive/delegation

    static DriveService BuildService() {
            X509Certificate2 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(),
        };
        var auth = new OAuth2Authenticator<AssertionFlowClient>(provider, AssertionFlowClient.GetState);
        return new DriveService(auth);
    }

but I get this warning when trying to build the project:

Warning 4 'Google.Apis.Authentication.OAuth2.DotNetOpenAuth.AssertionFlowClient' is obsolete: 'AssertionFlowClient is not supported any more and it's going to be removed in 1.7.0-beta. Consider using ServiceAccountCredential from the new Google.Apis.Auth NuGet package.'

and I also get this error:

Error 11 Argument 1: cannot convert from 'Google.Apis.Authentication.OAuth2.OAuth2Authenticator' to 'Google.Apis.Services.BaseClientService.Initializer'

Then I googled ServiceAccountCredential and ended up with this code (derived from this page: https://code.google.com/p/google-api-dotnet-client/wiki/OAuth2#Service_Accounts)

static DriveService BuildService() {
            X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable);

        ServiceAccountCredential credential = new ServiceAccountCredential(
            new ServiceAccountCredential.Initializer(SERVICE_ACCOUNT_EMAIL)
            {
                User = "[email protected]", 
                Scopes = new[] { DriveService.Scope.DriveFile }
            }.FromCertificate(certificate));

        var service = new DriveService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "Drive API Sample",
        });

        return service;
    }

When I try to build this code it seems all fine, but when I run it I get the following error.

A first chance exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll

Additional information: Det går inte att hitta det begärda objektet. (Translated : The requested object cannot be found)

If there is a handler for this exception, the program may be safely continued.

The error occurs on this line:

X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret", X509KeyStorageFlags.Exportable);

Anyone have any ideas?

Update 2013 Oct 31 I have tried this code:

{
        Console.WriteLine("Drive API - Service Account");
        Console.WriteLine("==========================");

        String serviceAccountEmail = "<some email>@developer.gserviceaccount.com";

        var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable);

        ServiceAccountCredential credential = new ServiceAccountCredential(
           new ServiceAccountCredential.Initializer(serviceAccountEmail)
           {
               User = "<someuser>@<mydomain>.mygbiz.com",
               Scopes = new[] { DriveService.Scope.Drive }
           }.FromCertificate(certificate));

        // Create the service.
        var service = new DriveService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "DrvMgr",
        });

        Console.WriteLine("Executing listing");
        FileList UserFiles = service.Files.List().Execute();

I get this error message:

An unhandled exception of type 'Google.Apis.Auth.OAuth2.Responses.TokenResponseException' occurred in Google.Apis.dll

Additional information: Error:"access_denied", Description:"", Uri:""

1

1 Answers

0
votes

It looks like the path to your p12 file is incorrect. See the Plus.ServiceAccount sample for a working solution.

I think that in this sample, the key.p12 was added to the project as a content file which is always copied to the output directory. Then mentioning "key.p12" file path from the code will result in grabbing this file from the output folder.