使用 Facebook 进行身份验证的网站的 REST API

Posted

技术标签:

【中文标题】使用 Facebook 进行身份验证的网站的 REST API【英文标题】:REST API for website which uses Facebook for authentication 【发布时间】:2012-08-17 10:13:37 【问题描述】:

我们有一个网站,唯一 使用该网站登录和验证自己的方式是使用 Facebook(这不是我的选择)。首次登录 Facebook 时,系统会自动为您创建一个帐户。

我们现在想为我们的网站创建一个 iPhone 应用程序,并为其他人创建一个公共 API 以使用我们的服务。

这个问题是关于如何通过应用程序/API 对我们的网站进行身份验证,分为两部分:

    处理从 API 到仅使用 Facebook OAuth 作为身份验证方法的网站的 REST 身份验证的正确方法是什么?

我已经阅读并研究了很多关于 REST API 的标准身份验证方法。我们不能使用Basic Auth over HTTPS 这样的方法,因为这样的用户没有凭据。 this 之类的东西似乎只用于使用 API 对应用程序进行身份验证。

目前,我认为最好的方法是在我们的 API 上点击 /authorize 端点,它会重定向到 Facebook OAuth,然后重定向回网站并提供 API 用户可以使用的“令牌”验证后续请求。

    对于我们创建的官方应用程序,我们不一定需要以相同的方式使用公共 API。那么与我们的网站对话和验证用户身份的最佳方式是什么?

我了解(我认为)如何使用 API(公共)密钥和秘密(私有)密钥对使用我们 API 的第 3 方应用程序进行身份验证。然而,当涉及到对使用该应用程序的用户进行身份验证时,当我们必须对用户进行身份验证的唯一方法是 Facebook 时,我对如何去做感到相当困惑。

我觉得我遗漏了一些非常明显的东西,或者不完全理解公共 REST API 应该如何工作,因此非常感谢任何建议和帮助。

【问题讨论】:

我在***.com/questions/30230482/… 有类似的问题,谈到了其中的一些问题 【参考方案1】:

更新:见下文

我也一直在认真思考这个问题。我还不完全清楚,但这是我正在考虑的路线。我正在创建一个 REST API,我的用户使用 Facebook 连接进行身份验证。

在客户端:

    使用 Facebook API 登录并获取 OAUTH2 代码。 将此代码交换为访问令牌。 在每次调用我的自定义 API 时,我都会包含 Facebook 用户 ID 和访问令牌。

在 API 上(对于每个需要用户身份验证的方法):

    使用上面的访问令牌向 /me Facebook 图发出请求。 验证返回的 Facebook 用户 ID 是否与从上面传递给我的 API 的用户 ID 匹配。 如果访问令牌已过期,则需要额外的通信。

我还没有对此进行测试。听起来怎么样?

--- 更新:2014 年 7 月 27 日回答问题---

我只在登录时使用上述交换一次。一旦我确定了哪个用户正在登录,我就会创建自己的访问令牌,并且从那时起使用该令牌。所以新的流程看起来像这样......

在客户端:

    使用 Facebook API 登录并获取 OAUTH2 代码。 将此代码交换为访问令牌。 从 my API 请求访问令牌,包括作为参数的 Facebook 令牌

在 API 上

    接收访问令牌请求。 使用 facebook 访问令牌向 /me Facebook 图发出请求 验证 Facebook 用户是否存在并与我的数据库中的用户匹配 创建我自己的访问令牌,将其保存并返回给客户端以供以后使用

【讨论】:

嘿,回复有点晚,但您的解决方案似乎解决了我在第一个答案中遇到的问题。当然,您必须使用 HTTPS 才能在网络上以明文形式发送 (id,token) 对。但它看起来应该可以工作! 我认为最好在服务器上调用 /me 并生成您自己的访问令牌,供移动客户端使用。 我发现将 FB 秘密存储在移动应用程序中是一种不好的做法。 Facebook 建议仅将其存储在您的服务器上。 developers.facebook.com/docs/opengraph/using-actions/… 如果我们每次都将 user_id 和 access_token 发送到 API 服务器(作为 post/get 参数)。如果有人能够拦截连接,它会造成安全漏洞吗? @NathanDo 在您的客户端和 API 服务器之间使用 HTTPS,如果有人拦截连接应该不是问题(Heartbleed 类型的漏洞除外)。【参考方案2】:

这是我使用 JWT(JSON Web 令牌)的实现,基本上类似于 Chris 的更新答案。我用过 Facebook JS SDK 和 JWT。

