OAuth2一次性授权以注册和丢失密码

Eve*_*ert 5 api passwords oauth oauth-2.0

我们正在构建主要由JS前端使用的REST服务。身份验证的主要手段是OAuth2。

我们使用password授权类型进行登录,但是我们遇到的一件事是:如何设计“丢失密码”功能。通常,这是通过允许用户输入其电子邮件地址,然后向其发送一次性令牌来完成的。

这需要以下条件:

  1. 未认证的端点。喜欢POST /lost-password并接受电子邮件地址。我意识到这并不是很轻松,但是我可以忍受。然后,此端点将带有一次性令牌的电子邮件发送给用户。
  2. 用户使用令牌返回前端后,我基本上希望允许客户端将该令牌交换为OAuth2承载令牌。

因此,我并没有grant_type在规范中真正看到此功能。我的问题是:

我是否应该扩展OAuth2并创建一个新的grant_type(特定于OAuth2支持的)新情况,以与OAUth2访问令牌交换1次身份验证令牌?

Joã*_*elo 2

TL;DR在创建新grant_type扩展时我会三思而后行,而是会考虑使用现有流程和 OpenID Connect,以便用隐式授权流程替换 ROPC 的使用,这将允许您获得基于访问令牌的在已经存在的身份验证会话上,以这种方式保存用户重新输入其凭据。

无聊的理论

这种情况不属于 OAuth 2.0 的范围;如果不是包含资源所有者密码凭据授予 (ROPC),那么用户身份验证的整个主题可能会被认为超出了范围,而资源所有者密码凭据授予 (ROPC) 似乎确实使规范内外的内容变得混乱。

但是,您应该考虑到 ROPC 是作为存储用户密码的应用程序的快速迁移路径而引入的,以便在用户离线时运行而不是作为解决用户身份验证主题的方法。

即使是明确关注用户身份验证的 OpenID Connect 也没有继续指定重置密码机制,因为这是特定于一种类型的用户凭据的。这通常作为身份提供者的实现细节保留。

看看替代方案

选项 A易于实施

我假设您考虑过,但希望避免以下选项 ( A ),它不需要任何令牌交换和/或自定义授予类型:

  1. 用户请求重置密码;
  2. 身份提供商通过电子邮件发送密码重置代码 URL;
  3. 用户访问URL并更改密码;
  4. 用户使用新密码登录应用程序(ROPC)并获取访问令牌;

这将适用于您当前的方法,而无需扩展或触及与 OAuth2 相关的任何内容;但是,这意味着用户在实际完成密码重置过程后必须重新输入其凭据。

选项B可能更优雅

另一个选项(B)更复杂,但仍然不需要扩展协议,也不需要强化您提到的/lost-password不太 REST'y 的内容。您可以将要请求的端点视为身份提供商的一部分,然后实际处理密码重置机制,而不是资源服务器(REST API)。

然后,您可以在每个需要用户身份验证的 OAuth2 流程中利用此身份提供程序会话。

选项B.1

当用户访问您的应用程序时,您使用 执行隐式授权身份验证请求(根据 OpenID Connect 规则)prompt=none

如果成功,则用户已经在身份提供者上进行了会话,并且您将获得一个令牌。当用户更改密码时将创建此会话。

如果失败,您将向用户显示您当前的登录界面并使用 ROPC 获取令牌。

选项B.2

您转储 ROPC 并开始对所有内容使用隐式授予。这要求您将身份验证用户界面从客户端应用程序移至身份提供程序中,然后需要处理基于重定向的流的具体细节,而不是 ROPC 更直接的请求/响应性质。

通过此设置,登录和密码重置操作都将创建身份验证会话的概念,然后客户端应用程序可以利用该概念作为获取令牌的方式,而无需打扰用户 - 通过隐式授权。

最后的笔记

就我个人而言,我认为拥有更成熟的身份提供商有一些优势;prompt=none此外,对于如何在 SPA 中刷新令牌的问题,带有支持的隐式授权似乎也是一个非常好的解决方案。

虽然 SPA 不能使用刷新令牌,但它们可以利用提供相同功能的其他机制。改善用户体验的解决方法是在调用端点时使用prompt=none/authorize。这不会显示登录对话框或同意对话框。除此之外,如果您/authorize从隐藏的 iframe 调用并从父框架中提取新的访问令牌,那么用户将看不到发生的重定向

(来源:Auth0 - 我应该使用哪个 OAuth 2.0 流程?;重点是我的)