安全断言标记语言 (SAML) 是一种基于 XML 的标记语言,用于在身份提供程序 (IdP) 和服务提供程序 (SP) 之间交换身份验证和授权信息。

SAML 身份验证

身份验证是验证用户身份的过程。这是为了确保授权/允许连接到系统的用户这样做。在过去几年里发生了重大转变,人们纷纷开始改用联合身份验证,即,将身份验证过程委托给身份提供程序以集中完成身份验证过程。SAML 是实现该目标的方法之一。

SAML 是旨在与任何系统互操作的标准化格式。由于您越来越依赖于托管的服务,SAML 对您的组织非常重要,因为它在 IdP 中提供单点身份验证。不会将凭据存储在多个不受信任的设备上,因为将使用 SAML 声明身份。另一个好处体现在用户体验上,因为用户无需记住多个凭据即可访问其应用程序。他们登录一次,即可使用一组凭据访问多个应用程序。它还减少了维护用于身份验证的硬件和软件以及在应用程序中添加身份验证机制的开销。

SAML 术语

客户端

尝试访问受保护资源的用户。

SP 和 IdP 之间的所有通信是通过客户端的浏览器完成的。

服务提供程序 (SP)

该实体托管保护的资源,并在授予客户端访问资源的权限之前从身份提供程序请求身份验证信息。

身份提供程序 (IdP)

这是一个受信任的实体,它验证客户端身份并向 SP 提供身份验证服务。

断言

在 IdP 和 SP 之间交换的 XML 消息。

SAML 请求

SP 传送到 IdP 以验证客户端身份的请求。

SAML 响应

IdP 传送到 SP 的断言,其中包含有关客户端的信息。

断言使用者服务 (ACS)

这是 SP 中的一种 HTTP 资源,它处理 SAML 协议消息,并返回一个 Cookie 以表示从消息中提取的信息。IdP 将 SAML 响应断言发送到 ACS。

实体 ID

必须在 IdP 和 SP 中保持一致的唯一字符串。

元数据

用于置备 SP 或 IdP 以相互通信的配置数据。SAML 2.0 提供了一种明确定义且可互操作的元数据格式,实体可以使用该格式以启动信任过程。

SAML 进程

有两种类型的 SAML 进程:

IdP 启动的 SSO:

客户端连接到身份提供程序,进行身份验证,然后访问服务提供程序中的资源。

SP 启动的 SSO:

客户端连接到服务提供程序,该提供程序随后将客户端重定向到身份提供程序以进行身份验证。在成功进行身份验证后,客户端将重定向到服务提供程序以允许访问资源。

注:

NSX Advanced Load Balancer 仅支持 SP 启动的 SSO,并由 NSX Advanced Load Balancer 虚拟服务充当服务提供程序。

SAML 绑定

IdP 和 SP 通过客户端相互交换 SAML 请求和 SAML 响应。传输这些消息的方法称为 SAML 绑定。SAML 支持多种绑定。

充当服务提供程序的 NSX Advanced Load Balancer 虚拟服务支持:

  • 重定向绑定以将客户端重定向到 IdP。将直接在 HTTP GET 请求的 URL 查询字符串中传输 SAML 请求。

  • POST 绑定以将响应发送到 SP。SAML 响应是使用 Base64 编码的内容在 HTML 表单中传输的。

SAML 断言

SAML 断言是 IdP 发送到 SP 的 XML 文档,其中包含用户信息。在 SAML 断言中具有三种不同类型的声明:

身份验证:

证明用户的身份。

属性断言:

将 SAML 属性作为断言的一部分传送到 SP 以提供有关用户的信息。

授权断言:

提供 SP 信息,以通过该信息了解是否授权用户使用服务。

NSX Advanced Load Balancer 虚拟服务作为服务提供程序的客户端的 SAML 身份验证



