OAuth 2.0不记名令牌到底是什么?

根据RFC6750-The OAuth 2.0授权框架:持名令牌使用,持名令牌是:

一种具有财产的安全令牌,任何拥有该令牌的一方(“持有人”)可以以任何其他拥有该令牌的一方可以使用的任何方式使用该令牌。

对我来说,这个定义很模糊,我找不到任何规范。

  • 假设我正在实现一个授权提供程序,我可以为承载令牌提供任何类型的字符串吗?
  • 它可以是一个随机的字符串吗?
  • 是否必须是某些属性的base64编码?< br / > 它应该被哈希吗?李< / >
  • 服务提供者是否需要查询授权提供者才能验证这个令牌?
241762 次浏览
< p >无记名标记< br > 一种具有任何一方拥有的财产的安全令牌 令牌(“持有者”)可以以任何其他方式使用令牌 拥有它的一方可以。使用不记名令牌则不然 要求持有人证明拥有密码匙资料 (所有权证明). < / p >

身份验证服务器为您创建了承载令牌。当用户对应用程序(客户端)进行身份验证时,身份验证服务器就会为您生成一个Token。无记名令牌是OAuth 2.0使用的主要访问令牌类型。一个不记名令牌基本上说的是“给这个令牌的持有者访问权”。

承载令牌通常是由身份验证服务器创建的某种不透明值。它不是随机的;它是基于用户给予您访问权限和应用程序的客户端获得访问权限而创建的。

例如,为了访问一个API,你需要使用一个访问令牌。访问令牌的寿命很短(大约一个小时)。您使用记名令牌来获得一个新的Access令牌。为了获得访问令牌,您将这个承载令牌连同您的客户端id一起发送给身份验证服务器。这样,服务器就知道使用承载令牌的应用程序就是为其创建承载令牌的应用程序。示例:我不能只是为您的应用程序创建一个不记名令牌,并将其用于我的应用程序,它不会工作,因为它不是为我生成的。

谷歌刷新令牌看起来像这样:1/mZ1edKKACtPAb7zGlwSzvs72PvhAbGmB8K1ZrGxpcNM

抄自评论:我认为对您提供的无记名代币没有任何限制。我唯一能想到的是,允许不止一个是好的。例如,用户可以对应用程序进行最多30次身份验证,而旧的不记名令牌仍然有效。哦,如果一个没有使用6个月,我会从你的系统中删除它。您的身份验证服务器将必须生成它们并验证它们,因此如何格式化取决于您。

更新:

在每个内联动作HTTP请求的授权报头中设置承载令牌。例如:

POST /rsvp?eventId=123 HTTP/1.1
Host: events-organizer.com
Authorization: Bearer AbCdEf123456
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/1.0 (KHTML, like Gecko; Gmail Actions)


rsvpStatus=YES

上面例子中的字符串"AbCdEf123456"是承载授权令牌。这是由身份验证服务器生成的加密令牌。与操作一起发送的所有不记名令牌都具有issue字段,受众字段将发送方域指定为https://.形式的URL例如,如果电子邮件来自noreply@example.com,受众是https://example.com

如果使用不记名令牌,请验证请求来自身份验证服务器,并且用于发送方域。如果令牌没有验证,则服务应该使用HTTP响应代码401(未授权)响应请求。

不记名令牌是OAuth V2标准的一部分,被许多api广泛采用。

当我读到你的问题时,我试图在互联网上搜索不记名令牌是如何加密或签名的,但没有成功。我猜不记名令牌没有散列(可能是部分散列,但不是完全散列),因为在这种情况下,将不可能解密它并从中检索用户属性。

但你的问题似乎是试图找到关于持名代币功能的答案:

假设我正在实现一个授权提供程序,我可以提供任何 一种承载令牌的字符串?它可以是一个随机的字符串吗?做 它必须是某些属性的base64编码?应该是吗? 散列?< / p >

因此,我将尝试解释持有者令牌和刷新令牌是如何工作的:

当用户向服务器请求通过SSL发送用户和密码的令牌时,服务器返回两个东西:访问令牌刷新令牌

访问令牌是一种记名令牌,您必须在所有请求头中添加该令牌,以便作为具体用户进行身份验证。

Authorization: Bearer <access_token>
Access令牌是一个加密的字符串,包含您希望的所有用户属性、声明和角色。(如果添加更多角色或声明,可以检查令牌的大小是否增加)。 一旦资源服务器接收到一个访问令牌,它将能够解密它并读取这些用户属性。这样,用户将与所有应用程序一起被验证和授予

访问令牌的有效期很短(即。30分钟)。 如果访问令牌的有效期很长,这将是一个问题,因为理论上不可能撤销它。因此,假设一个role=“Admin”的用户更改为“user”。如果用户保留了role="Admin"的旧令牌,他将能够使用Admin权限访问到令牌到期。 这就是为什么访问令牌的有效期很短

