未经资源所有者同意生成访问令牌的 OAuth 流程是啥?

Posted

技术标签:

【中文标题】未经资源所有者同意生成访问令牌的 OAuth 流程是啥?【英文标题】:What is the OAuth flow to generate access token without consent from resource owner?未经资源所有者同意生成访问令牌的 OAuth 流程是什么? 【发布时间】:2022-01-03 21:25:40 【问题描述】:

本题中使用的角色和术语与RFC 6749相同。

用例描述

我想允许受信任的 OAuth 客户端请求授权服务器代表资源所有者颁发访问令牌 未经他的同意(并且不涉及他和他的代理人)。

调查

据我所知,RFC 6749, Section 4 中没有任何与此流程匹配的授权:

Grant Suitable Why
Authorization Code GrantRFC 6749, Section 4.1 No It involves both Resource Owner and User-Agent.
Implicit GrantRFC 6749, Section 4.2 No It also involves both Resource Owner and User-Agent.
Resource Owner Password Credentials GrantRFC 6749, Section 4.3 No It might work if we knew the password of the resource owner, but we don't.
Client Credentials GrantRFC 6749, Section 4.4 No, but.. It doesn't involve the Resource Owner or his User-Agent but it's not granting access on behalf of a user.
Token ExchangeRFC 8693, Section 2 No, but.. It requires an initial token (named subject_token) which doesn't exist in my scenario.

客户凭证

Client Credentials 授权很有希望,因为它允许 client 访问由 资源所有者 拥有的受保护资源,而无需涉及他。虽然,据我了解,它并不代表资源所有者。引用RFC 6749, Section 4.4:

当客户端请求访问受其控制的受保护资源或之前已与授权服务器安排的其他资源所有者的受保护资源时,客户端可以仅使用其客户端凭据 (...) 请求访问令牌 (... ...)。

因此,使用 Client Credentials 授权返回的访问令牌,例如,不可能分配 RFC 7662, Section 2.2: OAuth 2.0 Token Introspection > Introspection Response 中定义的 sub 声明值(参见 @987654331 @)。

代币兑换

@Kaankom 建议了这项资助。 See @Kaankom 's answer.

RFC 8693 定义了如何使用模拟和委托获取安全令牌。对于我的用例来说,这听起来像是一个完美的授权,但这个授权需要一个subject_token 参数作为输入,该参数“代表代理方的身份。” RFC 说:

通常,这将是被授权使用请求的安全令牌并代表主体行事的一方。

我没有这个令牌。不过,我也许可以打造一个新的(参见解决方案 5)。

非标准解决方案

解决方案 1:新的 OAuth 授权

RFC 6749, Section 4.5 允许我们实现一个新的授权类型。与 Client Credentials 类似,这个全新的授权将需要在他的 Access Token Request 中添加一个额外的参数。此参数将定义资源所有者标识符,客户端将代表资源所有者对其进行操作。

解决方案 2:调整 Client Credentials 授权

我们可以在现有的 Client Credentials 授权中添加一个可选参数,而不是实施新的 OAuth 授权(参见解决方案 1)。如果指定,授权服务器应该验证客户端是否被允许代表请求的资源所有者(由新参数指定) .

解决方案 3:调整授权码授权

使用授权码授权,我们可以绕过RFC 6749, Section 4.1中定义的步骤A、B和C,让客户端请求访问令牌而无需添加coderedirect_uri,但带有其客户端凭据一个定义资源所有者的附加参数。

解决方案 4:在 OAuth 之外实现

浏览 互联网,您可能会发现绕过 OAuth 机制及其access_token 的实现。例如,在文章"How to Convert from APIKey to OAuth 2.0 Client Credentials" 中,他们在资源服务器 调用中使用了额外的HTTP 标头Acting-For

解决方案 5:代币兑换使用自造代币授予

令牌交换授权需要subject_token,但(据我所知)它没有定义授权服务器应该基于此应用的策略令牌。因此,从理论上讲,client 可以使用目标 subjectsub 声明)伪造一个未签名的 JWT,并获得一个签名的 JWT 作为回报。它看起来很有希望,但需要更多调查。

注意事项

我故意没有命名解决方案 1、2 和 3 中使用的参数。但是 OpenID Connect Core 1.0, Section 3.1.2.1/Section 4 定义了一个名为 login_hint 的可选参数,“提示授权服务器有关最终用户可能的登录标识符用于登录”。不过sub 可能是另一个不错的提议。

【问题讨论】:

好吧,我猜解决方案 1 仍然是“标准”... 我添加了 Kaankom 基于 RFC 8693 的提案。它看起来很有希望,但需要更多调查 【参考方案1】:

您并没有真正描述用例/要求,尽管我将描述一些可能符合您的用例并给您一些想法的东西。也许更多地考虑声明和 API 授权会以标准方式解决您的问题?

