Create a service account to authenticate with Google 
Tags: javascript, webdev, tutorial, node
Published: 2019-08-25 18:41:48

# 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:
```json
{
  "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](https://developers.google.com/drive/api/v2/about-auth)).

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

```js
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:
![shared folder id](https://thepracticaldev.s3.amazonaws.com/i/lp0h2cc8moykiemtdj9m.PNG)

The following code snippet uploads a text file with a content consisting of the string "Hello World".

```js
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