OAuth2 访问令牌中允许使用哪些字符? [英] What characters are allowed in an OAuth2 access token?

查看:20
本文介绍了OAuth2 访问令牌中允许使用哪些字符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

RFC6749RFC6750 似乎彼此不同意 OAuth2 访问令牌中允许使用哪些字符.

第 A.12 节 RFC6749(原始OAuth2 规范)定义访问令牌格式如下:

<块引用>

A.12.访问令牌"语法

<块引用>

access_token"元素在第 4.2.2 和 5.1 节中定义:

<块引用>

access-token = 1*VSCHAR

ABNF 格式中,VSCHAR 意味着:

<块引用>

VSCHAR = %x20-7E

(这基本上是所有可打印的 ASCII 字符)

但是,在 RFC6750(处理 OAuth2 承载令牌的使用)中 第 2.1 节似乎为访问令牌设置了更严格的允许字符子集.

<块引用>

承载凭证的语法如下:

<块引用>

b64token = 1*( ALPHA/DIGIT/

 "-";/."/_"/~"/+"//") *="

<块引用>

credentials = Bearer";1*SP b64token

所以这是一组限制性更强的字符,仅包括字母数字、六个特殊字符和用于填充的尾随 =.

我的问题是:

  1. 控制这些文件中的哪一个?RFC6750 是否优先,因为它的限制性更强?

  2. 就野外"的实际实现而言,访问令牌是否总是仅限于 RFC6750 字符集?

  3. 额外问题:有谁知道为什么这两个规范在同月发布的如此密切相关的主题在访问令牌格式上存在分歧?

解决方案

TL;DR: 标准之间没有冲突.OAuth 访问令牌通常可以包含任何可打印的 ASCII 字符,但是如果访问令牌是不记名令牌,它必须使用token64";符合 HTTP/1.1 的语法.

RFC 6749, §1.4 告诉我们:一个访问令牌是一个字符串"和通常对客户不透明".§A.12 将其定义为一个或多个可打印的 ASCII字符([ -~]+ 在正则表达式中).

RFC 6749 定义了用于获取访问令牌的各种方法,但不关心如何实际使用访问令牌,除了说您呈现它"到资源服务器,它必须验证然后接受或拒绝它.

但是 RFC 6749 确实要求授权服务器告诉客户端令牌类型(另一个字符串),客户端可以使用它来确定如何使用访问令牌.

token type 字符串是 IANA 注册的类型名称(如 Bearermac),或供应商 URL(如 http://oauth.example.org/v1),尽管 URL 只是一个方便的命名空间标识符,并且不必解析为任何内容.

在大多数部署中,令牌类型将是 Bearer,其语义在 RFC 6750 中定义.

RFC 6750 定义了向资源服务器提供承载访问令牌的三种方法(§§2.1–2.3).推荐方法(资源服务器必须支持以符合标准)是在 HTTP 授权标头中发送它(§2.1),在这种情况下,令牌必须是b64token";([-a-zA-Z0-9._~+/]+=* 在正则表达式中).

这与 HTTP/1.1 规范所称的token68"相匹配.(RFC 7235 §2.1),并且是允许令牌所必需的在 HTTP 授权标头中不加引号地使用.(至于为什么 HTTP/1.1 允许这些确切的字符,这归结为与 HTTP/1.0 和基本身份验证标准相关的历史原因,以及当前和历史 HTTP 实现的限制.网络协议是一项混乱的业务.)

b64token"(又名token68")允许使用通常与 base64 编码一起使用的 ASCII 字符子集,但(尽管名称如此)不记名令牌 不强加任何 base64 语义.它只是客户端从一个服务器接收并传递给另一个服务器的不透明字符串.实现可能会为其分配语义(例如 JWT),但这超出了 OAuth 或 Bearer 令牌标准.

RFC 6750 没有规定如果与其他两种(不推荐)方法一起使用,Bearer 访问令牌必须是 b64token,但考虑到客户端应该能够选择该方法,它不会有太大作用给它一个非 b64token 令牌是有意义的.

其他 OAuth 令牌类型可能不依赖于在 HTTP 标头中不加引号地传递(或者它们可能根本不使用 HTTP),因此可以自由使用任何可打印的 ASCII 字符.这可能例如对于对客户端不透明的令牌类型很有用;例如,我目前正在处理一个设置,其中访问令牌响应看起来有点像这样:

{"access_token": "{"endpoint": "srv8.example.org", "session_id": "fafc2fd"}",token_type":http://vendor.example.org/",expires_in":3600,refresh_token":tGzv3JOkF0XG5Qx2TlKWIA"}

此处,访问令牌是 JSON 编码的数据结构,客户端必须根据该结构(根据与供应商令牌类型关联的规则)访问受保护资源.

RFC6749 and RFC6750 seem to disagree with one another about what characters are allowed in an OAuth2 Access Token.

Section A.12 of RFC6749 (the original OAuth2 spec) defines the access token format as follows:

A.12. "access_token" Syntax

The "access_token" element is defined in Sections 4.2.2 and 5.1:

access-token = 1*VSCHAR 

In ABNF format, VSCHAR means:

VSCHAR = %x20-7E

(This is basically all printable ASCII characters)

However, in RFC6750 (which deals with the usage of OAuth2 bearer tokens) Section 2.1 seems to set out a stricter subset of allowed characters for access tokens.

The syntax for Bearer credentials is as follows:

b64token    = 1*( ALPHA / DIGIT /

                   "-" / "." / "_" / "~" / "+" / "/" ) *"="

credentials = "Bearer" 1*SP b64token

So that's a more restrictive set of characters, including only alphanumeric, six special characters, and trailing = for padding.

My questions are:

  1. Which of these documents is controlling? Does RFC6750 take precedence because it's more restrictive?

  2. In terms of actual implementations "in the wild", are access tokens always limited to the RFC6750 charset?

  3. Bonus question: Does anyone know why these two specs published the same month on such closely related topics disagree on the access token format?

解决方案

TL;DR: There's no conflict between the standards. OAuth access tokens can generally contain any printable ASCII character, but if the access token is a Bearer token it must use "token64" syntax to be HTTP/1.1 compliant.

RFC 6749, §1.4 tells us: "An access token is a string" and "usually opaque to the client". §A.12 defines it as one or more printable ASCII characters ([ -~]+ in regex terms).

RFC 6749 defines various methods for obtaining an access token, but doesn't concern itself with how to actually use an access token, other than saying that you "present it" to a resource server, which must validate and then accept or reject it.

But RFC 6749 does require the authorization server to tell the client the token type (another string), which the client can use to determine how the access token is used.

A token type string is either an IANA-registered type name (like Bearer or mac), or a vendor URL (like http://oauth.example.org/v1), though the URL is just a conveniently namespaced identifier, and doesn't have to resolve to anything.

In most deployments, the token type will be Bearer, the semantics of which are defined in RFC 6750.

RFC 6750 defines three methods (§§2.1–2.3) of presenting a Bearer access token to the resource server. The recommended method (which resource servers must support to be standards compliant) is to send it in the HTTP Authorization header (§2.1), in which case the token must be a "b64token" ([-a-zA-Z0-9._~+/]+=* in regex terms).

This matches what the HTTP/1.1 spec calls a "token68" (RFC 7235 §2.1), and is necessary to allow the token to be used unquoted in the HTTP Authorization header. (As for why HTTP/1.1 allows those exact characters, it comes down to historical reasons related to the HTTP/1.0 and Basic authentication standards, as well as limitations in current and historical HTTP implementations. Network protocols are a messy business.)

A "b64token" (aka "token68") permits a subset of ASCII characters usually used with base64 encoding, but (despite the name) the Bearer token does not impose any base64 semantics. It's just an opaque string that the client receives from one server and passes on to another. Implementations may assign semantics to it (e.g. JWT), but that's beyond the OAuth or Bearer token standards.

RFC 6750 doesn't state that a Bearer access token must be a b64token if used with the other two (unrecommended) methods, but given that the client is supposed to be able to choose the method, it wouldn't make much sense to give it a non-b64token token.

Other OAuth token types might not rely on being passed unquoted in an HTTP header (or they might not use HTTP at all), and would thus be free to use any printable ASCII character. This might e.g. be useful for token types that are not opaque to the client; as an example, I'm currently dealing with a setup in which the access token response looks a bit like this:

{
  "access_token": "{"endpoint": "srv8.example.org", "session_id": "fafc2fd"}",
  "token_type": "http://vendor.example.org/",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA"
}

Here, the access token is a JSON-encoded data structure, which the client must act upon (according to rules associated with the vendor token type) to access the protected resource.

这篇关于OAuth2 访问令牌中允许使用哪些字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