Using Google APIs in an App Engine Application with Node.js
Overview
Using Google APIs in an App Engine Node.js application can be confusing and there aren’t many articles about it. This article will explain how it works with Service Accounts and shows a working example to update a google sheet using Google Sheets Api.
Introduction
Accessing Google APIs from a Google App Engine application can be a very powerful tool. It can allow you to generate documents from templates with dynamic data from a database, updating spreadsheets based on web events, or automatically creating forms. This guide will explain how you can access Google APIs using a Service Account from a Node.js application running in Google App Engine. To follow this tutorial you should know the following items:
- Moderate Javascript experience
- Moderate Express experience
- Familiarity with Google Docs (Sheets, Drive, Documents, etc)
- Some Google Cloud experience
- Google Suite Admin Privileges
Google App Engine
So what is App Engine? Boiled down to a single sentence: It allows you to easily push code from a local machine to a virtual machine that Google manages, and then exposes that application on the internet. Typically I write an express layer that intercepts the HTTP requests and then runs logic accordingly.
High Level Concepts
In order to access Google APIs you need to be authenticated as the correct user using OAuth2.0. This is fine when you are running a local project and can authenticate using a token. But what if you want to have an application running in Google Cloud authenticate automatically and make updates in your name?
That’s where Service Accounts come in. Service Accounts are project level accounts that can access resources by impersonating a user. There are a couple things to keep in mind with service accounts when it comes cloud resources.
- What project level access do they have?
- What resources do they need access to?
Never give a service account more access then what is required. It can turn into a huge security loophole.
For a Service Account to authenticate with Google APIs there are a few more things to consider as well.
- What scopes do they have permission to access?
- What objects are shared with them?
Because a Service Account is identical to any other Google account, you need to share the documents you want them to manage with the Service Account. This can be done from the basic “Share” options from the document. Simply enter the Service Account name (because it is an email address) in the share field.
Scopes dictate the level of access that the Service Account has when interacting with Google APIs. An example would be giving read only access to Google Sheets, but write access to Google Docs. This helps prevent accidental security problems. Just like with cloud resources, only give the permissions that are required for the project.
For a Service Account to access these scopes, you need to enable them from the admin.google.com dashboard. We will go over this step in the following example project.
Example Project
The example project we are going to use in this application is very simple. We will create an application that will accept a POST request with specific fields in the body and write out that body into a Google Sheet that we control. While this project is very basic, it will explain all of the concepts required to build more complex applications.
Project Setup
Make sure to install the gcloud utility and setup a new Google Cloud project.
Let’s write some code.
Create a project folder on your local machine and run the following command
npm init -y
This will initialize a new Node.js project with default settings. Open the package.json file and add the following line to the “scripts” object.
“start”: “node app.js”
This defines a startup command, it will run the app.js file to run the application. Now create an app.js file in the root of the folder.
Run the following command to install express for the project.
npm install — save express
Add this code to your app.js file.
This code starts an express server on the correct port and responds to a GET request with the text “Hello World!”. This should serve as the foundation for any App Engine application that you write.
Google Cloud Setup
Hopefully you have already created a Google Cloud project for this tutorial. If not, do that now and make sure to enable billing. This project won’t cost anything upfront but billing is required to access the resources we are going to use.
Navigate to console.cloud.google.com and select your new project from the top dropdown. Then click the top left menu icon and select App Engine from the list. From this new screen select “Create Application”. Navigate through the following prompts. Make sure to select Node.js as your language and the Standard environment. That’s it! You have successfully created an App Engine instance.
Now lets deploy our basic application to test.
We need to setup a app.yaml file so App Engine knows how to run our application. Create app.yaml in the root of your project and add the following code.
Now run the following command
gcloud init
To select your project for the gcloud command line tool. After you have selected your project, run the following command inside of your project folder to deploy to App Engine.
gcloud app deploy
Gcloud will ask you to confirm your deployment target, enter “y” if has the correct project selected. Otherwise hit “n” and rerun gcloud init and select the correct project.
Deployment can take a few minutes, simply wait for the command to finish. Once it finishes run the following command
gcloud app browse
To see you app in action. It should display the text “Hello World”.
You have successfully deploy an App Engine application!
Service Account Authentication
Before we can start accessing Google APIs, we need to enable permissions for a service account.
Go back to the Google Cloud console and from the top left menu choose IAM & Admin. From there select Service Accounts from the left navigation. You should see an email address with the following pattern [project-id]@appspot.gserviceaccount.com. Save this email for later.
Select “edit” from the actions for the account. From here select “SHOW DOMAIN-WIDE DELEGATION” and check the box that appears. This will allow this service account to access G Suite resources. Give it a temporary Product Name and save the changes.
The account table will now show a Domain Wide Delegation column. Click “View Client ID” and save the Client ID for later as well (it should be a long string of numbers). Click on the actions again and select “Create Key”. Make sure JSON is selected and create the key. This will download a .json file locally to your computer.
Create a new folder in your project called “keys” and move the new json file into that folder. Rename the .json file to key.json for simplicity. It will be the only key in this folder.
This key will allow you to authenticate as this Service Account in your application.
The next step is to add the necessary scopes to the Service Account in GSuite.
Navigate to admin.google.com and select “Security”. Select “Advanced Settings” and “Manage API client access”. This is the screen where we can setup the scopes for our Service Account. Enter the client ID that we saved from earlier in the “Client Name” field.
Because we are only interested in writing to a spreadsheet, enter https://www.googleapis.com/auth/spreadsheets in the scopes field. If your application requires more scopes you can add them here as a comma delimited list. Then click “Authorize”.
Now your Service Account is all setup to start access GSuite resources!
We also need to enable the Google Sheets API. Back at console.cloud.google.com search for Sheets API and select “Google Sheets Api”. Click the “enable” button to enable the api for this project.
Google Sheets Setup
Let’s split our code into modules for readability. Create a folder called modules and then create a file called sheets.module.js in the folder. Add the following code to the file.
Make sure to run
npm install — save googleapis
To install the google api package.
The above code defines simple authentication and writeToSheet functions for us to use. Feel free to visit the Google documentation for more information.
Finishing Steps
Open drive.google.com and create a new spreadsheet and give it a title. Select “Share” from the top right and enter the email associated with the Service Account. It will ask you to confirm, select “Yes”.
We also need to get the ID of this spreadsheet. In the top address bar look for a long string of letters and numbers between /d/ and /edit#gid=0. Save this string for later.
Now we just need to update the app.js file to listen for a POST request, read the body, and write out to this spreadsheet.
For this example we’ll pretend that users are filling out a signup form and we want to save the data in our new spreadsheet. Add First Name, Last Name, Email, Company as column headers in your spreadsheet.
Update your app.js file with the code below.
And run
npm install — save body-parser
To install the body-parser module.
The above code listens to POST requests at /signup and if all required fields are available it updates the spreadsheet. It also has an index value so it can keep adding signups one after another.
To deploy, run
gcloud app deploy
And wait for it to finish.
Finally you can use Postman or https://apitester.com/ to test your new application. Use the following body as sample data.
And that’s it! Check your spreadsheet and see the new values coming in.
There are a number of hoops to jump through in order to make this work, but ultimately it enables you to create very powerful application that updates / generates documents that anyone can be comfortable working in.
Feel free to post comments with questions or thoughts that you may have while going through this article.