Introduction
When you want to use Google APIs on your website, you first have to authenticate to Google. For services like Google Map, you can simply generate an API key and pass it along with your requests. However, for services like Google Drive, the API key option is not available. Instead, you can create a service account (sort of a bot account).
Service accounts are different from user accounts (normal accounts) in that they do not have passwords (but have emails!) and cannot log in via browsers. In the case of Google Drive, for example, it means that you cannot manage the files of the service account using the website (google.drive.com), but only through the Drive API. For authentication to Google, they make use of a private/public RSA key-pairs.
How to create a service account
You can create such an account in your Google Cloud Console.
If not already done, create a new project and head to APIs and Services. Under Credentials, you can click the Create credentials button and choose Service account in the dropdown.
Once done, you will be prompted to download a JSON file containing the credentials. Keep this file safe and do not commit it to your GitHub repo.
The JSON file should look like this:
{
"type": "service_account",
"project_id": "xxxx",
"private_key_id": "xxx",
"private_key": "xxxx",
"client_email": "xxxx@xxxx.iam.gserviceaccount.com",
"client_id": "xxxx",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "xxxx",
"client_x509_cert_url": "xxxx"
}
Example: using a service account to access Google Drive
Under APIs and Services in the Cloud Console, look for the Drive API and enable it. Now you can programmatically manage files in the Drive linked to the service account you created.
However, as mentioned before, you won't be able to see them in the browser. What you can do though is to log into google.drive.com with a "real" user account, then create a folder (using the UI) and finally share that folder with the service account by providing the value of the "client_email" property in the JSON file.
Now if you upload files with the service account to this specific folder, you will see them in your user account on google.drive.com 😃
The owner of these files is still the service account, meaning that if you delete them from the user account, they will still exist in the service account.
Show me some code
For this example, we'll write code in Node.js with the help of the official npm package googleapis
which contains helpers for all of Google APIs.
We first need to initialize a new client by providing our credentials and the access permissions we need (called "scopes" here). For the permission, we'll give the scope https://www.googleapis.com/auth/drive.file
(more info about scopes here).
For the credentials, we need to pass the data from the JSON file. You can either read it directly from the JSON file or add it as a string to an env file and then parse it.
The getCredentials
function below uses the first approach and fallbacks to the second.
Authenticating
function getCredentials() {
const filePath = path.join(__dirname, 'credentials.json')
if (fs.existsSync(filePath)) {
return require(filePath)
}
if (process.env.CREDENTIALS) {
return JSON.parse(process.env.CREDENTIALS)
}
throw new Error('Unable to load credentials')
}
async function getDrive() {
const credentials = getCredentials()
const client = await google.auth.getClient({
credentials,
scopes: 'https://www.googleapis.com/auth/drive.file',
})
return google.drive({
version: 'v3',
auth: client,
})
}
Uploading a file
Don't forget to specify the shared folder ID as the upload location, otherwise you won't be able to see the uploaded file in your user account.
You can find this ID easily in the address bar:
The following code snippet uploads a text file with a content consisting of the string "Hello World".
getDrive().files.create({
requestBody: {
name: 'Test',
mimeType: 'text/plain',
parents: [SHARED_FOLDER_ID],
},
media: {
mimeType: 'text/plain',
body: 'Hello World',
},
}).catch(e => console.error(e))
If everything went well, you should be able to see this file in your shared folder.
In a future blog post, I will share a real-world case about backing up data to Google Drive using Netlify Cloud Function.
Stay tuned!
Resources:
https://medium.com/@bretcameron/how-to-use-the-google-drive-api-with-javascript-57a6cc9e5262
https://cloud.google.com/iam/docs/service-accounts
Top comments (7)
Thank you very much for the awesome insights! That helps me a lot to upload my data to google sheet as well! The tricky point is how you access the uploaded on google drive which is amazing!
Hi,
How can I delete files from Drive with a service account?
Or how can I get back a folder ownership once I gave it to the service account?
Thank you!
Hi! Thanks for reading and sorry the late reply.
1) In the complete function on GitHub, I delete older backups.
2) In the share modal on drive.google.com, click on
advanced
and then you can click on the X to stop sharing with the service account.you can set GOOGLE_APPLICATION_CREDENTIALS=file.json to avoid parsing credentials
Hi, thank you for the article.
How to get image from drive, how can I do it, is it possible?
"Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
I'm getting this error. Any clue ?
Awesome articles. Helped me a lot.