3

Hello

I'm am currently trying to create a file under a specific user account.
The user account is located within my Google Domain.
For Oauth im using a service account.

The DriveService()

private static DriveService Service()
    {
        var certificate = new X509Certificate2(Constants.P12, "notasecret", X509KeyStorageFlags.Exportable);
        var credential = new ServiceAccountCredential(
           new ServiceAccountCredential.Initializer(Constants.ServiceAccountEmail)
           {
               Scopes = new[] {
                   DriveService.Scope.Drive,
               }
           }.FromCertificate(certificate));

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

        return service;
    }

Creating a file

private static void CreateDriveDocument(string title)
    {
        Console.WriteLine("Google - Create New Document:" + Environment.NewLine);
        File body = new File();
        body.Title = title;
        body.Description = "A test document";
        body.MimeType = "text/plain";
        byte[] byteArray = System.IO.File.ReadAllBytes(@"C:\myDoc.txt");
        System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);

        //Callin the service at "Service()"
        FilesResource.InsertMediaUpload request = Service().Files.Insert(body, stream, "text/plain");
        request.Upload();
        File file = request.ResponseBody;
    }

So here I create a File, since I authenticated with the ServiceAccount, thats where the File is uploaded.

The Question

I need to be able to Create/Copy this file to a specific user withing my domain. And make that user owner of the file.

All help is appreciated.

Old post Reference

TransferOwnership Using Google SDK

Community
  • 1
  • 1
Nick Prozee
  • 2,823
  • 4
  • 22
  • 49

2 Answers2

3

I'll go with Marcel Balk anwser.

This way we will use impersonation!

we can use the service account to authenticate, then use any email account in our domain and upload files. The uploaded files will be visible in the users Drive under My Files (not Shared with me!) Files also are owned by the impersonated account. Tested in a little console app:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Services;

namespace UseWebServiceMethod
{
    class Program
    {
        // Goto https://admin.google.com/AdminHome?chromeless=1#OGX:ManageOauthClients
        // Login met admin account => ****@***.***
        // Add/edit Client Name (Use Client ID of service account here) => 2***8.apps.googleusercontent.com
        // One or More API Scopes => https://www.googleapis.com/auth/drive 

        public const string ImpersonatedAccountEmail = "****@***.***";
        public const string ServiceAccountEmail      = "2******8@developer.gserviceaccount.com";
        public const string Key                      = @"C:\Users\Wouter\Desktop\GoogleTester\GoogleTester\A****c.p12";
        public const string FileToUpload             = @"C:\Users\Wouter\Desktop\GoogleTester\GoogleTester\whakingly.txt";
        public const string ApplicationName          = "A***l";

        static void Main()
        {
            var certificate = new X509Certificate2(Key, "notasecret", X509KeyStorageFlags.Exportable);
            var initializer = new ServiceAccountCredential.Initializer(ServiceAccountEmail)
            {
                Scopes = new[] { DriveService.Scope.Drive },
                User = ImpersonatedAccountEmail
            };

            var credential = new ServiceAccountCredential(initializer.FromCertificate(certificate));
            var driveService = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = ApplicationName
            });

            // Show all files
            var list = driveService.Files.List().Execute();
            if (list.Items != null)
                foreach (var fileItem in list.Items)
                {
                    Console.WriteLine(fileItem.Title + " - " + fileItem.Description);
                }
            Console.WriteLine("Press Enter to continue.");
            Console.ReadLine();

            // Upload a new file
            File body = new File();
            body.Title = "whakingly.txt";
            body.Description = "A whakingly (that a new word I created just there) file thats uploaded with impersonation";
            body.MimeType = "text/plain";
            byte[] byteArray = System.IO.File.ReadAllBytes(FileToUpload);
            var stream = new System.IO.MemoryStream(byteArray);
            FilesResource.InsertMediaUpload request = driveService.Files.Insert(body, stream, "text/plain");
            request.Upload();
            File file = request.ResponseBody;
            Console.WriteLine("Press Enter to continue.");
            Console.ReadLine();

            // Show all files
            var list2 = driveService.Files.List().Execute();
            if (list2.Items != null)
                foreach (var fileItem in list2.Items)
                {
                    Console.WriteLine(fileItem.Title + " - " + fileItem.Description);
                }
            Console.WriteLine("Press Enter to continue.");
            Console.ReadLine();

        }
    }
}
1

You can easily do this by adding the user to the code. See the user i added.

private static DriveService Service()
{
    var certificate = new X509Certificate2(Constants.P12, "notasecret",X509KeyStorageFlags.Exportable);
    var credential = new ServiceAccountCredential(
       new ServiceAccountCredential.Initializer(Constants.ServiceAccountEmail)
       {
           Scopes = new[] {DriveService.Scope.Drive},
           User="someuser@somedomain.someextension" //Add this to your code!
       }.FromCertificate(certificate));

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

    return service;
}

Then go to admin.google.com --> Security --> Advance settings --> Manage oauth client access

Add the client id to the client name and add your scope (http://www.googleapis.com/auth/drive) to the "One or More API Scopes field"

Marcel Balk
  • 61
  • 1
  • 4