Google API with OAuth request from photon

Hi out there,
In my opinion one of the most interesting things of the photon board in particular and IoT in general is the availability to connect cloud information with the electronic devices world. After some time doing similar things thought android apps and their IO interface, the IoT seems to be the natural way to do it. I’m newly with photon and my first days on it has been invested to get a clear image of their possibilities, and certainly I’m very exciting with this. Coming to the original question, I’m very interested on how to make a photon OAuth request to Google services API to update the status of an electronic design. From my understanding there is different strategies: One is use a HTTP client with POST data and other could be the WebHook. After some time reading and working on this, really I have not success with the HTTP client, probably due my lack of experience on this, and before of go ahead with WebHooks I’d like if somebody help me to take a decision on the better way to push on it.

The code for the HttpClient was as result to modify some examples on WebIDE but always get Error 404 as result.

The code for a simple request code to Google API was:

...
// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
    //{ "Content-Type", "text/html" },
    { "content-type", "application/x-www-form-urlencoded" },
    { "cache-control", "no-cache"},
    { "Accept" , "*/*"},
    { "User-agent", "Particle HttpClient"},
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};

http_request_t request;
http_response_t response;

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

void loop() {
    if (nextTime > millis()) {
        return;
    }

    Serial.println();
    Serial.println("Application>\tStart of Loop.");
    // Request path and body can be set at runtime or at setup.
    request.hostname = "accounts.google.com";
    //request.ip = remoteIP;
    request.port = 80;
    request.path = "/o/oauth2/device/code";

    // The library also supports sending a body with your request:
    request.body = "{\"client_id\":\"xxxxx\"}";
    request.body = "{\"scope\":\"https://www.googleapis.com/auth/calendar\"}";

    // Get request
    http.post(request, response, headers);
    Serial.print("Application>\tResponse status: ");
    Serial.println(response.status);

    Serial.print("Application>\tHTTP Response Body: ");
    Serial.println(response.body);

    nextTime = millis() + 10000;
}

the response is an 404 Error, instead the good one like the following:

{
  "device_code": “xxxxxxxx",
  "user_code": "EZDW-ERSW",
  "verification_url": "https://www.google.com/device",
  "expires_in": 1800,
  "interval": 5
}

I was doing the request with Postman software like this:

but the response that I get from terminal is:

Application>	Start of Loop.
Application>	Response status: 404
Application>	HTTP Response Body: <!DOCTYPE html><html lang=en><meta charset=utf-8><meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width"><title>Error 404 (Not Found)!!1</title><style>*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo 

I’l appreciate any help on this.

It looks like you are trying to do HTTPS using httpclient, which only does HTTP. See this thread for a HTTPS client:

2 Likes

Great!, now I get a successfully connection. Now I’m including the post data as following below:

unsigned char httpRequestContent[] = "POST %s HTTP/1.0\r\n"
  "User-Agent: MatrixSSL/" MATRIXSSL_VERSION "\r\n"
  "Host: accounts.google.com\r\n"
  "Content-Type: application/x-www-form-urlencoded\r\n"
  "Content-Length: %d\r\n\r\n%s";

and I’m getting:

HTTP/1.0 400 Bad Request
Content-Type: application/json; charset=utf-8
Date: Thu, 07 Jan 2016 17:16:00 GMT
Expires: Thu, 07 Jan 2016 17:16:00 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Alternate-Protocol: 443:quic,p=1
Alt-Svc: quic=":443"; ma=604800; v="30,29,28,27,26,25"
Accept-Ranges: none
Vary: Accept-Encoding

{
  "error" : "invalid_request",
  "error_description" : "Missing required parameter: scope"
}

that is OK, because I need to add the additional body message. The questions is how to add the body message. When I’m adding the scope data:

unsigned char httpRequestContent[] = "POST %s HTTP/1.0\r\n"
  "User-Agent: MatrixSSL/" MATRIXSSL_VERSION "\r\n"
  "Host: accounts.google.com\r\n"
  "Content-Type: application/x-www-form-urlencoded\r\n"
  "Content-Length: %d\r\n\r\n%s"
  "scope: https://www.googleapis.com/auth/calendar\r\n";

the response change to “error_description” : “Missing required parameter: client_id” is OK, but when I add it to the httpRequestContent[] it never recognize and give me the same response…
What I’m missing?, How to add body message into the POST?. Thanks in advance.

Also I tried with Webhooks and seems to have a similar result. The webhook has been published as below:

{
    "eventName": "request",
    "url": "https://accounts.google.com/o/oauth2/device/code",
    "requestType": "POST",
    "form": {
        "client_id" : "xxxxxxxx.apps.googleusercontent.com",
        "scope" : "https://www.googleapis.com/auth/calendar"
    },
    "mydevices": true
}

And the firmware:

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);   
}

And I get the following response on the monitor:

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"
}

And this is the detail into the dashboard:

What I’m missing? Any help?

The whole procedure to connect from a device to google API is described on this link: https://developers.google.com/identity/protocols/OAuth2ForDevices

I can follow without problems with a sw like postman or similar. I can provide all steps. But I can’t found the way to do this with webhooks. As example, the first step is the “request code” showed in the postman picture above. But after test many different configurations of .json file for webhook, I can’t get that google server recognize the form data.

Somebody know how to build the correct .json for this https post, where there is two form data that must be uploaded to?
thanks

Did you ever get this to work? If so, how did you handle the refresh token? Would you be willing to share your code?