我通过以下方式自动调整我的应用程序:
// authorize app!
$('#authApp').click(function(){
var oauth_url = 'https://www.facebook.com/dialog/oauth/';
oauth_url += '?client_id=#{app.id}';
oauth_url += '&redirect_uri=' + encodeURIComponent('https://www.facebook.com/pages/null/#{fbPageId()}/?sk=app_#{app.id}');
oauth_url += '&scope=user_likes,user_photos';
oauth_url += '&app_data=7B%27game%27%3A+%27key%27%7D';
oauth_url += '&state=sbSbsbSb';
正如您所看到的,我将'state'参数设置为查询字符串的一部分。 现在,当用户授权应用程序时,他将被重定向到重定向URL。
然而,在state参数中传递的数据不会发布到我的应用程序,也不是我应用程序的iframe查询字符串的一部分。我期待将其作为签名请求的一部分,但不是。这是授权后发回的反序列化签名请求
{ algorithm: 'HMAC-SHA256',
expires: 1348927200,
issued_at: 1348921162,
oauth_token: 'AAA...',
page: { id: '490...', liked: true, admin: false },
user: { country: 'ec', locale: 'en_US', age: { min: 21 } },
user_id: '1...' }
我确实看到状态包含在父页面的查询字符串中。我需要从我的应用程序访问该参数(在iframe中运行)。我相信由于相同的原始政策限制,我不能只访问父页面的窗口位置。
我已阅读文档并在线搜索。需要使用state参数在应用程序自动化中保留数据。但是,一旦重定向回应用程序,就没有说明如何检索该状态参数。
这是关于州参数的facebook doc's:
用于维护请求之间的应用程序状态的唯一字符串 和回调。当Facebook将用户重定向回您的用户时 redirect_uri,此参数的值将包含在响应中。 您应该使用它来防止跨站点请求伪造。
我是否应该从父母的页面查询字符串中获取状态数据? 或者我做错了什么?
*编辑 * 我将用户存储在state参数中的用户请求Id中。例如,A邀请B通过facebook请求参与应用程序。一旦B授权应用程序A需要得到奖励。所以我需要知道B在A的邀请下来到应用程序。因此我将requestId存储在状态参数中,因此一旦B授权了应用程序,我就可以采取适当的行动。
*编辑2(解决方案)** 如果你的redirect_uri指向页面选项卡URL,那么facebook将不会发回状态参数!只有在您重定向到Canvas URL时才会发回它!!!!!
答案 0 :(得分:1)
我是否应该从父母的页面查询字符串中获取状态数据?
不,不是在画布/页面选项卡应用程序中进行身份验证时。在此方案中,唯一传递给您的应用的查询字符串参数是app_data
参数的内容。
但是在这种情况下你不需要state
参数 - 验证signed_request
是绝对足够的,因为它是用你的应用秘密签名的,只有你和Facebook知道。所以这已经足以防止“被操纵”的请求了。
请参阅https://developers.facebook.com/docs/authentication/canvas/ resp。 https://developers.facebook.com/docs/authentication/pagetab/了解更多详情。 (看看他们怎么没有提到state
参数。)
编辑:
我将用户存储在state参数中的用户请求ID中。例如,A邀请B通过facebook请求参与应用程序。一旦B授权应用程序A需要得到奖励。所以我需要知道B在A的邀请下来到应用程序。因此我将requestId存储在状态参数中,因此一旦B授权了应用程序,我就可以采取适当的行动。
这是对state
参数的误用......它应该实现完全不同的东西(CSRF保护,正如文档所说)。
虽然您的方案中可能 - 您为什么不使用app_data
参数传输此信息?这是指定的方式将信息传输到画布/页面选项卡应用程序。
答案 1 :(得分:1)
您引用的Facebook文档有点令人困惑。你应该对state参数做的唯一事情就是确保你不是CSRF的受害者。 Facebook's server side authentication flow在PHP中给出了一个例子。简而言之,您应该将状态值存储在会话中,然后验证会话值是否与Facebook在请求中传回给您的值相同。 PHP示例中的关键行是:
if($_SESSION['state'] && ($_SESSION['state'] === $_REQUEST['state'])) {
// Continue with application logic here because state matches.
// Otherwise, exit immediately because you're a victim of CSRF!
回到你的问题。从您的重定向网址和您获得的响应中,很明显您的应用程序位于Facebook页面标签上。请参阅authentication flow for page tabs了解您应该如何做到这一点。请注意,它们未在步骤2中使用state参数,并且页面选项卡身份验证流程中从未提及state参数。因此,即使你想将state参数用于非预期用途,你也不幸。
根据您的修改,我建议您查看documentation on requests。请注意,点击请求的用户将被重定向到画布应用,而不是页面标签。 “画布URL还将包含一个额外的GET参数request_ids,它是一个以逗号分隔的列表分隔的用户正在尝试处理的请求ID列表。”因此,您无需亲自尝试这样做。