api - 架构设计 - REST API 支持由移动应用程序完成的 Facebook 登录

标签 api rest facebook-graph-api oauth oauth-2.0

我正在尝试设计 REST API 以支持各种移动客户端(iOS 和 Android 应用程序)。这些应用程序将允许用户使用 Facebook 登录以及我们自己的电子邮件身份验证进行登录。你可以引用下图了解我的设计

Design flow

有两个级别的授权发生:

第一个是使用 OAuth2 的“客户端(或应用程序)授权”。因此,当用户在移动设备上安装我们的应用程序并启动应用程序时,首先,应用程序会进行“客户端(应用程序)授权”,如上图(第一张图)所示。然后服务器发回一个长期存在的 access_token到客户端用于所有后续调用。我的问题是:

Q1) 您可以看到客户端正在发送 client_keyclient_secret我将它们存储在 client_info table 。这个 secret 应该是纯文本还是应该是可解密的格式?如果我加密它,我仍然需要在我的系统中的某个地方保留加密 key 。那么它将如何使其安全?同样在每次调用中,解密将是一种开销。

Q2) 可以缓存 access_token对于redis中纯文本格式的客户端并首先使用该缓存?

Q3) 为了更加安全,我要求客户发送 appsecret_proof为了确保 access_token,他们发送的只属于这个客户端。它使用与 Facebook 相同的概念 https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof .它是hash_hmac('sha256', access_token, client_secret)
Q4) 我们将只有自己的 2 个移动应用程序(iOS 和 Android 各一个),并且不提供第三方使用我们的 API 来开发其他应用程序。这意味着,我们的 client_info对于每种类型的应用程序,表将只有两行。那么可以吗,在应用程序代码中,我们保留 client_keyclient_secret硬编码?如果是,那么将来当我们必须使新 secret 失效并使用新 secret 时,我们将如何实现替换这些信息?

Q5)由于它是我们自己的应用程序已有几年了,因此将针对相同的 client_key 创建多个 access_token|和 client_secret .为了保存所有这些,存储client_key 是不是一个好主意?作为键和 array of all access_tokens作为 redis 中的值。以后我们的API什么时候开放给第三方,那么这个redis存储设计还能扩展吗?

==================

稍后,用户决定在我的应用程序上执行一些操作,为此我们需要用户登录到他的帐户。对于该用户,单击“facebook 登录”。我的应用得到 facebook access_token和来自 facebook 的 fb 用户 id 并将这些信息传递给 API 服务器(如图 2 所示)。 API 服务器获取该 token 并调用 facebook API 来验证其 access_token .验证 token 后,服务器使用与该用户相关的一些元数据以及 FB 访问 token 来生成我们自己的 user_access_token ,让我们说 utoken .并通过 utoken返回到客户端以在每个后续用户特定的 API 调用中传回。我的问题是:

Q1) 可以保存 utoken在数据库中,user_token table 。这应该utoken是纯文本还是应该是可解密的格式?如果我加密它,我仍然需要在我的系统中的某个地方保留加密 key 。那么它将如何使其安全?同样在每次调用中,解密将是一种开销。

Q2) 在每个用户特定的 API 调用中,我应该每次都调用 facebook 来检查 facebook access_token仍然有效吗?我相信我不应该,因为这不会给我带来任何好处。请注意,Facebook 仅用于“Facebook 登录”。

Q3) 我应该加密哪些信息来生成utoken ?我想有一个散列或用户的关联数组 email , user id , rolefacebook token然后序列化该数据结构并最终对其进行加密。你认为这样就足够了。我理解它符合我的要求,但作为标准或通用应用程序,它们是否足够好?或者有什么最佳实践吗?

Q4) 客户应该存储 utoken在它的 cookie/缓存中?那不是很可怕吗?

Q5) 请注意,用户可能有多个设备,使用相同的用户凭据登录。这意味着,在 user_token 表中,我们必须存储多个 utokens对于那些已登录的 session ,而所有这些都将属于同一用户。听起来对吗?

一个与我有点相似的设计方案 REST API for website which uses Facebook for authentication

最佳答案

Q1.1:不!。客户端凭据不打算以这种方式使用。如果您的客户端是单页应用程序或移动应用程序,您将被迫将您的客户端凭据存储在不安全的环境中,即用户的机器。您应该使用 OAuth 的隐式流程

Q1.2:假设 token 是短暂的,缓存它没有问题。 OAuth 的关键是,除了确保您可以依赖其他应用程序来验证您的用户之外,您还可以使用短期 token 有效地替换长期存在的用户或应用程序凭据。因此,如果有人获得了 token 的访问权限,至少,他们对系统的访问将在时间上受到限制。

Q1.3:查看 facebook 文档:

Graph API calls can be made from clients or from your server on behalf of clients. Calls from a server can be better secured by adding a parameter called appsecret_proof.



它指出 appsecret_proof用于代表用户从服务器调用。这里的重点与 Q1.1 有关。如果您将 client_secret 存储在用户的设备中,他们可能会生成 appsecret_proof .

Q1.4:再次,不!您应该很好地阅读 OAuth 规范并了解不同的流类型以及何时使用它们。另请记住,如果您为应用程序提供 API,则该 API 是公开的,任何人都可以滥用。唯一的区别是它没有记录。 Web 应用程序也会发生同样的情况。一旦它在互联网上,我就可以编写一个抓取工具并滥用 Web 应用程序。这是完全正常的,请记住,互联网上的任何内容都不是私密的,只是未记录在案。

Q1.5:同样,代币应该是短暂的。如果它们的生命周期与凭证相同,在用户更改它们之前一直有效,那么 token 就失去了用途。

Q2.1:您应该保存该 token ReST 架构使用客户端缓存约束。

Q2.2:我不这么认为。 Facebook 只是告诉您,获得该 token 的用户具有某些身份(例如电子邮件),您可以将其关联到您系统中的某个用户。一旦您知道该关联,您就不必太在意 Facebook token ,而应该调用 Facebook API。但是你说的屁股,你只是为了登录使用它。

Q2.3:看起来不错,但再次检查 Oauth 规范,因为您似乎正在构建隐式流并使用 JWT token 。根据您要存储在 token 中的内容,似乎没问题。

Q2.4:JWT token 必须由客户端缓存。没什么可怕的,因为它们对客户端是不透明的,因为它们是加密的。客户端随每个请求发送 JWT token ,API 服务器使用私钥(从未在服务器外公开)解密 token ,并可以检查用户的身份。

Q2.5:记住短暂的代币。 token 必须过期!

关于api - 架构设计 - REST API 支持由移动应用程序完成的 Facebook 登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30230482/

相关文章:

api - 如何限制grails中域属性的可见性?

android - Unity Ads 4.0 - 奖励广告的多个 OnUnityAdsShowComplete 回调

rest - Golang gorilla mux REST api 在使用 PUT 和 DELETE 方法时出现 405 错误

javascript - REST API,从 PHP 返回 JSON 对象到 JS 文件

azure - Facebook Graph API 的重大变更是否由 Azure AD B2C 处理?

facebook - 获取我的网站访问者的 Facebook 用户 ID(无需身份验证)

php - 使用 LinkedIn V2 API 上传视频

java - 为什么 RestTemplate 忽略 rootUri

facebook-graph-api - Oauth 2.0 无法从 signed_request 'code' 值中获取访问 token

android - Android 中本月 Facebook 好友生日