视频

在 2015 年的 F8 开发者大会上,Jonathan Gross 和 Brent Dorman 畅谈了如何增强 Facebook 登录集成的安全性。

安全检查清单

下方检查清单应视为所有使用 Facebook 登录的应用至少必须遵循的内容。其他功能属于应用独有的功能,而且您需要始终思考如何尽量确保应用的安全性。不安全的应用会失去其受众的信任,用户也会停止使用这类应用。

切勿在客户端或可反编译的代码中添加应用密钥

使用应用密钥为所有服务器到服务器的图谱 API 调用签名

在客户端上使用唯一的短期口令

不要盲目相信您的应用使用的访问口令实际由您的应用生成

在使用登录对话框时使用状态参数

尽可能使用我们的官方 SDK

锁定 Facebook 应用设置,减少应用的受攻击面

使用 HTTPS

应用密钥

应用密钥在一些登录流程中用于生成访问口令,密钥本身旨在确保应用仅由受信任的用户使用。密钥可用于轻松创建应用访问口令,而此访问口令可代表应用的任意用户发出 API 请求,因此务必要确保应用密钥不被盗用。

因此切勿将应用密钥或应用访问口令添加到任何代码中。

为提供最佳安全性,我们建议只从应用的服务器直接使用应用访问口令。对于原生应用,我们建议应用与您自己的服务器通信,然后服务器再使用应用访问口令向 Facebook 发出 API 请求。因此,如果将应用面板的高级设置下的“应用类型”设置为 Native/Desktop,系统就会认为您原生应用的二进制文件中含有应用密钥或应用访问口令,并阻止使用应用访问口令签名的调用继续执行。所以,API 的行为就会与未提供访问口令时一样。

通过 appsecret_proof 保护服务器端调用

您可以要求服务器到服务器的 Facebook API 调用使用 appsecret_proof 参数签名,以降低被恶意软件和垃圾邮件发送者攻击的可能性。应用密钥证明是访问口令的 sha256 散列值,使用应用密钥作为键值。如需查找应用密钥,请前往应用面板的设置 > 基本

生成证明

以下代码示例展示了 PHP 中的调用:

$appsecret_proof= hash_hmac('sha256', $access_token.'|'.time(), $app_secret); 

一些操作系统和编程语言将返回一个时间戳(浮点数)。在计算应用密钥证明之前,请务必将浮点数转换为整数值。一些编程语言会创建散列值作为 digest 对象。请务必以十六进制对象的形式来表示散列值。

添加证明

将生成的证明添加为 appsecret_proof 参数,该参数中的 appsecret_time 应设为对您每次所发出调用的应用密钥进行散列处理时所使用的时间戳:

curl \
  -F 'access_token=ACCESS-TOKEN' \
  -F 'appsecret_proof=APP-SECRET-PROOF' \
  -F 'appsecret_time=APP-SECRET-TIME' \
  -F 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/accounts"}]' \
  https://graph.facebook.com

对于带有时间戳的应用密钥证明,其有效期为 5 分钟,因此建议您在每次调用图谱 API 时都生成一个新内联证明。

要求提供证明

在应用面板设置 > 高级部分的安全部分,启用必须提供应用密钥。启用该设置时,我们将仅允许包含 appsecret_proof 的 API 调用。

通过短期口令和代码流程保护客户端调用的安全

在一些配置下,应用会在多个客户端之间重复使用同一个长期口令,但切勿这样操作。请转为使用通过代码流生成的短期口令,正如访问口令文档所述。

口令劫持

如要了解口令劫持是如何发生的,您可以假设一个原生 iOS 应用想要调用 API,但并非直接调用,而是与此应用拥有的服务器通信,并向此服务器传递使用 iOS SDK 生成的口令。然后,服务器就可以使用此口令调用 API。

服务器用于接收口令的端点可能被盗用,之后其他人就可以向此端点传递其他应用的访问口令。这显然非常不安全,但有一种方法可以防御这种情况:绝不能盲目相信访问口令来自于使用该口令的应用,而是应该使用调试端点检查口令

定期检查访问口令的有效性

