fleet/server/sso/authorization_response_test.go
Roberto Dip 78cc59e690
lowercase DisplayName attributes when reading SSO response (#12545)
this is to accommodate providers like [Okta][1] that send the user's
full name as an attribute named `displayName`

[1]:
https://developer.okta.com/docs/reference/api/users/#default-profile-properties
2023-06-28 12:19:13 -03:00

648 lines
40 KiB
Go

package sso
import (
"fmt"
"testing"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDecodeSuccessfulSalesforceResponse(t *testing.T) {
const samlResponse = `<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost:8080/api/v1/kolide/sso/callback" ID="_52f2515c5319f2adf3f072d9d9f2b6881493305396746" InResponseTo="4982b430-73e1-4ad2-885a-4a775a91f820" IssueInstant="2017-04-27T15:03:16.747Z" Version="2.0">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://kolide-dev-ed.my.salesforce.com</saml:Issuer>
<ds:Signature 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="#_52f2515c5319f2adf3f072d9d9f2b6881493305396746">
<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#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml samlp xs xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>syKA9xe4vLJ+W1WxYrTDV8gjXdc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
SHXNEnRlRmTOpgfAtS14VNwAFmzR8u23rLNcr/K8Oh5e3l9LTtbL9QtvLsyYNUFoizDs4fbHfyBH
DcBD3zCEXFVnvS+3TA3SpUMH+4usdTsLkRhS1K5Ira/MK/aumR43IdMFilMcecF8J4YAblRtJIyh
KvSd1VKukUoTDv7YOMEwco4hxzL+gVrE9HzHfAv/fSyxOMXohEHLPO8QedBsX4ZKIr4ZuOPuViiJ
Au+01A8AO01gbZWuXmTKmI/WDH66tBQUcPRF2RBWwvzirpY86N4Sdv58VLdM5IMa/hhvLHMOHlGM
+kERr7KqLhMNFTTw9VnoybBmniR0ioAg2lwpZA==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIErDCCA5SgAwIBAgIOAVuhH3WkAAAAAB5NpvIwDQYJKoZIhvcNAQELBQAwgZAxKDAmBgNVBAMM
H1NlbGZTaWduZWRDZXJ0XzI0QXByMjAxN18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0
ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNV
BAgMAkNBMQwwCgYDVQQGEwNVU0EwHhcNMTcwNDI0MTgwMDQ1WhcNMTgwNDI0MTIwMDAwWjCBkDEo
MCYGA1UEAwwfU2VsZlNpZ25lZENlcnRfMjRBcHIyMDE3XzE4MDA0NDEYMBYGA1UECwwPMDBENkEw
MDAwMDAxN3Q4MRcwFQYDVQQKDA5TYWxlc2ZvcmNlLmNvbTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNj
bzELMAkGA1UECAwCQ0ExDDAKBgNVBAYTA1VTQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAIOR7h8BF2eFOlQHhV/1S7uOBN22Jv7PDCXMz2fU0uLc+mrv9xDGj6ElfW+9dSdXaCbQzD3+
Xq4reS4pYRafJZ/27OtygXl3rpoPjSlhRiW+oYVuDcCURJpu0KuZ4I0fm5q1BDYqxcBxNPSe85OH
E3+ucmKqvPozhQgYLPCregMIomC3yyANZnLCoGfCv9TpQl6/+I182tST4WPNhVPxKxijoPU4Rh6x
Y34Ez8+Jr8KdmzmYSNe4ukkIASplpvG7rKka824Hf8zI1BWnjWLDxb5IAxgUBbdr4x8d8C3kPfTf
+3/6yC5wSOm9NSs0BA4OJNowtXZFryMzFfXzDzjl69kCAwEAAaOCAQAwgf0wHQYDVR0OBBYEFO+D
koP6qkysi9ZC74yTPuJVVg2yMA8GA1UdEwEB/wQFMAMBAf8wgcoGA1UdIwSBwjCBv4AU74OSg/qq
TKyL1kLvjJM+4lVWDbKhgZakgZMwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzI0QXByMjAx
N18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5j
b20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0GCDgFb
oR91pAAAAAAeTabyMA0GCSqGSIb3DQEBCwUAA4IBAQAVhYBv5GJvhltks2j7Zc9wdFHW7yB4/hPF
o05y0yiOf71tLjOlBucSyxtmXLPjrECJvIJwKhsAIgYXnVp7ditxfauCcxczJgfeL1/dxH/Ge8eP
kmH6SdsO71cJL8dXEzOsoF+PAVQzUhqh8zxIipntL0wwNGTD0zIVQeTSozm0KF0SsSHIfbNy279u
ReGonC61i4Ouk5AMKA7Re9fVeUs6tqM2at22h9Zaj/r/OhXoDcZhzkd8Wq0ER/UKLZA1CyJHgwOC
7REEZOuKrqgfWcYt4dGo5q6gqGHHPMv0N7s/MxqCvJCwGA8eJGvOO56I321vhWHQ6ZSJDWUqQFM/
Ze7A</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_9ffad90ab367f32a52b749d5c4b2b7df1493305396749" IssueInstant="2017-04-27T15:03:16.749Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://kolide-dev-ed.my.salesforce.com</saml:Issuer>
<ds:Signature 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="#_9ffad90ab367f32a52b749d5c4b2b7df1493305396749">
<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#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml xs xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>BOhmqkd//KYBmBJIZfUqgEx6iLc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
UaSyePoQdNc8ApcL7Ak7NhWuZY9ilmqbJDbkIFjfYoikPWpiqq0Z5DHxPVCHgRi42KC9oclXPjWh
v8acBZrMZlqn0yVaEeVwozcKYGwxh7mhnWnU2zrd4hnnfDZbwyU3pchUVNXyndPmfwnRR8wBDcID
+/uL10u6zBzGbtzvx1rG33Od8f4h+RDDOTRVX1iVKw5pbnvjrrYcY1gqI5OQKBoki1X6LhZE4qk5
77DG3U9Z3qut2GTYzupRp9nszbOv1l0jXuavy+94zZ3K3oqeLNH3ZW1fB8XG8b3nX9rFEYzto5CQ
SSQaUypAljmg9XrmfVoljUDpabRWKWi0eiEvxQ==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIErDCCA5SgAwIBAgIOAVuhH3WkAAAAAB5NpvIwDQYJKoZIhvcNAQELBQAwgZAxKDAmBgNVBAMM
H1NlbGZTaWduZWRDZXJ0XzI0QXByMjAxN18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0
ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNV
BAgMAkNBMQwwCgYDVQQGEwNVU0EwHhcNMTcwNDI0MTgwMDQ1WhcNMTgwNDI0MTIwMDAwWjCBkDEo
MCYGA1UEAwwfU2VsZlNpZ25lZENlcnRfMjRBcHIyMDE3XzE4MDA0NDEYMBYGA1UECwwPMDBENkEw
MDAwMDAxN3Q4MRcwFQYDVQQKDA5TYWxlc2ZvcmNlLmNvbTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNj
bzELMAkGA1UECAwCQ0ExDDAKBgNVBAYTA1VTQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAIOR7h8BF2eFOlQHhV/1S7uOBN22Jv7PDCXMz2fU0uLc+mrv9xDGj6ElfW+9dSdXaCbQzD3+
Xq4reS4pYRafJZ/27OtygXl3rpoPjSlhRiW+oYVuDcCURJpu0KuZ4I0fm5q1BDYqxcBxNPSe85OH
E3+ucmKqvPozhQgYLPCregMIomC3yyANZnLCoGfCv9TpQl6/+I182tST4WPNhVPxKxijoPU4Rh6x
Y34Ez8+Jr8KdmzmYSNe4ukkIASplpvG7rKka824Hf8zI1BWnjWLDxb5IAxgUBbdr4x8d8C3kPfTf
+3/6yC5wSOm9NSs0BA4OJNowtXZFryMzFfXzDzjl69kCAwEAAaOCAQAwgf0wHQYDVR0OBBYEFO+D
koP6qkysi9ZC74yTPuJVVg2yMA8GA1UdEwEB/wQFMAMBAf8wgcoGA1UdIwSBwjCBv4AU74OSg/qq
TKyL1kLvjJM+4lVWDbKhgZakgZMwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzI0QXByMjAx
N18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5j
b20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0GCDgFb
oR91pAAAAAAeTabyMA0GCSqGSIb3DQEBCwUAA4IBAQAVhYBv5GJvhltks2j7Zc9wdFHW7yB4/hPF
o05y0yiOf71tLjOlBucSyxtmXLPjrECJvIJwKhsAIgYXnVp7ditxfauCcxczJgfeL1/dxH/Ge8eP
kmH6SdsO71cJL8dXEzOsoF+PAVQzUhqh8zxIipntL0wwNGTD0zIVQeTSozm0KF0SsSHIfbNy279u
ReGonC61i4Ouk5AMKA7Re9fVeUs6tqM2at22h9Zaj/r/OhXoDcZhzkd8Wq0ER/UKLZA1CyJHgwOC
7REEZOuKrqgfWcYt4dGo5q6gqGHHPMv0N7s/MxqCvJCwGA8eJGvOO56I321vhWHQ6ZSJDWUqQFM/
Ze7A</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">john@kolide.co</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="4982b430-73e1-4ad2-885a-4a775a91f820" NotOnOrAfter="2017-04-27T15:08:16.760Z" Recipient="https://localhost:8080/api/v1/kolide/sso/callback"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2017-04-27T15:02:46.760Z" NotOnOrAfter="2017-04-27T15:08:16.760Z">
<saml:AudienceRestriction>
<saml:Audience>kolide</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2017-04-27T15:03:16.750Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="userId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">0056A000000Q6Rl</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="username" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">john@kolide.co</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">john@kolide.co</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="is_portal_user" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">false</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>`
auth, err := decodeSAMLResponse([]byte(samlResponse))
require.Nil(t, err)
require.NotNil(t, auth)
info, ok := auth.(*resp)
require.True(t, ok)
status, err := info.status()
assert.Nil(t, err)
assert.Equal(t, Success, status)
assert.Equal(t, "john@kolide.co", auth.UserID())
assert.NotEmpty(t, auth.RequestID())
}
func TestDecodeWithCommentInName(t *testing.T) {
// Testing for vuln described at
// https://duo.com/blog/duo-finds-saml-vulnerabilities-affecting-multiple-implementations
// Relevant XML snippets:
// <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
// <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">john@kol<!---->ide.co</saml:NameID>
const samlResponse = `<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost:8080/api/v1/kolide/sso/callback" ID="_52f2515c5319f2adf3f072d9d9f2b6881493305396746" InResponseTo="4982b430-73e1-4ad2-885a-4a775a91f820" IssueInstant="2017-04-27T15:03:16.747Z" Version="2.0">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://kolide-dev-ed.my.salesforce.com</saml:Issuer>
<ds:Signature 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="#_52f2515c5319f2adf3f072d9d9f2b6881493305396746">
<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#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml samlp xs xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>syKA9xe4vLJ+W1WxYrTDV8gjXdc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
SHXNEnRlRmTOpgfAtS14VNwAFmzR8u23rLNcr/K8Oh5e3l9LTtbL9QtvLsyYNUFoizDs4fbHfyBH
DcBD3zCEXFVnvS+3TA3SpUMH+4usdTsLkRhS1K5Ira/MK/aumR43IdMFilMcecF8J4YAblRtJIyh
KvSd1VKukUoTDv7YOMEwco4hxzL+gVrE9HzHfAv/fSyxOMXohEHLPO8QedBsX4ZKIr4ZuOPuViiJ
Au+01A8AO01gbZWuXmTKmI/WDH66tBQUcPRF2RBWwvzirpY86N4Sdv58VLdM5IMa/hhvLHMOHlGM
+kERr7KqLhMNFTTw9VnoybBmniR0ioAg2lwpZA==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIErDCCA5SgAwIBAgIOAVuhH3WkAAAAAB5NpvIwDQYJKoZIhvcNAQELBQAwgZAxKDAmBgNVBAMM
H1NlbGZTaWduZWRDZXJ0XzI0QXByMjAxN18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0
ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNV
BAgMAkNBMQwwCgYDVQQGEwNVU0EwHhcNMTcwNDI0MTgwMDQ1WhcNMTgwNDI0MTIwMDAwWjCBkDEo
MCYGA1UEAwwfU2VsZlNpZ25lZENlcnRfMjRBcHIyMDE3XzE4MDA0NDEYMBYGA1UECwwPMDBENkEw
MDAwMDAxN3Q4MRcwFQYDVQQKDA5TYWxlc2ZvcmNlLmNvbTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNj
bzELMAkGA1UECAwCQ0ExDDAKBgNVBAYTA1VTQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAIOR7h8BF2eFOlQHhV/1S7uOBN22Jv7PDCXMz2fU0uLc+mrv9xDGj6ElfW+9dSdXaCbQzD3+
Xq4reS4pYRafJZ/27OtygXl3rpoPjSlhRiW+oYVuDcCURJpu0KuZ4I0fm5q1BDYqxcBxNPSe85OH
E3+ucmKqvPozhQgYLPCregMIomC3yyANZnLCoGfCv9TpQl6/+I182tST4WPNhVPxKxijoPU4Rh6x
Y34Ez8+Jr8KdmzmYSNe4ukkIASplpvG7rKka824Hf8zI1BWnjWLDxb5IAxgUBbdr4x8d8C3kPfTf
+3/6yC5wSOm9NSs0BA4OJNowtXZFryMzFfXzDzjl69kCAwEAAaOCAQAwgf0wHQYDVR0OBBYEFO+D
koP6qkysi9ZC74yTPuJVVg2yMA8GA1UdEwEB/wQFMAMBAf8wgcoGA1UdIwSBwjCBv4AU74OSg/qq
TKyL1kLvjJM+4lVWDbKhgZakgZMwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzI0QXByMjAx
N18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5j
b20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0GCDgFb
oR91pAAAAAAeTabyMA0GCSqGSIb3DQEBCwUAA4IBAQAVhYBv5GJvhltks2j7Zc9wdFHW7yB4/hPF
o05y0yiOf71tLjOlBucSyxtmXLPjrECJvIJwKhsAIgYXnVp7ditxfauCcxczJgfeL1/dxH/Ge8eP
kmH6SdsO71cJL8dXEzOsoF+PAVQzUhqh8zxIipntL0wwNGTD0zIVQeTSozm0KF0SsSHIfbNy279u
ReGonC61i4Ouk5AMKA7Re9fVeUs6tqM2at22h9Zaj/r/OhXoDcZhzkd8Wq0ER/UKLZA1CyJHgwOC
7REEZOuKrqgfWcYt4dGo5q6gqGHHPMv0N7s/MxqCvJCwGA8eJGvOO56I321vhWHQ6ZSJDWUqQFM/
Ze7A</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_9ffad90ab367f32a52b749d5c4b2b7df1493305396749" IssueInstant="2017-04-27T15:03:16.749Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://kolide-dev-ed.my.salesforce.com</saml:Issuer>
<ds:Signature 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="#_9ffad90ab367f32a52b749d5c4b2b7df1493305396749">
<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#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml xs xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>BOhmqkd//KYBmBJIZfUqgEx6iLc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
UaSyePoQdNc8ApcL7Ak7NhWuZY9ilmqbJDbkIFjfYoikPWpiqq0Z5DHxPVCHgRi42KC9oclXPjWh
v8acBZrMZlqn0yVaEeVwozcKYGwxh7mhnWnU2zrd4hnnfDZbwyU3pchUVNXyndPmfwnRR8wBDcID
+/uL10u6zBzGbtzvx1rG33Od8f4h+RDDOTRVX1iVKw5pbnvjrrYcY1gqI5OQKBoki1X6LhZE4qk5
77DG3U9Z3qut2GTYzupRp9nszbOv1l0jXuavy+94zZ3K3oqeLNH3ZW1fB8XG8b3nX9rFEYzto5CQ
SSQaUypAljmg9XrmfVoljUDpabRWKWi0eiEvxQ==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIErDCCA5SgAwIBAgIOAVuhH3WkAAAAAB5NpvIwDQYJKoZIhvcNAQELBQAwgZAxKDAmBgNVBAMM
H1NlbGZTaWduZWRDZXJ0XzI0QXByMjAxN18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0
ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNV
BAgMAkNBMQwwCgYDVQQGEwNVU0EwHhcNMTcwNDI0MTgwMDQ1WhcNMTgwNDI0MTIwMDAwWjCBkDEo
MCYGA1UEAwwfU2VsZlNpZ25lZENlcnRfMjRBcHIyMDE3XzE4MDA0NDEYMBYGA1UECwwPMDBENkEw
MDAwMDAxN3Q4MRcwFQYDVQQKDA5TYWxlc2ZvcmNlLmNvbTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNj
bzELMAkGA1UECAwCQ0ExDDAKBgNVBAYTA1VTQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAIOR7h8BF2eFOlQHhV/1S7uOBN22Jv7PDCXMz2fU0uLc+mrv9xDGj6ElfW+9dSdXaCbQzD3+
Xq4reS4pYRafJZ/27OtygXl3rpoPjSlhRiW+oYVuDcCURJpu0KuZ4I0fm5q1BDYqxcBxNPSe85OH
E3+ucmKqvPozhQgYLPCregMIomC3yyANZnLCoGfCv9TpQl6/+I182tST4WPNhVPxKxijoPU4Rh6x
Y34Ez8+Jr8KdmzmYSNe4ukkIASplpvG7rKka824Hf8zI1BWnjWLDxb5IAxgUBbdr4x8d8C3kPfTf
+3/6yC5wSOm9NSs0BA4OJNowtXZFryMzFfXzDzjl69kCAwEAAaOCAQAwgf0wHQYDVR0OBBYEFO+D
koP6qkysi9ZC74yTPuJVVg2yMA8GA1UdEwEB/wQFMAMBAf8wgcoGA1UdIwSBwjCBv4AU74OSg/qq
TKyL1kLvjJM+4lVWDbKhgZakgZMwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzI0QXByMjAx
N18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5j
b20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0GCDgFb
oR91pAAAAAAeTabyMA0GCSqGSIb3DQEBCwUAA4IBAQAVhYBv5GJvhltks2j7Zc9wdFHW7yB4/hPF
o05y0yiOf71tLjOlBucSyxtmXLPjrECJvIJwKhsAIgYXnVp7ditxfauCcxczJgfeL1/dxH/Ge8eP
kmH6SdsO71cJL8dXEzOsoF+PAVQzUhqh8zxIipntL0wwNGTD0zIVQeTSozm0KF0SsSHIfbNy279u
ReGonC61i4Ouk5AMKA7Re9fVeUs6tqM2at22h9Zaj/r/OhXoDcZhzkd8Wq0ER/UKLZA1CyJHgwOC
7REEZOuKrqgfWcYt4dGo5q6gqGHHPMv0N7s/MxqCvJCwGA8eJGvOO56I321vhWHQ6ZSJDWUqQFM/
Ze7A</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">john@kol<!---->ide.co</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="4982b430-73e1-4ad2-885a-4a775a91f820" NotOnOrAfter="2017-04-27T15:08:16.760Z" Recipient="https://localhost:8080/api/v1/kolide/sso/callback"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2017-04-27T15:02:46.760Z" NotOnOrAfter="2017-04-27T15:08:16.760Z">
<saml:AudienceRestriction>
<saml:Audience>kolide</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2017-04-27T15:03:16.750Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="userId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">0056A000000Q6Rl</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="username" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">john@kolide.co</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">john@kolide.co</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="is_portal_user" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">false</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>`
auth, err := decodeSAMLResponse([]byte(samlResponse))
require.Nil(t, err)
require.NotNil(t, auth)
info, ok := auth.(*resp)
require.True(t, ok)
status, err := info.status()
assert.Nil(t, err)
assert.Equal(t, Success, status)
assert.Equal(t, "john@kol<!---->ide.co", auth.UserID())
assert.NotEmpty(t, auth.RequestID())
}
func TestDecodeSuccessfulGoogleResponse(t *testing.T) {
const samlResponse = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost:8080/api/v1/kolide/sso/callback" ID="_83579a9008ef726f87c52aad4b6dcc04" InResponseTo="SGJhi1g5D4/npOwXaw8t6A==" IssueInstant="2017-07-18T14:47:08.035Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://accounts.google.com/o/saml2?idpid=C0171bstf</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_500061990acc00723288833a327cc986" IssueInstant="2017-07-18T14:47:08.035Z" Version="2.0">
<saml2:Issuer>https://accounts.google.com/o/saml2?idpid=C0171bstf</saml2:Issuer>
<ds:Signature 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/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_500061990acc00723288833a327cc986">
<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/2001/04/xmlenc#sha256"/>
<ds:DigestValue>nZmgK9XtjyT7sBApU0tyZbUE4WWMwCsDz8j6IZE5Ixw=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>DHdU+LnOX/u8Hujx+IpDmozt9u2ROD9UU2Ob5El0ZjEpAESqyY2Pj9Y4Kd01IsDTf/gFKJWOyVMz
PP3io5P4eiA96p+0g0YNuO6ickVF9BHAJyjET38C3pB95rgqUb7rLaD6XdfAXFQ7l2dalHS9yLa/
KBtT3f3ykYPb74NrAhihV8Z0gvPpyWqBDg23B76tIerWn26LooZkPNXPTGv/sy8ocY5oz56plKvZ
OmVdwpzwH7/7i/UEnNv6sis3/es0Omm5gxeKLP40vWb9lTm1HmvLTV3sZiHZQQmUwmfcsZL6gyVE
eaJNDQP4yOw+vXKdeyAlVC6jtt06MgY9V0zj5g==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509SubjectName>ST=California,C=US,OU=Google For Work,CN=Google,L=Mountain View,O=Google Inc.</ds:X509SubjectName>
<ds:X509Certificate>MIIDdDCCAlygAwIBAgIGAV1SKeijMA0GCSqGSIb3DQEBCwUAMHsxFDASBgNVBAoTC0dvb2dsZSBJ
bmMuMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQDEwZHb29nbGUxGDAWBgNVBAsTD0dv
b2dsZSBGb3IgV29yazELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEwHhcNMTcwNzE3
MjAwNzQzWhcNMjIwNzE2MjAwNzQzWjB7MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEWMBQGA1UEBxMN
TW91bnRhaW4gVmlldzEPMA0GA1UEAxMGR29vZ2xlMRgwFgYDVQQLEw9Hb29nbGUgRm9yIFdvcmsx
CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAzLXNn7VmJBkvVNYHffTzDoow/8eSklauVeYjhELY6dtFv56wAQsFNeMovFUPxPeG
7Fci50/KStvoNZOdKqZFCwYkfI2ssXuMpBP37x2iprV7moVwGdGJb52elMNe0DesgTPbJ/IWIvzF
3GYxqYCHUlHuzJEzBYsdtvM8T/PClBxiLXRNbnjotzleFqb25w3XRfayOZg5GdQPeEmceWXDBhCa
eQyEPOrUTZ+//pZXSuKnOyaFfESNFNgvQJlYQQukjnhPtf674eWT6OdgZHyq8EBbZKfEhs5+KiAN
U43bDh9rpTJCB7rAKk1BFAW3r72pggwN9Z/sfp/C5B7uKAM5hwIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQAZXypikbbRzichNXLdK96M/do9nGS5Q3xVgA2uxTzm/6qNkAfOSGSk8OcLrppPonbohkeZ
WVnNB5VZZava4DoSZ6OZsvKc1FM0wKvPJd83KUb7Syk1bV7TkT8DPEclfsLnn5s5g0oHlhsqkNly
0WPFTAoGHXYyOKGEARPoC/o+ZfgfvoMNyZkSQHiRboVVP2cT1ckJt4iCA65hNGXte29hSGmnX7QG
QyrBRp8n4UR9PjoeIy0tTCmG0tqu/NackFH4PkamY84Etxe9uH0StmkhID46QTT4Cv2+jqCaklg+
7VYqXbY64Wc/k0sK7WI1o3IVLWAPNb8ajV6Eo0Y8u+1N</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">john@edilok.net</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="SGJhi1g5D4/npOwXaw8t6A==" NotOnOrAfter="2017-07-18T14:52:08.035Z" Recipient="https://localhost:8080/api/v1/kolide/sso/callback"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2017-07-18T14:42:08.035Z" NotOnOrAfter="2017-07-18T14:52:08.035Z">
<saml2:AudienceRestriction>
<saml2:Audience>kolide.edilok.net</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AttributeStatement>
<saml2:Attribute Name="myattribute">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:anyType">john@edilok.net</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
<saml2:AuthnStatement AuthnInstant="2017-07-18T14:33:41.000Z" SessionIndex="_500061990acc00723288833a327cc986">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</saml2p:Response>`
auth, err := decodeSAMLResponse([]byte(samlResponse))
require.Nil(t, err)
require.NotNil(t, auth)
info, ok := auth.(*resp)
require.True(t, ok)
status, err := info.status()
assert.Nil(t, err)
assert.Equal(t, Success, status)
assert.Equal(t, "john@edilok.net", auth.UserID())
assert.NotEmpty(t, auth.RequestID())
}
func TestDecodeAttributes(t *testing.T) {
const samlResponse = `<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_8419c6009d891c39b454f53b34454818bdab19bd3a" Version="2.0" IssueInstant="2022-08-10T19:42:34Z" Destination="https://localhost:8080/api/v1/fleet/sso/callback" InResponseTo="idJpL4A6IM6MMBQ9eH">
<saml:Issuer>http://localhost:9080/simplesaml/saml2/idp/metadata.php</saml:Issuer>
<ds:Signature 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/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_8419c6009d891c39b454f53b34454818bdab19bd3a">
<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/2001/04/xmlenc#sha256"/>
<ds:DigestValue>HtQ1uTkyzTwwNZ6XJQT8ROuQsfaw99TiQktm2EhKPWk=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>EawypjAfab8xnhmF994nIq8oSqd/DenA4HGj7A85MRlAGa5W3fftFwmovXPhbGZeDZsQtAGssnvtJgZ7FEraWF9oYGxqdZQZ2Oethx6uKxaryxKmp22erd8ctd0JMMmK5vu2PFqLCoP2qFvmruM4ruYHbee5sl8EMWHJ/FExuq4bWoeAa08ZCYdJnPawO2AyIzJtAku2nXQwz1756VrV1mX7tenaADxqMexCJdyXSuDG1I1nXp/qnRIOjUbfsfIN0WkG8jY9MDdUUi8ah0UYgdv2kQn1d/FYoI1/AuPXRl72QLtN4jFbg0ZZJAX5wtP66vvbC29cK6SN3h1ghSFFCg==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIDXTCCAkWgAwIBAgIJALmVVuDWu4NYMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTYxMjMxMTQzNDQ3WhcNNDgwNjI1MTQzNDQ3WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzUCFozgNb1h1M0jzNRSCjhOBnR+uVbVpaWfXYIR+AhWDdEe5ryY+CgavOg8bfLybyzFdehlYdDRgkedEB/GjG8aJw06l0qF4jDOAw0kEygWCu2mcH7XOxRt+YAH3TVHa/Hu1W3WjzkobqqqLQ8gkKWWM27fOgAZ6GieaJBN6VBSMMcPey3HWLBmc+TYJmv1dbaO2jHhKh8pfKw0W12VM8P1PIO8gv4Phu/uuJYieBWKixBEyy0lHjyixYFCR12xdh4CA47q958ZRGnnDUGFVE1QhgRacJCOZ9bd5t9mr8KLaVBYTCJo5ERE8jymab5dPqe5qKfJsCZiqWglbjUo9twIDAQABo1AwTjAdBgNVHQ4EFgQUxpuwcs/CYQOyui+r1G+3KxBNhxkwHwYDVR0jBBgwFoAUxpuwcs/CYQOyui+r1G+3KxBNhxkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAAiWUKs/2x/viNCKi3Y6blEuCtAGhzOOZ9EjrvJ8+COH3Rag3tVBWrcBZ3/uhhPq5gy9lqw4OkvEws99/5jFsX1FJ6MKBgqfuy7yh5s1YfM0ANHYczMmYpZeAcQf2CGAaVfwTTfSlzNLsF2lW/ly7yapFzlYSJLGoVE+OHEu8g5SlNACUEfkXw+5Eghh+KzlIN7R6Q7r2ixWNFBC/jWf7NKUfJyX8qIG5md1YUeT6GBW9Bm2/1/RiO24JTaYlfLdKK9TYb8sG5B+OLab2DImG99CJ25RkAcSobWNF5zD0O6lgOo3cEdB/ksCq3hmtlC/DlLZ/D8CJ+7VuZnS1rR2naQ==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_ec34771d0b777b553f5e0363dbbb36fc973e183f29" Version="2.0" IssueInstant="2022-08-10T19:42:34Z">
<saml:Issuer>http://localhost:9080/simplesaml/saml2/idp/metadata.php</saml:Issuer>
<ds:Signature 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/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_ec34771d0b777b553f5e0363dbbb36fc973e183f29">
<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/2001/04/xmlenc#sha256"/>
<ds:DigestValue>AuiXXRBMG03hyrsjxHQeaI82pfb6JQ/8FJMqu1zC46o=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>Tsjsa0xPER51uAOlM+smsX+kBkqy/0xXlFEohzdflfP6N0qtjEla/jOC9M5j1F+bfkjeP3Lo2cp5OvU2PeQRWpfp+CTfF1tZCuP+F/Du0n4wfKMAU6bjNhq8LYEjC/LbNIyLnDNxT33lZp9udBWPmXwe4U92jcCEY54Tnql7xdqh/ez7J1A3TjNbsbTc9D9NWD9ZG7QR8+GcNVAq5fOxcElxSFrgZJGhoUO+PPes4C9oiB44f6FTcEoKHD9gYycMB9kich1lguG0DO9v+daZZ9HQyeoUaF50W231TM2Iax1YGD3QLZg674X90HGG7YKuRIenocVCyZgljzS2tAeNog==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIDXTCCAkWgAwIBAgIJALmVVuDWu4NYMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTYxMjMxMTQzNDQ3WhcNNDgwNjI1MTQzNDQ3WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzUCFozgNb1h1M0jzNRSCjhOBnR+uVbVpaWfXYIR+AhWDdEe5ryY+CgavOg8bfLybyzFdehlYdDRgkedEB/GjG8aJw06l0qF4jDOAw0kEygWCu2mcH7XOxRt+YAH3TVHa/Hu1W3WjzkobqqqLQ8gkKWWM27fOgAZ6GieaJBN6VBSMMcPey3HWLBmc+TYJmv1dbaO2jHhKh8pfKw0W12VM8P1PIO8gv4Phu/uuJYieBWKixBEyy0lHjyixYFCR12xdh4CA47q958ZRGnnDUGFVE1QhgRacJCOZ9bd5t9mr8KLaVBYTCJo5ERE8jymab5dPqe5qKfJsCZiqWglbjUo9twIDAQABo1AwTjAdBgNVHQ4EFgQUxpuwcs/CYQOyui+r1G+3KxBNhxkwHwYDVR0jBBgwFoAUxpuwcs/CYQOyui+r1G+3KxBNhxkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAAiWUKs/2x/viNCKi3Y6blEuCtAGhzOOZ9EjrvJ8+COH3Rag3tVBWrcBZ3/uhhPq5gy9lqw4OkvEws99/5jFsX1FJ6MKBgqfuy7yh5s1YfM0ANHYczMmYpZeAcQf2CGAaVfwTTfSlzNLsF2lW/ly7yapFzlYSJLGoVE+OHEu8g5SlNACUEfkXw+5Eghh+KzlIN7R6Q7r2ixWNFBC/jWf7NKUfJyX8qIG5md1YUeT6GBW9Bm2/1/RiO24JTaYlfLdKK9TYb8sG5B+OLab2DImG99CJ25RkAcSobWNF5zD0O6lgOo3cEdB/ksCq3hmtlC/DlLZ/D8CJ+7VuZnS1rR2naQ==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID SPNameQualifier="https://localhost:8080" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">sso_user@example.com</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2022-08-10T19:47:34Z" Recipient="https://localhost:8080/api/v1/fleet/sso/callback" InResponseTo="idJpL4A6IM6MMBQ9eH"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2022-08-10T19:42:04Z" NotOnOrAfter="2022-08-10T19:47:34Z">
<saml:AudienceRestriction>
<saml:Audience>https://localhost:8080</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2022-08-10T19:42:34Z" SessionNotOnOrAfter="2022-08-11T03:42:34Z" SessionIndex="_4d73872e0cb05ec4ca29cc1c7ea86b0f731234f675">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">1</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">group1</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="displayname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">SSO User 1</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">sso_user@example.com</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>`
auth, err := decodeSAMLResponse([]byte(samlResponse))
require.Nil(t, err)
require.NotNil(t, auth)
info, ok := auth.(*resp)
require.True(t, ok)
status, err := info.status()
assert.Nil(t, err)
assert.Equal(t, Success, status)
assert.Equal(t, "sso_user@example.com", auth.UserID())
assert.Equal(t, "SSO User 1", auth.UserDisplayName())
assert.NotEmpty(t, auth.RequestID())
}
func TestEmptyResponse(t *testing.T) {
var auth resp
assert.Equal(t, "", auth.UserID())
assert.Equal(t, "", auth.UserDisplayName())
assert.Equal(t, "", auth.RequestID())
}
func TestUserDisplayName(t *testing.T) {
cases := []struct {
attrName string
values []AttributeValue
out string
}{
{"name", []AttributeValue{{Value: "Name Surname"}}, "Name Surname"},
{"displayname", []AttributeValue{{Value: "Name Surname"}}, "Name Surname"},
{"displayName", []AttributeValue{{Value: "Name Surname"}}, "Name Surname"},
{"cn", []AttributeValue{{Value: "Name Surname"}}, "Name Surname"},
{"urn:oid:2.5.4.3", []AttributeValue{{Value: "Name Surname"}}, "Name Surname"},
{"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", []AttributeValue{{Value: "Name Surname"}}, "Name Surname"},
{"name", []AttributeValue{{Value: ""}}, ""},
{"", []AttributeValue{{Value: ""}}, ""},
{"displayname", []AttributeValue{{Value: ""}, {Value: "Name Surname"}}, "Name Surname"},
}
for _, c := range cases {
t.Run(fmt.Sprintf("%s attribute with %v values", c.attrName, c.values), func(t *testing.T) {
var response Response
var auth resp
response.Assertion.AttributeStatement.Attributes = []Attribute{{Name: c.attrName, AttributeValues: c.values}}
auth.response = &response
assert.Equal(t, c.out, auth.UserDisplayName())
})
}
}
func TestDecodeOktaResponseWithCustomAttrs(t *testing.T) {
const samlResponseSample = `<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response Destination="https://example.com/api/v1/fleet/sso/callback" ID="id163119768052374872101569422" InResponseTo="id1Juy6Mx2IHYxLwsi" IssueInstant="2023-02-27T17:41:53.505Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.okta.com/exk8glknbnr9Lpdkl5d7</saml2:Issuer>
<ds:Signature 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/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#id163119768052374872101569422">
<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#">
<ec:InclusiveNamespaces PrefixList="xs" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>YjhYEzGsKy0vrLtgepjdmeAYf8ZkSiPMsKvSV/QSXZY=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>REDACTED</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>REDACTED</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion ID="id16311976805446352575023709" IssueInstant="2023-02-27T17:41:53.505Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.okta.com/exk8glknbnr9Lpdkl5d7</saml2:Issuer>
<ds:Signature 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/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#id16311976805446352575023709">
<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#">
<ec:InclusiveNamespaces PrefixList="xs" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>/W9NXsxZTI5GljYgaUNnl21ZlgF4L4A/npt/mpOyOeg=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>REDACTED</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>REDACTED</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">foo@example.com</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="id1Juy6Mx2IHYxLwsi" NotOnOrAfter="2023-02-27T17:46:53.506Z" Recipient="https://example.com/api/v1/fleet/sso/callback"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2023-02-27T17:36:53.506Z" NotOnOrAfter="2023-02-27T17:46:53.506Z" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:AudienceRestriction>
<saml2:Audience>example.com</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2023-02-27T17:41:53.505Z" SessionIndex="id1Juy6Mx2IHYxLwsi" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:Attribute Name="FLEET_JIT_USER_ROLE_TEAM_1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">observer</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="FLEET_JIT_USER_ROLE_TEAM_2" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">maintainer</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="foo" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">bar</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</saml2p:Response>`
auth, err := decodeSAMLResponse([]byte(samlResponseSample))
require.NoError(t, err)
require.NotNil(t, auth)
info, ok := auth.(*resp)
require.True(t, ok)
status, err := info.status()
assert.NoError(t, err)
assert.Equal(t, Success, status)
assert.Equal(t, "foo@example.com", auth.UserID())
assert.NotEmpty(t, auth.RequestID())
attrs := auth.AssertionAttributes()
assert.Equal(t, []fleet.SAMLAttribute{
{
Name: "FLEET_JIT_USER_ROLE_TEAM_1",
Values: []fleet.SAMLAttributeValue{{
Type: "",
Value: "observer",
}},
},
{
Name: "FLEET_JIT_USER_ROLE_TEAM_2",
Values: []fleet.SAMLAttributeValue{{
Type: "",
Value: "maintainer",
}},
},
{
Name: "foo",
Values: []fleet.SAMLAttributeValue{{
Type: "",
Value: "bar",
}},
},
}, attrs)
}