5

在各种情况下,Facebook 内部的 AccessToken(用于 Facebook API 中的各种功能和其他情况)可能会失效。例如,如果用户在使用依赖 Facebook 登录的应用程序的会话之间更改了她的密码。还有一些其他情况。

但是,发生的情况是您的应用程序实际上崩溃了,并出现如下错误:data={"error":{"message":"Error validating access token: Session does not match current stored session. This may be because the user changed the password since the time the session was created or Facebook has changed the session for security reasons.", "type":"OAuthException", "code":190, "error_subcode":460}}.

Passport 的 Facebook 策略使用 AccessToken,只要用户通过 Passport 登录/验证,它就可供应用程序使用。但是,问题是遇到上述错误时该怎么办。Facebook 提供了一个复杂的重新授权流程作为 PHP 中的示例,但一般意义上是您需要使用 Facebook 重新授权您的应用程序。

问题是,即使从您的 Facebook 页面中删除 Facebook 应用程序,并强制依赖 Facebook 登录的应用程序重新授权自己,Passport + Facebook 策略似乎仍在从浏览器的会话存储中获取最后一个现有的 AccessToken。(至少这是我在 Mozilla/Fx 26 中看到的)。我已经多次重新授权我的应用程序,但是在调试并查看 Passport 返回的内容时,我总是返回相同的无效 AccessToken。似乎如果会话存储中存在 AccessToken,Passport 会选择它而不是从 Facebook 获取新的。

那么有没有一种方法 - 在 Passport + Facebook 策略中 - 基本上忽略或覆盖任何存储的 AccessToken 并总是从 Facebook 请求一个新的,如果发生这种错误?完全不清楚如何实现这一点。谢谢您的帮助。

更新:调用策略的示例代码有refreshToken一个参数;这是做什么的?这个参数有可能的解决方案吗?

passport.use(new FacebookStrategy(
{
...
},
function(accessToken, refreshToken, profile, done) 
{
4

1 回答 1

7

我找到了我的问题的答案,如果其他人遇到同样的问题,我会保留它。

Passport 在其VerifyCallback功能中将 AccessToken 传递给应用程序。建议(默认或其他)当然是将此 AccessToken 保存为用户持久记录的一部分(例如,MongoDB 文档)。在对 Facebook API 进行后续调用时将需要它,尽管它可能可以从request.user通过Express中间件传递的对象中安全地检索到,但拥有自己的本地副本可能是有意义的。

现在,当您通过 Passport 完成对用户的身份验证后,您仍然会提取用户的持久记录以获取其他用户数据。Passport 文档具有一个通用函数,调用Users.findOrCreate()该函数作为该函数的模型/原型供您实现。这就是问题所在:如果您通过此功能找到用户(已经存在),您将在整个应用程序中使用该记录。如果该记录还包含一个 AccessToken,并且该 AccessToken 已更改,那么您当然会遇到麻烦:Passport/Facebook 正在向您传递一个新的 AccessToken,但您使用的是一个过时的 AccessToken。

所以简单的解决方法是这样的:如果你已经实现了一个Users.findOrCreate()持久化用户的函数并依靠它来检索用户的数据集——并且该记录还存储了 AccessToken——那么确保你检查当前(旧)AccessTokenVerifyCallback当用户刚刚通过身份验证时,一个 Passport/Facebook 正在传递给您;如果两者不同,更新用户的持久化记录并使用这个新的 Token。

于 2013-11-09T13:09:54.317 回答