python - 使用 Flask-Oauthlib 向 Facebook 进行身份验证时出现 "Invalid Response from Facebook"

标签 python authentication oauth flask facebook-oauth

在构建示例代码 here 时,使用 Oauthlib 通过 Facebook 进行身份验证时,我始终收到“来自 Facebook 的无效响应”错误。

我在下面概述了相关代码的各个部分。

设置:

设置 Oauth 请求对象。

未图示:导航路线和 Flask 应用初始化。

from flask_oauthlib.client import OAuth, OAuthException

oauth = OAuth()

facebook = oauth.remote_app('facebook',
  base_url='https://graph.facebook.com/',
  request_token_url=None,
  access_token_url='/oauth/access_token',
  authorize_url='https://www.facebook.com/dialog/oauth',
  consumer_key=config.get("app_id"),
  consumer_secret=config.get("app_secret"),
  request_token_params={'scope': 'public_profile,email'}
)

@facebook.tokengetter
def get_facebook_token():
  if current_user.is_authenticated():
    return current_user.get_facebook_token()

  else:
    return None

登录处理程序:

将用户发送到此处以开始该过程,并将 facebook 回调的 url 附加到根 URL。

@app.route('/facebook/login')
def facebook_login():
  return facebook.authorize(callback="http://example.com%s" % url_for('facebook_callback'))

Facebook 回调,问题根源:

从这里我可以发现返回了一个代码(大概是 token ),但 Oauthlib 无法正确解析它。

@app.route('/facebook/callback')
def facebook_callback(response):
  response = facebook.authorized_response()
  if response is None:
    flash("You denied the request to sign in.", "error")
    return redirect(url_for('index'))

  if isinstance(response, OAuthException):    
    flash("Access denied: %s" % response.message, "error")
    return redirect(url_for('index'))

  # Request fails here, returns the redirect above.

通过转储请求参数,我可以相当清楚地看到,在定向到 Facebook 并成功连接后,有一个很长的 token 沿着“?code=1234567890-abcdefghijklmnop”的行返回到回调,但实际上尝试对此进行身份验证失败,并显示“来自 Facebook 的无效响应”。

这是一个示例请求转储:

ImmutableMultiDict([('code', 'AQAPedwWavTb_cBx6NVy-qy3AL5YPr780oG5tA1LfITpVwkk-kr_4I0lG6B-vlhcYEubhuKhEM46bPs-1WpWUpJzcWfhkQ64lIkdLm9uSHSqeBHBM_6zw7SDpvVmGK-JKWBpAqRJuBKenl9zslQizthox96104iiul0uYQY67cmZgPXZi9uL-mcgZ5dRj387eKJIjNninBXxwCGgFkg5kLVHYt7t0ktUH58stYlxn2f98AXuSlrIvWsA5NeHsVbM8XY0XQrDrNbCvjDmEwHQGkZ3uZRbyaecN7MAi0bM0TrZzpuQ8j3M34DnQp_v9n4ktM4')])

在使用了基于 Twitter 示例的类似代码后,我认为这可能是由于 Facebook API 更改而导致的库错误,但我将不胜感激!

最佳答案

对于将来从 Google 偶然发现此问题的任何人,我在一个可以阅读的解决方案中解决了此问题 here .

Hey there, I solved this issue in a very hacky way which I would not recommend for production environments, but I eventually found the issue a few days after my last message.

When you ask Facebook for an access token, it does NOT give you an access token in the way you might expect. What I assumed to be a failure on Facebook's side was instead a (perhaps intentional) formatting error.

What you might expect:

http://example.com/callback?access_token=00000000000

or

http://example.com/callback with the access token passed as a POST argument in the headers.

What actually happens is that Facebook responds like this:

http://example.com/callback?#access_token=0000000000

Because of this, it is -impossible- for any server side language to parse it, as the access token will now only be visible to the browser itself. It is not passed to the backend whatsoever.

捕获请求:

@app.route('/facebook/translate', methods=['GET'])
def facebook_translate():
  # Facebook responds with the access token as ?#access_token, 
  # rather than ?access_token, which is only accessible to the browser.
  # This part is where things get really, really dumb.
  return '''  <script type="text/javascript">
    var token = window.location.href.split("access_token=")[1]; 
    window.location = "/facebook/callback?access_token=" + token;
  </script> '''

照常进行:

@app.route('/facebook/callback', methods=['GET', 'POST'])
def facebook_callback():
  access_token = request.args.get("access_token")

  if access_token == "undefined":
    flash("You denied the request to sign in.", "error")
    return redirect(url_for('index'))

  graph = facebooksdk.GraphAPI(access_token)
  profile = graph.get_object("me")

关于python - 使用 Flask-Oauthlib 向 Facebook 进行身份验证时出现 "Invalid Response from Facebook",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26726926/

相关文章:

python - 如何在 Luigi Task 中输出 zip 文件?

python - 在 jupyter notebook 上导入 OpenCV

python - 在python中跨文件设置全局变量

git - 使用 Codenvy 推送到 GitHub 时出现问题 : "Can' t store ssh key. 无法获取私有(private) ssh key 。”

java - GAE 联合登录和 Linkedin

python - 如何从Python脚本中包装交互式ssh session 的调用?

php - 使用 Web 服务 PHP 在 Android 中登录

python - 非管理员仪表板的 Django 登录页面

asp.net - 为什么底层成员(member)资格提供商应该决定是否……?

java - 尝试使用 play.libs.OAuth 连接到 Twitter 时出现错误 401