架构设计 - REST API支持由Mobile app完成的Facebook登录

JVK*_*JVK 10 api rest oauth facebook-graph-api oauth-2.0

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

设计流程

授权分为两级:

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

Q1)可以看到客户端发送client_keyclient_secret,我将它们存储在client_info表中.这个秘密应该是纯文本还是应该是可解密的格式?如果我加密它,我仍然需要在我的系统中的某处保留加密密钥.那它将如何使其安全?同样在每次通话中,解密都是一种开销.

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硬编码?如果是,那么将来当我们必须使新秘密失效并使用新秘密时,我们将如何取代这些信息呢?

Q5)因为它是我们自己的应用程序几年,所以会有多个access_token将被创建针对相同client_keyclient_secret.为了保存所有这些,在redis中存储client_key键和array of all access_tokens值是一个好主意.将来,当我们将API打开给第三方时,这个redis存储设计仍然可以扩展吗?

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

稍后,用户决定对我的应用程序执行某些操作,因为我们需要用户登录他的帐户.对于该用户,请单击"facebook login".我的应用程序facebook access_token从Facebook 获取和fb用户的id并将这些信息传递给API服务器(如第二张图所示).API服务器获取该令牌并调用facebook API来验证它access_token.一旦令牌被验证,服务器使用该用户相关的一些元数据与FB访问令牌一起产生我们自己user_access_token,让我们说utoken.并将其传递utoken回客户端,以便在每个后续用户特定的API调用中传回.我的问题是:

Q1)可以将其保存utoken在数据库,user_token表中.这utoken应该是纯文本还是应该是可解密的格式?如果我加密它,我仍然需要在我的系统中的某处保留加密密钥.那它将如何使其安全?同样在每次通话中,解密都是一种开销.

Q2)在每个用户特定的API调用中,我是否应该每次调用facebook进行检查facebook access_token仍然有效?我相信我不应该,因为这对我没有任何意义.请注意,Facebook仅用于"facebook登录".

Q3)我应该加密生成utoken什么信息?我想有一个散列或用户的关联数组email,user id,rolefacebook token再序列化数据结构,并最终对其进行加密.你觉得那样会好吗?我理解它符合我的要求,但作为标准或普通应用程序,它们是否足够好?还是有最好的做法?

Q4)客户端应该存储utoken在其cookie /缓存中吗?这不可怕吗?

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

对于使用Facebook进行身份验证的网站REST API,有点熟悉的设计方案

Dan*_*edo 1

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

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

Q1.3:查看 facebook 文档:

图形 API 调用可以从客户端或代表客户端从您的服务器进行。通过添加名为 appsecret_proof 的参数可以更好地保护来自服务器的调用。

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

Q1.4:再说一次,不!您应该仔细阅读 OAuth 规范,并了解不同的流类型以及何时使用每种流类型。另请记住,如果您为应用程序提供 API,则该 API 是公开的,任何人都可以滥用。唯一的区别是它没有记录。Web 应用程序也会发生同样的情况。一旦它进入互联网,我就可以编写一个爬虫并滥用该网络应用程序。这是完全正常的,只要记住互联网上的任何内容都不是私人的,它只是没有记录的。

Q1.5:同样,代币应该是短暂的。如果它们的生命周期与凭证相同,直到用户更改它们为止,那么令牌就失去了它们的用途。

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

Q2.2:我不这么认为。Facebook 只是告诉您,获得该令牌的用户拥有某种身份(例如电子邮件),您可以将其与系统中的用户关联起来。一旦您知道了该关联,您就不应该太关心 Facebook 令牌,而应该关心 Facebook API 的调用。但正如你所说,你只是用它来登录。

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

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

Q2.5:记住短期令牌。令牌必须过期!