这是我的实现。

    客户端:使用 Facebook JS SDK 登录并获取访问令牌。

    客户端:通过调用 /verify-access-token 端点从我的 API 请求 JWT。

    MyAPI:接收访问令牌,通过调用 Facebook API 的/me 端点进行验证。

    MyAPI: 如果访问令牌有效,则从数据库中查找用户,如果存在则登录该用户。创建一个包含必填字段作为有效负载的 JWT,设置过期时间,使用密钥签名并发送回客户端。

    客户端:将 JWT 存储在本地存储中。

    客户端: 发送令牌(来自步骤 5 的 JWT)以及下一次 API 调用的请求。

    MyAPI: 使用密钥验证令牌,如果令牌有效,则将令牌换成新的,连同 API 响应一起发送回客户端。 (此处不再调用外部 API 来验证令牌)[如果令牌无效/过期请求客户端再次进行身份验证并从 1 开始重复]

    客户端将存储的令牌替换为新令牌并将其用于下一次 API 调用。一旦令牌到期,令牌到期撤销对 API 的访问。

每个令牌都使用一次。

阅读有关安全性和 JWT 的更多答案

How secure is JWT

If you can decode JWT how are they secure?

JSON Web Tokens (JWT) as user identification and authentication tokens

【讨论】:

我猜#3 应该是/debug_token,所以您可以检查该令牌实际上是否适用于您的应用程序。 不要在客户端请求access_token。使用“代码工作流程”。将code 传递给MyAPI 并再次往返Facebook 以将codeaccess_token 交换。此处对此进行了更彻底的解释:developers.facebook.com/docs/facebook-login/security【参考方案3】:

我正在尝试回答同样的问题,并且最近阅读了很多内容......

我不会有“答案”,但对我来说事情变得更清楚了。你读过the article you mentioned中的cmets吗?我发现它们非常有趣且很有帮助。

因此,鉴于自第一篇文章撰写以来的发展情况,我认为我将采取以下措施:

HTTPS 无处不在 — 这让您可以忘记 HMAC、签名、随机数……

使用 OAuth2:

当身份验证请求来自我自己的应用程序/网站时,请使用前面提到的 reply to the article 中描述的这个“技巧”(或其变体)。

就我而言,我有两种类型的用户:具有经典登录名/密码凭据的用户和使用 Facebook Connect 注册的用户。 所以我会提供一个带有“用 Facebook 登录”按钮的常规登录表单。如果用户使用他的“经典”凭据登录,我只需使用 grant_type=password 将这些凭据发送到我的 OAuth2 端点。 如果他选择通过 Facebook 登录,我认为这将是一个两步过程:

首先,使用 Facebook ios SDK 打开一个 FBSession 完成此操作并且应用程序被交还控制权后,应该有一种方法可以为该用户获取 Facebook ID。我会单独将此 ID 发送到我的 OAuth2 端点,并使用我的服务器理解为“使用 FB 用户 ID”的 extension grant。

请注意,我仍在对所有这些东西进行大量研究,因此这可能不是一个完美的答案……甚至可能不是一个正确的答案!但我认为这将是一个很好的起点。 为 Facebook 身份验证使用“扩展授权”的想法可能涉及必须注册它才能正确执行操作?我不太确定。

无论如何,我希望我能帮到你一点点,至少它可以开始讨论以找到这个问题的最佳解决方案:)

更新 Facebook 登录不是 cmets 中指出的解决方案:任何人都可以发送任意用户 ID 并在 API 上以该用户身份登录。

这样怎么样:

显示带有“Facebook 登录”按钮的登录表单 如果选择了这种登录方式,就像 Facebook SDK 一样:从您的身份验证服务器打开一个网页,这将启动 Facebook 登录。 一旦用户登录,Facebook 将使用您的重定向 URL 进行确认;使该 URL 指向您的身份验证服务器的另一个端点(可能带有指示调用来自应用的额外参数?) 当身份验证端点被命中时,身份验证可以安全地识别用户,保留其 FB 用户 ID/FB 会话,并使用自定义 URL 方案向您的应用返回访问令牌,就像 Facebook SDK 所做的那样

看起来更好?

【讨论】:

感谢您的回复!我已经考虑了你所说的大部分内容,但我对使用 FB iOS SDK 然后发送 Facebook 用户 ID 的主要担忧是,将任何你想要的 ID 发送到你的 API 端点并声称是不容易的另一个用户?这就是我通常最终被卡住的地方.. 确实!我不去想那个是愚蠢的......所以解决方案必须以某种方式通过你自己的身份验证服务器...... 我已经用另一个解决方案的想法更新了我的答案......但刚刚意识到你在原来的问题中提到了它!我暂时看不到其他任何东西......

以上是关于使用 Facebook 进行身份验证的网站的 REST API的主要内容,如果未能解决你的问题,请参考以下文章

如何从网站获取 Facebook 身份验证令牌

Spring Boot OAuth2 - 使用本地用户数据库向 Facebook 进行身份验证

UIWebView 中的 Facebook 身份验证不会重定向回我网站上要求身份验证的原始页面

像 Facebook 一样的 OAuth 身份验证

作为 iOS 上 FaceBook 身份验证的一部分登录我们的网站

如何使用浏览器重定向创建 Facebook 风格的应用内身份验证?