Google Drive API authentication without user interaction

I'm looking for a Google Drive API authentication scheme that will grant application use rights (on the server) to create shared documents in a Drive folder without user intervention.

The current Google unique name for the particular authentication scheme I have to use for this is probably a sufficient answer to this question.

Although the document creation will occur in response to user action, the documents will not be permanently associated with these users, and I do not want to require any user to submit a Google account. Instead, I want the user to be able to access the document through the Anyone Can Edit Link URL displayed on the web page after the document is created.

This is intended to automatically generate documents for several usually anonymous people to work with, and all documents will be stored in one folder.

There is a good chance this is a duplicate of this question: Google Drive API username + password authentication . Unfortunately the accepted answer doesn't provide enough information for me to find my way now that the links it links to are dead.

This may be a duplicate of the other issues that have received, but vague answers, such as: the API the Google Docs authentication (without user interaction) , How can I authenticate the Google Calendar API v3 without user interaction? and Download documentation from the API disk from the server without user interaction .

+3


source to share


1 answer


Authenticating as a service account was the appropriate approach.

The actions of the Google SDK are simply misleading. When I presented some wrong values, it went back to custom authentication (automatically opening a web browser to prompt for interactive credentials). I misinterpreted this to mean that the service account functionality was implemented as a long-term key, approved and in the context of a specific interactive user, or something similar.

No user interaction required, however a .p12 certificate is required and not any credentials provided by the default .json file (which I tried in multiple ways). Here is the code I used:

using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Http;
using Google.Apis.Services;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

using GData = Google.Apis.Drive.v2.Data;

public class Drive
{
    private const string GoogleDocMimeType = "application/vnd.google-apps.document";

    /// <summary>
    /// Creates a drive service, authenticated using information found in the Google Developers Console under "APIs & auth / Credentials / OAuth / Service account"
    /// </summary>
    /// <param name="svcEmail">The service account "Email address"</param>
    /// <param name="certPath">The path to the service account "P12 key" file</param>
    public Drive(string svcEmail, string certPath)
    {
        Service = AuthenticateService(svcEmail, certPath);
    }

    private DriveService Service
    {
        get;
        set;
    }

    /// <summary>
    /// Creates a "Google Doc" and shares it with anyone with the link
    /// </summary>
    /// <param name="title"></param>
    /// <returns>The drive FileId, accessible at https://docs.google.com/document/d/FileId </returns>
    public async Task<string> CreateShared(string title)
    {
        var fileId = await CreateDocument(title);
        await ShareFile(fileId);
        return fileId;
    }

    private async Task<string> CreateDocument(string title)
    {
        var file = new GData.File
        {
            Title = title,
            MimeType = GoogleDocMimeType
        };
        file = await Service.Files.Insert(file).ExecuteAsync();
        return file.Id;
    }

    private async Task ShareFile(string fileId)
    {
        Permission permission = new Permission
        {
            Type = "anyone",
            Role = "writer",
            WithLink = true
        };
        var a = Service.Permissions.Insert(permission, fileId);
        await a.ExecuteAsync();
    }

    private static DriveService AuthenticateService(string svcEmail, string certPath)
    {
        string[] scopes = new[] { DriveService.Scope.DriveFile };
        X509Certificate2 certificate = new X509Certificate2(certPath, "notasecret", X509KeyStorageFlags.Exportable);

        var init = new ServiceAccountCredential.Initializer(svcEmail) { Scopes = scopes };
        IConfigurableHttpClientInitializer credential = new ServiceAccountCredential(init.FromCertificate(certificate));

        return new DriveService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "Document Management Service",
        });
    }
}

      



And here's an experimental consumer:

internal class Program
{
    private const string svcEmail = "serviceaccountid@developer.gserviceaccount.com";
    private const string certPath = @"credentials\projectname-fingerprintprefix.p12";
    private readonly static Drive drive = new Drive(svcEmail, certPath);

    private static void Main(string[] args)
    {
        string id = drive.CreateShared("my title").Result;
        Console.WriteLine(id);
    }
}

      

This is similar to using Google Drive storage in a sandboxed data repository for apps / projects. According to other posts, there is no way to get the interactive Drive UI. I don't know if it is using my personal storage quota, etc. But this is the best approach I have so far and I will answer these questions for myself (not here).

+2


source







All Articles