Google Drive API V3 Service Account 68


Google Drive API V3

Google Drive API V3

This Tutorial was completely rewritten in April, 2021

There are a lot of use cases for accessing the Google Drive API v3 with a service account. Think of a service account as a dummy user. You can pre authorize a service account granting it access to your data. So I can take the service accounts email address and share with it a directory on my Google Drive account then it will have access
to upload to that directory on my google drive account. It’s that simple there will be no need for user interaction and a consent screen to popup.

You should consider using a service account if you are going to be accessing private data that you the developer own, if you are going to be accessing data that belongs to another user then you should be using Oauth2.

So you will need to go to Google developer console and create a new service account. Download the json key file and don’t forget to enable the google drive api
under libraires. If you have any issues I have a video which you can go check out and it will walk you through creating
service account credential key file.

How to create Google Oauth2 Service account credentials.

Create .net core console application

For this i am going to create a .net core console application, but you can use service accounts, with libraries or with asp .net core its up to you which type
of project you create but for this example we are going to keep it simple and just use a console app.

you will need to include the google.apis.drive.v3 nuget package.

Add constant

At the top of my program class i am going to create a couple of constants.

The first is the path to the credentials.json file we downloaded from google developer console, as always don’t share your credentials with anyone these should
be stored save and secure for only your team to access.

I will need another constant for the service account email address, you can get this from google developer console or you can just open the key file in a text editor
and you will find it there its the one that contains an @ and looks kind of like an email address.

In my project i have created a simple text document called Test hello.txt remember to set this file to copy always under its properties. So i have added the name
as a constant here just for consistency.

Finally i have a directory id constant which is the file id of the directory on my google drive account which i shared with the service account. The easiest way
to find the directory name here is to do a file.list and it will list all of the files that the service account has access to it will also return the directory
that we shared with it so we can get the file id we will need to upload our files.


        private const string PathToServiceAccountKeyFile = @"C:\Youtube\dev\ServiceAccountCred.json";

Authorize service account

Ok now we we will need to load the credentials into our application. We simply load the credentials key file and set which scope we will be using. Due to the fact that we will
be uploading a file we will need write access to the drive account. so we will be using the drive scope, to attain full access to the users drive account.


// Load the Service account credentials and define the scope of its access.
var credential = GoogleCredential.FromFile(PathToServiceAccountKeyFile)
                .CreateScoped(DriveService.ScopeConstants.Drive);

Create Google Drive API V3 service object.

Finally we will create our drive service. All calls to the Google drive api will be run through the Google Drive API v3 service object.


// Create the  Drive service.
var service = new DriveService(new BaseClientService.Initializer()
    {
    HttpClientInitializer = credential
    });

List files from the Google Drive API

By default when you first create the service account it wont actually have any files uploaded to its Google Drive account. However if you go to your personal Google drive account and share a directory with the service account email address it will then have access to the files with in that directory. I can use the Q parameter as part of the files list method in order to search for the files within that directory. I have another tutorial which goes in to much more detail as to how to use the Q parameter with the Google Drive Api
Search files with Google Drive api v3


// Search for text files in the directory on my account.
var request = service.Files.List();
requestSheet.Q = "parents in '10krlloIS2i_2u_ewkdv3_1NqcpmWSL1w'";
var responseSheet = await requestSheet.ExecuteAsync();

Conclusion

You can use a service account to access data on the Google Drive API v3 whenever you need to access data that you the developer own. Service accounts can be very useful when sharing standard images and files to your user which you would like to control on your own account but still grant your users the ability to download them though the Service account.


About Linda Lawton

My name is Linda Lawton I have more than 20 years experience working as an application developer and a database expert. I have also been working with Google APIs since 2012 and I have been contributing to the Google .Net client library since 2013. In 2013 I became a a Google Developer Experts for Google Analytics.

Leave a Reply to Joebet Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

