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.
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
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.
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
There are two reasons that i know of to get the invalid_grant error. check this post Google API Error List
Can this function work for Gmail API?
No you cant use a service account with Gmail
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…
OAuth2 you cant use a service account with Gmail. Authenticate your service once then just use the authentication returned from that point on.
How do I have the service account grant my Google account access?
Check permissions I have plans on extending the tutorial series if enough people request it.
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.
I don’t know of any that have been developed this is probably something you will have to develop yourself.
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?
A success from file.insert should return a file resource, if its not there is something wrong with your application.
“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 ?
As far as i have tested, the file is owned by the person or the service account that uploads the file. You have to patch the permissions after insert.
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?
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.
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.
The service account has to have access to the files just like a user does. So you need to share the files with it if you want it to have access.
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!
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.
the automatic formatting partially deleted this: $parent->setId(‘the shared folder ID’);
Wow congrats you fixed it faster then i could respond to the comment 🙂
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.
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?
Create a service account and grant it access to your Google Drive using the service accounts email address. Have the users upload using the service account.
Hi Linda,
Can I have more than 15GB storage to my service account ?
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.
Ah interresting, so if I share the folder of the service account in my google pro account I can have more space ?
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.
Alright thank you very much Linda 🙂
Is there any way to use this technique to manipulate the Google Shared Contacts?
I am not sure I dont have access to Shared Contacts so i cant test it.
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?
I havent been able to find a way of sharing a Picasaweb album with a service account yet. If you figure it out please let us know.
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
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.
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]
]
As far as i know this is bugged right now. I have seen a few questions about this on stackoverflow.
Hello! you have this example in github ?
Yes if you look at the top number 5 says Google Drive API with C# .net – Sample project
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?
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.
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.
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)
);
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.
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
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
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,
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.
Okay, i will check and let you know.
Thanking you very much for quick reply
Is there a possibility to increase the disk space at a service account?
No as far as i know its linked to the account of the developer who created the service account.
Good day. I have a Service account key. Use this account key I upload the file to google drive. And in fact, the owner of these files is a service account. How to show files of the account service, open storage this service account? Or how to make the owner of the files was my account someemail.gmail.com?
You need to update the permissions on the file after you have uploaded it making yourself the owner of the file and not the service account. https://developers.google.com/drive/api/v3/reference/permissions
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
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.
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
If you pop your question up on I would be happy to have a look at your code
Hi, how get Contacts from google people api, my contacts account, with service account ??
You cant as far as i know google contacts doesn’t support service accounts.
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?
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.
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…
are you sure this is an issue with the json key file and not just with the p12?
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
Google maps is a javascript library it wont work with service accounts. It just runs with an api key you should be able to use that with blazor.