如果您不使用 Facebook SDK,请定期检查访问口令是否有效。虽然访问口令有预定的过期时间,但也可能出于安全原因而提前过期。如果您的应用不使用 Facebook SDK,则请您一定以手动方式频繁检查口令的有效性(至少每天一次),以确保您的应用所使用的口令并未因安全原因而提前过期。

状态参数

如果您在自己的网站上使用 Facebook 登录对话框,则 state 参数是可用于防范应用遭受跨站请求伪造攻击的唯一字符串。

启用严格模式

严格模式可防止不良行为者劫持重定向 URI,从而保护应用的安全。所有应用都必须启用严格模式。

在应用面板中启用严格模式之前,请在 Facebook 登录设置中执行以下操作,确保您当前的重定向流量仍然有效:

  • 对于使用动态重定向 URI 的应用,请使用状态参数将动态信息回传给数量有限的重定向 URI。然后将每个重定向 URI 添加到有效 OAuth 重定向 URI 清单。

  • 对于重定向 URI 数量有限的应用,请将每个 URI 添加到有效 OAuth 重定向 URI 清单。

  • 对于仅使用 Facebook JavaScript SDK 的应用,其重定向流量已受到保护。无需采取进一步操作。

完成这些操作后,请确保启用严格模式。

严格模式的工作方式

严格模式要求 URI 与您有效 OAuth 重定向 URI 清单中的 URI 完全匹配,以防止重定向 URI 遭到劫持。举例而言,如果您的清单中包含 www.example.com,则在严格模式下,不允许使用 www.example.com/token 作为有效重定向 URI。此外,这种模式也不允许出现有效 OAuth 重定向 URI 清单未包含的其他任何额外查询参数。

使用 HTTPS

使用 HTTPS 互联网协议,而不是 HTTP,原因就在于前者采用了加密技术。正因如此,HTTPS 能够保持传输数据的私密性并防止窃听攻击。它还能防止数据在传输期间被篡改,例如植入广告或恶意代码。

自 2018 年 10 月 6 日起,所有应用都需要使用 HTTPS。

为 Facebook 登录启用 JavaScript SDK

当您将使用 JavaScript SDK 登录开关切换为“是”来表明自己将使用 JavaScript SDK 登录功能时,托管 SDK 的页面的网域必须与 JavaScript SDK 允许使用的网域清单中的任一条目相匹配。这有助于确保仅向授权网域的回调返回访问口令。仅 https 页面支持使用 Facebook JavaScript SDK 执行验证操作。

对于在 2021 年 8 月 10 日之前创建的既有 JSSDK 集成,此清单会根据当前的使用情况回填值。无需采取进一步操作。

对于在 2021 年 8 月 10 日之后创建的新集成,您必须向此清单添加值。

如果您看到应用的 JSSDK 网域字段包含以 *. 开头的网址,请将其更改为绝对网域网址以提高安全性。

重定向 URI 检查程序的运作方式

不良行为者在登录请求中提供未经授权的 redirect_uri 参数会引发开放式重定向攻击,致使访问口令等敏感信息可能通过重定向 URI 中的查询字符串或片段泄漏。

对于自定义网站集成,您应在应用设置中提供经授权的重定向 URI 以规避此类攻击。当履行登录请求时,系统将根据此清单中的条目检查 redirect_uri 参数。整个 URI 必须完全匹配,其中包括所有参数,但可选的状态参数除外,因为该参数的值将忽略不计。

应用内浏览器和 JavaScript SDK

JavaScript SDK 通常依赖弹出窗口和回调来完成登录。但对于某些阻止弹出窗口的应用内浏览器,这种方式可能无法奏效。当遭遇此情况时,SDK 将自动尝试使用访问口令重定向至启动调用操作的页面。仅当页面的完整 URI 与有效 OAuth 重定向 URI 所示条目匹配时,它才能安全地执行此重定向操作。

如果应用内浏览器场景对您的网页应用至关重要,您应将登录页面的网域添加到“允许使用的网域”,并将其完整 URI(包括路径和查询参数)添加到“有效 OAuth 重定向 URI”。如果您有多个不同的 URI 可以登录您的应用,则您可以手动指定 fallback_redirect_uri 作为 FB.login() call 的一个选项,这样您只需将一个条目添加到“有效 OAuth 重定向 URI”清单即可。

