传统身份验证通常采用OAuth、OIDC等协议,自分发的分布式数字身份验证协议与传统的验证协议不同,但应该后向兼容传统协议。这个规范给出了依赖方验证自分发数字身份的方案。该规范适用于移动或桌面浏览器或基于浏览器的应用程序。
原文链接:https://identity.foundation/did-siop/#protocol-flow-0](https://identity.foundation/did-siop/#protocol-flow-0
以下是翻译,enjoy~
摘要
这个规范定义了"SIOP DID Profile" (SIOP DID)是一种 DID AuthN方法,它将OpenID Connect (OIDC)以及强大的去中心化的、具有隐私和安全保障的分布式标识符DID结合,为每个需要将身份钱包集成到他们的web端应用程序的开发者提供通用方案。
文档状态
SIOP DID是一个正在 Decentralized Identity Foundation (DIF)中开发的草案规范。此规范将会不断更新,鼓励参与者去以下位置参与贡献:https://github.com/decentralized-identity/did-siop
目录
1.术语
2.介绍
2.1 目的
2.2 目标
3.协议流
3.1 生成SIOP请求
3.2 SIOP请求验证
3.3 生成SIOP响应
3.4 SIOP发现
4.UX考虑
5.安全性考虑
6.IANA考虑
7.OIDC考虑
A.参考
A.1 参考规范
A.2 参考资料
1、术语
术语 | 描述 |
---|---|
DID | Decentralized Identifier参考[DID] |
DID Document | DID Document 参考[DID] |
SIOP DID | Self-Issued OpenID Connect Provider DID 配置,参考一种在OIDC SIOP工作流中具体使用的DID授权方式. |
JWT | JSON Web Token 参考[RFC7797] |
JWE | JSON Web Encryption 参考[RFC7516] |
JWS | JSON Web Signature 参考[RFC7515] |
JWK | JSON Web Key 参考[RFC7517] |
JWKS | JWK Set 参考[RFC7517] |
OIDC | OpenID Connect 参考[OIDC.Core] |
OIDC client | 与Relying Party 同义(参见 RP) |
OP | OpenID Provider 参考[OIDC.Core] |
SIOP | Self-issued OpenID Providre参考[OIDC.Core] |
RP | Relying Party,在[OIDC.Core]中使用 |
Identity Wallet | 身份钱包是指在DID持有者控制下并代表DID持有者的应用,也叫身份代理。身份钱包可以有不同的形式,如移动APP,浏览器拓展应用/插件等。 |
DID AuthN | 指一种以认证为目的的证明拥有DID控制权的方法 |
2、介绍
分布式身份社区识别出一种身份日常使用场景——在web应用程序上注册或登录。现在,注册或登录通常是通过社交登录方案来实现的,比如谷歌登录。虽然去中心化身份社区对社交登录存在严重的担忧,但底层协议OIDC在设计上并没有这些缺陷。通过利用身份钱包,SIOP提供了巨大的潜力,例如,作为一个智能手机端运行的应用程序或运行在web端。这将阻止第三方跟踪用户正在与哪些web应用程序交互,以此增加和保护用户的隐私。
注意
虽然该规范侧重于以浏览器扩展/插件或智能手机应用的形式集成身份钱包,但它并没有排除开发者在其他场景中使用所提议的方法,例如,在两个具有预置DIDs的web服务之间使用。
2.1 目的
主要目的是注册/登录到RP,即web应用程序。假设用户操作移动桌面浏览器,或基于浏览器的应用程序,这些应用程序可以根据该规范响应SIOP请求。
注意
在RP和SIOP之间,SIOP协议流是点对点的。可以基于DID验证持有者,或设置/引导DID Comm和可能需要的与任何DID之间的连接路由,或根据[OIDC.CIBA]在支持客户端发起的后端通道(CIBA)的DID Document 中提供login_hint到OpenID Connect的服务。
2.2 目标
该规范的主要目标是:
- 与现有的OIDC客户端和执行SIOP规范的OPs保持向后兼容,SIOP规范是OIDC核心规范的一部分,以应用于更广泛的社区。
- 为已提供AuthN支持的OIDC客户端添加验证规则,以充分利用DIDs。
- 不依赖任何中介,如传统的集中式公共或私有OP,同时仍然遵循OIDC。
3、协议流
该规范假设用户正在操作移动或桌面浏览器来访问web应用程序或使用基于浏览器的应用程序。
首先,用户单击注册或登录的UX组件。然后RP将生成到openid://
注意
在移动设备上,注册或登录动作将打开身份钱包应用程序,例如uport, connect.me。在桌面浏览器上,要么显示一个QR码,它或者可以被身份钱包应用程序扫描,或者重定向到可以由实现SIOP的浏览器扩展应用或插件处理,例如,openid://。
SIOP将基于所支持的特定DID方法生成
此规范不显式支持任何中间集线器或云代理。它是用来交换DID的协议。您可以使用DID文档中的服务端点与hub/云代理交互。
不同于按 [OIDC.Core]工作的OIDC授权代码流程, SIOP不会返回访问令牌给RP。如果需要,可以按照上述CIBA流程[OIDC.CIBA]来实现。除此之外,SIOP与授权代码流的不同之处在于它不依赖于一个集中且已知的OP。在用户开始使用其身份钱包与RP交互之前,RP可能不知道SIOP。OIDC授权代码流仍然是一种有用的方法并可以被使用,只要OP是已知的,并且发现OP是可能的,例如在服务部分中已经交换或预置了包含openid元素的DID Document。如果实现了SIOP规范,则SIOP协议允许将身份钱包与普通的OIDC客户端集成。相反,在OIDC授权代码流中使用 DID AuthN作为身份验证手段,将需要与OP供应商集成。
3.1 生成SIOP请求
Redirect 重定向
请求包含scope、response_type和client_id作为查询字符串参数,以向后兼容OAuth2规范[RFC6749]。response_type必须是id_token,而client_id必须指定RP的重定向URI(根据[OIDC.Core])。依据[OIDC]规定,所有其他OIDC请求参数必须在请求对象中提供,且被编码为JWT。这使 RP能够使用 RP的DID对SIOP进行身份验证。请求对象可以通过request请求参数中的值传递,也可以通过引用request_uri参数传递。
EXAMPLE 1
openid://?response_type=id_token
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request=
在上面的示例中, DID AuthN
EXAMPLE 2
openid://?response_type=id_token
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request_uri=https%3A%2F%2Frp.example.com%2F90ce0b8a-a910-4dd0
在上面的示例中,DID AuthN
RP元数据
与其他OIDC流(例如授权码流)不同,RPs可以在registeration请求参数中提供客户端元数据。客户端可以包含OpenID Connect Registration 1.0 中定义的任何注册元数据参数,服务器可以根据需要使用这些参数。
除了RS256之外,本规范的SIOP必须支持request_object_signing_alg的EdDSA和ES256K [draft-ietf-cose-webauthn-algorithms-03], request_object_signing_alg可以省略。实现DID AuthN配置文件的RPs不能对request_object_signing_alg使用none。
Request Object必须可由 RP的DID Document中的验证方法直接或间接地验证,并直接由 RP的JWKS验证。JWKS必须在注册参数的jwks_uri或jwks条目中提供。JWKS必须包含一个带有与Request Object中的kid匹配的kid条目。出于与普通SIOP OPs后向兼容的考虑,jwks_uri必须按照[DID.Resolution]使用HTTP(s) DID解析绑定。只有在无法直接从DID文档获取公钥的情况下,才能使用jwks请求参数。
RPs可以决定是否接收加密的SIOP Response。要启用加密,根据OIDC客户端元数据[OIDC.Registration] 的规定,注册参数必须使用id_token_encrypted_response_alg和id_token_encrypted_response_enc。本规范建议在Encryption部分和[draft-amringer-jose-chacha-00]描述的JWE中使用echt-es和X25519曲线算法。
请求对象 Request Object
Request Object遵循OIDC规范,例如,添加nonce、state、response_type和client_id参数。
请求包含scope、response_type和client_id作为查询字符串参数,以向后兼容OAuth2规范 [RFC6749]。response_type必须是id_token,而client_id必须指定RP的重定向URI(根据[OIDC.Core]规定)。所有其他OIDC请求参数必须按照[OIDC.Core]规定在Request Object中提供,且被编码为JWT。这使RP能够使用RP的 DID对SIOP进行身份验证。请求对象可以通过request请求参数中的值传递,也可以通过引用使用request_uri参数传递。
Request Object遵循OIDC规范,例如,添加nonce、state、response_type和client_id参数。
该规范为Request Object的请求参数和声明引入了附加规则:
- REQUIRED. iss 必须包含可解析为DID Document的RP的DID。DID Document必须在身份验证部分包含一种验证方法,例如公钥,它允许SIOP验证请求对象。
注意
默认地,iss声明引用了client_id,但SIOP假设client_id是RP的重定向URI。这就是DID没有编码到client_id中的原因。iss和client_id使用不同的值是符合OIDC规范的。
- REQUIRED. kid必须是一个引用RP DID Document中的authentication部分中的验证方法的DID URL,例如DID:example:0xab#key1。SIOP必须能够使用该验证方法直接或间接地验证Request Object。此外,registeration参数中引用的JWKS必须包含具有相同kid的条目。
- REQUIRED.scope必须包括did_authn,以表明使用了 SIOP DID配置文件。
- REQUIRED.registeration必须包含在Request Object中
- REQUIRED.client_id必须在Request Object中重复
- OPTIONAL. response_mode指定 SIOP如何将响应返回给重定向URI。实现此规范的SIOP可以将response_mode设置为form_post。fragment是默认的响应模式。在指定此请求参数时,RPs必须考虑用户代理平台。
注意
参见OAuth 2.0 后响应模式[OAuth2.FormPost]和OAuth 2.0多响应类型编码实践[OAuth2.ResponseTypes]以获得更多有关response_mode的信息。
- OPTIONAL. response_context指定响应是否应该返回重定向URI到现有系统浏览器会话的环境中,或者响应是否可以返回到一个新的/空环境(wallet的response_context请求)。默认的response_context是rp,表示响应应该在RP现有的系统浏览器会话环境中提交。
注意
钱包的response_context向SIOP表明用户流应该在SIOP中结束,且不需要任何重定向信号返回给RP。这种行为在跨设备工作流中非常有用,在这种情况下,流的移动部分应该在钱包中终止。
- OPTIONAL.claims 遵循OIDC Core schema,添加一个顶级vc属性作为id_token和userinfo的同族成员(并遵循其模式)。在vc集合中的请求声明表明请求方希望接收(如果essential为false),或者请求 (如果为true) 特定的一组可验证凭证类型,这组凭证在SIOP响应的.vp.verifiableCredential列中。特定的VC types是用VC类的完整URI识别的。
注意
当以这种方式提供声明时,SIOP响应充当W3C的可验证表示;在表示中展示可验证凭证组,以在响应中提供所请求的凭证。
下面是一个Request Object的JWT头的非规范示例:
EXAMPLE 3
{
"alg": "ES256K",
"typ": "JWT",
"kid": "did:example:0xab#veri-key1"
}
下面是一个不要求
EXAMPLE 4
{
"iss": "did:example:0xab",
"response_type": "id_token",
"client_id": "https://my.rp.com/cb",
"scope": "openid did_authn",
"state": "af0ifjsldkj",
"nonce": "n-0S6_WzA2Mj",
"response_mode" : "form_post",
"registration" : {
"jwks_uri" : "https://uniresolver.io/1.0/identifiers/did:example:0xab;transform-keys=jwks",
"id_token_signed_response_alg" : "ES256K"
}
}
下面是一个不规范的例子:RP的HTTP 302重定向响应,它触发用户代理使用请求对象的值向SIOP发送一个SIOP DID身份验证请求(行内的值仅用于显示目的):
EXAMPLE 5
HTTP/1.1 302 Found
Location: openid://?
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request=
下面是一个RP的HTTP 302重定向响应的非标准示例,它通过引用SIOP,触发用户代理使用请求对象发出一个SIOP DID身份验证请求(行内的值仅用于显示目的):
EXAMPLE 6
HTTP/1.1 302 Found
Location: openid://?
response_type=id_token
&client_id=https%3A%2F%2Frp.example.com%2Fcb
&scope=openid%20did_authn
&request_uri=https%3A%2F%2Frp.example.com%2F90ce0b8a-a910-4dd0
加密
JWE加密应该使用Diffie-Hellman密钥协议,即使用X25519曲线的ECDD-ES算法,该曲线使用临时密钥和直接密钥协议。Diffie-Hellman算法从RP的公钥推导出对称密钥,随机生成临时私钥。相应的临时公钥包含在epk中的JWE的头中,派生的对称密钥用于直接加密JWT内容。为了对称加密内容,算法代码为XC20P的XChaCha20Poly1305被采用。
下面是一个保护结果JWE头的示例:
EXAMPLE 7
{
"alg": "ECDH-ES",
"epk":
{
"kty": "OKP",
"crv":"X25519",
"x":"hSDwCYkwp1R0i33ctD73Wg2_Og0mOBr066SpjqqbTmo"
}
"enc": "XC20P",
"kid": "did:example:0xab#key-1"
}
注意,上面的kid指示DID和RP的密钥,即,这个公钥和临时私钥是发送方用来推导共享密钥的。在加密过程中,XChaCha20算法中的24字节nonce字段作为初始化向量。身份验证标签是MAC,它是由Poly1305函数计算出来的。它有16个字节长。
要加密的消息是id_token的JWT,包括头和签名。JWT在加密之前是通过base64url编码的。
对于JWE的最终编码,采用了[RFC7516]中的JWE紧凑序列化方案。该消息的结构如下:
EXAMPLE 8
BASE64URL(JWE Protected Header) || '.' || '.' ||
BASE64URL(JWE Initialization Vector) || '.' ||
BASE64URL(JWE Ciphertext) || '.' ||
BASE64URL(JWE Authentication Tag)
注意两个'.'上面的字符表示加密密钥是空的,因为我们使用的是直接密钥协议。
3.2 SIOP请求验证
SIOP必须验证
注意
上面描述的步骤确保根据OIDC规范验证请求对象。这包括基本的JWS验证。
如果作用域包含did_authn作用域,接收的SIOP必须进一步验证
- 从iss请求参数中指定的RP's DID中解析DID Document。
- 如果jwks_uri存在,请确保jwks_uri中的DID与iss声明中的DID匹配。
- 从与SIOP请求的kid匹配的RP的DID Document中确定验证方法。
- 按照上述验证方法对SIOP请求进行验证。此步骤取决于DID文档中的authentication部分中的验证方法,并且超出了本规范的范围。
注意
如果签名SIOP Request的密钥对引用了验证方法所指示的同一密钥,那么就不需要进行额外的验证,因为SIOP验证将验证JWS的签名。
3.3 生成SIOP 响应
按照[
该规范为id_token中的声明引入了附加规则:
REQUIRED.sub_jwk必须包含一个kid,它是一个DID URL,引用SIOP's DID Document的验证方法,可以直接或间接地验证id_token的JWS。
REQUIRED. did必须是 SIOP的DID
注意
出于向后兼容性的原因,必须提供sub_jwk声明。DID Document中的验证方法可以不同于公钥,可以使用publicKey属性值而不是 publicKeyJwk
下面是一个未加密的id_token的JWT头的非规范示例:
EXAMPLE 9
{
"alg": "ES256K",
"typ": "JWT",
"kid": "did:example:0xab#key-1"
}
下面是一个id_token的JWT负载未加密的非规范示例:
EXAMPLE 10
{
"iss": "https://self-issued.me",
"nonce": "n-0S6_WzA2Mj",
"exp": 1311281970,
"iat": 1311280970,
"sub_jwk" : {
"crv":"secp256k1",
"kid":"did:example:0xcd#verikey-1",
"kty":"EC",
"x":"7KEKZa5xJPh7WVqHJyUpb2MgEe3nA8Rk7eUlXsmBl-M",
"y":"3zIgl_ml4RhapyEm5J7lvU-4f5jiBvZr4KgxUjEhl9o"
},
"sub": "9-aYUQ7mgL2SWQ_LNTeVN2rtw7xFP-3Y2EO9WV22cF0",
"did": "did:example:0xcd"
}
3.4 SIOP 响应验证
RP必须验证
- 可选地解密JWE以获得包含id_token的JWS。
- 验证id_token是由sub_jwk声明中指定的密钥签名的。
此外,RP必须根据SIOP的DID文档验证id_token,如下所示: - 从did声明中指定的 SIOP的DID解析DID Document。
- 从与id_token中sub_jwk声明的kid匹配的SIOP'的DID Document中确定验证方法。
- 根据上面的验证方法验证id_token。此步骤取决于DID文档中的authentication部分中的验证方法,不在本规范的范围内。
注意
如果签署id_token的密钥对引用了验证方法所指示的同一密钥,那么就不需要进行额外的验证,因为SIOP验证将验证JWS的签名。
3.5 SIOP 发现
SIOP规范假设有以下OP发现元数据:
“id_token_signing_alg_values_supported”:“RS256”,
“request_object_signing_alg_values_supported”:“none”,“RS256”)
DID AuthN配置文件采用以下OP发现元数据:
"id_token_signing_alg_values_supported": ["RS256", "ES256K", "EdDSA"],
“request_object_signing_alg_values_supported”:
["none","RS256", "ES256K", "EdDSA"]
这一改变将允许DID AuthN使 RPs能够使用SSI社区成员之间常用的其他签名算法。
注意
“自行发布的OpenID提供者发现”是不规范的,不包含任何必须、应该或可能声明。因此,使用与RS256不同的签名算法不会破坏SIOP规范。启用了DID AuthN的RP将提供id_token_signed_response_alg来在上面列出的三个id_token_signing_alg_values_supported选项中指示它选择的签名算法。
4.UX考虑
本节不规范。
SIOP使用自定义URL方案openid://。移动浏览器将打开注册了该方案的应用程序。桌面浏览器扩展/插件支持类似的功能。使用QR码的情况不在本规范的范围内。如果用户使用的是桌面浏览器,而没有浏览器扩展/插件,可以选择提供二维码。
在Android上,如果多个应用注册了相同的自定义URL方案,用户可以选择打开哪个应用。在iOS上,行为是未定义的。一种方法是检查用户是否在iOS设备上,然后不提供按钮,如果这是一个问题。在iOS上可以使用自定义模拟类型,但需要考虑用户体验需要是否友好。注意,这个问题不是SIOP特有的,而是影响所有使用自定义URL方案的应用程序。如果使用了二维码,用户必须先打开应用程序,然后扫描二维码,这个问题就会得到缓解。
5.安全考虑
本节不规范。
威胁:拦截重定向URI
如果攻击者可以使
这种攻击可以通过增强 RP来减轻,例如,不支持开放的重定向器模式。
威胁:浏览器历史记录中的身份令牌泄漏
攻击者可以从浏览器的历史记录中获取
这种攻击无法完全减轻。建议对id_token使用较短的过期时间,并指示浏览器不应该缓存响应。
威胁:身份令牌泄露给第三方脚本
在RP页面上使用第三方脚本是比较常见的,比如分析工具,崩溃报告。应用程序的作者可能无法完全了解在应用程序中运行的全部代码。当片段中返回一个
这种攻击可以通过在 RP的页面或基于浏览器的应用程序上使用受信任/审计的第三方脚本来减轻。
对策
尽可能使用response_mode=form_post来降低上述风险。在某些情况下,例如,在纯分布式应用(dApp)的情况下是不可能的。
威胁:跨设备流中的会话固定
当协议在一个设备上开始并在另一个设备上结束时,就存在跨设备传输被劫持的风险。例如,考虑这样一个流:RP先显示一个二维码,当用户扫描二维码时,将其传输到移动钱包。在这个场景中,攻击者可以欺骗用户扫描与合法RP的登录请求相关联的QR码,从而导致用户在攻击者会话环境中进行身份验证。
对策
验证提交DID SIOP响应的浏览器会话是否与显示DID SIOP请求的浏览器会话属于同一用户。即使这些会话在不同的设备上,RP也可以采取步骤来确保这些会话属于同一用户(例如,通过检查现有会话是否存在,或者通过要求用户通过非SIOP方式登录)。
其他安全考虑
OWASP基金会为web应用程序维护了一组安全建议和最佳实践,建议在基于该规范创建SIOP或RP时遵循这些最佳实践。
6.IANA考虑
本节不规范。
该规范在JWT中定义的IANA JSON Web令牌声明注册表中注册did声明。
7.OIDC考虑
本节不规范。
该规范的目标是向后兼容现有的OIDC clients和实现SIOP规范的OPs。虽然SIOP规范是OIDC核心规范的一部分,但它还没有被广泛采用。其中一个原因是,没有多少应用程序能提供我们可以在身份钱包中找到的功能。尽管如此,SIOP使用相同或类似的请求和响应消息,并且应该很容易允许OIDC供应商升级现有的 OIDC客户端来支持SIOP。
A.1 参考规范
[DID.Resolution]
Decentralized Identifier Resolution. Markus Sabadello; Dmitri Zagidulin. Credentials Community Group. Draft Community Group Report. URL: https://w3c-ccg.github.io/did-resolution/
[draft-amringer-jose-chacha-00]
Chacha derived AEAD algorithms in JSON Object Signing and Encryption (JOSE). G. Amringer. 2018. URL: https://tools.ietf.org/html/draft-amringer-jose-chacha-00
[draft-ietf-cose-webauthn-algorithms-03]
COSE and JOSE Registrations for WebAuthn Algorithms. M. Jones. 2019. URL: https://tools.ietf.org/html/draft-ietf-cose-webauthn-algorithms-03
[OIDC.Core]
OpenID Connect Core 1.0 incorporating errata set 1. N. Sakimura; J. Bradley; M. Jones; B. de Medeiros; C. Mortimore. 2014. URL: https://openid.net/specs/openid-connect-core-1_0.html
[OIDC.Registration]
OpenID Connect Dynamic Client Registration 1.0 incorporating errata set 1. N. Sakimura; J. Bradley; M. Jones. 2014. URL: https://openid.net/specs/openid-connect-registration-1_0.html
[RFC6749]
The OAuth 2.0 Authorization Framework. D. Hardt, Ed.. IETF. October 2012. Proposed Standard. URL: https://tools.ietf.org/html/rfc6749
[RFC7516]
JSON Web Encryption (JWE). M. Jones; J. Hildebrand. IETF. May 2015. Proposed Standard. URL: https://tools.ietf.org/html/rfc7516
A.2 参考资料
[DID]
https://www.w3.org/TR/did-core/. Drummond Reed; Manu Sporny; Dave Longley; Christopher Allen; Ryan Grant; Markus Sabadello. Decentralized Identifier Working Group. Working Draft. URL: https://www.w3.org/TR/did-core/
[OAuth2.FormPost]
OAuth 2.0 Form Post Response Mode. M. Jones; B. Campbell. 2015. URL: https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html
[OAuth2.ResponseTypes]
OAuth 2.0 Multiple Response Type Encoding Practices. B. de Medeiros, Ed.; M. Scurtescu; P. Tarjan; M. Jones. 2014. URL: https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html
[OIDC.CIBA]
OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 draft-02. G. Fernandez; F. Walter; A. Nennker; D. Tonge; B. Campbell. 2019. URL: https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0-ID1.html
[RFC7515]
JSON Web Signature (JWS). M. Jones; J. Bradley; N. Sakimura. IETF. May 2015. Proposed Standard. URL: https://tools.ietf.org/html/rfc7515
[RFC7517]
JSON Web Key (JWK). M. Jones. IETF. May 2015. Proposed Standard. URL: https://tools.ietf.org/html/rfc7517
[RFC7797]
JSON Web Signature (JWS) Unencoded Payload Option. M. Jones. IETF. February 2016. Proposed Standard. URL: https://tools.ietf.org/html/rfc7797