68 thoughts on “Google Drive API V3 Service Account

  • Russell Graves

    This is nice, but I don’t think it works because “ServiceAccountCredential” does not exist in “Google.Apis.Authentication.OAuth2” it was part of “Google.Apis.Auth.OAuth2” which is obsolete now.

    This is the problem I have been having for some time. I have yet to find a Google Service Account C# example that will actually compile.

    This article says Feb 10, 2015, but have you really tried it with current stuff? I hope I am just an idiot, and that there is something I’m missing here.

    Any input??

    Thanks,

    Russell

    • Linda Lawton

      No input at all. I just ran this and it ran fine. Uploaded 3 files, my usings are

      using System;
      using Google.Apis.Drive.v2;
      using Google.Apis.Auth.OAuth2;
      using System.Threading;
      using Google.Apis.Util.Store;
      using Google.Apis.Services;
      using System.Security.Cryptography.X509Certificates;
      using System.IO;

      I will add this code to the sample code lib asap. I have just been having GitHub learning issues.

  • Vo Son Ha

    Dear Linda Lawton,

    – I try this for my project in my computer, it’s work fine. But when I run on my server (Windows Server 2008 R2) , it show error : “invalid_grant”.
    Can you help me please

    Regards,
    Havs

  • Sun

    Now, I need a function to do this:
    the service will read my own gmail-box every fifteen minutes.
    so which authentication are applied to me? please…

  • Daria

    Linda, you have such a great research at google drive api. I need to use such application on my website – uploading files to google drive with php. Where I can find such implementation in PHP? I checked your article about Google calendar service account using but got problems doing it at google drive api. Thanks a lot.

  • Joebet

    When i try to upload a file it returns null. even when i tried to edit ServiceAccountEmail with a wrong one it doesnt return nulll in the service.. do you know anything about it?

  • Darrell Sveistrup

    “Using a service account to access Google Drive API can be very useful but it is important to remember that a service account is not you. If you want to be able to access the files it uploads you must grant yourself access to them though the service account.”

    If you create a folder on google drive,
    And give your service access to create new files in that folder.
    Would the new files not have the credentials of the parent folder and you will have access to any created ?

  • pregunton

    it’s great. LindaLawtonDK marvellous guru.

    Any full source sample application using YouTube API C# Using good patterns and practices?

    First, i’m very newbie using google APIs.

    I want create unit test in C# for get (and add) URLs videos to my playlist in YouTube. then, I want use YouTube API.

    I’m confused about authentication methods: Simple Key, OAuth2, Service Account, etc ?.

    Any suggestions about it?

    • Linda Lawton

      wow when did i reach guru status? I should put that on my email signature.

      The best i can do is this Youtube I know it says Google Analytics but some of it is YouTube I was testing and uploaded it but never finished.

      You can use a public key for a lot of the YouTube API, anything that is not public you will need to use OAuth2 for. The YouTube API doesn’t support service account access, unfortunately.

  • Santhosh

    Using service account When I try to access the files from Google drive I am unable to get any file, But when I shared the files to service account email, I am able to get all shared files and folders. Instead of sharing to service account email is their any way to get all file of Google drive, using service account email.

  • Hernán

    Hi Linda. I’ve successfully managed to get php to upload files and list them. I can see they’re there. But, I have no idea how to access them through the regular Google Drive interface. Is it possible to see the service account’s files that way? Is it possible to see them outside the API?

    BTW, I couldn’t have done it without your article, thanks!

    • Hernán

      After a little bit of struggle, I understood how to upload files and see them as a regular user with php:

      1. I created a folder as a regular Google Drive user.
      2. I shared it with the service account email.
      3. I used:
      $parent = new Google_Service_Drive_ParentReference();
      $parent->setId(”);
      4. I inserted the file.

      Voilá! I can see and synchronize it with Google Drive.

    • Linda Lawton

      A service account is its own Sudu user, you are uploading files to the service accounts Google Drive account. If you want to see them on your account. Do a patch on the files and update the permissions Grant your google drive account access to the files.

  • vishal middha

    Hello linda,
    As i am working on a project and i want to allow users to upload files from their account. i want to store that files into my google drive.
    Can you please help me with this issue?

    • Linda Lawton Post author

      Probably not. Its probably the default size of a google drive account. Try running About about = service.About.Get().Execute(); see how much space it has. Either way you won’t be able to extend it. You can however give it access to a folder on your Google drive account then you can pay for an extension of the size of that.

        • Linda Lawton Post author

          The other way around. Create a folder on your Google Pro account. Add the service account email address as a user, give it write access.

          The service account can now upload to that folder. However it is important to remember after you do a file.insert using the service account to do a permissions.insert on the file that you just inserted to give yourself access to the file other wise the service account will own the file.

          ————————————-
          But yes if we create a bunch of service accounts and just share the folder with ourselves technically we would get more space for free 🙂 Just don’t delete the service account in dev console or you will loose it and there is no way of getting it back.

  • flashharry

    I am aware that it i possible to show your Google Photos as a subfolder within Google Drive.

    Can you use this technique in order to a service account access to your Google Photos using the Google Picasaweb API?

  • Gopal Biswas

    I couldn’t find the section Service Account details screen(showing CLIENT ID/ Email Address/ Certificate Fingerprints) section as mentioned in this article from my console.developers.google.com.
    Actually an error is showing for FileList filesFeed = list.Execute();
    and the error stated as “”invalid_client”, Description:”The OAuth client was invalid.”, Uri:”””.

    Currently I’m using my email id as it is for AuthenticateServiceAccount and I want to check and use the google created email id.
    One more thing please tell me the way to create a directory and give full permissions to it.
    Please help

    • Linda Lawton Post author

      a service account isn’t you and you cant use your email address to authenticate you need to use the service account email address from google developers console.

      • pantonis

        When I try to do

        Permission permission = new Permission();
        permission.EmailAddress = “myemail@gmail.com”;
        permission.Type = “user”;
        permission.Role = “reader”;

        var cr = service.Permissions.Create(permission, obj.Id).Execute();
        var updatePermission = service.Permissions.Update(permission, obj.Id, cr.Id);
        updatePermission.TransferOwnership = true;
        updatePermission.Execute();

        I get

        Google.Apis.Requests.RequestError
        The transferOwnership parameter must be enabled when the permission role is ‘owner’. [403]
        Errors [
        Message[The transferOwnership parameter must be enabled when the permission role is ‘owner’.] Location[transferOwnership – parameter] Reason[forbidden] Domain[global]
        ]

  • Walter ZAMBOTTI

    Hello Linda

    Thank you for providing these fine examples.

    In relation to the Google Drive API with a Service Account example I have successfully used it to create a drive service as expected.

    However I am unable to use the resulting drive service to do anything (list files, upload etc).

    Can you help me to understand the significance of the “ApplicationName” in relation to the drive service and what should this application refer to? i.e: Is this application something that I need to register via the google admin console?

    • Walter ZAMBOTTI

      I had a break through!

      When I was supplying the google account email I was using the email address of the associated with the actually google drive. For example

      MyGmailAccount@gmail.com : It was was under this google account that have my normal access and where I created the service account key.

      However when setting up my service account key I noticed another email address called the service account ID.

      For example:

      Service-Account-Name@logical-codex-149004.iam.gserviceaccount.com (which is auto generated by the admin console)

      When I use this email address with ServiceAccountCredential.Initializer it all works.

      I am a little confused! Any clarification appreciated.

      • Linda Lawton Post author

        A service account isn’t you even though it was created by your gmail account in Google developer console. Think of service accounts as dummy user accounts, it has its own google drive account, google calendar, and probably a bunch more. It has access it its own account, you can share your information with it like you would any other user. (Try sharing a file with it from your drive account by adding its email address like you would any other user).

        You might want to try reading this Google Developer console service account it should help remove your confusion.

        • Walter ZAMBOTTI

          And further if you use this to initialize the credentials all files uploaded via the service account will immediately appear for the regular use of the google account without playing around with permissions.

          sacredential = new ServiceAccountCredential
          (
          new ServiceAccountCredential.Initializer(serviceAccountEmail)
          {
          Scopes = scopes,
          User = regularAssociatedAccountEmail // add this to allow the account user to see uploaded files

          }.FromCertificate(certificate)
          );

          • Linda Lawton Post author

            That one i wasn’t aware of. Going to have to dig around in the library on that one. I though User was just for creating the credentials on the machine. Nice find.

          • Luca

            Hi. I was looking for the same functionality but I am using a v3 REST service from an Angular2 application:
            – I retrieve the access token for the service account through my server
            – I have shared a folder in my main Google Drive account (Pro version) with the service account email
            – I can use the REST calls to upload files in the folder of the Pro account
            – the owner of the files remain the service account
            – when I try to change the owner using the “permissions” REST interface, I get errors like “ACL change not allowed”. I can only create a “write” permission of the Pro account, not an “owner” permission.
            In summary what I try to achieve is to move the files from the service account to the pro account programmatically.
            I have tried to find this “regularAssociatedAccountEmail” in the documentation, but I was not able to find anything.
            Any suggestion?
            Thanks

          • Luca

            Update:
            I found out that service accounts can be used to “impersonate” another user inside the domain:
            https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
            When getting the Auth token from my server I just have to set the email address of the user to impersonate:
            http://stackoverflow.com/questions/22640488/how-do-i-use-jwt-to-access-google-directory-admin-sdk-using-nodejs-client-libr
            The token received allows to store files with correct owner and not service account owner.
            Bye
            Luca

  • Sanket

    Hi,
    cann’t we use Google driver api with service account for accessing other google user’s drive information ?
    we have requirement like above. we wrote code and its working for google user in which we created service account but not for other user google.
    we added other user email at where we set scope.
    we got error like “unauthorized…..
    can you please help in this case?

    Regards,

    • Linda Lawton Post author

      Service accounts must be pre-authorized. Any directory you want it to be able to access must be shared with it. Have the other user take the service account email address and share a directory with it. Service accounts can only access directories of users who have shared with them.

  • Dkns

    Hi Linda,
    Is there any code or methods of google drive api so that i can iterate for each user drive by service account. We have enterprise account and generate p12 for that service account and got the list of users but stuck to access every users files and folders

    • Linda Lawton Post author

      The service account is a user you can only access the files that the service account has access to not another users.

      I suggest you try looping though each file and see who the owner is if its not the service accounts its probably one of the other users you are speaking of.

  • harsha parchure

    Hi Linda,
    I have a service account. I want to use google drive as storage for my application (an ASP.net server, to be precise). Users upload & download files from my application & the storage is transparent to them. In short, my application owns the drive & files uploaded by users to my application.
    i have obtained a .json file which is something like this (property values are changed) :
    ———————————
    {
    “type”: “service_account”,
    “project_id”: “myapp4321”,
    “private_key_id”: “892f858b43b070296b6b5ee2bcd5db04d16782f2”,
    “private_key”: “—–BEGIN PRIVATE KEY—–\nQEFAASCBKcwggSjAgEPtfjSIWQH6nsK3o4YI8y/R7WQeNqpTCDTnfcwTRsY\nz0MmDVSvVeD/cJhg9fX2GSNJ8pUk0usvvs2Ah5M8WG9afJcOAHVEDUEtZTHKMIIEvQIBADANBgkqhkiG9w0BA2U8z\nk5xi3CBmmzwcbPx1Vnzrv/n0glA\nmFtBBhfTn8kErQMCidDAuhMaN8ZLa6zMDwQ1BSNHl2tBPQ+2ly0F28uU+lUq8SNx\n86APf5FbtZWY0vI25inPgHtIUlpyFk02MAcxo4v0/04FdO/uV7G6pQVtWZi4F2zA\nH8Dc3GUeDJS+bu6AcCfIYvq6eCcG7lgc30u4JbJwgqgAFkJkmMb9ZnRM62XfjPK6\nbd8Fvpj/AgMBAAECggEAFaYXoLTTYuLJUXkQhpnHZvKR5y7m9lTrMp+RfaZSTrcR\naK03n1HaHD1O0ZaRF3q3T3Ggw5qCAFYKUYaNZxM17/q3dk04C7AXdzpsZfcJ0qo5\nbnf8l+5QDaLF5mdhk2YC1od45VD+vse2jjj2fH8hBhm3lzSMCFnB2VnFlC35ksrC\nSStZWGu7DB6jDxiN9M2zE/8u0+3YbWmf02+0UJIK/thjiodhsxnSMlHxS1r6VdKc\nPBeJVdanxqJbix7ls2U4VQhXhYmmB+qR/svgf7Ftgpd+fTQBsrRe8OHalLuJrxaY9anMl2KENrc/rf9by3XePdPnhE/AoGAKg3X3V3X1r42DiVrQm6j\n13j1Mhrkj/F5svNXUC+b3apEy+RiMHmiL+h/cKZOKfCWEtlchKVOc+td+U0vsPhNnBRLgGJQ+5mcY5h6kie\nN3svg1BYk3N8PE1GvD0ZCQHhJSmGFwXIKywCjNq8yb93CrmL0n/9amzgHYy06ZIv\nO1X4GlRiyJvYoaX50pOU8AntmQKBgQDwg6B6OExUzg/CmtDLIOYXsnYg8iFCorZa\n2/I3OvW+dARH+MbOfb64SCWxd6EU6/a69kaLnpCY1qiy7WFk\nt0lfHVoAI3QNUZ6baGtF7Rns8Av2buUJ+BaqQs6G4QKBgQD6cHB4VgARTeZzragV\nfNP8YB9TuitVeMYmtGw8Pc9h8CLbJk9cdOugJCs5YNT7O\n+icZfJ/chlx8wae5KNZ8N/V8X57+PmQ9AnBfOvs4KLCl28gGGYi8zGovrYo+/jlW\nnqZm75+qBxrMHnps6BgQDocNHCrrdzWCUreqNGBkzOsfyBfopX0ze+lrjalNfVY+zmpCCh\nRj3+GAixktlFP3yxrAya9WTgykbHlGaACqiX6b356ClIxsNGgtIGWXjYGeDXZqjk\nJ0W6vDcNAAdoGpkqMF7AuzWAMYz2IM+gbOcW1oE6Ck2znBzrqUl28++TCQKBgGIM\ndvZ8Tvnfi2M9M9MrVUHh2fByZQbCSG7f7W2AlsAOkdQ5Yeq6Lm730o33g+6Ah3QO\nhBHVsd5+qBhqag2DCp6lsju/O0B35Fz3ACpF9nlqvI/RRtid485IW10Gfm3P+AKz\nBoBnzG5eMWebp8X6GtKClISwt6IhD\nVeml5JVu/7jPyrY1aqkLuGGiP8qJLbHHl3c7rYlhFDR+m2a82awqUV+Wp63zLk0q\ncc10DVnqVwKEr++/Q=\n—–END PRIVATE KEY—–\n”,
    “client_email”: “abc-123@abcd0001.iam.gserviceaccount.com”,
    “client_id”: “117247463677611826389”,
    “auth_uri”: “https://accounts.google.com/o/oauth2/auth”,
    “token_uri”: “https://oauth2.googleapis.com/token”,
    “auth_provider_x509_cert_url”: “https://www.googleapis.com/oauth2/v1/certs”,
    “client_x509_cert_url”: “https://www.googleapis.com/robot/v1/metadata/x509/abc-123%abcd0001.iam.gserviceaccount.com”
    }
    ———————
    X509Certificate2 call is throwing an error : Cannot find the requested object.
    Stack trace is as follows :
    at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
    at System.Security.Cryptography.X509Certificates.X509Utils._QueryCertFileType(String fileName)
    at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags)
    at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)
    at DigiDoc.Entities.GoogleDriveAccessor.AuthenticateServiceAccount(String srvcAcctEmail, String keyFilePath) in E:\DigiDoc\DigiDoc\DigiDoc\Entities\GoogleDriveAccessor.cs:line 75

    Could you please help me with this ?
    Thanks in advance.
    Regards

  • Maninder Sran

    For some Google API such as the cloud storage there are methods that allow you to implicitly authorize your application using default credentials associated with the service account. Do you have experience with this or know if it can be done with the Drive API, as then you wouldnt need to store the credentials?

    • Linda Lawton Post author

      not unless you have a google workspace account. Cloud service accounts work differently then discovery services api service accounts the system has been around a while and there been any changes.

  • Scott

    Just a heads up, I’m tracking down an issue with the newer IIS and ServiceAccountCredential. It seems that IIS doesn’t have access to the keystores and none of the fixes I’ve found thus far have allowed access. So this code may not work in IIS…

  • John M

    Linda,

    I watched your video relating to this blog and was wondering if you could advise on how best to adapt this for google maps. I have a few people who create google maps with shapes and other data on them which are then shared to a limited number of people ie the link is not public. What i would like to do is then access these maps via a blazor app. Your blog has pointed me to a google service account but i’m not sure it will actually do what i want. I’m not sure simply because i have read that google maps don’t work the same as google drive.

    Ideally the user would create the map and then store it in a database and the blazor app would use that URL combined with the appropriate authentication to display said map. I have spent the whole day researching this and not found anything that answers the question. Your blog seems to be the closest, but before i invest more time can you advise it i’m even on the right track..

    thanks

    John