请求流程如下所述:

  • 用户尝试访问 NSX Advanced Load Balancer 上托管的资源,即,NSX Advanced Load Balancer 充当服务提供程序:GET https://sales.avi.com/。

  • 如果尚未验证用户身份,则 NSX Advanced Load Balancer 生成 SAML 请求,并将用户重定向到身份提供程序 SSO 服务以使用 302 重定向进行身份验证。

  • 客户端的浏览器向 IdP 的 SSO 服务发送 GET 请求。将直接在 HTTP GET 请求的 URL 查询字符串中包含 SAML 请求。

    示例:

    https://idp.example.com/app/avinetworks_samlapp_1/exkfop30u1uCi2FEv0h7/sso/saml?SAMLRequest=fZJfb4IwFMW%2FCum7UBRFGyVB0cxkf8gke9iL6aDMRmhrb8Ht26%2FgYtzDfD33nJz7u%2B0caF0pEjfmIF7ZqWFgnK%2B6EkD6wQI1WhBJgQMRtGZATE528dMjGbqYKC2NzGWFbiL3ExSAacOlQM42WaD9OIzH%2FjoI%2FHC9Ccc4CKbxJJ6Es1kwXo6SYYKcN6bB%2BhfIxm0IoGFbAYYKYyXszwZ4OMBh5k8JxmQUvCMnsQxcUNOnDsYoIJ5HWy6YOUt9BFceDVWatZyd3VzWHlXqdr7vMMpTIaw%2B2vse%2BzqWUo1w4zcrPtysW3wIPQDpdT7kbKTOWX%2B%2FBSppBazbMrWgvGVXJf291JKLgovP%2B0f6uJiAPGRZOkhfdhmK5l0Z6fF11EFZpk4yFtaltr0nATX3bo3zy%2Bs%2B24ptksqK59%2FdvjU1%2F2%2Fgu36v8GJQ9lbSCFAs5yVnBXLiqpLnlWbUXOm86NL69xtFPw%3D%3D

  • IdP 向用户提供一个表单以输入凭据,除非他们已通过同一浏览器中的以前会话在 IdP 中进行了身份验证。在验证凭据后,将在 IdP 级别对用户进行身份验证。

  • 在任一情况下,IdP 中的 SSO 服务在成功验证身份后返回一个 XHTML 文档,它在 SAML 响应参数中包含 SP 所需的信息。SAML 响应将:

    • 表明它确实来自受信任的 IdP 并且没有被更改。

    • 表明用户成功在 IdP 中进行了身份验证。

    • 通过名称 ID(SAML 断言中使用的一个标准属性)表明用户是谁。

  • 使用 POST 请求将 SAML 响应参数从客户端传送到 NSX Advanced Load Balancer ACS 服务。

  • NSX Advanced Load Balancer 验证断言并为客户端设置 Cookie。

  • 客户端发送 GET 请求以使用 SP 提供的 Cookie 访问资源。

  • 客户端现在可以请求资源。

示例元数据

在下面的示例中,IdP 公钥放在 <ds:X509Certificate> and </ds:X509Certificate> 之间。

