为什么我不能使用带有 id_token 响应类型(“隐式”流)的查询响应模式?

信息安全 开放式连接
2021-08-30 18:03:20

虽然我认为 OpenID 2.0 是比 OpenID Connect 更干净、更好的身份验证协议,但我必须实现一个 OpenID Connect IdP。

我喜欢 OpenID 2.0 的一点是,IdP 可以(通过用户代理)向依赖方返回签名身份,并且 RP 和 IdP 之间没有额外的往返。

乍一看,OpenID Connect 定义了一个对我来说很好的“隐式”流。但是当我查看细节时,它似乎被设计为仅用于“使用脚本语言在浏览器中实现的客户端”。

我认为无论如何我都可以使用“隐式”流和服务器端 RP,使用“查询”响应模式,但是“OAuth 2.0 多响应类型编码实践”文档明确禁止使用“查询”响应模式id_token 响应类型…

为什么被禁止?更一般地说,为什么“隐式”流程不受欢迎?

据我了解,只要对 ID 令牌进行签名,并且 RP 使用(并验证)随机数,“隐式”流程就应该是安全的。

1个回答

2020-12 更新

有一个OAuth 2.1 草案摆脱隐式流程 - 简短摘要 OAuth 2.1 汇集了最新的 OAuth 2 最佳实践。

TLDR;如果可以,最好避免隐式流。


更一般地说,为什么“隐式”流程不受欢迎?

因为访问令牌暴露给用户代理(浏览器)。请参阅OAuth 2 规范中的隐式流程图,然后将其与不向用户代理公开令牌的授权代码流程进行比较。

...明确禁止使用带有 id_token 响应类型的“查询”响应模式...为什么禁止?

快速定义:

scheme://host:port/path?query#fragment

URL 的“查询”部分很容易被多方检查 - 它可能被用户代理记录(例如浏览器历史记录),并且经常在 Web 服务器请求日志中找到。经验法则是永远不要通过“查询”参数发送任何敏感信息(例如令牌、授权代码、密码)。

但是,“片段”部分永远不会在 HTTP 请求中发送,也不会出现在 Referer 标头中。只有在用户代理(浏览器)上执行的 JavaScript 才能访问它。

例如,客户端(浏览器)可以发出这样的请求:

GET /authorize?
  response_type=id_token%20token
  &client_id=s6BhdRkqt3
  &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  &state=af0ifjsldkj HTTP/1.1
Host: server.example.com

身份验证服务器将响应(注意用“#”表示的“片段”):

HTTP/1.1 302 Found
Location: https://client.example.org/cb#
  access_token=SlAV32hkKG
  &token_type=bearer
  &id_token=eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso
  &expires_in=3600
  &state=af0ifjsldkj

然后,浏览器在重定向到目标位置时会排除“片段”。浏览器中的 JavaScript 代码应使用更安全的机制(例如 POST 正文)提交相关令牌。

各种浏览器之间存在一些怪癖,但没有任何明显的问题可以违背安全假设。