Note that there are some explanatory texts on larger screens.

plurals
  1. POGoogle+ API error - Invalid Credentials
    primarykey
    data
    text
    <p>I am signing users in using their Google+ account. I sign them in and grab basic information and store it in the database. In this process, I store the <code>access_token</code> in the session and move on.</p> <p>However, today I am trying to write a script that allows me to post to their 'moments' on Google+ using their in session <code>access_token</code>.</p> <p>I am getting an error and the response looks like:</p> <pre><code>{ "error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" } } </code></pre> <p>I am not sure why this is happening, below is the code I am using to make the request (it is in ColdFusion script, but you should be able to see the principles behind it even if you do not know this syntax).</p> <pre><code>local.http = new http(); local.http.setMethod("post"); local.http.setCharset("utf-8"); local.http.setUseragent(cgi.http_user_agent); local.http.setResolveurl(true); local.http.setTimeout(20); local.http.setUrl("https://www.googleapis.com/plus/v1/people/" &amp; session.user.sourceid &amp; "/moments/vault"); local.target = {}; local.target["kind"] = "plus##moment"; local.target["type"] = "http://schemas.google.com/AddActivity"; local.target["description"] = params.pin["description"]; local.target["image"] = session.user.image; local.target["name"] = params.pin["title"]; local.target["url"] = URLfor(route="pinShow", key=obfuscateParam(pin.id), onlyPath=false); local.target["latitude"] = session.user.latitude; local.target["longitude"] = session.user.longitude; local.http.addParam(type="formField", name="target", value=serialize(local.target)); local.http.addParam(type="formField", name="kind", value="plus##moment"); local.http.addParam(type="formField", name="type", value="http://schemas.google.com/AddActivity"); local.http.addParam(type="formField", name="access_token", value=session.access_token); local.result = local.http.send().getPrefix(); </code></pre> <p>As you can see, it all seems straight-forward.</p> <p>I have test this straight-after signing in and despite that, it says the token is invalid in the header response:</p> <pre><code>HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="https://www.google.com/accounts/AuthSubRequest", error=invalid_token Content-Type: application/json; charset=UTF-8 Content-Encoding: gzip Date: Wed, 11 Sep 2013 13:12:28 GMT Expires: Wed, 11 Sep 2013 13:12:28 GMT Cache-Control: private, max-age=0 X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block Content-Length: 162 Server: GSE Alternate-Protocol: 443:quic </code></pre> <p>Does anyone have any idea why this is happening and how to solve it?</p> <p>I am not using any kind of library, as there isn't one for ColdFusion. In addition, I didn't want to, as my needs are only very basic and I wanted to see how it all worked.</p> <p>Am I missing something obvious here?</p> <p>Any help would be greatly appreciated as it's driving me nuts!</p> <p>Thanks, Mikey.</p> <p>PS - I have removed the app from my account, cleared all cookies and sessions and then signed in again granting all permissions, so it seems that side of it has been eliminated.</p> <p><strong>UPDATE 1:</strong></p> <p>After some light shone from other users here, it turns out I should be posting a JSON response in the HTTP body, to make the request. So I changed my code to this:</p> <pre><code>local.request = {} local.request["kind"] = "plus##moment"; local.request["type"] = "http://schemas.google.com/AddActivity"; local.request["target"] = {}; local.request.target["kind"] = "plus##itemScope"; local.request.target["type"] = "http://schemas.google.com/AddActivity"; local.request.target["description"] = params.pin["description"]; local.request.target["image"] = session.user.image; local.request.target["name"] = params.pin["title"]; local.request.target["url"] = URLfor(route="pinShow", key=obfuscateParam(pin.id), onlyPath=false); local.request.target["latitude"] = session.user.latitude; local.request.target["longitude"] = session.user.longitude; local.http = new http(); local.http.setMethod("post"); local.http.setCharset("utf-8"); local.http.setUseragent(cgi.http_user_agent); local.http.setResolveurl(true); local.http.setTimeout(20); local.http.setUrl("https://www.googleapis.com/plus/v1/people/" &amp; session.user.sourceid &amp; "/moments/vault?debug=true&amp;fields=kind%2Ctype%2Cdescription%2Cimage%2Curl&amp;key={GOOLE_API_KEY}" ); local.http.addParam(type="header", name="Content-Type", value="application/json"); local.http.addParam(type="header", name="Authorization", value="Authorization: Bearer " &amp; session.access_token); local.http.addParam(type="body", value=serializeJSON(local.request)); local.result = local.http.send().getPrefix(); </code></pre> <p>However, now I get another error (401 unauthorized):</p> <pre><code>{ "error": { "errors": [ { "domain": "global", "reason": "required", "message": "Login Required", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Login Required" } } </code></pre> <p>Does anybody know how I can pass the <code>access_token</code> using my new method above?</p> <p><strong>UPDATE 2</strong></p> <p>It has been highlighted to me that this could originate from my original OAuth 2 process. I have removed the app from my Google+ account and started the confirmation / signin process again. Here is the generated URL:</p> <blockquote> <p><a href="https://accounts.google.com/ServiceLogin?service=lso&amp;passive=1209600&amp;continue=https://accounts.google.com/o/oauth2/auth?response_type%3Dcode%26scope%3Dhttps://www.googleapis.com/auth/userinfo.email%2Bhttps://www.googleapis.com/auth/userinfo.profile%2Bhttps://www.googleapis.com/auth/plus.login%26redirect_uri%3Dhttp://" rel="nofollow noreferrer">https://accounts.google.com/ServiceLogin?service=lso&amp;passive=1209600&amp;continue=https://accounts.google.com/o/oauth2/auth?response_type%3Dcode%26scope%3Dhttps://www.googleapis.com/auth/userinfo.email%2Bhttps://www.googleapis.com/auth/userinfo.profile%2Bhttps://www.googleapis.com/auth/plus.login%26redirect_uri%3Dhttp://</a>{MY_DOMAIN}.com/oauth/google/?do%253Dredirect%26state%3D2BFFBC14-29F9-4488-ABBF661C0E9E53DB%26client_id%3D{MY_CLIENT_ID}%26hl%3Den-GB%26from_login%3D1%26as%3D-593afcc82466f5f&amp;ltmpl=popup&amp;shdf=CnALEhF0aGlyZFBhcnR5TG9nb1VybBoADAsSFXRoaXJkUGFydHlEaXNwbGF5TmFtZRoIVW5pYmFuZHMMCxIGZG9tYWluGghVbmliYW5kcwwLEhV0aGlyZFBhcnR5RGlzcGxheVR5cGUaB0RFRkFVTFQMEgNsc28iFOyetn24YRlbdWKLAKGXFCH5C1p9KAEyFPquOHBH18K6iV1GTAg_P9zB2x60&amp;sarp=1&amp;scc=1</p> </blockquote> <p>Am I missing something here? Is it a scope that is missing that should allow me to post to their AddActivity stream?</p> <p><strong>UPDATE 3</strong></p> <p>My OAuth login URL (I've tried to split on to new lines to improve readability):</p> <blockquote> <p><a href="https://accounts.google.com/o/oauth2/auth" rel="nofollow noreferrer">https://accounts.google.com/o/oauth2/auth</a>? scope= https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+ https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+ https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login&amp; request_visible_actions= https%3A%2F%2Fschemas.google.com%2FAddActivity&amp; state= 65B4A4D1-0C49-4C65-9B46163E67D88EAD&amp; redirect_uri= http%3A%2F%2FXXXXXXX.com%2Foauth%2Fgoogle%2F%3Fdo%3Dredirect&amp; response_type= code&amp; client_id= XXXXXXXX.apps.googleusercontent.com</p> </blockquote> <p>And on the permissions screen on Google+, this is what I see:</p> <p><img src="https://i.stack.imgur.com/aY3EM.png" alt="enter image description here"></p> <p>When I try to post an addActivity now, I get a bad request error as before.</p> <p>The error JSON returned:</p> <pre><code>{ "error": { "errors": [ { "domain": "global", "reason": "invalid", "message": "Invalid Value" } ], "code": 400, "message": "Invalid Value" } } </code></pre> <p>The header returned:</p> <pre><code>HTTP/1.1 400 Bad Request Content-Type: application/json; charset=UTF-8 Content-Encoding: gzip Date: Fri, 13 Sep 2013 11:38:20 GMT Expires: Fri, 13 Sep 2013 11:38:20 GMT Cache-Control: private, max-age=0 X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block Content-Length: 123 Server: GSE Alternate-Protocol: 443:quic </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload