Google Oauth2 API Explained

Pumudu Ruhunage
6 min readApr 13, 2020

--

ESP8266 based google sheet data feeder for one of my home projects (Based on Google APIs)

As we all know Google is a powerful cloud service provider with numerous products and services. For application developers there’s even more offered by Google. It provides more than 280+ (as of march 2020) API’s from maps to machine learning. This opens up various opportunities for app developers to utilize these services within their applications/projects.

Google Cloud APIs only accept requests from registered applications, which are uniquely identifiable applications that present a credential at the time of the request. Requests from anonymous applications are rejected.

There are several methods to authenticate for Google API platform. As for web applications most common method is to use Oauth2 client credentials. Google has several documentations explaining the Oauth2 flow with examples.

In this article i’ll try to explain the Google Oauth2 flow in most simple request/response manner to understand the flow. (This comes in handy when invoke google api’s for IoT use cases with minimum resource utilization)

Google OAuth Flow — In Theory

Google OAuth Flow — Sequence Diagram

Above sequence diagram sums up the flow in theory. In my opinion this flow can’t be any simplified with the amount of services google exposes.

Following are the main parties involving the OAuth flow.

Application : Application is the entity or which request access to certain google resource owned by different party.

Resource Owner : Resource owner is the person/organization whom own the given google resource. This person/organization should allow access to application via login page and consent to access the resources to complete the flow.

OAuth Service : Google OAuth service have two endpoints (‘/auth’ and ‘/token’).

“/auth” endpoint provides short lived “authorization code” which confirms user credentials and consent is valid for given scope.

“/token” endpoint exchange code and return bearer and refresh token. With this bearer token and refresh token, application can access the consented resource by resource owner.

Resource Service : Resource service exposes the google resources via structured, well documented set of APIs. Once a request received for this service it will verify the token and execute given request if token is valid.

Resource : This is the actual resource which exposes via APIs. For example, google sheet which creates and maintains by the resource owner is a resource.

Google OAuth Flow — In Practice

To explain the Oauth flow i’ll be using google sheets api. For that, before begin we need a google sheet resource to access.

Create google sheet document and note down the sheet id and tab name. Add some dummy data between A1:D3 cells which we’ll be reading via google sheets api later on.

Google sheet Id can be seen in url as below :

https://docs.google.com/spreadsheets/d/190Ym4DG9s7Nk_YxA8cr1D_8VEmNpCnYsskyRgAxdadc/edit#gid=0

Sheet Id : 190Ym4DG9s7Nk_YxA8cr1D_8VEmNpCnYsskyRgAxdadc

Tab Name : Sheet1

Step 1 : Create Project and Retrieve Client Credentials for Application

In-order to get the client Id and client secret for the application we need to create the application via google api console.

  1. ogin to google account and open google api dashboard.

2. Create new project if not already created, with appropriate name.

3. Enable API service(s) for the given Project. (in this example we’ll be using google sheets api)

4. Create Oauth consent screen under “OAuth consent screen” tab.

Since I just need to access my own test google sheet, i’ll be selecting external unverified consent screen.

On create, just provide the name of the application(any name) and click on save without any app verification.

Unverified applications are limited to 10,000 users per day, but it’s more than sufficient for this OAuth test.

In-order to authenticate with google we need client credentials. For that, OAuth client ID needs to be created as shown below.

Based on the requirement we can create several types of client credentials, For my usecase, I created basic credentials with ‘other’ option.

Once created, this will provide clientId and secret for the given application. Note down these clientId and client secret values for next steps of the Oauth flow.

Step 2 : Get the authorization code

Open a browser tab and enter following url with query parameters.

scope : https%3A//www.googleapis.com/auth/spreadsheets
access_type: offline
response_type: code
redirect_uri: http%3A//localhost:8000
client_id: 985957988504-sgp8fm02ob4keorekf2t544u765961l1.apps.googleusercontent.com

https://accounts.google.com/o/oauth2/v2/auth?scope=https%3A//www.googleapis.com/auth/spreadsheets&access_type=offline&response_type=code&redirect_uri=http%3A//localhost:8000&client_id=985957988504-sgp8fm02ob4keorekf2t544u765961l1.apps.googleusercontent.com

If all goes well this should redirect to a google login screen and consent screens.

Since we have used unverified consent screen it will throw a warning as well highlighting this app is not yet verified.

Once consent is granted, page will then get redirected to above given redirect_uri with the code.

http://localhost:8000/?code=4/ygHeyskWdKW58DPow-a41rn3IZqXB2y16ga3UBBmFI5BijDPmMfogUuA1CXbEtJJpT_G1tnhC9hbMwMR45GT_vw&scope=https://www.googleapis.com/auth/spreadsheets

Authorization code : 4/ygHeyskWdKW58DPow-a41rn3IZqXB2y16ga3UBBmFI5BijDPmMfogUuA1CXbEtJJpT_G1tnhC9hbMwMR45GT_vw

Note down the code returned with the redirect url.

Step 3 : Exchange authorization code with bearer token and refresh token

Once we have the authorization code, it’s time to retrieve bearer token from token endpoint.

Following POST request is required to retrieve tokens from authorization code.

POST https://oauth2.googleapis.com/tokenredirect_uri=’http://localhost:8000'code=4/ygHeyskWdKW58DPow-a41rn3IZqXB2y16ga3UBBmFI5BijDPmMfogUuA1CXbEtJJpT_G1tnhC9hbMwMR45GT_vwclient_id=985957988504-sgp8fm02ob4keorekf2t544u765961l1.apps.googleusercontent.comclient_secret=ZMdFZHB8LbJllKMxWUGrKTjhgrant_type=authorization_code

I’ll be using curl commands to invoke OAuth requests as below. This can be done via postman, python scripts etc.

