在前端使用 OAuth 成功验证后如何与后端交互?

Posted

技术标签:

【中文标题】在前端使用 OAuth 成功验证后如何与后端交互?【英文标题】:How to interact with back-end after successful auth with OAuth on front-end? 【发布时间】:2016-02-24 22:09:04 【问题描述】:

我想构建小型应用程序。会有一些用户。我不想制作自己的用户系统。我想将我的应用程序与 oauth/oauth2.0 集成。

我的前端应用和oauth 2.0集成没有问题。有很多有用的文章,如何做到这一点,甚至在 ***.com 上。例如this post 很有帮助。

但是。前端授权成功后怎么办?当然,我可以只在客户端上有一个标志,上面写着“好的,伙计,用户已通过身份验证”,但是我现在应该如何与我的后端交互呢?我不能只是提出一些要求。后端 - 一些提供 API 功能的应用程序。每个人都可以访问这个 api。

所以,无论如何,我的 FE 和 BE 之间都需要一些身份验证系统。这个系统应该如何工作?

ps 我的英语有一些问题,可能我不能正确地“询问谷歌”。您能否提供正确的问题,请:) 或者至少提供一些关于我的问题的文章。

更新

我正在寻找概念。我不想为我当前的问题找到一些解决方案。我认为我使用哪个 FE 和 BE 并不重要(无论如何我会 在下面提供有关它的信息)

FE 和 BE 将使用 JSON 进行通信。 FE 将发出请求,BE 将发送 JSON 响应。我的应用程序将具有这种结构(可能):

前端 - 可能是 AngularJS 后端 - 可能是 Laravel(laravel 会实现逻辑,结构中还有数据库)

也许像 google.com、vk.com、twitter.com 等“服务提供商”会记住用户的状态?在FE上成功认证后,我可以从BE询问用户状态吗?

【问题讨论】:

您是否使用 JSON 进行通信?基本上,这取决于您如何在后端实施授权。我通常会在访问 API 时将标志的值作为键值对作为 JSON 数据的一部分发送到我的后端。我会在启动会话或将令牌字符串发送回客户端时检查此密钥。 您使用的是什么服务器端框架?您是如何实现 Oauth2 身份验证的? @Dvir ,解决我的问题真的很重要吗?我问的是概念,而不是这个问题的解决方案。 我了解您将在前端使用 javascript,在后端使用 php。无论您使用什么,您都需要将数据发送到后端以通知用户已成功通过身份验证。发送此数据的最佳方式是将其添加到您的请求中。 我问是因为听起来你在问当用户获得令牌时我应该怎么做?您实际上假设将其添加到请求的标头中,以便获取请求的服务器将获取令牌并知道处理与发送请求的用户相对应的请求。 【参考方案1】:

我们在创建 API 时有 3 个主要的安全问题。

    身份验证:像 Google 这样的身份验证提供商只是部分解决方案。因为您不想提示用户为每个 API 请求登录/确认他们的身份,所以您必须自己实现后续请求的身份验证。您必须存储,后端可访问:

      用户的 ID。 (取自身份提供者,例如:电子邮件) 用户令牌。 (您生成的临时令牌,可以通过 API 代码进行验证)

    授权:您的后端必须根据用户 ID(这是您自己的业务)实施规则。

    传输安全:HTTPS 和过期 cookie 是安全的,其他人无法重播。 (HTTPS 对流量进行加密,因此可以抵御中间人攻击,而过期的 cookie 可以在稍后的时间内抵御重放攻击)

所以你的 API / 后端有一个随机字符串的电子邮件查找表。现在,您不必公开用户的 ID。令牌是无意义的和临时的。

在这个系统中,流程是这样工作的:

User-Agent    IdentityProvider (Google/Twitter)   Front-End    Back-End
 |-----------------"https://your.app.com"---------->|
                                                    |---cookies-->|
                                 your backend knows the user or not.
                                       if backend recognizes cookie, 
                          user is authenticated and can use your API

否则:

                                             if the user is unknown:
                                                    |<--"unknown"-|
                     |<----"your/login.js"----------+
                "Do you Authorize this app?"
 |<------------------+
 |--------"yes"----->|
                     +----------auth token--------->|
                     |<---------/your/moreinfo.js---|
                     |-------access_token ---------->|
                1. verify access token
                2. save new user info, or update existing user
                3. generate expiring, random string as your own API token
                                                    +----------->|
 |<-------------- set cookie: your API token --------------------|

