为 iOS 应用程序中的 Facebook 身份验证设计,该应用程序还访问安全的 Web 服务
Posted
技术标签:
【中文标题】为 iOS 应用程序中的 Facebook 身份验证设计,该应用程序还访问安全的 Web 服务【英文标题】:Design for Facebook authentication in an iOS app that also accesses a secured web service 【发布时间】:2011-06-05 04:04:35 【问题描述】:目标: 允许用户通过 Facebook 向需要访问我正在运行的受保护网络服务的 ios 应用程序进行身份验证。
假设: 对于那些选择不使用 Facebook 登录的用户,有一个本地身份验证(和注册)系统。
详情:
假设我们希望为用户提供使用 Facebook 登录的选项,而无需为我们的系统创建单独的帐户/凭据。 因为我们支持自己的本地身份验证机制(用户名和密码),所以我们拥有自己的用户 ID 并颁发身份验证令牌,用于在初始凭据验证后进行后续交互。我很惊讶 Facebook 在他们的开发者文档中没有这方面的最佳实践。所有现有文档都假设您正在将 FB auth 构建到网站中,或者假设您正在将 FB auth 构建到网站中,或者是没有需要身份验证的服务的独立移动应用程序。
这是我对如何设计它的初步想法,但希望验证它是否正确。
-
客户端弹出 Facebook iOS 登录
UI 用户使用 Facebook 凭据登录并获取访问令牌
iOS 应用将访问令牌传递给我们的服务器
我们的服务器使用访问令牌与 FB 图形 API 对话,以 (a) 验证令牌并 (b) 获取该访问令牌的 FB 用户 ID。
例如我们的服务器会调用https://graph.facebook.com/me/?access_token=XYZ,它会在 JSON 对象中返回配置文件信息
假设它是有效的,我们的服务器从 JSON 对象中提取用户 ID 并检查用户是否已经有一个帐户。如果是这样,我们会向客户端发出我们自己的身份验证票以用于该会话。如果用户没有帐户,我们会使用 Facebook 用户 ID 创建一个新帐户,分配我们自己的唯一用户 ID 并签发我们的身份验证票。
然后客户端在需要身份验证的后续交互中传回身份验证票。这对我来说似乎是正确的方法,但不确定我是否错过了一些非常基本的东西并走上了错误(复杂)的道路。
【问题讨论】:
这是如何解决的?我也在考虑传递访问令牌,并在服务器上启动用户。看起来很学术,但我在问。 这是我使用 Rails 和设计的实现:***.com/questions/7232490/… 为什么不传递整个 auth_hash 而不必对 FB API 进行两次调用(一次来自 iOS 设备,一次来自服务器)? 如果您想从其他设备登录(意味着您没有身份验证票)怎么办?如果你刚刚收到一张新的身份验证票,是什么阻止了某人在途中劫持 facebook id/token 并在自己的设备上使用它? 出于好奇,在第 5 步中,为什么要签发您自己的身份验证票?您不能在每个后续服务器调用中使用 Facebook 访问令牌吗?我确实意识到,对于每个应用程序->服务器调用,而不仅仅是第一个调用,它需要从服务器调用 Facebook API。 【参考方案1】:我自己刚刚处理了这个问题,这就是让我感到痛苦的部分:
在您的第 5 步中... 用户可以在与您的 Facebook ID 完全不同的情况下注册一个帐户,对吗?然后他们又用 Facebook 登录……而你刚刚为他们创建了第二个帐户,却丢失了他们的第一个帐户。
需要有一种方法可以登录到您的网络服务,然后登录到 facebook,并捕获 facebook ID 和本地帐户之间的关联。
除此之外,你的计划听起来很可靠。
更新:Facebook 添加了一个文档,概述了这种情况HERE
【讨论】:
是的,我已经考虑过这一点,你就对了。如果是相同的电子邮件地址,我们计划合并帐户,如果不是,我们将创建另一种合并方式。 您在服务器端使用哪个服务器库来发出请求? @TimLeung - 我的理解是访问令牌嵌入了应用 ID,如果没有应用 ID,您就无法获得访问令牌。 @TimLeunge:我们正在使用 Graph API 来处理带有用户访问令牌的请求。【参考方案2】:您的解决方案完全有效。
也许另一种选择:为什么不从最初的社交服务请求中获取客户端上的电子邮件并发送到您的网络服务? Web 服务可以只存储电子邮件,也可以存储一个 social_provider。我了解您的网络服务将无法验证电子邮件的来源,但您的网络服务与您的客户之间是否存在高度信任关系?如果有,似乎您可以依赖来自正确位置的电子邮件。有人请让我知道我遗漏了什么明显的东西,这使得基于电子邮件的方法变得愚蠢......
【讨论】:
我可以很容易地找出客户端是如何与服务器通信的。然后我可以向它发送电子邮件,直到我受到打击。总是需要某种形式的验证 高度信任和客户?请不要在同一个句子中。当然除了前一句。【参考方案3】:如 Facebook 所述,使用 https 将身份验证令牌传输到您的服务器
访问令牌共享
我们的数据政策明确禁止共享访问令牌 为您的应用程序与任何其他应用程序。但是,我们确实允许开发人员 在本机实现和服务器之间共享令牌 只要实现相同的应用程序(即使用相同的应用程序 ID) 使用 HTTPS 进行传输。
【讨论】:
【参考方案4】:我可以看到这个策略的一个问题是,有人可以给你一个为不同的 facebook 应用程序获得的访问令牌。据我所知,无法验证访问令牌是否适用于您的应用程序,因此您只需继续使用它即可。
不过,这听起来并不是很有害。通常人们/应用程序会尝试保护访问令牌,而不是共享它们。
一种可能的利用方式是,某人创建自己的网站或移动应用程序,为其用户获取访问令牌并尝试使用您的 API 对他们进行身份验证。如果成功(用户在您的站点中有一个 facebook 帐户),恶意站点将能够使用您的 API 来模拟用户。
这有点远,但我认为它可以工作。
编辑:看起来毕竟有一种方法可以验证访问令牌。请参阅@Daaniel 对问题Get application id from user access token (or verify the source application for a token) 的回答。
【讨论】:
发送appsecret_proof
应该可以防止这种情况发生(见here)
@Tony 你能解释一下appsecret_proof
在这里有什么帮助吗?据我了解,它可以向 Facebook 证明服务器知道密钥。但是,ivant 指的是恶意应用程序获取令牌,然后将它们发送到您的 API。服务器可以验证app ID,但是app ID很容易被恶意app欺骗。那么......如何减轻这种情况?
您可以通过https://graph.facebook.com/app/?access_token=[user_access_token]
返回app id,然后比较app id来验证token是不是为您的app生成的以上是关于为 iOS 应用程序中的 Facebook 身份验证设计,该应用程序还访问安全的 Web 服务的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用 Ionic 实现一键式 Facebook 登录?
NodeJS上的Facebook iOS access_token身份验证