sam的通信协议(干货浅析SAML标准协议)
sam的通信协议(干货浅析SAML标准协议)必须属性名称不难看出,认证请求消息是一个基于XML的文本,其顶层节点为,命名空间为:urn:oasis:names:tc:SAML:2.0:Protocol。认证请求消息支持ID、Version、IssueInstant 等属性,还可以包含 Issuer、NameIDPolicy 等子节点,下面我们将逐一对这些属性进行讲解。认证请求消息支持的属性
在上篇文章中,我们向大家介绍了 SAML 协议 Web Browser SSO 场景的基本流程,包括 HTTP Redirect Binding、HTTP POST Binding、HTTP Artifact Binding,并以 “阿里云 IDaaS 单点登录 阿里云RAM”为例,演示了 SSO 流程中的HTTP报文。本文将为大家揭秘 SAML 认证请求消息的基本格式和用法规约。
认证请求消息的基本格式
在 SAML Web Browser SSO 场景中 ,当 SP 需要进行用户身份认证时,可以向 IdP 发送一个 认证请求消息( AuthnRequest ),要求 IdP 签发一个认证断言,从而完成用户认证,与客户端建立一个安全的上下文会话。下图是 SP 向 IdP 提交的一个认证请求消息样例。
在实际认证流程中,该消息需要进行 Base64 编码,然后通过 SAMLRequest 参数提交给 IdP,可以参考《简析SAML标准协议(二)》中的介绍。
不难看出,认证请求消息是一个基于XML的文本,其顶层节点为,命名空间为:
urn:oasis:names:tc:SAML:2.0:Protocol。认证请求消息支持ID、Version、IssueInstant 等属性,还可以包含 Issuer、NameIDPolicy 等子节点,下面我们将逐一对这些属性进行讲解。
认证请求消息支持的属性
属性名称 |
必须 |
说明 |
ID |
是 |
请求的唯一标识,必须保证全局唯一,并且基于该请求签发的响应的 InResponseTo 属性,必须与请求中的 ID 属性值保持一致。 |
Version |
是 |
协议的版本号,如果使用的SAML2.0,则该值固定为:2.0 。 |
IssueInstant |
是 |
请求的签发时间,必须统一采用 UTC 时间,例如:2022-03-11T04:08:47.628Z 。 |
Destination |
否 |
一个 URI 引用,用于标识此请求预期发送到的地址,可以用于防止请求被恶意的发给非预期的接受者,当存在该属性时,请求的实际接受者必须校验接收地址与该属性值一致,如果不一致,则应该丢弃该请求。 |
Consent |
否 |
用于向 IdP 声明,在发送该请求时,是否已经获取了委托人的授权许可: urn:oasis:names:tc:SAML:2.0:consent:unspecified 没有向委托人提出任何授权同意的请求 urn:oasis:names:tc:SAML:2.0:consent:obtained 表示消息的发布者已获得委托人的同意 urn:oasis:names:tc:SAML:2.0:consent:prior 表示消息的发布者在发送本消息之前的某个时间点已获得委托人的同意 urn:oasis:names:tc:SAML:2.0:consent:current-implicit 表示消息的发布者在发送过程中隐式获得了委托人的同意 urn:oasis:names:tc:SAML:2.0:consent:current-explicit 表示消息的发布者在发送过程中显示获得了委托人的同意 urn:oasis:names:tc:SAML:2.0:consent:unavailable 表示消息的发布者未获得同意 urn:oasis:names:tc:SAML:2.0:consent:inapplicable 表示消息的发布者不认为他们需要获得或报告同意 |
IsPassive |
否 |
值为布尔类型,如果请求中不包含该值,则默认为 false 。如果为 true,则 IdP 不能显示的通过浏览器与用户进行交互。简单理解,不能让用户感知到认证过程。 |
ForceAuthn |
否 |
值为布尔类型,如果请求中不包含该值,则默认为 false 。如果为 true,则 IDP 必须强制验证用户的身份,而不能依赖当前已经存在的会话或认证上下文。简单来说,不管当前是否已经有用户登录的信息,都要强制进行认证。如果 ForceAuthn 和 IsPassive 同时为 true ,IsPassive 的优先级更高一些,即在保证不违反 IsPassive 约束的前提下,可以强制进行认证,如果强制认证会违反 IsPassive 约束,则不应该进行认证。 |
ProtocolBinding |
否 |
一个 URI 引用,标识返回响应时要使用的 SAML Binding,该属性与 AssertionConsumerServiceIndex 互斥,通常与 AssertionConsumerServiceURL 组合使用。 |
AssertionConsumerServiceURL |
否 |
URL 格式,用于声明 SP 的断言消费地址,该地址即 IdP 认证用户成功后,回调 SP 的地址。该属性与 AssertionConsumerServiceIndex 互斥,通常与 ProtocolBinding 组合使用。IdP 必须通过某种可信的机制,来验证该属性值与请求实际发出的 SP 是一致的:比如通过 SAML metadata 或者 请求消息签名 。 |
AssertionConsumerServiceIndex |
否 |
一个间接的地址索引,用于声明 IdP 认证用户成功后,应该回调的 SP 地址。IdP 必须通过某种可信的机制,来维护这些间接地址索引与真实地址之间的映射关系,如果不存在该属性,那么 IdP 应该使用 SP 配置的默认回调地址。如果该值存在但是无效,那么 IdP 可以返回错误,或者使用 SP 配置的默认回调地址。 |
AttributeConsumingServiceIndex |
否 |
一个间接的索引标识,用于声明 SP 支持的以及必须包含的属性。 |
ProviderName |
否 |
SP 的名称,通常是一个用户友好的、易于记忆的名称。 |
认证请求消息支持的子元素
元素名称 |
必须 |
说明 |
saml:Issuer |
否 |
用于标识请求消息的实际签发者,通常情况下也是 URI 格式。 |
saml:Subject |
否 |
用于描述 SP 希望 IdP 在签发响应断言时,包含的主题信息,简单理解为:希望对哪个用户进行认证。 |
saml:Conditions |
否 |
IdP 向 SP 签发响应断言时,通常会设置一些接收断言的条件,例如时间条件(标识断言在什么时间内生效,超过该时间范围时,SP 可以丢弃此断言)、接收者条件(标识该断言是签发给哪个 SP 的,如果当前 SP 与断言声明的接受者不一致,那么 SP 可以丢弃次断言)等。SP 在向 IdP 方发送 SAML 请求消息时,也可以包在消息中添加 Conditions 子节点,但该节点的作用是:描述 SP 希望 IdP 在签发响应断言时,都包含哪些限制条件或验证条件。IdP 可在其认为必要时修改或补充该条件集合。换句话说,此信息用作 IdP 构造断言过程的输入,而不是作为验证请求时需要使用的约束条件。 |
samlp:RequestedAuthnContext |
否 |
用于描述 SP 希望 IdP 验证用户身份时使用的认证方式。 |
samlp:NameIDPolicy |
否 |
用于描述 SP 希望 IdP 在签发响应断言时,使用的主题名称标识符的约束限制。如果请求中没有包含该子节点,代表 IdP 可以使用任何其支持的名称标识符类型,具体使用哪一种,IdP 可以根据服务自身的一些相关策略来决定。 |
samlp:Scoping |
否 |
对代理身份验证进行相关限制。 |
NameIDPolicy 的用法说明
元素名称 |
必须 |
说明 |
Format |
否 |
一个 URI 引用,用来描述 SP 希望 IdP 在签发响应断言时,返回的被认证的用户的唯一标识的格式。SAML 2.0 已经定义的 Format 包括: urn:oasis:names:tc:SAML:1.1:nameid-Format:unspecified urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos urn:oasis:names:tc:SAML:2.0:nameid-format:entity urn:oasis:names:tc:SAML:2.0:nameid-format:persistent urn:oasis:names:tc:SAML:2.0:nameid-format:transient urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted |
SPNameQualifier |
否 |
用于描述 描述 SP 希望 IdP 在签发响应断言时,返回的被认证的用户的唯一标识的命名空间。 |
AllowCreate |
否 |
布尔类型值,用于声明,IdP 在处理当前请求期间,SP 是否允许 IdP 创建一个新的标识符来表示认证的主体,默认为 false 。如果为 false ,IdP 只有能够向 SP 提供当前被认证主体的符合要求的标识符时,才可以签发断言,否则应该返回错误。 |
当认证请求中包含了 NameIDPolicy 元素时:
- IdP 如果无法解析其内容,或者其属性值无法被支持,则 IdP 必须返回一个 SAML Error 响应,并且响应的状态码,可以设置为:
- urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy 。
- 如果 Format 属性被省略了,或者值为:
- urn:oasis:names:tc:SAML:2.0:nameidformat:unspecified 则 IdP 可以返回任意格式的唯一标识符。
- 如果 Format 属性值为:
- urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted 则 IdP 返回的响应断言中,必须用< EncryptedID>元素,加密返回被认证主体的唯一标识。其原始的明文唯一标识,可以是 IdP 支持的任意格式。
- 当 SP 允许 IdP 为当前被认证的主体新建一个标识符时,应当将 AllowCreate 的值设置为 true 。
Scoping用法说明
名称 |
类型 |
必须 |
说明 |
ProxyCount |
属性 |
否 |
定义从 SP 当前请求的 IdP 跳转到最终认证用户的 IdP 的次数限制,如果为 0 ,代表不允许跳转,必须由当前请求的 IdP 进行对用户进行认证。如果没有该属性,则代表无限制。 |
IDPList |
子元素 |
否 |
用于描述 描述 SP 支持的可以对当前请求进行相应的 IdP 及其相关信息的集合。 |
RequesterID |
子元素 |
否 |
用于描述 处理过当前认证请求的 SP 以及 IdP 的集合。 |
IDPList 子元素的定义
名称 |
类型 |
必须 |
说明 |
IDPEntry |
属性 |
是 |
至少一个,也可以包含多个,每个元素定义了一个 IdP 的基本信息。该元素有三个属性:
|
GetComplete |
子元素 |
否 |
URI 地址,用于说明 IDPList 元素下的 IDPEntry 是否包含了所有支持的 IdP 信息,如果列表中给出的 IdP 并不完整,那么可以通过该属性值中的地址,获取所有支持的 IdP 列表。 |
代理身份验证
当 IdP(记作A)收到了一个认证请求,且无法直接对用户进行认证时,如果 A 知道当前用户已经被其他 IdP(记作B)认证通过,那么 A 可以重新签发一个认证请求,并提交给 B,此时 A 被称作“代理 IdP” 。当 A 接收到 B 的认证成功响应后,就可以针对最初接收的来自 SP 的认证请求,签发响应,从而完成整个认证信息交换的流程。整个流程被称作“代理身份验证”。
无论是 SP 还是最终完成用户身份认证的 IdP,都可以对“代理 IdP”的行为进行约束和限制。例如:SP 可以通过在认证请求消息报文中,通过 Scoping 元素,来声明请求可以被代理的次数,以及 SP 支持的 IdP 的列表。
- 当 IdP 收到了认证的认证请求,包含 Scoping 元素,并且其 ProxyCount 属性值大于 0 或者没有设置 ProxyCount 时,IdP 可以根据自身的策略,来决定是否发起代理身份验证流程、是否从 IDPList 中选择一个 IdP 进行代理认证。
- 当 IdP 收到了认证的认证请求,包含 Scoping 元素,并且其 ProxyCount 属性值等于 0 时,如果 IdP 无法直接对用户进行认证,应该返回 SAML Error 响应,并且将状态码设置为:
- urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded,IdP 不能发起代理身份验证。
- 如果 IdP 选择发起代理认证,那么其签发给其他三方 IdP 的认证请求,必须保证:
1)RequestedAuthnContext、IsPassive 等限制策略与原始认证消息是一致的。
2)如果原始的认证请求的 IsPassive 为 true 并且三方的 IdP 又支持 SAML,代理 IdP 与 三方 IdP 必须通过其他途径,保证认证过程用户无感知。
3)ProxyCount 属性值必须小于原始认证请求的值;如果原始认证请求没有设置 ProxyCount ,新的认证请求中可以增加该属性进行限制。
4)如果原始认证请求中包含 IDPList ,那么新的认证请求也必须包含该元素,并且不能从 IDPList 中移除原始的值,但是可以增加新的 IdP。
小结
SAML作为一个安全类的应用协议,主要用于安全领域的单点登录系统。九州云腾推出的应用身份服务 IDaaS 是领先的云端集中式身份管理服务,单点登录作为 IDaaS 核心优势之一,已通过SAML协议来实现了逾百种应用的集成,包括但不限于Saleforce、Jira、Confluence、Sonarqube、Jenkins、简道云等。本文只针对 SAML 认证请求消息的格式、用法做了简单的剖析,小编将在下一篇文章中,为大家继续讲解 SAML 认证响应报文的格式,欢迎围观。