facebook - 应如何在服务器端使用 Facebook 用户访问 token ?

标签 facebook security authentication facebook-access-token facebook-authentication

前言

我正在开发几个 Web 服务和一些客户端(Web 应用程序、移动设备等),它们将通过 HTTP(s) 与所述服务进行交互。我目前的工作项目是为产品设计一个身份验证和授权解决方案。我决定利用外部身份提供商,例如 Facebook、Google、Microsoft、Twitter 等进行身份验证。

我正在尝试解决“当请求到达我的服务器时,我如何知道用户是谁以及我如何确定?”的问题。下面还有更多问题...

需求

  • 依靠外部身份来表明我正在与谁打交道('userId' 本质上是我关心的全部)。
  • 系统应该使用基于 token 的身份验证(而不是例如 cookie 或基本身份验证)。

    我相信这是在提供松散耦合的同时跨多个客户端和服务器进行扩展的正确选择。

  • 工作流程

    根据我对基于 token 的身份验证的阅读和理解,以下是我想象的工作流程。现在让我们关注 网页浏览器中的 Facebook .我的假设是其他外部身份提供者应该具有类似的功能,尽管我还没有确认。

    请注意,在撰写本文时,我将以下内容基于 Facebook 登录版本 2.2
  • 客户:使用 JavaScript SDK 开始登录 Facebook
  • Facebook :用户验证和批准应用权限(例如访问用户的公开个人资料)
  • Facebook :向客户端发送包含用户访问 token 、ID 和签名请求的响应
  • 客户:在浏览器 session 中存储用户访问 token ( handled by SDK conveniently )
  • 客户:通过在授权 header 中发送用户的访问 token + 用户 ID(可能在自定义 header 中),向我的 Web 服务发出对安全资源的请求
  • 服务器:从请求头中读取用户访问 token ,并通过向 Facebook 提供的 debug_token 图 API 发送请求来启动验证
  • Facebook :使用用户访问 token 信息(包含 appId 和 userId)响应服务器
  • 服务器:通过将 appId 与预期的(自身已知的)以及 userId 与客户端请求中发送的内容进行比较来完成 token 的验证
  • 服务器:使用请求的资源响应客户端(假设为快乐授权路径)

  • 我想象着对服务器的后续请求将重复步骤 5-9(当用户的访问 token 有效时 – 未过期、从 FB 端撤销、应用程序权限更改等)

    这是一个图表,可帮助您完成这些步骤。请理解本系统是不是 单页应用程序 (SPA)。提到的 Web 服务本质上是将 JSON 数据提供给客户端的 API 端点;他们不提供 HTML/JS/CSS(Web 客户端服务器除外)。

    Workflow diagram

    问题
  • 首先,根据我的前言和要求,所描述的方法是否有任何明显的差距/坑?
  • 正在向 Facebook 执行出站请求以验证访问 token (上面的步骤 6-8)每个客户请求 需要/推荐吗?

    我至少知道,我必须验证来自客户端请求的访问 token 。但是,我不知道第一次之后的后续验证的推荐方法。如果有典型的模式,我有兴趣了解它们。我了解它们可能取决于我的要求;然而,我只是不知道该找什么。一旦我有了一个基本的想法,我就会进行尽职调查。

    例如,可能的想法:
  • 在第一次验证完成后散列访问 token + userId 对,并将其存储在分布式缓存中(所有 Web 服务器均可访问),其到期时间与访问 token 相同。根据来自客户端的后续请求,散列访问 token + userId 对并检查其在缓存中的存在。如果存在,则请求被授权。否则,请联系 Facebook 图形 API 以确认访问 token 。我假设如果我使用 HTTPS(我将使用 HTTPS),这个策略可能是可行的。但是,性能如何比较?
  • this StackOverflow question 中接受的答案建议在 Facebook 用户 token 的第一次验证完成后创建自定义访问 token 。然后将自定义 token 发送到客户端以用于后续请求。然而,我想知道这是否比上述解决方案更复杂。这将需要实现我自己的身份提供者(我想避免这样做,因为我想首先使用外部身份提供者......)。这个建议有什么好处吗?
  • 上面第 3 步中的响应中是否存在 signedRequest 字段(提到 here ),等效于签名请求参数 here在“游戏 Canvas 登录”流程中?

    它们似乎被暗示为等价的,因为前者在文档中链接到后者。然而,我很惊讶游戏页面上提到的验证策略在“手动构建登录流程”中没有提到page的网络文档。
  • 如果 #3 的答案是"is",那么解码签名和比较的相同身份确认策略是否可以在服务器端使用?

    Decode & compare from FB docs

    我想知道是否可以利用它而不是对 debug_token 图形 API(上面的第 6 步)进行出站调用来确认访问 token ,如推荐 here :

    debug_token graph API from FB docs

    当然,为了在服务器端进行比较,签名的请求部分需要与请求一起发送到服务器(上面的第 5 步)。除了不牺牲安全性的可行性之外,我想知道与进行出站调用相比性能如何。
  • 当我在做的时候,在什么情况下/出于什么目的,你会把用户的访问 token 持久化到数据库中吗?
    我没有看到需要这样做的场景,但是,我可能忽略了一些东西。我很好奇一些常见的场景可能会引发一些想法。

  • 谢谢!

    最佳答案

    根据您的描述,我建议使用服务器端登录流程,如

  • https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2

  • 这样 token 已经在您的服务器上,不需要从客户端传递。如果您使用非加密连接,这可能存在安全风险(例如,对于中间人攻击)。

    步骤是:

    (1) 登录人员

    您需要指定要从 scope 中的用户那里收集的权限。范围。可以通过普通链接触发请求:
    GET https://www.facebook.com/dialog/oauth?
        client_id={app-id}
       &redirect_uri={redirect-uri}
       &response_type=code
       &scope={permission_list}
    


  • https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#login

  • (2) 确认身份
    GET https://graph.facebook.com/oauth/access_token?
        client_id={app-id}
       &redirect_uri={redirect-uri}
       &client_secret={app-secret}
       &code={code-parameter}
    
  • https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#confirm

  • (3) 检查访问 token

    您可以通过在您的问题中已经说过的方式检查 token
    GET /debug_token?input_token={token-to-inspect}
        &access_token={app-token-or-admin-token}
    

    这应该只在服务器端完成,否则你会让你的应用程序访问 token 对最终用户可见(不是一个好主意!)。


  • https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#checktoken

  • (4) 扩展访问 token

    获得(短暂的) token 后,您可以调用以扩展 token ,如
  • https://developers.facebook.com/docs/facebook-login/access-tokens#extending

  • 像下面这样:
    GET /oauth/access_token?grant_type=fb_exchange_token
        &client_id={app-id}
        &client_secret={app-secret}
        &fb_exchange_token={short-lived-token}
    

    (5) 访问 token 的存储

    关于在服务器上存储 token ,FB 建议这样做:
  • https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#token

  • (6) 处理过期的访问 token

    由于 FB 不会通知您 token 是否已过期(并且如果您在拨打电话之前不保存到期日期并将其与当前时间戳进行比较),如果 token 无效,您可能会收到来自 FB 的错误消息(最多 60 天后)。错误代码将为 190 :
    {
      "error": {
        "message": "Error validating access token: Session has expired at unix 
                    time SOME_TIME. The current unix time is SOME_TIME.", 
        "type": "OAuthException", 
        "code": 190
      }
    }
    


  • https://developers.facebook.com/docs/facebook-login/access-tokens#expiredtokens

  • If the access token becomes invalid, the solution is to have the person log in again, at which point you will be able to make API calls on their behalf once more. The login flow your app uses for new people should determine which method you need to adopt.

    关于facebook - 应如何在服务器端使用 Facebook 用户访问 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27294165/

    相关文章:

    security - 我应该如何创建我的 DES key ?为什么 7 个字符的字符串不够用?

    scala - 我应该如何解决两个不同用户的登录身份验证问题?

    facebook - 加载 Iframe Facebook(X-Frame-Options 拒绝加载)

    javascript - 旧版 FBJS 导致错误

    javascript - 返回页面后,Facebook Like 按钮移动并变为 1000px 高

    java - Glassfish 如何信任 SSL 的过期证书

    PHP 忘记密码功能

    php - fbconnect登录成功后如何刷新页面

    python - 使用Python登录ask.fm

    javascript - 没有httpOnly的Cookie,有多不安全?