我正在使用Google+帐户与用户签名。我签了他们并获取基本信息并将其存储在数据库中。在此过程中,我将access_token
存储在会话中并继续。
但是,今天我正在尝试编写一个脚本,允许我使用他们的会话access_token
在Google+上发布他们的“片刻”。
我收到错误,响应如下:
{ "error": { "errors": [ { "domain": "global", "reason": "authError", "message": "Invalid Credentials", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Invalid Credentials" } }
我不确定为什么会发生这种情况,下面是我用来发出请求的代码(它在ColdFusion脚本中,但即使你不知道这种语法,你也应该能够看到它背后的原理)
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/" & session.user.sourceid & "/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();
正如你所看到的,这一切似乎都是直截了当的。
我在登录后直接测试了这一点,尽管如此,它表示令牌在标题响应中无效:
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
有谁知道为什么会这样,以及如何解决它?
我没有使用任何类型的库,因为没有ColdFusion的库。此外,我不想,因为我的需求只是非常基本,我想看看它是如何工作的。
我错过了一些明显的东西吗?
任何帮助都会非常感激,因为它让我疯了!
谢谢, MIKEY。
PS - 我已经从我的帐户中删除了该应用,清除了所有Cookie和会话,然后再次登录授予所有权限,因此它似乎已被淘汰。
更新1:
在这里发现其他用户的一些亮光后,我发现我应该在HTTP正文中发布一个JSON响应来发出请求。所以我把我的代码更改为:
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/" & session.user.sourceid & "/moments/vault?debug=true&fields=kind%2Ctype%2Cdescription%2Cimage%2Curl&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 " & session.access_token);
local.http.addParam(type="body", value=serializeJSON(local.request));
local.result = local.http.send().getPrefix();
但是,现在我收到另一个错误(401未经授权):
{ "error": { "errors": [ { "domain": "global", "reason": "required", "message": "Login Required", "locationType": "header", "location": "Authorization" } ], "code": 401, "message": "Login Required" } }
有人知道如何使用上面的新方法传递access_token
吗?
更新2
我一直强调,这可能源于我最初的OAuth 2流程。我已从Google+帐户中删除该应用,并再次启动确认/登录过程。这是生成的URL:
https://accounts.google.com/ServiceLogin?service=lso&passive=1209600&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:// {MY_DOMAIN}的.com / OAuth的/谷歌/?做%253Dredirect%26state%3D2BFFBC14-29F9-4488-ABBF661C0E9E53DB%26client_id%3D {MY_CLIENT_ID}%26hl%3Den-GB%26from_login%3D1% 26AS%3D-593afcc82466f5f&安培; ltmpl =弹出&安培; SHDF = CnALEhF0aGlyZFBhcnR5TG9nb1VybBoADAsSFXRoaXJkUGFydHlEaXNwbGF5TmFtZRoIVW5pYmFuZHMMCxIGZG9tYWluGghVbmliYW5kcwwLEhV0aGlyZFBhcnR5RGlzcGxheVR5cGUaB0RFRkFVTFQMEgNsc28iFOyetn24YRlbdWKLAKGXFCH5C1p9KAEyFPquOHBH18K6iV1GTAg_P9zB2x60&安培; SARP = 1&安培; SCC = 1
我在这里遗漏了什么吗?它是一个缺少的范围,应该允许我发布到他们的AddActivity流吗?
更新3
我的OAuth登录网址(我尝试拆分新行以提高可读性):
https://accounts.google.com/o/oauth2/auth?范围= 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&安培; request_visible_actions = HTTPS%3A%2F%2Fschemas.google.com%2FAddActivity&安培;状态= 65B4A4D1-0C49-4C65-9B46163E67D88EAD&安培; REDIRECT_URI = HTTP%3A%2F%2FXXXXXXX.com%2Foauth%2Fgoogle%2F%3Fdo%3Dredirect&安培; response_type = code& client_id = XXXXXXXX.apps.googleusercontent.com
在Google+上的权限屏幕上,这就是我看到的内容:
当我尝试发布addActivity时,我得到了一个错误的请求错误。
JSON返回错误:
{ "error": { "errors": [ { "domain": "global", "reason": "invalid", "message": "Invalid Value" } ], "code": 400, "message": "Invalid Value" } }
标题返回:
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
答案 0 :(得分:2)
至少有一个标题存在明确问题:
local.http.addParam(type="header", name="Authorization", value="Authorization: Bearer " & session.access_token);
你有两次授权,应该是。
local.http.addParam(type="header", name="Authorization", value="Bearer " & session.access_token);
人们可能会发生什么事情。电话是它正在拿起API密钥并公开返回而不是签名用户。
正如Brett所说,要编写应用活动,您需要将& request_visible_actions = http://schemas.google.com/AddActivity添加到您首先向用户发送的auth URL(如果不使用JS登录按钮),为了让用户批准你写这种动作(就像另一种类型的范围)。
答案 1 :(得分:1)
你究竟是如何获得访问令牌的?你在使用OAuth吗?
您每次使用新的访问令牌吗?不是在DB中存储一次的那个?您需要记住,令牌可以很快到期。
这一位: “reason”:“authError”,“message”:“Invalid Credentials”,“locationType”:“header”,“location”:“Authorization”
可能意味着您的Authorization标头不正确 - 我怀疑不存在,因为我看不到您提供的代码中发送任何签名。
我没有使用过G + API,但您似乎需要使用正确的OAuth 2.0来获取任何数据: https://developers.google.com/+/api/latest/people/get#examples
这里有一个OA库的CF库http://oauth.riaforge.org/
更新:
如果您到这里:https://developers.google.com/+/api/latest/moments/insert#try-it并尝试运行示例(使用“我”)作为用户ID,您将看到请求如下所示:
POST https://www.googleapis.com/plus/v1/people/me/moments/vault?debug=true&key={YOUR_API_KEY}
Content-Type: application/json
Authorization: Bearer ya29.XXXXXXXXXXXXXXXXXXXXXXXXXXXX
您需要提供“授权”标头。
答案 2 :(得分:1)
虽然我对ColdFusion并不完全熟悉,但看起来你可能在这里混合了两个不能混合的概念。 access_token通常在HTTP标头中指定,或者作为URL查询参数指定。它通常不设置为POST参数,这可能是问题的一部分。
如果在标头中完成,HTTP标头应为
Authorization: Bearer 1/fFBGRNJru1FQd44AzqT3Zg
如果使用URL查询参数,您的网址可能需要类似
https://www.googleapis.com/plus/v1/people/123456789012345/moments/vault?access_token=1/fFBGRNJru1FQd44AzqT3Zg
有关详细信息,请参阅https://developers.google.com/accounts/docs/OAuth2UserAgent#callinganapi
不确定这是否相关,虽然它可能是,但我不确定你的POST的正文是否正确。您没有为正文设置内容类型,我不知道CF是否会使用类似“application / www-form-url-encoded”或“multipart / form-data”的内容,这些都不是有效的。正文应该是“application / json”。
<强>更新强>
因此,考虑到您更改的代码,您可能希望setUrl行类似于
local.http.setUrl("https://www.googleapis.com/plus/v1/people/" & session.user.sourceid & "/moments/vault?access_token=" & session.access_token );
我在上面提供的网址为Google提供了OAuth2的权威文档。我不确定您尝试添加到URL的其他参数或原因,但如果它们必不可少,您可以通过这种方式在访问令牌之后添加它们。
答案 3 :(得分:1)
为响应更新2而修改
这听起来像是设置OAuth流程的问题。您似乎缺少基于您的OAuth生成的网址,您遗漏了request_visible_actions
参数丢失或格式错误。
将以下查询参数添加到您的OAuth网址,这应该开始有效:
&request_visible_actions=http%3A%2F%2Fschemas.google.com%2FAddActivity
您的请求的另一个问题是您应该从请求中删除userinfo.profile
范围。该范围不是必需的,因为您包含plus.login
,可能会导致一些奇怪的问题。
最后,确保目标网址上的网页具有AddActivity moment type所需的最低级别schema.org元数据。这不是你现在的问题,但可能是你遇到的下一个问题。