Curl :

curl --data redirect_uri='http://localhost:8000' --data code=4/ygHeyskWdKW58DPow-a41rn3IZqXB2y16ga3UBBmFI5BijDPmMfogUuA1CXbEtJJpT_G1tnhC9hbMwMR45GT_vw --data client_id=985957988504-sgp8fm02ob4keorekf2t544u765961l1.apps.googleusercontent.com --data client_secret=ZMdFZHB8LbJllKMxWUGrKTjh --data grant_type=authorization_code https://oauth2.googleapis.com/token

Response :

{
"access_token": "ya29.a0Ae4lvC20haaIxuYpJBx4_DS3fKicdT6OTWJYILJNrjALVu9AQPM9VwuRgiEgipdPvnaExdG7q8CIMDuU6TDPMAceZYde0IIa1zogXuy9v8NH2ts79Nl82t0A4RzyoyG2IhfX8wx0Fa4AxBU6iuTGtmO9ugNic66aIWU",
"expires_in": 3599,
"refresh_token": "1//0g6GkDsirYq1uCgYIARAAGBASNwF-L9IrhQJOfpESn6FUTbUgO_S9ZAMP-rnd154A5CIAMJSjZL6XYbqH286y3qMA-yxSVE9tOHc",
"scope": "https://www.googleapis.com/auth/spreadsheets",
"token_type": "Bearer"
}

With bearer token, finally we can invoke google sheets api resources.

Step 4 : Invoke resource service

Once we have the bearer token it needs to be sent as a header value with each and every api request. Google sheet api’s are well documented with samples for reference.

Following is a simple read operation which reads from given cell rage. Depending on the operation it can be GET, POST,PUT, DELETE rest call.

Add ‘sheet id’ and the ‘sheet tab name’ from the sample google sheet which created early on.

GET https://sheets.googleapis.com/v4/spreadsheets/190Ym4DG9s7Nk_YxA8cr1D_8VEmNpCnYsskyRgAxdadc/values/Sheet1!A1:D3?majorDimension=COLUMNSHeader : "Authorization: Bearer ya29.a0Ae4lvC20haaIxuYpJBx4_DS3fKicdT6OTWJYILJNrjALVu9AQPM9VwuRgiEgipdPvnaExdG7q8CIMDuU6TDPMAceZYde0IIa1zogXuy9v8NH2ts79Nl82t0A4RzyoyG2IhfX8wx0Fa4AxBU6iuTGtmO9ugNic66aIWU"

Curl :

curl -H "Authorization: Bearer ya29.a0Ae4lvC20haaIxuYpJBx4_DS3fKicdT6OTWJYILJNrjALVu9AQPM9VwuRgiEgipdPvnaExdG7q8CIMDuU6TDPMAceZYde0IIa1zogXuy9v8NH2ts79Nl82t0A4RzyoyG2IhfX8wx0Fa4AxBU6iuTGtmO9ugNic66aIWU" 'https://sheets.googleapis.com/v4/spreadsheets/190Ym4DG9s7Nk_YxA8cr1D_8VEmNpCnYsskyRgAxdadc/values/Sheet1!A1:D3?majorDimension=COLUMNS'

Response :

{
"range": "Sheet1!A1:D3",
"majorDimension": "COLUMNS",
"values": [
[
"Description",
"Test Iteration 221",
"Test Iteration 222"
],
[
"Value1",
"939",
"781"
],
[
"Value2",
"421",
"242"
],
[
"Value3",
"1725",
"1137"
]
]
}

Step 5 : Refresh token (not shown in the sequence diagram)

Bearer token is short lived and requires to regenerate once expired. For this we can use the returned refresh token with token endpoint.

POST https://oauth2.googleapis.com/tokenclient_id : 985957988504-sgp8fm02ob4keorekf2t544u765961l1.apps.googleusercontent.comclient_secret : ZMdFZHB8LbJllKMxWUGrKTjh

refresh_token : 1//0g6GkDsirYq1uCgYIARAAGBASNwF-L9IrhQJOfpESn6FUTbUgO_S9ZAMP-rnd154A5CIAMJSjZL6XYbqH286y3qMA-yxSVE9tOHc
grant_type : refresh_token

Curl :

curl --data client_id=985957988504-sgp8fm02ob4keorekf2t544u765961l1.apps.googleusercontent.com --data client_secret=ZMdFZHB8LbJllKMxWUGrKTjh --data refresh_token=1//0g6GkDsirYq1uCgYIARAAGBASNwF-L9IrhQJOfpESn6FUTbUgO_S9ZAMP-rnd154A5CIAMJSjZL6XYbqH286y3qMA-yxSVE9tOHc --data grant_type=refresh_token https://oauth2.googleapis.com/token

Response :

{
"access_token": "ya29.a0Ae4lvC0_TklRtYGFPJ-GR-9BrOLkMrpF8zw1QGlWtk26ccoZ2ibfbbcObOtvTZ12adFGjMjDO3CNYmrdRaCrC6nzs0sQpzhbbKL8FiBbOMGkedcQ_o7-m6YBcZ5kAIZecpup5kWR9RarlJAYUSh6gsom75xtaoR-cK0",
"expires_in": 3599,
"scope": "https://www.googleapis.com/auth/spreadsheets",
"token_type": "Bearer"
}

Update: These oauth credentials along with the project has been deleted before publishing this article. Therefore, none of the codes, credentials mentioned are valid at this point.

What’s Next ?

Possibilities are endless with google resources. GCP provide large number of free/almost free APIs which enables developers to build crazy new features and experiments.

For example, i developed IoT device which feeds data directly to google sheet using these REST APIs for one of my home projects.

ESP8266 uploads data directly to google sheets

It’s a story for another article. :)

--

--