OAuth2流在web前端和REST API


OAuth2 flow in web frontend and REST API

我正在研究一个基于Phalcon的项目,该项目由两个不同的独立子项目组成:一个php + angular前端和一个php REST API

我用OAuth2保护API,使用PhpLeague OAuth2 Server。API服务器是OAuth2的授权服务器和资源服务器。

这是实际的流程:

  1. 用户可以浏览前端的公共端点,当点击私有页面时,被重定向到登录页面;
  2. 登录页面有用户名和密码,发送到前端服务器;
  3. 前端服务器调用API服务器上的公共方法,该方法正在等待密码凭据授予:它验证凭据并发回访问令牌和刷新令牌;
  4. 前端服务器缓存会话中的访问和刷新令牌,并将其用于一些API调用:其中第一个是'/users/me',它获取有关当前用户及其在前端部分的ACL的信息;
  5. 前端服务器将页面发送给浏览器,浏览器加载其javascript文件。

现在,OAuth2声明访问令牌应该是短暂的,而刷新令牌应该是长期的:在前端服务器逻辑中,接收401(由过期的访问令牌引起)的API调用将通过首先发送刷新令牌以通过刷新令牌授予获得新的访问令牌来重试。如果第二个调用被拒绝,我假设用户不再登录(刷新令牌过期/撤销)。

这些页面使用Angular来执行数据和ux/ui管理。我的问题是

Angular代码应该直接调用API服务器吗?

实际上,我的javascript代码做的第一件事是从前端服务器获取一个配置对象,它也包含访问令牌,并使用它来调用API服务器。这方面的问题是,我应该再次重写"刷新令牌逻辑"在javascript(过期后,我得到401),并通过我所读的主题我明白,最好不要使刷新令牌可见到客户端(因为它可以生成新的访问令牌)。

所以我在考虑一个"两步方法",其中每个javascript API调用去端点上的前端服务器中继到API服务器,但这显然是较慢的(JS -> frontend -> API和API -> frontend -> JS)。

正确的方法是什么?我不太清楚前端是否应该被视为两个客户端 (php + js),它们应该单独工作,因为我想象一个假设的iOS应用程序将100%调用API服务器。

我在自己的项目中使用了相同的方法。我们面临的问题是客户端不安全。为了生成/刷新令牌,您需要将安全信息传递给授权服务器。

我基本上和你做的一样,让后端处理令牌和它们的临时存储。您不能也不应该信任客户端,让其提供让您生成令牌的重要信息。至于延迟,我不会太担心,因为你不会做那么多额外的工作,你甚至不会注意到延迟。我有一个这样的系统,被成千上万的用户使用,绝对没有问题。

现在,你在这里说了一些事情,让我想知道你在做什么。

OAuth2不是一个用户认证系统,而是一个应用程序认证系统。您不是传递用户及其密码并为他们生成令牌,而是传递ClientID和ClientSecret,它们为您生成令牌。然后您有一个端点,它为您提供该用户的用户详细信息,您传递userid或username并获取该用户的详细信息。

令牌过期并不意味着您的用户已注销。这是两件完全不同的事情。例如,当用户想要注销时,您将如何使令牌过期?您不能,您的令牌将仍然有效,直到它在设定的时间过期后过期。

一个令牌可以使用半个小时,但你的用户可能使用网站一个小时。在你到达任何API端点之前,你可以检查。这个令牌过期了吗?如果是,那么你可以去刷新它并继续工作,而不必用新的登录屏幕打扰你的用户。

OAuth2系统的全部要点是确保只有授权的客户端才能访问它。客户端不是用户,而是应用程序。例如,你可以有一个网站,你只希望该网站的用户访问你的API。

你可以有像ValidateUser这样的端点,在那里你接受一个用户名和一个密码并返回一个是或否,然后你基于它登录你的用户。

无论语言/框架如何,第二种方法都比第一种方法更安全,因为通过向授权服务器提供刷新令牌来获得访问令牌,它仍然需要客户端ID和Secret,出于安全原因,它们永远不应该传递给浏览器。

在第一种方法中,由于浏览器的同源策略,如果您的Authz服务器托管在与前端服务器不同的域上,则直接调用它将不起作用。即使它们在同一域,你仍然会暴露客户端ID和Secret,这将危及你的前端服务器