2

我正在让用户使用他们的 Google+ 帐户登录。我登录并获取基本信息并将其存储在数据库中。在这个过程中,我将其存储access_token在会话中并继续前进。

但是,今天我正在尝试编写一个脚本,允许我使用他们的 in session 发布到他们在 Google+ 上的“时刻” access_token

我收到一个错误,响应如下所示:

{ "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 的库。此外,我不想这样做,因为我的需求只是非常基本的,我想看看它是如何运作的。

我在这里遗漏了一些明显的东西吗?

任何帮助将不胜感激,因为它让我发疯!

谢谢,米奇。

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+ 帐户中删除该应用程序并再次开始确认/登录过程。这是生成的网址:

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/google/?do%253Dredirect%26state%3D2BFFBC14-29F9-4488-ABBF661C0E9E53DB%26client_id%3D{MY_CLIENT_ID}%26hl%3Den-GB%26from_login%3D1%26as%3D-593afcc82466f5f<mpl=popup&shdf=CnALEhF0aGlyZFBhcnR5TG9nb1VybBoADAsSFXRoaXJkUGFydHlEaXNwbGF5TmFtZRoIVW5pYmFuZHMMCxIGZG9tYWluGghVbmliYW5kcwwLEhV0aGlyZFBhcnR5RGlzcGxheVR5cGUaB0RFRkFVTFQMEgNsc28iFOyetn24YRlbdWKLAKGXFCH5C1p9KAEyFPquOHBH18K6iV1GTAg_P9zB2x60&sarp=1&scc=1

我在这里错过了什么吗?是否缺少允许我发布到他们的 AddActivity 流的范围?

更新 3

我的 OAuth 登录 URL(我尝试拆分为新行以提高可读性):

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& state= 65B4A4D1-0C49-4C65-9B46163E67D88EAD& redirect_uri= http%3A%2F%2FXXXXXXX.com%2Foauth%2Fgoogle%2F%3Fdo%3Dredirect& response_type=代码&client_id=XXXXXXXXX.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 
4

4 回答 4

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

people.get 调用可能发生的情况是它正在获取 API 密钥并公开返回,而不是作为登录用户返回。

正如布雷特所说,要编写应用程序活动,您需要将 &request_visible_actions= http://schemas.google.com/AddActivity到您首先将用户发送到的身份验证 URL(如果不使用 JS 登录按钮) ,为了让用户批准你写那种动作(它就像另一种类型的范围)。

于 2013-09-12T09:04:47.690 回答
1

虽然我对 ColdFusion 并不完全熟悉,但看起来您可能在这里混合了两个无法混合的概念。access_token 通常在 HTTP 标头中指定,或作为 URL 查询参数指定。它通常不设置为 POST 参数,这可能是问题的一部分。

如果在标头中完成,则 HTTP 标头应该是

Authorization: Bearer 1/fFBGRNJru1FQd44AzqT3Zg

如果使用 URL 查询参数完成,您的 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”之类的东西,这两者都不是有效的. 正文应该是“应用程序/json”。

更新

因此,鉴于您更改的代码,您可能希望 setUrl 行类似于

local.http.setUrl("https://www.googleapis.com/plus/v1/people/" & session.user.sourceid & "/moments/vault?access_token=" & session.access_token );

我在上面提供的 URL 给出了 Google 的 OAuth2 的权威文档。我不确定您尝试将哪些其他参数添加到 URL,或者为什么,但如果它们是必不可少的,您可以通过这种方式在访问令牌之后添加它们。

于 2013-09-11T14:21:39.200 回答
1

您究竟是如何获得访问令牌的?你在使用 OAuth 吗?

您每次都使用新的访问令牌吗?不是曾经存储在数据库中的那个?您需要记住,令牌可以很快过期。

此位:“原因”:“authError”,“消息”:“无效凭据”,“locationType”:“标题”,“位置”:“授权”

可能意味着您的 Authorization 标头不正确-我怀疑不存在,因为我看不到在您提供的代码位中发送任何签名。

我没有使用 G+ API,但您似乎需要使用适当的 OAuth 2.0 来获取任何数据: https ://developers.google.com/+/api/latest/people/get#examples

这里有一个用于 OAuth 的 CF 库http://oauth.riaforge.org/

更新:

如果你去这里:https ://developers.google.com/+/api/latest/moments/insert#try-it并尝试以用户 ID 运行示例(使用“me”),你会看到请求看起来像这个:

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

您需要提供“授权”标头。

于 2013-09-11T13:40:31.197 回答
1

为响应更新 2 编辑

这听起来像是设置 OAuth 流程的问题。您似乎缺少基于您的 OAuth 生成的 URL,您缺少request_visible_actions参数丢失或格式错误。

将以下查询参数添加到您的 OAuth URL,这应该开始工作:

&request_visible_actions=http%3A%2F%2Fschemas.google.com%2FAddActivity

您的请求的另一个问题是您应该userinfo.profile从请求中删除范围。该范围不是必需的,因为您已经plus.login包含并可能导致一些奇怪的问题。

最后,确保目标 URL 处的页面具有AddActivity 时刻类型所需的最低级别 schema.org 元数据。这不是您现在的问题,但可能是您遇到的下一个问题。

于 2013-09-12T02:34:57.960 回答