删除offline_access权限的明智解决方案

时间:2012-07-23 11:58:02

标签: facebook facebook-access-token offline-mode

在离开FB平台一段时间后我回来建立一个FB应用程序,我发现旧的offline_access权限已被删除并替换为long(ish)-expiry tokens [1]。

所以,现在看来,任何需要根据外部应用中的时间表或某些活动将数据推送到Facebook的外部应用都需要应对已过期的长访问令牌。这更令人沮丧,因为现在注销FB的用户也将终止任何长期到期令牌[2],而之前,即使用户注销,offline_access仍然存在。

我仍处于思考解决阶段,但有两个想法浮现在脑海中:

1)每当我的应用程序联系具有FB集成的用户时,都会要求他们单击一个链接,该链接将触发与FB重新授权以获取新的长访问令牌。我的用户通常会在长访问令牌的生命周期内多次联系,因此 应该有效地继续更新长访问令牌,只要他们需要(即使它确实会增加一些烦人的摩擦到我的应用程序)

2)因为我无法保证1)将始终有效(例如,由于用户未点击我的应用程序的电子邮件通知中的重新验证链接或他们退出Facebook,我)还必须处理FB交互失败,将它们置于保留队列中,并通过电子邮件通知用户明确要求他们再次授予长访问令牌。不酷,但我看不到其他选择。如果他们在X尝试要求他们重新授予权限后没有回复请求,我只需要将任务分开并通过电子邮件发送给他们,以解释这是由于FB限制,而不是我的应用程序。再次,不酷。

是否有人必须提出任何更好的解决方案来维持与身份验证/显式权限的用户帐户交互的能力?我很想知道你做了什么。

(这一切都在等待我重新阅读FB ToS,当然 - 这完全有可能违反规则,这将更令人沮丧)

编辑/更新:我需要推送的数据是图像到相册,该相册将从各种来源到达我的服务器,然后被推送到相应用户的相册(当然,具有预先授予的许可)。我无法保证在图像到达我的服务器的时间点进行任何基于Web的最终用户交互,以便让最终用户授予我新的短寿命令牌。基本上,offline_access对于这个IMO来说真的是理想的。

更新2:注意:我的用例非常关键,当需要授予或扩展令牌时,用户不一定会使用我的应用程序或Facebook。

[1] https://developers.facebook.com/roadmap/offline-access-removal/ [2] http://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/

3 个答案:

答案 0 :(得分:4)

你有两个正确的选择,但我会指出第三个选项和一个鲜为人知的事实,可能与你需要将数据推送到Facebook的具体情况相关或不相关

首先,假设您为应用程序实现了移动网络或画布,则另一个选项可用于应用程序请求或通知。用户将在书签列表中的应用名称旁边显示一个小通知计数器指示符。如果他们响应请求或书签/通知计数器让他们点击您的应用程序,您可以触发服务器端令牌续订/扩展过程。这个过程对用户是透明的 - 假设他们仍然安装了你的应用程序,他们什么也看不见。

其次,今天很多人使用offline_access只是发布到用户的流。如果这就是您所需要的,并且您不需要执行大量FQL查询或在图API上执行其他操作,那么如果您获得了publish_stream权限,则实际上并不需要offline_access或当前用户令牌。使用publish_stream,您可以使用应用访问令牌在用户离线时发布。

答案 1 :(得分:2)

对于特定的“需要推送数据”方案,facebook announcedPage object connections允许您创建具有特定发布时间的帖子。理论上你可以通过在创建这些用户时对用户进行身份验证来解决问题,并让Facebook发布这些用户而不是预定的工作。

答案 2 :(得分:1)

这里有第3个选项作为建议。

对于每个经过身份验证的用户,您有access_token和expires_in(假设您已将它们存储在数据库中)

1)编写计划任务,使用expires_in值检查现有令牌 当你发现任何令牌接近到期时间时,

2)您可以通过HTTP GET调用(下面的示例代码)从服务器端更新此令牌

requestUrl = "https://graph.facebook.com" + "/oauth/access_token"
            + "?" + "client_id="+facebook_appId 
            + "&"+"client_secret="+facebook_appSecret
            + "&" + "grant_type=fb_exchange_token"
            + "&" + "fb_exchange_token="+currentToken;

            req = WS.url( requestUrl );
            Logger.info("renew token, req.url : %s", req.url);
            req.timeout = 20;
            resp = req.get();

            // access_token=....&expires=5181096
            Map<String, String> respMap = LocoUtils.decodeUrl( resp.getString() );
            token = respMap.containsKey("access_token")? respMap.get("access_token") : "";

            facebookToken.access_token = token;
            facebookToken.expires_in = respMap.containsKey("expires")?LocoUtils.stringToLong(respMap.get("expires")) : 0L;