OAuth2访问令牌中允许使用哪些字符?

时间:2018-04-25 22:05:52

标签: oauth-2.0 character special-characters access-token specifications

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

RFC6749(原始OAuth2规范)的

Section A.12定义了访问令牌格式,如下所示:

  

A.12。 "&的access_token#34;语法

     

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

access-token = 1*VSCHAR 

ABNF format中,VSCHAR表示:

  

VSCHAR =%x20-7E

(这基本上是all printable ASCII characters

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

  

Bearer凭证的语法如下:

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

这是一个限制性更强的字符集,包括字母数字,六个特殊字符和填充=

我的问题是:

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

2)在实际实施方面"在野外"中,访问令牌是否始终限于RFC6750字符集?

3)奖金问题:有没有人知道为什么这两个规范在同一个月发布的关于访问令牌格式的这些密切相关的主题不一致?

3 个答案:

答案 0 :(得分:1)

TL; DR:这些标准之间没有冲突。 OAuth访问令牌可以通常包含任何可打印的ASCII字符,但是如果访问令牌是Bearer令牌,则它必须使用“ token64”语法来符合HTTP / 1.1要求。 >

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

RFC 6749定义了获取访问令牌的各种方法,但与如何实际使用访问令牌无关,只是说您“出示”它”到资源服务器,该资源服务器必须先进行验证,然后接受或拒绝它。

但是RFC 6749确实要求授权服务器告知客户端令牌类型(另一个字符串),客户端可以使用它确定使用的方式

令牌类型字符串是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和Basic身份验证标准相关的历史原因,以及当前和历史HTTP实现的限制。网络协议是一团糟。)

“ b64token”( aka “ token68”)允许通常与base64编码一起使用的ASCII字符子集,但是(尽管有名称)Bearer令牌does not impose any base64 semantics。客户端从一个服务器接收并传递给另一个服务器只是一个不透明的字符串。实现可以为其分配语义(例如JWT),但这超出了OAuth或Bearer令牌标准。

RFC 6750并未指出,如果将Bearer访问令牌与其他两种(不推荐使用)方法一起使用,则它必须是b64token,但是考虑到客户端应该能够选择该方法,因此这样做不会有多大用处赋予它非b64令牌的意义。

其他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编码的数据结构,客户端必须对它进行操作(根据与供应商令牌类型相关的规则),以访问受保护的资源。

答案 1 :(得分:0)

嗯,我不是专业人士,但根据我的工作经验,我可以告诉你,你应该总是尝试使用RFC6750;它在技术上声明使用base64编码的字符串。为什么?,因为大多数要求您使用OAuth方法的请求都会建议您使用Authorization HTTP标头,而base64编码使用安全的ASCII字符,这可以保证您的HTTP请求可读(几乎)所有服务器。 Base64也更容易解析,并且在JSON规范中使用它也是安全的。

这更有可能回答你的问题2.

修改

嗯,根据您提供的链接,以下是他们的摘要:

<强> RFC6749

  

OAuth 2.0授权框架支持第三方使用   应用程序,以获得对HTTP服务的有限访问,或者在   通过编排批准交互来代表资源所有者   资源所有者和HTTP服务之间,或通过允许   第三方应用程序以代表自己获取访问权限。这
  规范取代并废弃所描述的OAuth 1.0协议   在RFC 5849中。

<强> RFC6750

  

本规范描述了如何在HTTP中使用承载令牌   请求访问受OAuth 2.0保护的资源。中的任何一方   拥有持票人令牌(&#34;持票人&#34;)可以使用它来获取访问权限   相关资源(没有证明拥有权)   加密密钥)。为防止滥用,持票人令牌需要为   防止在存储和运输中泄露。

根据每个规范的各自摘要,您应该清楚何时使用其中一个。换句话说,当您要提供对Web服务的有限访问权限,然后要求提供身份验证令牌时,请使用 RFC6749 。当您要在Web服务中请求Bearer令牌时,请使用 RFC6750 。承载令牌应始终位于HTTP请求的Authentication头中,并且Base64字符串可以作为请求的一部分直接传输。

答案 2 :(得分:0)

TLDR:授权标头遵循 RFC2617中定义的基本架构。所以令牌应该是base64编码。

以下短语rfc6750

突出显示了这一点
  

&#34;授权&#34;的语法此方案的标头字段      遵循第2节中定义的基本方案的用法      [RFC2617]

如果您去检查RFC2617,以下是对用户凭据进行base64编码的ABNF。

  

凭据=&#34;基本&#34;基本的凭证

     

basic-credentials = base64-user-pass

但正如OP指出的那样,ABNF定义为b64token,它允许的不仅仅是base64编码。因此,在现实世界的实现中,我们可以看到例如用作承载令牌的JWT(base64的ABNF和.分离)。这是可以接受的,因为它来自b64token ABNF。

OP的问题答案,

  1. 访问令牌可以包含%x20-7E范围内的任何字符。没有 对此的限制以及访问令牌的定义。
  2. 如果访问令牌是承载令牌(token_type = bearer),那么它必须遵循b64token AKA token68。此使访问令牌有资格放入授权标题
  3. RFC6749定义Access令牌的格式。 RFC6750定义了如何利用Authorization标头传输访问令牌。
  4. b64token vs token68

    b64token的命名似乎有些混乱。

    经过一些搜索,我在discussions上遇到了IETF RFC7235。 RFC7235定义了HTTP身份验证的当前标准(也包括Authorizationheader)

    根据这些讨论,b64token是一种特定的编码。有人建议将b64token重命名为token68。他们已做出此更改,基本上b64token指的是token68

    Appendix section在HTTP授权标题上解释token68,(注意 - 这些是提取的。转到链接检查ABNF的完整说明)

      

    授权=凭证

         

    credentials = auth-scheme [1 * SP(token68 / [(&#34;,&#34; / auth-param)*(OWS&#34;,&#34; [OWS auth-param]) ])

         

    令牌68 = 1 *(ALPHA / DIGIT /&#34; - &#34; /&#34;。&#34; /&#34; _&#34; /&#34;〜& #34; /&#34; +&#34; /&#34; /&#34;)*&#34; =&#34;

    正如我所看到的,RFC6750没有更新这些命名(这些定义在编写时正在进行中)。