<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
 entityID="https://app.onelogin.com/saml/metadata/48171389-531f-4d3f-b9e3-9d44abb23ee8">
    <IDPSSODescriptor xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
	protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
       <KeyDescriptor use="signing">
         <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:X509Data>
               <ds:X509Certificate>
                 MIID6zCCAtOgAwIBAgIUJMCbFE2bd/6sCjz7gZr8AJXM6vswDQYJKoZIhvcNAQEF
			     BQAwSjEVMBMGA1UECgwMQXZpIG5ldHdvcmtzMRUwEwYDVQQLDAxPbmVMb2dpbiBJ
			     ZFAxGjAYBgNVBAMMEU9uZUxvZ2luIEFjY291bnQgMB4XDTE4MDkyNDEyMjE0NVoX
			     DTIzMDkyNDEyMjE0NVowSjEVMBMGA1UECgwMQXZpIG5ldHdvcmtzMRUwEwYDVQQL
			     DAxPbmVMb2dpbiBJZFAxGjAYBgNVBAMMEU9uZUxvZ2luIEFjY291bnQgMIIBIjAN
			     BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApOIRYePmMm+LMxgvh4PQWxhBtwzf 
			     KPbFj2LUcVZQsNHDwZp7s1b+htv3DZ6OY7yJ1Judu6BcVGJMyTRlb3eZ++5YjRyX
			     Zmabg4RQf1lBYfcdqmrIG5fMKoM9OWqQ7aRJb/KYtj/YymK0/Im3dFB7ioGkvSP0
			     b2Q5sle0HJnnpFih0LQjX0x6HaGBYvlF5tyrdKtUVXM7fLevwW0h0bB2LOhzKbgq
			     paDn/yH0zGoGdHH3MA7C6s1Wdy2YqKxf6BVDNjzor0oOstdkkKT2IBpnqI56W5xJ
			     w4rms2H6umk4G3zqKI4IWKPzQ7tPqZpsI+9zeitELOiOuyLbTO//YxRlbQIDAQAB
			     o4HIMIHFMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFP0c2czccqKP14DFa+NHeTni
			     3ewfMIGFBgNVHSMEfjB8gBT9HNnM3HKij9eAxWvjR3k54t3sH6FOpEwwSjEVMBMG
			     A1UECgwMQXZpIG5ldHdvcmtzMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxGjAYBgNV
			     BAMMEU9uZUxvZ2luIEFjY291bnQgghQkwJsUTZt3/qwKPPuBmvwAlczq+zAOBgNV
			     HQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQEFBQADggEBAKQQt1Goo3zeyAtjWkfxW9A8
			     o1ydzAqq7u779z9OsutbHsixy525Cs62Na/252CG39yk0Uy69ar+V9gBeBLaKNaz
			     w4JbaweFQgHlCVmT4lGEe1kmnsPwgP7nLq2SvkwTYqpcVq5KE+UfRpTixA/KJ61C
			     6yV03UCM7/T9NZ1pw/oYaweuxbtOn7rXT/NTiPIm7owA4soegDBEXIZ20KuMAkGc
			     dRAi5zoIqHsm7w/v/MT8DhTtZE2sH2mSegjUj8DOH5AcxdlNpp6VI2NApi+lTpEf
			     rqnQoDKs3BPp6SwcIvNqmSZ+R3eZkyGeJuCK4sxj2Od1plRpYihaRe32sNNjnwM=
               </ds:X509Certificate>
            </ds:X509Data>
         </ds:KeyInfo>
      </KeyDescriptor>
      <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
	  Location="https://avi-networks-test-dev.onelogin.com/trust/saml2/http-redirect/slo/869509"/>
      <NameIDFormat>
        urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
      </NameIDFormat>
      <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
	  Location="https://avi-networks-test-dev.onelogin.com/trust/saml2/http-redirect/sso/869509"/>
      <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
	  Location="https://avi-networks-test-dev.onelogin.com/trust/saml2/http-post/sso/869509"/>
      <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
	  Location="https://avi-networks-test-dev.onelogin.com/trust/saml2/soap/sso/869509"/>
   </IDPSSODescriptor>
</EntityDescriptor>john-doe

示例 SAML 请求

SP 发出该命令以隐式请求包含身份验证声明的断言。

<samlp:AuthnRequest
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
    ID="_B28D3D30B4D077D88FA2C7BF64CC0F8B" 
    Version="2.0" 
    IssueInstant="2018-12-13T11:31:59Z" 
    Destination="https://avi-networks-test-dev.onelogin.com/trust/saml2/http-redirect/sso/860690"
    ForceAuthn="false" 
    IsPassive="false" 
    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
    <saml:Issuer>avi-saml-vs</saml:Issuer>
    <samlp:NameIDPolicy 
        Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" 
        AllowCreate="false"/>
</samlp:AuthnRequest>

示例 SAML 响应

