目录 |
|
OpenID Connect 1.0 是 OAuth 2.0 协议之上的简单身份层。它使客户端能够根据授权服务器执行的身份验证来验证最终用户的身份,并以可互操作和类似 REST 的方式获取有关最终用户的基本配置文件信息。
本文档介绍如何管理 OpenID Connect 会话,包括何时注销最终用户。
1.
简介
1.1.
要求符号和约定
1.2.
术语
2.
创建和更新会话
3.
会话状态更改通知
3.1.
RP iframe
3.2.
OP iframe
3.3.
OpenID 提供商发现元数据
4.
验证
5.
实施注意事项
5.1.
用户代理阻止访问第三方内容
6.
安全注意事项
7.
IANA 注意事项
7.1.用户代理阻止对第三方内容的访问
OAuth 参数注册表
7.1.1.
注册表内容
7.2.
OAuth 授权服务器元数据注册表
7.2.1.
注册内容
8.
参考文献
8.1.
规范性参考文献
8.2.
参考文献
附录 A.
致谢
附录 B.
通知
§
作者地址
目录 |
OpenID Connect 1.0 是 OAuth 2.0 [RFC6749](Hardt, D., Ed.,“OAuth 2.0 授权框架”,2012 年 10 月。)协议 之上的简单身份层 。它使客户端能够根据授权服务器执行的身份验证来验证最终用户的身份,并以可互操作和类似 REST 的方式获取有关最终用户的基本配置文件信息。
该规范通过定义如何持续监控最终用户在 OpenID 提供商处的登录状态来补充 OpenID Connect Core 1.0(Sakimura, N.、Bradley, J.、Jones, M.、de Medeiros, B. 和 C. Mortimore,“OpenID Connect Core 1.0”,2014 年 11 月。) [OpenID.Core] 规范,以便依赖方可以注销已注销的最终用户。 OpenID 提供商。
此规范和 OpenID Connect 前通道注销 1.0(Jones, M.,“OpenID Connect 前端注销 1.0”,2022 年 9 月。) [OpenID.FrontChannel] 规范都使用前通道通信,该通信通过用户代理将注销请求从 OP 传送到 RP。相比之下, OpenID Connect 反向通道注销 1.0(Jones, M. 和 J. Bradley,“OpenID Connect 后台注销 1.0”,2022 年 9 月。) [OpenID.BackChannel] 规范使用 OP 和注销的 RP 之间的直接反向通道通信。 OpenID Connect RP 发起的注销 1.0(Jones, M.、de Medeiros, B.、Agarwal, N.、Sakimura, N. 和 J. Bradley,“OpenID Connect RP 发起的注销 1.0”,2022 年 9 月。) [OpenID.RPInitiated] 规范通过定义依赖方请求 OpenID 提供商注销最终用户的机制来补充这些规范。该规范可以与其他三个规范单独使用或结合使用。
目录 |
本文档中的关键词“必须”、“不得”、“要求”、“应”、“不应”、“应该”、“不应该”、“推荐”、“不推荐”、“可以”和“可选”应按照RFC 2119(Bradner, S.,“RFC 中用于指示需求级别的关键词”,1997 年 3 月。) [RFC2119] 中的描述进行解释。
在本文档的 .txt 版本中,引用值表示应按字面意思理解。在协议消息中使用这些值时,不得将引号用作值的一部分。在本文档的 HTML 版本中,按字面意思取的值是通过使用这种固定宽度字体来指示的。
目录 |
本规范使用OAuth 2.0(Hardt, D., Ed.,“OAuth 2.0 授权框架”,2012 年 10 月。) [RFC6749] 定义的术语“授权端点”、“授权服务器”、“客户端”和“客户端标识符”、RFC 7230(菲尔丁,R.,埃德。和 J. Reschke, Ed.,“超文本传输协议 (HTTP/1.1):消息语法和路由”,2014 年 6 月。) [RFC7230]定义的术语“用户代理”以及定义的术语由 OpenID Connect Core 1.0(Sakimura, N.、Bradley, J.、Jones, M.、de Medeiros, B. 和 C. Mortimore,“OpenID Connect Core 1.0”,2014 年 11 月。) [OpenID.Core] 提供。
本规范还定义了以下术语:
- 会议
- 最终用户依赖 OpenID 提供商执行的最终用户身份验证来访问依赖方的连续时间段。
读者重要提示:本节中的术语定义是本规范的规范部分,对实现提出了要求。本规范文本中的所有大写单词(例如“Session”)均引用这些定义的术语。每当读者遇到它们时,都必须遵循本节中的定义。
目录 |
在 OpenID Connect 中,RP 上的会话通常在 RP 验证最终用户的 ID 令牌时启动。请参阅 OpenID Connect Core 1.0 [OpenID.Core](Sakimura, N.、Bradley, J.、Jones, M.、de Medeiros, B. 和 C. Mortimore,“OpenID Connect Core 1.0”,2014 年 11 月。) 规范,了解如何获取 ID 令牌并验证它。当OP支持会话管理时,它还必须返回会话状态作为身份验证响应中的附加session_state参数,并且还应该返回会话状态作为身份验证错误响应中的附加session_state参数。 OpenID Connect 身份验证响应在 OpenID Connect Core 1.0 的第 3.1.2.5 节中指定。 OpenID Connect 身份验证错误响应在 OpenID Connect Core 1.0 的第 3.1.2.6 节中指定。
这个参数是:
- 会话状态
- 会话状态。 JSON [RFC7159](Bray, T., Ed.,“JavaScript 对象表示法 (JSON) 数据交换格式”,2014 年 3 月。)字符串,表示最终用户在 OP 的登录状态。它不得包含空格 (" ") 字符。该值对于 RP 来说是不透明的。如果支持会话管理,则这是必需的。
会话状态值最初是在服务器上计算的。用户代理中的 OP iframe 也会重新计算相同的会话状态值。合适的会话状态值的生成在第 3.2 节(OP iframe)中指定,并且基于客户端 ID、原始 URL 和 OP 用户代理状态的加盐加密哈希。对于原始 URL,服务器可以使用身份验证响应的原始 URL,遵循RFC 6454(Barth, A.,“Web 起源概念”,2011 年 12 月。) [RFC6454] 第 4 节中指定的算法。
目录 |
非常希望能够确定最终用户在 OP 的登录状态。为此,可以使用 提示=无重复身份验证请求。然而,这会导致网络流量,并且这对于日益流行的移动设备来说是个问题。因此,一旦使用身份验证请求和响应建立了会话,就希望能够通过使用受源限制的 postMessage 从 RP iframe 轮询隐藏的 OP iframe,来检查 OP 的登录状态,而不会导致网络流量,如下所示。
目录 |
RP 从自身加载一个不可见的 iframe。这个 iframe 必须知道:
RP iframe 以适合 RP 应用程序的时间间隔使用 postMessage 轮询 OP iframe。对于每个 postMessage,它发送第 3.2 节(OP iframe)中定义的会话状态。 RP iframe 必须强制它只处理来自 OP 帧来源的消息。它必须拒绝来自任何其他来源的 postMessage 请求,以防止跨站点脚本攻击。
来自 RP iframe 的 postMessage 传递以下串联作为数据:
它还必须能够接收从 OP iframe 返回的 postMessage。接收到的数据将被更改或 不变, 除非 OP 确定发送的消息的语法格式错误,在这种情况下,接收到的数据将是错误的。收到 changed后,RP必须执行 prompt=none的重新认证,以获得OP的当前会话状态。收到 错误后,RP 不得使用提示=无执行重新身份验证,以免导致潜在的无限循环,从而生成到 OP 的网络流量。
以下是 RP iframe 的非规范示例伪代码:
var stat = "unchanged"; var mes = client_id + " " + session_state; var targetOrigin = "https://server.example.com"; // Validates origin var opFrameId = "op"; var timerID; function check_session() { var win = window.parent.frames[opFrameId].contentWindow win.postMessage(mes, targetOrigin); } function setTimer() { check_session(); timerID = setInterval(check_session, 5 * 1000); } window.addEventListener("message", receiveMessage, false); function receiveMessage(e) { if (e.origin !== targetOrigin) { return; } stat = e.data; if (stat === "changed") { clearInterval(timerID); // then take the actions below... } } setTimer();
当 RP 检测到会话状态更改时,它应该首先尝试在 iframe 内发出提示=无请求来获取新的 ID 令牌和会话状态,并将旧的 ID 令牌作为id_token_hint发送。如果 RP 收到同一最终用户的 ID 令牌,它应该简单地更新会话状态的值。如果它没有收到 ID 令牌或收到另一个最终用户的 ID 令牌,则需要将这种情况作为原始最终用户的注销来处理。如果原始最终用户已经在 RP 处注销,而状态变化表明最终用户应该注销,则认为注销已成功。
请注意,会话状态是原始绑定的。在多个子域共享同一 RP 会话的部署中,父窗口和 RP iframe 都设置相同的 document.domain以遵守同源限制非常重要。这将允许 RP iframe 定位父窗口的嵌入式 OP iframe。
目录 |
RP 还会从 OP 的 check_session_iframe加载一个不可见的 OP iframe 到自身中。 RP 必须为 iframe 分配一个id属性,以便它可以对其进行寻址,如上所述。 OP iframe 必须强制调用者来自预期的来源。它必须拒绝来自任何其他源的 postMessage 请求,以防止跨站点脚本攻击。
如第 3.1 节(RP内嵌框架) 中所述,来自 RP iframe 的 postMessage 传递以下串联作为数据:
OP iframe 可以访问 OP 上的用户代理状态(在 cookie 或 HTML5 存储中),它用于计算并与 RP 传递的 OP 会话状态进行比较。 OP iframe 必须根据先前获得的客户端 ID、源原始 URL(来自 postMessage)和当前 OP 用户代理状态重新计算它。出于隐私原因,会话状态包含所有这些信息,以便同一用户代理中活动的不同客户端具有不同的会话状态值。
如果收到的 postMessage 语法错误,导致发布的客户端 ID 和原始 URL 无法确定或语法无效,则 OP iframe 应该将字符串错误postMessage返回源。如果接收到的值和计算出的值不匹配,则 OP iframe 必须将更改后的字符串发送回源。如果匹配,那么它必须 postMessage 字符串 不变。
以下是 OP iframe 的非规范示例伪代码:
window.addEventListener("message", receiveMessage, false); function receiveMessage(e){ // e.data has client_id and session_state var client_id = e.data.substr(0, e.data.lastIndexOf(' ')); var session_state = e.data.substr(e.data.lastIndexOf(' ') + 1); var salt = session_state.split('.')[1]; // if message is syntactically invalid // postMessage('error', e.origin) and return // if message comes an unexpected origin // postMessage('error', e.origin) and return // get_op_user_agent_state() is an OP defined function // that returns the User Agent's login status at the OP. // How it is done is entirely up to the OP. var opuas = get_op_user_agent_state(); // Here, the session_state is calculated in this particular way, // but it is entirely up to the OP how to do it under the // requirements defined in this specification. var ss = CryptoJS.SHA256(client_id + ' ' + e.origin + ' ' + opuas + ' ' + salt) + "." + salt; var stat = ''; if (session_state === ss) { stat = 'unchanged'; } else { stat = 'changed'; } e.source.postMessage(stat, e.origin); };
OP 用户代理状态通常存储在 cookie 或 HTML5 本地存储中。它是与授权服务器绑定的源。它捕获有意义的事件,例如登录、注销、用户更改、最终用户使用的客户端的身份验证状态更改等。因此,OP 应更新用户代理状态的值以响应此类有意义的事件。因此,在此类事件发生后,下次调用 check_session() 将返回更改的值。建议 OP 在没有有意义的事件的情况下不要过于频繁地更新用户代理状态,以便在客户端响应虚假更改事件时避免过多的网络流量。
除了用户代理状态之外,响应不成功的身份验证请求而返回的会话状态的计算还应该以盐的形式包含足够的随机性,以防止在连续调用 OP 的授权端点时识别最终用户。
在授权客户端(成功的身份验证响应)的情况下,OP 应在以下事件之一下更改返回给客户端的会话状态值:
此外,用于验证会话状态的用户代理状态应该随此类事件而改变。在此类事件发生后,对 check_session() 的调用将返回 针对早期版本的会话状态的更改。建议在没有此类事件的情况下,用户代理状态不应变化得太频繁,以最大限度地减少客户端对更改 通知的响应所引起的网络流量。
如果身份验证请求不成功导致身份验证错误响应(如 OpenID Connect Core 1.0 第 3.1.2.6 节中指定),则返回的会话状态值应随每个请求而变化。但是,除非发生有意义的事件,否则用户代理会话状态不需要更改。特别地,会话状态的许多值可以同时有效,例如通过在响应不成功的认证请求而发出的会话状态中引入随机盐。
如果使用 cookie 来维护 OP 用户代理状态,则可能无法为此 cookie 设置 HttpOnly 标志,因为需要从 JavaScript 访问它。因此,不应该将可用于识别用户的信息放入cookie中,因为它可以被不相关的JavaScript读取。
在一些实现中,仅当最终用户的会话发生改变时才会发生改变的 通知,而在其他实现中,它们也可能由于用户代理和OP之间的其他会话的改变而发生。 RP 需要为这两种可能性做好准备,默默地处理可能发生的任何误报。
目录 |
为了支持OpenID Connect会话管理,RP需要获取会话管理相关的OP元数据。此 OP 元数据通常通过 OP 的 Discovery 响应获取,如OpenID Connect Discovery 1.0(Sakimura, N.、Bradley, J.、Jones, M. 和 E. Jay,“OpenID Connect Discovery 1.0”,2014 年 11 月。) [OpenID.Discovery] 中所述,或者可以通过其他机制获知。
当支持会话管理和发现时,此 OpenID 提供者元数据参数必须包含在服务器的发现响应中:
- 检查会话 iframe
- 必需的。 OP iframe 的 URL,支持使用 HTML5 postMessage API 与 RP 客户端进行会话状态信息的跨源通信。该 URL 必须使用https方案,并且可以包含端口、路径和查询参数组件。该页面是从嵌入在 RP 页面中的不可见 iframe 加载的,以便它可以在 OP 的安全上下文中运行。它接受来自相关 RP iframe 的 postMessage 请求,并使用 postMessage 回发最终用户在 OP 的登录状态。
目录 |
如果本规范中定义的任何验证过程失败,则必须中止任何需要未能正确验证的信息的操作,并且不得使用未能正确验证的信息。
目录 |
该规范定义了依赖方和选择实施会话管理的 OpenID 提供商所使用的功能。所有这些依赖方和 OpenID 提供商必须实现本规范中列出的“必需”或“必须”描述的功能。
目录 |
请注意,在撰写本文时,一些用户代理(浏览器)开始默认阻止对第三方内容的访问,以阻止用于跟踪最终用户跨网站活动的某些机制。具体而言,被阻止的第三方内容是来源与焦点用户代理窗口来源不同的网站内容。网站数据包括 Cookie 和任何 Web 存储 API(sessionStorage、localStorage 等)。
这可以防止来自 RP 处的 OP 的通知能够访问 RP 的用户代理状态以实施本地注销操作。特别是,cookie 和 Web 存储 API 在 RP 上下文中加载的 OP 框架中可能不可用。这里的副作用是,根据所使用的机制(cookie 或 Web 存储),重新计算session_state所需的数据可能不可用。基于 Cookie 的实现可能会为每次调用返回更改,从而导致重新身份验证的无限循环。因此,建议此规范的部署包含防御代码来检测这种情况,并在可能的情况下通知最终用户无法执行请求的 RP 注销。所需防御代码的详细信息超出了本规范的范围;它可能因用户代理而异,并且可能随着时间的推移而变化,因为用户代理跟踪预防情况是不稳定的并且不断发展。
(Jones, M. 和 J. Bradley,“OpenID Connect 后台注销 1.0”,2022 年 9 月。)目前尚不清楚 OpenID Connect Back-Channel Logout 1.0 [OpenID.BackChannel] 是否会受到这些开发的影响。
目录 |
OP iframe 必须强制调用者来自预期的来源。它必须拒绝来自任何其他源的 postMessage 请求,以防止跨站点脚本攻击。
RP iframe 必须强制它只处理来自 OP 帧来源的消息。它必须拒绝来自任何其他源的 postMessage 请求,以防止跨站点脚本攻击。
目录 |
目录 |
本规范在RFC 6749 [RFC6749] 建立的 IANA“OAuth 参数”注册表[IANA.OAuth.Parameters](IANA,“OAuth 参数” 。)中注册以下参数。 (Hardt, D., Ed.,“OAuth 2.0 授权框架”,2012 年 10 月。)
目录 |
目录 |
本规范在[RFC8414] 建立的 IANA“OAuth 授权服务器元数据”注册表[IANA.OAuth.Parameters](IANA,“OAuth 参数” 。)中注册以下元数据名称。 (Jones, M.、Sakimura, N. 和 J. Bradley,“OAuth 2.0 授权服务器元数据”,2018 年 6 月。)
目录 |
目录 |
目录 |
[IANA.OAuth.参数] | IANA,“ OAuth 参数”。 |
[OpenID.BackChannel] | Jones, M. 和 J. Bradley,“ OpenID Connect 后台注销 1.0 ”,2022 年 9 月。 |
[OpenID.核心] | Sakimura, N.、Bradley, J.、Jones, M.、de Medeiros, B. 和 C. Mortimore,“ OpenID Connect Core 1.0 ”,2014 年 11 月。 |
[OpenID.发现] | Sakimura, N.、Bradley, J.、Jones, M. 和 E. Jay,“ OpenID Connect Discovery 1.0 ”,2014 年 11 月。 |
[OpenID.FrontChannel] | Jones, M.,“ OpenID Connect 前端注销 1.0 ”,2022 年 9 月。 |
[OpenID.RP发起] | Jones, M.、de Medeiros, B.、Agarwal, N.、Sakimura, N. 和 J. Bradley,“ OpenID Connect RP 发起的注销 1.0 ”,2022 年 9 月。 |
[RFC2119] | Bradner, S.,“ RFC 中用于指示需求级别的关键字”,BCP 14,RFC 2119,DOI 10.17487/RFC2119,1997 年 3 月。 |
[RFC6454] | Barth, A.,“ Web 起源概念”,RFC 6454,DOI 10.17487/RFC6454,2011 年 12 月。 |
[RFC6749] | Hardt, D., Ed.,“ OAuth 2.0 授权框架”,RFC 6749,DOI 10.17487/RFC6749,2012 年 10 月。 |
[RFC7159] | Bray, T., Ed.,“ JavaScript 对象表示法 (JSON) 数据交换格式”,RFC 7159,DOI 10.17487/RFC7159,2014 年 3 月。 |
[RFC7230] | 菲尔丁,R.,埃德。和 J. Reschke, Ed.,“超文本传输协议 (HTTP/1.1):消息语法和路由”,RFC 7230,DOI 10.17487/RFC7230,2014 年 6 月。 |
目录 |
[RFC8414] | Jones, M.、Sakimura, N. 和 J. Bradley,“ OAuth 2.0 授权服务器元数据”,RFC 8414,DOI 10.17487/RFC8414,2018 年 6 月。 |
目录 |
OpenID 社区感谢以下人员对此规范做出的贡献:
纳文·阿加瓦尔 (Naveen.Agarwal@microsoft.com),微软
阿曼达·安加内斯 (aanganes@mitre.org),MITRE
约翰·布拉德利 (ve7jtb@ve7jtb.com),尤比科
布雷诺·德·梅代罗斯 (breno@google.com),Google
弗拉基米尔·朱维诺夫 (vladimir@connect2id.com),Connect2id
乔治·弗莱彻 (gffletch@aol.com),第一资本
埃德蒙·杰伊 (ejay@mgi1.com),伊鲁米拉
迈克尔·B·琼斯 (mbj@microsoft.com),微软
汤姆·琼斯 (thomasclinganjones@gmail.com),独立人士
托德·莱恩哈特 (lainhart@us.ibm.com),IBM
托斯顿·洛德斯泰特 (torsten@lodderstedt.net),yes.com
安东尼·纳达林 (nadalin@prodigy.net),独立
Axel Nennker (axel.nennker@telekom.de),德国电信
Justin Richer (justin@bspk.io),定制工程
Nat Sakimura (nat@nat.consulting),NAT.Consulting
菲利普·斯科坎 (panva.ip@gmail.com),Auth0
汉斯·赞德贝尔特 (hans.zandbelt@zmartzone.eu),ZmartZone
目录 |
版权所有 (c) 2022 OpenID 基金会。
OpenID 基金会 (OIDF) 向任何贡献者、开发者、实施者或其他相关方授予非排他性、免版税、全球版权许可,以复制、分发、执行和展示本实施者草案或最终规范、准备衍生作品、分发、执行和展示仅用于 (i) 制定规范,以及 (ii) 根据此类文件实施实施者草案和最终规范,前提是注明材料来源为 OIDF,但此类来源并不表示认可由 OIDF 制定。
本规范中描述的技术来自各种来源的贡献,包括 OpenID 基金会的成员和其他人。尽管 OpenID 基金会已采取措施帮助确保该技术可供分发,但它对可能声称与实施或使用该技术相关的任何知识产权或其他权利的有效性或范围不持任何立场。本规范或此类权利下的任何许可可能或可能不可用的范围;它也不代表它已做出任何独立努力来确定任何此类权利。 OpenID 基金会和本规范的贡献者不做出(并特此明确否认任何)与本规范相关的保证(明示、暗示或其他方式),包括适销性、不侵权、特定用途的适用性或所有权的暗示保证。规范,并且实施该规范的全部风险由实施者承担。 OpenID 知识产权政策要求贡献者提供专利承诺,不会针对其他贡献者和实施者提出某些专利主张。 OpenID 基金会邀请任何感兴趣的各方提请其注意可能涵盖实践本规范所需的技术的任何版权、专利、专利申请或其他专有权利。
目录 |
布雷诺·德·梅代罗斯 | |
谷歌 | |
电子邮件: | breno@google.com |
网址: | https://stackoverflow.com/users/311376/breno |
纳文·阿加瓦尔 | |
微软 | |
电子邮件: | 纳文.Agarwal@microsoft.com |
网址: | https://www.linkedin.com/in/nvnagr |
纳特·萨基穆拉 | |
NAT咨询 | |
电子邮件: | nat@nat.consulting |
网址: | https://nat.sakimura.org/ |
约翰·布拉德利 | |
尤比科 | |
电子邮件: | ve7jtb@ve7jtb.com |
网址: | http://www.thread-safe.com/ |
迈克尔·琼斯 | |
微软 | |
电子邮件: | mbj@microsoft.com |
网址: | https://self-issued.info/ |