企业资产使用案例

有时资产不属于最终用户,而实体有权对部分用户进行操作:

投资银行可能能够在更广泛的交易系统中为其员工更新某些详细信息

医生的手术室可能能够在包含全国性数据的系统中更新其患者的医疗详细信息

在 OAuth 术语中,银行/手术将使用客户端凭据授权,并通过客户端 ID 或可能在颁发的令牌中的自定义声明进行标识。

如果银行 A 尝试使用他们的访问令牌来更新银行 B 交易员的详细信息,它将无法通过 API 授权,他们将收到状态为 404 的 HTTP 响应,即data not found for caller

虽然银行 A 在更新该记录时获取Jane Doe 的访问令牌是不自然的,因为这不是调用者身份。在审计层面:

授权服务器将指示令牌已发给银行 A API 将表明 Jane Doe 的记录已由银行 A 更新。

API 可能有许多复杂的特定于域的规则,围绕哪些类型的数据更新是允许的。这些通常在 API 逻辑中进行管理,而访问令牌仅包含 API 可以在应用规则之前以数字方式信任的关键调用者身份信息。

有关此主题的更多信息,请参阅我们的 Claims Best Practices 文章。

【讨论】:

【参考方案2】:

您描述的用例听起来像是模仿。

看看这个:RFC 8693 - Token Exchange

【讨论】:

感谢@Kaankom,确实,它看起来像“模拟”,但使用 RFC 8693 授权是不可行的,因为它需要在我的场景中不存在的 subject_token 作为输入。顺便说一句,subject_token“代表了代表提出请求的一方的身份”(引用RFC),这实际上是我试图做的。我将在我的问题列表中添加此赠款。非常感谢您的意见! 在这里。我在与您的提案相关的问题中添加了第 5 个解决方案。这个想法是使用令牌交换授权,作为 subject_token,一个由客户端伪造的令牌。在确认它有效之前我必须做一些测试!【参考方案3】:

简介

以下答案描述了可用于允许受信任的 OAuth 客户端在没有事先资源所有者同意的情况下获得access_token 的流程、授权和参数。此方法在模拟场景中使用 Token Exchange 授权(在 RFC 8693 中定义),其中 client 必须伪造一个不安全的 subject_token 并将其交换为安全access_token。此方法假定 授权服务器 生产和使用 JWT (RFC 7519)。它不适用于不透明的令牌。

时序图

第 1 步:伪造初始 JWT

在第一步中,客户端伪造一个初始的unsecured JWT token (RFC 7519, Section 6)。此 JWT 必须至少包含主题 (sub) 声明,其值为 资源所有者 或客户端想要模拟的另一个 主题

第 2 步:客户端请求将初始不安全 JWT 交换为安全访问令牌

客户端将步骤 1 中伪造的 JWT 交换为安全的访问令牌。根据RFC 8693 Section 2.1,client 发送了一个 Token Exchange 请求,其中包含以下标头/参数:

Authorization 标头包含 client 凭据(client idclient secret),遵循 Basic Authentication em> 方案。 主体参数grant_type指定我们要使用的授权类型:token_exchange body 参数subject_token 包含在步骤 1 中伪造的 JWT body 参数subject_token_type 指定我们伪造的主题令牌类型:access_token(实际上是 JWT)

这是客户端必须发送的最低要求。虽然它应该可能指定audience、目标resource 服务器和scope 列表。

第三步:授权服务器返回访问令牌

根据其策略,授权服务器客户端识别为受信任,因此允许在输入中生成带有不安全subject_tokenaccess_tokensubject_tokensub 声明)中定义的主题在生成的access_token 中被回收。

授权服务器还将根据RFC 8693, Section 4.1添加Actor声明 (act)。此声明的值是一个 JSON 对象,具有另一个 sub 键和 client id 作为值。

第 4 步:客户端请求一个资源

在此示例中,客户端使用访问令牌请求“个人”资源 (/my/resource)。 JWT 中的sub 声明用于识别“我的”,即主题

第 5 步:返回 resource 并模拟 subject

就是这样。

免责声明

我从未实施或测试过这个解决方案。这显然需要对您的授权服务器 及其策略进行一些更改。未执行任何安全审计。小心这个流程。实施前应获得 OAuth 专家的确认。

【讨论】:

@kaankom 再次感谢您的回答。设计这个解决方案真的很有用。

以上是关于未经资源所有者同意生成访问令牌的 OAuth 流程是啥?的主要内容,如果未能解决你的问题,请参考以下文章

OAuth 2.0

OAuth 2.0

OAuth 2.0

SpringBootSecurity学习(15)前后端分离版之 OAuth2.0简单示例

OAuth2.0

如何在 OAuth 资源服务器中验证访问令牌