现在,用户可以直接使用您的 API:

 |--------------- some API request, with cookie ---------------->|
 |<-------------- some reply, depends on your logic, rules ------|

编辑

基于讨论 - 添加后端可以通过使用身份提供者验证访问令牌来验证用户:

例如,Google exposes this endpoint 检查令牌XYZ123

https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123

【讨论】:

我有一个关于开发第一部分的问题:身份验证。正如我所说,从提供者(如谷歌等)获取用户 ID 不是问题。正如你所说,我需要一些用户令牌,它是在客户端生成并由 API(后端、服务器)验证的。这个令牌必须如何在客户端生成?服务器将如何验证它?你能提供确切的例子:第一个用户从某个提供商登录(所以服务器不知道用户)然后登录?这将会非常棒。我了解基本授权。 我不明白一件事。是的,我有来自 google ouath 的令牌,我有一些用户 ID。但是我的 API 不知道这个用户和这个令牌。第一次登录怎么办?因为我认为任何人都可以拿走我的电子邮件,从脑海中获取一些令牌,提出请求并获取受限数据。你能解释一下吗? 令牌必须由您的后端生成。研究流程图,您将看到后端生成令牌,因为最后,它必须验证令牌。它应该是随机的:只需生成一个 200 个字符长的随机字符串,并将其保存在相关用户的某个查找表中。这是一个类似 /api/generate_token 的端点。这需要使用带有随机字符串值的“Set-Cookie”标头进行响应。 Google 令牌是不同的令牌。您的 API 也必须生成自己的令牌。前端必须向 Google 发出请求以获取用户标识符(电子邮件),然后将其发布到您的 API (/api/generate_token),这将允许您的前端代码向您的 API 发出更多请求。 我更新了我的答案。无论您在哪里看到电子邮件,都可以替换为 access_token。这可以由您的后端验证。我误解了你想要保护的内容。【参考方案2】:

我非常仔细地阅读了所有答案,超过一半的回答者完全错过了这个问题。在服务提供商颁发 OAuth 令牌之后,OP 正在请求 FE 和 BE 之间的 INITIAL 连接。

您的后端如何知道 OAuth 令牌有效?请记住,您的 BE 可以向服务提供商发送请求并确认 OAuth 令牌的有效性,该令牌首先由您的 FE 接收。此 OAuth 密钥只能由服务提供商解密,因为只有他们拥有密钥。一旦他们解密密钥,他们通常会回复用户名、电子邮件等信息。

总结:

用户授权后,您的 FE 会收到来自 Service Provider 的 OAuth 令牌。 FE 将 OAuth 令牌传递给 BE。 BE 将 OAuth 令牌发送给服务提供商以验证 OAuth 令牌。服务提供商使用用户名/电子邮件信息回复 BE。然后,您可以使用用户名/电子邮件创建一个帐户。

然后,在您的 BE 创建帐户后,您的 BE 应该生成自己的 OAuth 令牌实现。然后,您将这个 OAuth 令牌发送给您的 FE,并且在每个请求中,您的 FE 都会在标头中将此令牌发送给您的 BE。由于只有您的 BE 拥有验证此令牌的密钥,因此您的应用程序将非常安全。您甚至可以在每次请求时刷新您的 BE 的 OAuth 令牌,每次都为您的 FE 提供一个新密钥。如果有人从您的 FE 窃取了 OAuth 令牌,该令牌将很快失效,因为您的 BE 已经为您的 FE 创建了一个新的 OAuth 令牌。

有更多关于您的 BE 如何验证 OAuth 令牌的信息。 How to validate an OAuth 2.0 access token for a resource server?

【讨论】:

不错的答案。想象一下,我的 BE 不会阻止自己的 OAuth 令牌。所以我必须在每个请求中从前端发送令牌,如果令牌是有效的 每次 时间,后端将请求服务提供商,对吗? 好的,想象一下我实现了自己的 OAuth 令牌系统。我将有一个地方,我将存储这个令牌。客户端将发出请求并发送一些令牌。 BE 检查 BE 存储中是否存在 token,如果存在则正确响应,否则返回 403 等。对吗? 这是最好的答案,它的工作流程非常干净和正确,谢谢。 当BE生成一个新的token并返回给FE时,它只对一个请求有效。如果有人在该请求之前加固了与 FE 共享的新令牌,并在调用 BE 时操纵该请求怎么办。如何处理这种情况? FE 可以在接收响应或传入请求时隐藏令牌吗?【参考方案3】:

嗯,您的前端不需要用户系统。 前端只是一种与您的服务器交互并通过有效用户和密码请求令牌的方式。