但是,我想到了一个问题。如果一个访问令牌的有效期很短,我们必须在每个短时间内发送用户和密码。这安全吗?不,它不是。我们应该避免它。这时就出现了Refresh令牌来解决这个问题。

刷新令牌存储在DB中,过期时间很长(例如:1个月)。

用户可以使用刷新令牌获得一个新的访问令牌(例如,当它过期时,每30分钟一次),该令牌是用户在第一次请求令牌时收到的。 当访问令牌过期时,客户端必须发送一个刷新令牌。如果这个刷新令牌在DB中存在,服务器将返回给客户端一个新的访问令牌和另一个刷新令牌(并将用新的刷新令牌替换旧的刷新令牌)

如果用户访问令牌已被破坏,则必须从DB中删除该用户的刷新令牌。这样,令牌将只在访问令牌过期之前有效,因为当黑客试图获得发送刷新令牌的新访问令牌时,此操作将被拒绝。

记名符号是字母、数字、&;-&;,“!”、“;_"、“~““+”;,“/”;后面跟着0个或多个"="。

2.1. RFC授权请求报头字段(格式为ABNF (Augmented BNF))

The syntax for Bearer credentials is as follows:


b64token    = 1*( ALPHA / DIGIT /
"-" / "." / "_" / "~" / "+" / "/" ) *"="
credentials = "Bearer" 1*SP b64token

它看起来像Base64,但根据标头中的标记应该是base64编码吗?,它不是。

深入挖掘“;HTTP/1.1, part 7: Authentication" 然而,我看到b64token只是一个ABNF语法定义 允许在base64、base64url等中使用的字符。所以 b64token没有定义任何编码或解码,而是仅仅定义了 定义在授权部分中可以使用哪些字符

.访问令牌

这完全解决了OP问题列表中的前3项。所以我扩展了这个答案来解决第四个问题,关于令牌是否必须验证,所以@mon可以随意删除或编辑:

授权者负责接受或拒绝http请求。如果授权者说令牌是有效的,则由您来决定这意味着什么:

  • 授权者是否有方法检查URL、识别操作并查找一些基于角色的访问控制数据库以查看是否允许该操作?如果是并且请求通过,则服务可以假定它是允许的,并且不需要验证。
  • 令牌是否全有或全无,因此如果令牌正确,则允许所有操作?那么服务就不需要验证了。
  • 令牌是否意味着“允许此请求,但这里是角色的UUID,您检查是否允许该操作”。然后由服务来查找该角色,并查看是否允许该操作。

参考文献

请先阅读Rfc6749 SEC 7.1中的示例。

承载令牌是一种访问令牌,它不需要PoP(所有权证明)机制。

PoP是一种多因素认证,使访问令牌更加安全。裁判

所有权证明是指可以降低安全令牌被攻击者窃取和使用的风险的加密方法。与“持有者令牌”相反,仅仅拥有安全令牌就允许攻击者使用它,PoP安全令牌不能如此容易地使用——攻击者必须同时拥有令牌本身和与令牌相关的某些密钥的访问权(这就是为什么它们有时被称为“密钥持有者”(HoK)令牌)。

也许事实并非如此,但我想说,

  • 访问令牌=支付方式
  • 无记名代币=现金
  • 带有PoP机制的访问令牌=信用卡(将验证签名或密码,有时需要出示您的ID以匹配卡上的名称)

顺便说一句,“OAuth 2.0拥有权证明(PoP)安全体系结构”的草案;现在。

无记名代币类似于纸币,例如100美元纸币。人们不用问任何问题就可以使用这种纸币。

不记名令牌具有任何一方的属性的安全令牌 持有该令牌(“持有者”)可以以任何方式使用该令牌 任何其他拥有它的人都可以。使用不记名令牌则不然 要求持有人证明拥有密码匙资料 (所有权证明). < / p >

承载令牌是一个b64token字符串,要求如果拥有它,就可以使用它。除此之外,不能保证该字符串在规范中的实际含义是什么。这取决于执行。

5.2. 缓解气候变化的威胁

本文档没有指定 令牌;因此,对
的均值给出了详细的建议 保证令牌完整性保护不在本文讨论范围之内 文档。令牌完整性保护必须足够

.禁止修改令牌

https://datatracker.ietf.org/doc/html/rfc6750#section-5.2

虽然令牌在每次发布时都是随机的,但缺点是服务器端需要跟踪令牌数据(例如过期)。JSON Web令牌(JWT)通常用作承载令牌,因为服务器可以根据令牌内的内容做出决定。

< p > JWT: https://jwt.io/ < / p >