使用SAML 2.0进行Indeavor单点登录概述
本文概述如何使用SAML 2.0配置单点登录。
SSO概述
安全断言标记语言(SAML)允许客户在登录Indeavor时根据自己的系统进行身份验证。我们的实现会采用SAML 2.0协议。
SAML是一个基于XML的框架,用于在服务提供者和身份提供者两个实体之间进行身份验证和授权。服务提供者同意委托身份提供者进行用户身份的验证。作为回报,身份提供者会生成一个身份验证断言,表明用户已通过身份验证。
SAML是一个标准的单点登录(SSO)格式。身份验证信息通过数字签名的XML文件进行交换。这是一个复杂的单点登录(SSO)实现,支持无缝身份验证,主要在企业与企业之间进行。
身份提供者(IDP)/断言方:客户。常见实现有Microsoft Active Directory Federated Services(ADFS)或Azure。
服务提供者(SP)/依赖方:Indeavor
Indeavor专业提示:Indeavor仅支持SP发起的请求。
身份提供者配置
客户将需要我们的服务提供者元数据,以便在其IDP中将Indeavor添加为依赖方。
身份提供者是一个系统实体,为委托人创建、维护和管理身份信息,同时向联盟或分布式网络内的依赖方应用程序提供身份验证服务。
身份提供者将用户身份验证作为一种服务来提供。依赖方应用程序(如Web应用程序)将用户身份验证步骤外包给受信任的身份提供者。这种依赖方应用被称为联盟式应用,也就是说,其使用的是联盟式身份。
身份提供者是“一种受信任的提供者,支持您使用单点登录(SSO)来访问其他网站”。SSO通过减少密码疲劳来增强可用性,此外还通过减少潜在攻击面来提高安全性。
具体来说,SAML身份提供者是一个系统实体,结合SAML的SSO配置文件发布身份验证断言。使用这些身份验证断言的依赖方称为SAML服务提供者。[1]
[1] https://en.wikipedia.org/wiki/Identity_provider
元数据可通过Indeavor的一个URL进行检索:
https://identity.[ENVIROMENTNAME].indeavor.com/saml/metadata.xml
推荐的最佳实践
- SHA-256算法
- Indeavor SSO要求将ADFS提供的唯一标识符字段包含在响应的属性 语句块中。 大部分客户发现使用电子邮件地址是实现这一结果的最佳唯一标识符。
- Indeavor随身份验证SAML请求发送的“中继状态”参数必须包含在返回Indeavor的联邦服务的SAML响应中。
Indeavor(服务提供者)配置
SAML服务提供者是一个系统实体,它与安全断言标记语言(SAML)的单点登录(SSO)配置文件一起接收并接受身份验证断言。
在SAML域模型中,SAML依赖方是从另一个系统实体接收和接受信息的任何系统实体。特别值得注意的是SAML依赖方,它接收并接受由SAML授权机构发出的SAML断言。
SAML授权机构的一个重要类型是SAML身份提供者,这是一个系统实体,结合SAML的SSO配置文件发布身份验证断言。使用这类断言的依赖方被称为SAML服务提供者(或者在该域名可理解的情况下简称为服务提供者)。因此,SAML服务提供者是一个系统实体,它接收并接受由SAML身份提供者发出的身份验证断言。[1]
[1] https://en.wikipedia.org/wiki/Service_provider_(SAML)
断言
SAML断言包含安全信息包
SAML断言通常可以从身份提供者传输到服务提供者。断言包含服务提供者用于做出访问控制决策的语句。SAML提供三类语句:
- 身份验证语句
- 属性语句
- 授权决定语句
身份验证语句向服务提供者断言委托人确实在特定时间使用特定身份验证方法对身份提供者进行了身份验证。关于已验证委托人的其他信息(称为身份验证上下文)可能会在身份验证语句中披露。
属性语句断言某个主题与特定属性相关。属性只是一个名称-值对。依赖方使用属性来做出访问控制决定。
授权决定语句断言,在证据E的情况下,主体被允许对资源R执行操作A。SAML中授权决定语句的表达能力被有意限制。[1]
协议
SAML协议描述了某些SAML元素(包括断言)是如何被封装在SAML请求和响应元素中的,并给出了SAML实体在生成或使用这些元素时必须遵循的处理规则。在大多数情况下,SAML协议是一个简单的请求-响应协议。
SAML 2.0 Core中详细描述了以下协议:
- 断言查询和请求协议
- 身份验证请求协议
- 组件解决协议
- 命名身份管理协议
- 单点登出协议
- 命名身份映射协议[2]
绑定
SAML绑定是SAML协议消息到标准信息格式和/或通信协议的映射过程。例如,SAML SOAP绑定指定如何将SAML消息封装在SOAP信封中,而SOAP信封本身则绑定到HTTP消息中。
SAML中描述了以下绑定:
- SAML SOAP绑定(基于SOAP 1.1)
- 反向SOAP(PAOS)绑定
- HTTP重定向(GET)绑定
- HTTP POST绑定
- HTTP组件绑定
- SAML URI绑定
配置文件
SAML配置文件详细描述了SAML断言、协议和绑定应如何组合以支持定义的用例。最重要的SAML配置文件是Web浏览器SSO配置文件。
SAML中描述了以下协议:
- SSO配置文件
- Web浏览器SSO配置文件
- 增强的客户端或代理(ECP)配置文件
- 身份提供者发现配置文件
- 单点登出配置文件
- 命名身份管理配置文件
- 组件解决配置文件
- 断言查询/请求配置文件
- 命名身份映射配置文件
- SAML属性配置文件
我们用什么
在登录工作流中,我们使用“网络浏览器单点登录配置文件”,支持的绑定是“HTTP重定向(GET)绑定”(移动)、“HTTP POST绑定”(网络)。
在登出工作流中,我们使用“单点登出配置文件”,支持的绑定是“HTTP重定向(GET)绑定”、“HTTP POST绑定”。
[1] https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language
[2] https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language
元数据
SAML元数据是在系统实体之间自动协商协议所需的配置数据,包括标识符、绑定支持和端点、证书、密钥、加密功能以及安全和隐私策略。一些SAML规范标准化了元数据结构和内容,从而支持适用于可销售部署的高效管理流程。
随着SAML规范的不断发展,有多个文档都包含元数据相关规范。这份非规范性文件提供了综合概述以及规范性规范的链接。[1]
[1] https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf
必须在Indeavor中启用SSO,元数据端点才可用。
ADFS配置
端点
Indeavor专业提示:必须在域中启用SSO,才能使用元数据链接。
Web
元数据和端点
URL:https://identity.[ENVIROMENTNAME].indeavor.com/saml/metadata.xml
说明:返回服务提供者元数据(请参阅Saml描述/元数据)。如果没有为请求的域启用SAML提供者,端点会返回404。
断言使用者处理程序
说明:接受来自服务提供者的断言响应的端点。实现对给定断言的验证,从配置的属性中提取用户名,如果是有效的Indeavor用户,则允许该用户登录。
单点登出服务
说明:接受来自服务提供者的登出请求/响应的端点。实现对给定请求/响应的验证,并允许Indeavor用户登出。
Saml登录页面
说明:通过SAML身份提供者实现登录的页面。用户填写域名输入,应用程序找到正确的服务提供者,创建身份验证请求并将用户重定向至身份提供者的SingleSignOnService。
Indeavor配置
添加Indeavor凭证以加密/签署Saml请求
- 创建包含SAML凭证的文件,该文件应通过应用程序来访问
- 将文件路径添加到Data/Config/SamlSSO.config <samlSSOSettings certificate="certificate path" password="file password" />
在安全连接(HTTPS)下运行应用程序,Saml提供者要求使用HTTPS
在系统级别设置元数据和UID模式
https://support.workloud.com/hc/en-us/articles/115001794466
为单点登录创建用户配置文件
https://support.workloud.com/hc/en-us/articles/115001796366
有何期待
XML
身份提供者元数据
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://idp.cloudroll.gr">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
...
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
...
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.cloudroll.gr/idp/SingleLogoutService" index="0" isDefault="false"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.cloudroll.gr/idp/SSOService" index="0" isDefault="false"/>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
entityID:身份提供者唯一标识符。
IDPSSODescriptor:包含IdP信息。
KeyDescriptor:实体用于响应签名和加密的密钥。
NameIDFormat:用户唯一标识符的格式。
SingleSignOnService:使用SSO的URL。
SingleLogoutService:使用SLO的URL。
Location:绑定的URL。
Binding:绑定响应的类型。
index:绑定的索引。
isDefault:是否为此进程的默认绑定服务
服务提供者元数据
<md:EntityDescriptor entityID="https://sp.cloudroll.gr" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui">
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
...
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
...
</md:KeyDescriptor>
<md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://sp.cloudroll.gr/Artifact/SOAP" index="1" isDefault="false"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://sp.cloudroll.gr/SLO/SOAP" />
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sp.cloudroll.gr/SLO/POST" />
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sp.cloudroll.gr/SAML2/POST" index="1" />
</md:SPSSODescriptor>
</md:EntityDescriptor>
entityID:身份提供者唯一标识符。
SPSSODescriptor:包含SP信息。
KeyDescriptor:实体用于响应签名和加密的密钥。
NameIDFormat:用户唯一标识符的格式。
SingleSignOnService:使用SSO的URL。
SingleLogoutService:使用SLO的URL。
Location:绑定的URL。
Binding:绑定响应的类型。
index:绑定的索引。
isDefault:是否为此进程的默认绑定服务
身份验证请求
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="…"
Version="2.0"
IssueInstant="2015-01-31T06:00:00"
AssertionConsumerServiceIndex="0"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
<saml:Issuer>www.workloud.com</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...</ds:Signature>
</samlp:AuthnRequest>
ID:身份验证请求的标识符。
Issuer:签发人(SP)的标识符。
Signature:用于检查请求有效性的签发人签名(如果xml已签名)。
AssertionConsumerServiceIndex:IDP在用户身份识别后返回断言的URL。
AssertionConsumerServiceURL:IDP在用户身份识别后返回断言的URL。
ProtocolBinding:应返回断言的响应类型。
断言
下面是一个断言示例
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" IssueInstant="2015-01-31T12:00:00Z">
<saml:Issuer>www.workloud.com</saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"> cloudroll@example.com</saml:NameID>
</saml:Subject>
<saml:Conditions NotBefore="2015-01-31T12:00:00Z" NotOnOrAfter="2015-01-31T12:00:00Z"> </saml:Conditions>
<saml:AuthnStatement
AuthnInstant="2004-12-05T09:22:00"
SessionIndex="b07b804c-7c29-ea16-7300-4f3d6f7928ac">
<saml:AuthnContext>
<saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" FriendlyName="eduPersonAffiliation">
<saml:AttributeValue>admin</saml:AttributeValue>
</saml:Attribute> </saml:AttributeStatement>
</saml:Assertion>
断言包括:
Issuer:签发人(Idp)的标识符。
Signature:用于检查请求有效性的签发人签名(xml已签名时)。
Subject:用户标识符。
AuthnStatement:描述用户身份的声明。
Conditions:描述断言有效的条件。
AuthnInstant:断言发出的时刻。
SessionIndex:IdP标识用户的会话索引。
AuthnContext:IdP中用于标识用户的验证上下文
AttributeStatement:包括用户属性
Name:属性的名称
FriendlyName:属性的友好名称。
LogoutRequest
<samlp:LogoutRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="..."
Version="2.0" IssueInstant="2014-07-18T01:13:06Z"
Destination="www.workloud.com/SingleLogoutService">
<saml:Issuer>www.workloud. com </saml:Issuer>
<saml:NameID SPNameQualifier="www.workloud. com " Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">......</saml:NameID>
</samlp:LogoutRequest>
ID:身份验证请求的标识符。
Issuer:签发人(SP)的标识符。
Signature:用于检查请求有效性的签发人签名(如果xml已签名)。
IssueInstant:发出登出响应的时刻。
Destination:使用请求的Web服务。
InResponseTo:响应所属请求的标识符。
NameID:请求所属的用户标识符。
LogoutResponse
<samlp:LogoutResponse
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="...."
Version="2.0"
IssueInstant="2014-07-18T01:13:06Z"
Destination="www.workloud.gr/SingleLogoutService"
InResponseTo="...">
<saml:Issuer>www.workloud.gr</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
</samlp:LogoutResponse>
ID:身份验证请求的标识符。
Issuer:签发人(SP)的标识符。
Signature:用于检查请求有效性的签发人签名(如果xml已签名)。
IssueInstant:发出登出响应的时刻。
Destination:使用响应的Web服务。
InResponseTo:响应所属请求的标识符。
Status:响应的状态。
Web登录工作流
- 转到SAML登录页面
- 选择域并点击登录
- 应用程序会创建包含这些参数的自动提交表单
- RelayState是一个传给IDP的参数,应按原样传回给我们的SP,该参数保留了我们的SP所需的域名。
RelayState值示例:url=/Default.aspx&dmn=demo - SAMLRequest包含已编码的AuthnRequest Base-64。此值包含有关请求签发人的信息
- RelayState是一个传给IDP的参数,应按原样传回给我们的SP,该参数保留了我们的SP所需的域名。
- 用户重定向至服务提供者
- 提供者验证身份验证请求
- 提示用户登录
- 身份提供者使用用户信息发出断言
- 用户通过SAMLResponse和SAML请求的RelayState重定向到Indeavor断言使用者处理程序
- 断言使用者处理程序验证请求(签名、过期等)
- 提取断言属性的UserName
- 用户登录
移动登录工作流
- 用户转到登录视图
- 选择域并点击登录
- 应用程序会创建包含这些参数的URL
- RelayState是一个传给IDP的参数,应按原样传回给我们的SP,该参数保留了我们的SP所需的域名。
RelayState值示例:url=/Default.aspx&dmn=demo - SAMLRequest包含已编码的AuthnRequest Base-64。此值包含有关请求签发人的信息
- RelayState是一个传给IDP的参数,应按原样传回给我们的SP,该参数保留了我们的SP所需的域名。
- 移动应用会打开带有生成的URL的Web视图
- 用户重定向至服务提供者
- 提供者验证身份验证请求
- 提示用户登录
- 身份提供者使用用户信息发出断言
- 用户通过SAMLResponse和SAML请求的RelayState重定向到Indeavor断言使用者处理程序
- 断言使用者处理程序验证请求(签名、过期等)
- 提取断言属性的UserName
- 用户登录