您的服务器应该管理用户和权限。

用户登录场景

用户通过输入他的用户名和密码来请求令牌。 服务器 API 接受请求,因为它是匿名方法(每个人都可以调用此方法而无需关心是否登录。

服务器检查数据库(或一些存储)并将用户详细信息与他拥有的详细信息进行比较。 如果详细信息匹配,服务器将向用户返回令牌。

从现在开始,用户应该在任何请求中设置此令牌,以便服务器识别用户。 令牌实际上保存了用户角色、时间戳等......

当用户通过 API 请求数据时,它会从 header 中获取用户令牌,并检查是否允许用户访问该方法。

一般情况下是这样的。

我的回答基于 .NET。但是大多数 BE 库都是这样工作的。

【讨论】:

你说的我都明白。我没有问普通用户系统应该如何工作。我完全理解。我的问题是关于如何处理 OAuth 2.0、前端和后端。我在 FE 上使用某些服务(Google)成功登录,现在我需要与我的 BE 交互的方法。这就是问题所在。 @SharikovVladislav,您授权后,您可以发送带有Authorization Header的http请求,该请求的值是授权服务器(google oauth服务器)颁发的访问令牌的值。 @lessisawesome 是的,但是第一次登录呢?好的,我有来自 google oauth 的令牌,但我的 API 对这个令牌一无所知。所以我需要注册之类的东西。是的,我有用户 ID(即电子邮件),一些身份验证令牌。我现在应该如何与我的 API 交互?只发送电子邮件和令牌?所以每个人都可以接收我的电子邮件、拨打一些请求并访问受限数据? 你的API服务器(资源服务器)和授权服务器之间有一些联系。例如,认证服务器使用加密算法将用户身份和授权信息放入令牌字符串中,资源服务器应该知道用于解密令牌的算法。 @SharikovVladislav 如果使用谷歌登录,访问令牌只能用于向谷歌请求资源。对你自己的 api 服务器没有任何意义。【参考方案4】:

我们用OAuth的概念开始,这里的FE是Client,这里的BE是Resource Server

由于您的客户端已经授权,授权服务器应该授予 访问令牌到客户端。 客户端使用访问令牌向资源服务器发出请求 资源服务器验证访问令牌,如果有效,处理请求。

你可能会问,Access Token是什么,Access Token是授权服务器颁发,授权给客户端,资源服务器识别的。

Access token是一个字符串,表示授权信息(如用户信息、权限范围、过期时间...)。

访问令牌为了安全可能会加密,请确保资源服务器可以解密。

更多详情请阅读OAuth2.0规范https://www.rfc-editor.org/rfc/rfc6749。

【讨论】:

Authorization server 是 OAtuh 提供者,对吗?另外,资源服务器将如何验证访问令牌【参考方案5】:

在为 SSO 做一个项目时,根据我对您问题的理解,我可以建议您在客户端 -frontend- 成功获得授权后,在后端创建一个端点以生成会话帐户所有者,并从提供者那里获取用户信息,您将该信息发布到后端端点,后端端点生成一个会话并存储该信息,并发送回会话 ID - 经常命名为 jSessionId- 和一个 cookie回到客户端 - 前端 - 以便浏览器可以为您保存它,并且在此之后对后端的每个请求都被认为是经过身份验证的用户。

要注销,只需在后端创建另一个端点以接受会话 ID,以便后端可以将其删除。

希望对你有所帮助。

【讨论】:

是的,但是防守呢?例如,每个人都可以发送一些用户电子邮件并访问用户数据。正确的?还是我也应该创建注册并使用提供商提供的一些静态信息作为密码?所以我将注册用户并使用他的凭据登录。【参考方案6】:

您需要将令牌存储在应用程序的状态中,然后将其与每个请求一起传递到后端。可以在标头、cookie 或参数中传递到后端 - 取决于后端的实现方式。

按照代码查看所有实际操作的一个很好的示例(不是我的代码) 此示例设置 Authorization: Bearer TOKEN 标头 https://github.com/cornflourblue/angular-registration-login-example

【讨论】:

后端如何验证这个令牌? 后端如何确切验证这个令牌?

以上是关于在前端使用 OAuth 成功验证后如何与后端交互?的主要内容,如果未能解决你的问题,请参考以下文章

前端端口是怎么交互后端

JWT生成token及过期处理方案

前端如何高效的与后端协作开发

前端如何高效的与后端协作开发

怎么看前端有没有展示后端的数据

前端与后端的交互(定义接口)