在还可以访问安全Web服务的iOS应用中设计Facebook身份验证


402

目标: 允许用户通过Facebook身份验证进入iOS应用程序,该应用程序需要访问我正在运行的受保护的Web服务。

假设: 为那些不选择使用Facebook登录的用户提供了本机身份验证(和注册)系统。

细节:

  • 假设我们要为用户提供使用Facebook登录的选项,而无需为我们的系统创建单独的帐户/凭据。
  • 因为我们支持我们自己的本机身份验证机制(用户名和密码),所以我们拥有自己的用户ID并发出身份验证令牌,该令牌用于初始凭据验证后的后续交互。

我很惊讶Facebook在其开发人员文档中没有针对此的最佳实践。现有的所有文档都是假设您正在将FB身份验证构建到网站中,或者是一个独立的移动应用程序,其中不包含需要身份验证的服务。

这是我对如何设计的初步想法,但想验证它是否正确。

  1. 客户端弹出Facebook iOS登录
  2. UI用户使用Facebook凭据登录并获取访问令牌
  3. iOS App将访问令牌传递给我们的服务器
  4. 我们的服务器使用访问令牌与FB graph API进行对话,以(a)验证令牌,并(b)获取该访问令牌的FB用户ID。

    例如,我们的服务器将调用https://graph.facebook.com/me/?access_token=XYZ,它将在JSON对象中返回配置文件信息

  5. 假设它是有效的,我们的服务器从JSON对象提取用户ID,并检查用户是否已经有一个帐户。如果是这样,我们会向客户端颁发自己的身份验证票证以用于该会话。如果用户没有帐户,我们将使用Facebook用户ID创建一个新帐户,分配我们自己的唯一UserID并颁发身份验证票证。

  6. 然后,客户端将身份验证票证传回需要身份验证的后续交互。

这对我来说似乎是正确的方法,但是不确定我是否缺少一些疯狂的基本知识并且走错了(复杂的)道路。


1
如何解决的?我也在考虑传递访问令牌,并在服务器上分散用户。似乎学术,但我在问。
克里斯·范·布斯克

这是我使用rails和devise的实现: stackoverflow.com/questions/7232490/…–
Matt

为什么不传递整个auth_hash而不是必须两次调用FB API(一次来自iOS设备,一次来自服务器)?
bsiddiqui 2013年

1
如果要从其他设备登录(意味着您没有身份验证票)怎么办?并且,如果您只是收到新的身份验证票,是什么阻止某人在途中劫持了Facebook ID /令牌并在自己的设备上使用它?
Amitloaf 2014年

出于好奇,在第5步中,为什么要发行自己的身份验证票?您能否在以后的每次服务器调用中都不使用Facebook访问令牌?我确实意识到,对于每个应用程序,都需要从服务器调用Facebook API->服务器调用,而不仅仅是第一个。
安德斯2014年

Answers:


80

我只是自己处理这个问题,这是困扰我的部分:

在您的第5步中...用户可以与您的帐户完全独立地使用其Facebook ID进行注册,对吗?然后其他时间他们使用Facebook登录...。您刚刚为他们创建了第二个帐户,却丢失了他们的第一个帐户。

必须有一种方法可以登录到您的Web服务,然后登录到Facebook,并捕获Facebook ID与本地帐户之间的关联。

除此之外,您的计划听起来很可靠。

更新:Facebook已经增加了DOC概述这种情况下HERE


7
是的,我已经考虑过了,您会发现的。如果帐户是相同的电子邮件地址,我们计划合并帐户,否则,我们将创建另一种合并帐户的方式。
TMC

您在服务器端使用哪个服务器库来发出请求?
TimLeung 2011年

7
@TimLeung-我的理解是访问令牌嵌入了应用程序ID,如果没有将应用程序ID嵌入其中,就无法获得访问令牌。
丹·雷

1
@TimLeunge:我们正在使用Graph API来处理带有用户访问令牌的请求。
TMC

29

如Facebook所述,使用https将身份验证令牌传输到您的服务器

共享访问令牌

我们的数据政策明确禁止您的应用程序与任何其他应用程序共享访问令牌。但是,我们确实允许开发人员在同一应用程序的本机实现和服务器实现之间共享令牌(即,使用相同的App ID),只要使用HTTPS进行传输即可。


16

我可以用这种策略看到的一个问题是,有人可以给您一个从其他Facebook应用程序获得的访问令牌。据我所知,无法验证访问令牌是否适用于您的应用程序,因此您将继续使用它。

不过,听起来并不十分有害。通常,人们/应用程序会尝试保护访问令牌,而不是共享它们。

一种可能的利用方法是,对于某个人来说,创建自己的网站或移动应用程序,为其用户获取访问令牌并尝试使用您的API对其进行身份验证。如果此操作成功(用户在您的站点中拥有一个Facebook帐户),则恶意站点将能够使用您的API冒充用户。

这有点远,但是我认为它可以工作。

编辑:看来毕竟有一种方法可以验证访问令牌。有关问题的信息,请参阅@Daaniel的答案:从用户访问令牌获取应用程序ID(或验证源应用程序的令牌)


发送appsecret_proof应避免这种情况(请参阅此处
Tony

@Tony您能解释一下appsecret_proof这里有什么帮助吗?据我了解,它可以向Facebook证明服务器知道密钥。但是,ivant指的是恶意应用程序,它获取令牌并将其发送到您的API。服务器可以验证应用程序ID,但是该应用程序ID容易被恶意应用程序欺骗。那么...如何减轻这种情况?
YSK 2015年

3
您可以验证令牌是为您的应用生成的https://graph.facebook.com/app/?access_token=[user_access_token],并通过该令牌返回应用ID,然后比较应用ID
Nader Alexan

4

您的解决方案完全有效。

也许是另一种选择:为什么不从最初的社交服务请求中获取客户端的电子邮件并将其发送到您的Web服务?Web服务可以只存储电子邮件,也可以存储social_provider。我了解您的Web服务将无法验证电子邮件的来源,但是您的Web服务与客户之间是否没有高度信任的关系?如果有,您似乎可以依靠来自正确位置的电子邮件。有人请让我知道我缺少什么明显的东西,这使基于电子邮件的方法变得愚蠢...


3
我可以轻松地找出客户端与服务器的通讯方式。然后,我可以向它发送电子邮件,直到获得成功为止。总是需要某种形式的验证
克里斯,克里斯

5
高信任度和客户?请不要在同一句话中。当然除了前面的句子。
EralpB 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.