title: Google+ API error - Invalid Credentials
body: <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>