锁定 Facebook 应用设置

启用和/或禁用应用未使用的任何身份验证流程,充分缩小遭到攻击的范围。

  • 在客户端使用代码生成的短期访问口令,而非客户端生成的口令或服务器提供的长期口令。代码生成短期访问口令的流程要求应用服务器使用对应代码交换获得口令,这比在浏览器中获得口令更安全。为提高安全性,应用应尽可能首选使用此流程 - 如果应用只启用这个流程,用户电脑上运行的恶意软件就无法获得访问口令进行违规使用。详情请参阅我们的访问口令文档

  • 禁用客户端 OAuth 登录(如果应用未使用)。“客户端 OAuth 登录”是使用 OAuth 客户端口令流程的全局切换开关。如果应用未使用任何客户端 OAuth 流程(包括 Facebook 登录 SDK),则应该禁用此流程。注意,如果禁用了客户端 OAuth 登录,您就无法请求访问口令的权限。如需查找此设置,请前往应用面板的产品 > Facebook 登录 > 设置部分。

  • 禁用 OAuth 网页授权登录流程或指定重定向白名单。“OAuth 网页授权登录”设置可允许使用 Facebook 网页版登录对话框的任何 OAuth 客户端口令流程将口令返回至您的网站。如需查找此设置,请前往应用面板的产品 > Facebook 登录 > 设置部分。如果您不构建自定义的网页版登录流程或不在网页上使用 Facebook 登录 SDK,则应禁用此设置。

  • 强制实施 HTTPS。此设置要求 OAuth 重定向使用 HTTPS,并且要求所有返回或需要访问口令的 Facebook JavaScript SDK 调用只能从 HTTPS 页面执行。2018 年 3 月起创建的所有新应用都将默认启用此设置,且您应该计划在 2018 年 10 月 6 日之前迁移现有的任何应用,以便使用纯 HTTPS 网址。大部分主流云应用主机都可以为您的应用程序提供免费自动的 TLS 证书配置。如果您自行托管应用或托管服务未默认提供 HTTPS,则可以通过 Let's Encrypt 为网域获取免费证书。

  • 禁用嵌入的浏览器 OAuth 流程(如果应用未使用)。一些桌面和移动版原生应用通过在嵌入的网页视图内执行 OAuth 客户端流程,以验证用户身份。如果您的应用不执行此流程,则应在应用面板的产品 > Facebook 登录 > 设置部分禁用此设置。

  • 禁用移动单点登录流程(如果应用未使用)。如果应用未使用 iOS 或 Android 版登录功能,则应在设置 > 基本的 iOS 和 Android 部分禁用“单点登录”设置。

应用面板中有许多其他设置,允许开发者关闭可能以其他方式导致安全问题的攻击目标:

  • 基本 > 应用密钥:如果应用密钥被盗,则可以在这里重置。
  • 基本 > 应用网域:通过此设置锁定可用于代表您的应用执行 Facebook 登录的网域和子网域。
  • 高级 > 应用类型:创建移动或桌面版原生应用并在其中添加应用密钥时,应将应用类型设置为 Native/Desktop,以防止应用被反编译及应用密钥被盗。
  • 高级 > 服务器 IP 白名单:指定 IP 地址清单,以便从这些 IP 地址使用应用密钥调用图谱 API。从清单以外的 IP 地址使用应用密钥发出的图谱 API 调用请求将会失败。通过用户访问口令发出的调用请求不会受此设置的影响。
  • 高级 > 更新设置 IP 白名单:将 IP 地址锁定为特定范围,确保只有来自这些地址的用户可以修改相关的应用设置。在使用家庭宽带时,请谨慎设置 IP 白名单。如果您的 IP 地址更改,您就无法编辑应用的设置。
  • 高级 > 更新通知邮箱:当应用面板中的应用设置有所更改时,向邮箱发送通知。
  • 高级 > 信息流发布网址保护:此设置会阻止应用发布未指向应用所拥有网域的任何网址。此设置并非始终有用,尤其是在您知道自己的应用会向其他网站发布链接的情况下。