在下面的示例中查找带有说明文本的箭头 <-:

<samlp:Response 
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
    ID="R5e5c1b3cff12759e78f27c723a99963acf94fff5" 
    Version="2.0" 
    IssueInstant="2018-12-13T11:32:00Z" 
    Destination="http:/test-onelogin.auth.com/sso/acs/" 
    InResponseTo="_B28D3D30B4D077D88FA2C7BF64CC0F8B">
    <saml:Issuer>https://app.onelogin.com/saml/metadata/4e4332e8-be0f-4650-9bac-2ea85fa16d12</saml:Issuer>
    samlp:Status>
        <samlp:StatusCode 
            Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </samlp:Status>
    <saml:Assertion   <-- Beginning of SAML assertion. Within assertion there can be kinds of statements: authentication statement, authorization statement and attribute statement.
        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        Version="2.0" 
        ID="pfx01cfd769-cd0d-f4dd-677c-f24b1ff887ef" 
        IssueInstant="2018-12-13T11:32:00Z">
        <saml:Issuer>https://app.onelogin.com/saml/metadata/4e4332e8-be0f-4650-9bac-2ea85fa16d12</saml:Issuer>  <-- The element which contains the identity provider's unique identifier
        <ds:Signature   <-- This shows that this is a signed assertion.
            xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod 
                    Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                <ds:SignatureMethod 
                    Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <ds:Reference 
                    URI="#pfx01cfd769-cd0d-f4dd-677c-f24b1ff887ef">
                    <ds:Transforms>
                        <ds:Transform 
                            Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                        <ds:Transform 
                            Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    </ds:Transforms>
                    <ds:DigestMethod 
                        Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                    <ds:DigestValue>
                        3fAOHPB8meQtrDlQIRz5gRzUAJs=
                    </ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            The below SignatureValue contains an integrity-preserving digital signature.
            ds:SignatureValue>aVpr6bjhsHW+SkkN5Fb0IMqZCBbfqucF12EhS+pO0ZrZM8qQ5LqOvNF9MY1WzO3tTscyYwsP3gScBaZzm0KHHIn/OyXj77nqT+BNBiDij7tyXfg4RvMYH6o7R36yRR8Bop9HeJ66fgRNkKA4j54sXF7BQXM+I7FFC5bT9GzXnEi47towME3kHAUlrggt+/GfA6z8Jot13a6xCmrnMaKDVOJbHqcO5LuK2zFd4VQYmpuB+0T6az19S/Hmyc89auI/dw/9uyOAC5on9b+3brKWzK1Qke54ZbQMU/
                N3BNE8fwBAYIki5j6lnw0Txzun8EsW8UosSlh1tXlSwRhA76Wwng==
            </ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>                          <ds:X509Certificate>MIID6zCCAtOgAwIBAgIUJMCbFE2bd/6sCjz7gZr8AJXM6vswDQYJKoZIhvcNAQEFBQAwSjEVMBMGA1UECgwMQXZpIG5ldHdvcmtzMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxGjAYBgNVBAMMEU9uZUxvZ2luIEFjY291bnQgMB4XDTE4MDkyNDEyMjE0NVoXDTIzMDkyNDEyMjE0NVowSjEVMBMGA1UECgwMQXZpIG5ldHdvcmtzMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxGjAYBgNVBAMMEU9uZUxvZ2luIEFjY291bnQgMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApOIRYePmMm+LMxgvh4PQWxhBtwzfKPbFj2LUcVZQsNHDwZp7s1b+htv3DZ6OY7yJ1Judu6BcVGJMyTRlb3eZ++5YjRyXZmabg4RQf1lBYfcdqmrIG5fMKoM9OWqQ7aRJb/KYtj/YymK0/Im3dFB7ioGkvSP0b2Q5sle0HJnnpFih0LQjX0x6HaGBYvlF5tyrdKtUVXM7fLevwW0h0bB2LOhzKbgqpaDn/yH0zGoGdHH3MA7C6s1Wdy2YqKxf6BVDNjzor0oOstdkkKT2IBpnqI56W5xJw4rms2H6umk4G3zqKI4IWKPzQ7tPqZpsI+9zeitELOiOuyLbTO//YxRlbQIDAQABo4HIMIHFMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFP0c2czccqKP14DFa+NHeTni3ewfMIGFBgNVHSMEfjB8gBT9HNnM3HKij9eAxWvjR3k54t3sH6FOpEwwSjEVMBMGA1UECgwMQXZpIG5ldHdvcmtzMRUwEwYDVQQLDAxPbmVMb2dpbiBJZFAxGjAYBgNVBAMMEU9uZUxvZ2luIEFjY291bnQgghQkwJsUTZt3/qwKPPuBmvwAlczq+zAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQEFBQADggEBAKQQt1Goo3zeyAtjWkfxW9A8o1ydzAqq7u779z9OsutbHsixy525Cs62Na/252CG39yk0Uy69ar+V9gBeBLaKNazw4JbaweFQgHlCVmT4lGEe1kmnsPwgP7nLq2SvkwTYqpcVq5KE+UfRpTixA/KJ61C6yV03UCM7/T9NZ1pw/oYaweuxbtOn7rXT/NTiPIm7owA4soegDBEXIZ20KuMAkGcdRAi5zoIqHsm7w/v/MT8DhTtZE2sH2mSegjUj8DOH5AcxdlNpp6VI2NApi+lTpEfrqnQoDKs3BPp6SwcIvNqmSZ+
                        R3eZkyGeJuCK4sxj2Od1plRpYihaRe32sNNjnwM=
                    </ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>
        <saml:Subject>
            <saml:NameID  <-- A standard attribute used in SAML assertions
                Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">[email protected]
            </saml:NameID>
            <saml:SubjectConfirmation 
                Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData 
                    NotOnOrAfter="2018-12-13T11:35:00Z" 
                    Recipient="http:/test-onelogin.auth.com/sso/acs/" 
                    InResponseTo="_B28D3D30B4D077D88FA2C7BF64CC0F8B"/>
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions 
            NotBefore="2018-12-13T11:29:00Z" 
            NotOnOrAfter="2018-12-13T11:35:00Z">
            <saml:AudienceRestriction>
                <saml:Audience>jenkins-saml-vs</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement  <-- marks the beginning of authentication statement, which says the principal identified in the <saml:Subject> element was authenticated at "2018-12-13T11:31:59Z" by means of a password sent over a protected channel.
            AuthnInstant="2018-12-13T11:31:59Z" 
            SessionNotOnOrAfter="2018-12-14T11:32:00Z" 
            SessionIndex="_a16c6df0-e0f8-0136-f6b8-5b63382161ef">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>     <-- End of authentication statement
        <saml:AttributeStatement>  <-- Beginning of attribute statement
            <saml:Attribute 
                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" 
                Name="User.email">
                <saml:AttributeValue 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:type="xs:string">[email protected]
                </saml:AttributeValue>
            </saml:Attribute>
            <saml:Attribute 
                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" 
                Name="User.FirstName">
                <saml:AttributeValue 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:type="xs:string">Mittali
                </saml:AttributeValue>
            </saml:Attribute>
            <saml:Attribute 
                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" 
                Name="PersonImmutableID">
                <saml:AttributeValue 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:type="xs:string"/>
            </saml:Attribute>
            <saml:Attribute 
                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" 
                Name="User.LastName">
                <saml:AttributeValue 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:type="xs:string">Chawla
                </saml:AttributeValue>
            </saml:Attribute>
            <saml:Attribute 
                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" 
                Name="memberOf">
                <saml:AttributeValue 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:type="xs:string"/>
            </saml:Attribute>
        </saml:AttributeStatement>   <-- End of attribute statement
    </saml:Assertion>                <-- End of assertion
</samlp:Response>                    <-- End of SAML response