Google Calendar API OAuth with webhooks

Hi all,

I’m trying to get the the google calendar event list from photon. Google API describes this procedure here:
https://developers.google.com/identity/protocols/OAuth2ForDevices

basically you need to perform the following requests:

1.Request Code: this is a POST to https://accounts.google.com/o/oauth2/device/code with a form body including a “client_id” and “scope” for this request. Those dates are provided by your google developer console account.
The response to this request provide us with a “device_code” an “user_code”. The user code must be showed to the user to provide us with a calendar access permission under https://www.google.com/device

2.Check for approval: this is a POST to https://www.googleapis.com/oauth2/v4/token with a form body with your credentials (client_id, client_secret and device_code getting in the previous request). If the user accepted previously the permissions requested then this post provide us with an “access_token” valid during 3600 sec. Also provide a “refresh_token” for access renovation.

3.Finally we can get access to calendar events by a GET request to https://www.googleapis.com/calendar/v3/calendars/calendarId/events as described here

I can do the whole process under Postman without problems and this let me check all keys and values in each request.

An easy way to port this procedure to the photon firmware is with the help of webhooks. I’ll try to describe below the process that I follow without success:

To cover the first POST request described above I create a .json file:

{
    "eventName": "request",
    "url": "https://accounts.google.com/o/oauth2/device/code",
    "requestType": "POST",
    "headers": {
           "Content-Type": "application/x-www-form-urlencoded"
     },
    "form": {
         "client_id" : "xxxxxxxr.apps.googleusercontent.com",
         "scope" : "https://www.googleapis.com/auth/calendar"
    },
   "mydevices": true
}

and declare in the Cloud using the particle CLI command $ particle webhook create request.son

the photon firmware is:

void setup() {
    Serial.begin(9600);

    Spark.subscribe("hook-response/request", requestprocess, MY_DEVICES);
    
    for(int i=0;i<10;i++) {
        Serial.println("waiting " + String(10-i) + " seconds before we publish");
        delay(1000);
    }
}

    void loop() {
        // Let's request the calendar pass but no more than once every 60 seconds.
        Serial.println("Requesting Calendar pass!");
    
        // publish the event that will trigger our Webhook
        Spark.publish("request");
    
        // and wait at least 60 seconds before doing it again
        delay(60000);
        
    }
    
    void requestprocess(const char *name, const char *data) {
        String str = String(data);
        Serial.println("The response:\r\n " + str);   
    }

I get the following response:

before we publish
waiting 9 seconds before we publish
waiting 8 seconds before we publish
waiting 7 seconds before we publish
waiting 6 seconds before we publish
waiting 5 seconds before we publish
waiting 4 seconds before we publish
waiting 3 seconds before we publish
waiting 2 seconds before we publish
waiting 1 seconds before we publish
Requesting Calendar pass!
Requesting Calendar pass!
The response:
 {
  "error" : "invalid_request",
  "error_description" : "Missing required parameter: scope"
}
Requesting Calendar pass!
The response:
 {
  "error" : "invalid_request",
  "error_description" : "Missing required parameter: client_id"
}
Requesting Calendar pass!
The response:
 {
  "error" : "invalid_request",
  "error_description" : "Missing required parameter: client_id"
}
Requesting Calendar pass!
The response:
 {
  "error" : "invalid_request",
  "error_description" : "Missing required parameter: client_id"
}
Requesting Calendar pass!
Requesting Calendar pass!
The response:
 {
  "error" : "invalid_request",
  "error_description" : "Missing required parameter: client_id"
}

The dashboard:

So, sorry about this detailed introduction but the issue is that I can get server connection but for any reason the body form with “scope” and “client_id” fields are not recognized by the server.

Please, any suggestion about?

I am currently also trying to workout the google API as I want to write data to google cloud datastore. It currently seems much harder than it should be !

Looking at your code it doesnt deem that you are passing the access-token when you use the webhook. Given this expires and has to be renewed it may not be suited to webhooks unless you publish an authentication request, get the access-token back and then pass that to a second publish which makes the call to the google calendar.

Thanks for you comments deancs.

You are talking about the access-token, required by the google API ? . At this point, the webhook above is only to cover the first step required by the Google API, that is for “requesting a code”, where you only must to provide your “client_id” and “scope” as x-form into a POST request. After that, you are right, other webhook publish request must be deployed to check for approval and up to a third one to refresh the permissions for a “refresh_token” request. But unfortunately I can’t go ahead with the first step. The server always sent me back with “missing required parameters” and I really have not idea where the webhook definition fails. If you want, I can provide you with detailed information about how to follow the whole procedure in your laptop with software like Postman, this allow test your credential and other data involved in each request.

Hi agarcia

OK I understand where you are upto in the API calls and the short answer is your code worked for me.

I took your request.json and inserted my google id and created a webhook via particle webhook create ~/request.json
I then flashed a photon with your exact code and I can see the correct response in the dashboard.

My only suggestion would be you delete your webhook via the cli, recreate it and see if that resolves the issue.

Hi deanes,

Your feedback help me a lot! because for any reason seems that I have any fault in my .json. After check some times I still getting the same missing response from google server. Please se below the cli command response when I’m creating the webhook in the cloud:

Using settings from the file calendar_request_oauth.json
Sending webhook request  { uri: 'https://api.particle.io/v1/webhooks',
  method: 'POST',
  json: 
   { event: 'request',
     url: 'https://accounts.google.com/o/oauth2/device/code',
     deviceid: undefined,
     requestType: 'POST',
     mydevices: true },
  headers: { Authorization: 'Bearer 8cxxxxxxxxxxxxb7' } }
Successfully created webhook with ID 56xxxxxxxxxxxxxd4

Take a look into for a while. This response from particle cloud does not include the form body requested in the .json, where the “client_id” and “scope” are declared. Curiously these are the missing parameters requested by google in my request. Please, could you check for me if you are getting the same confirmation when you are creating your webhook??. Thanks in advance.

Hi agarcia

Thats interesting. I see the client-id in the confirmation from the hook create

I am running Particle CLI version 1.8.22 on OSX.

1 Like

Great!. SOLVED. I had this CLI version, but for any reason it was’t processing the .json right. I had to uninstall CLI and Node and reinstall again. Many many thanks for you support. Now it working and I’m going ahead successfully with the next requests to get the google server approvals.

That is great. I am keen to learn from your google authentication work !

OK. I’ll keep you informed. thanks.