2017-05-09 00:43:48 +00:00
package sso
import (
"bytes"
"encoding/base64"
"encoding/xml"
"testing"
"time"
dsig "github.com/russellhaering/goxmldsig"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
2021-03-30 19:56:20 +00:00
func testMetadata ( ) Metadata {
var metadata Metadata
if err := xml . Unmarshal ( [ ] byte ( `
2017-05-09 00:43:48 +00:00
< ? xml version = "1.0" encoding = "UTF-8" ? >
2021-06-06 23:58:23 +00:00
< md : EntityDescriptor xmlns : md = "urn:oasis:names:tc:SAML:2.0:metadata" entityID = "https://fleet-dev-ed.my.salesforce.com" validUntil = "2027-04-29T19:22:40.750Z" xmlns : ds = "http://www.w3.org/2000/09/xmldsig#" >
2017-05-09 00:43:48 +00:00
< md : IDPSSODescriptor WantAuthnRequestsSigned = "false" protocolSupportEnumeration = "urn:oasis:names:tc:SAML:2.0:protocol" >
< md : KeyDescriptor use = "signing" >
< ds : KeyInfo >
< ds : X509Data >
< ds : X509Certificate > MIIErDCCA5SgAwIBAgIOAVuhH3WkAAAAAB5NpvIwDQYJKoZIhvcNAQELBQAwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzI0QXByMjAxN18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0EwHhcNMTcwNDI0MTgwMDQ1WhcNMTgwNDI0MTIwMDAwWjCBkDEoMCYGA1UEAwwfU2VsZlNpZ25lZENlcnRfMjRBcHIyMDE3XzE4MDA0NDEYMBYGA1UECwwPMDBENkEwMDAwMDAxN3Q4MRcwFQYDVQQKDA5TYWxlc2ZvcmNlLmNvbTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzELMAkGA1UECAwCQ0ExDDAKBgNVBAYTA1VTQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIOR7h8BF2eFOlQHhV / 1 S7uOBN22Jv7PDCXMz2fU0uLc + mrv9xDGj6ElfW + 9 dSdXaCbQzD3 + Xq4reS4pYRafJZ / 27 OtygXl3rpoPjSlhRiW + oYVuDcCURJpu0KuZ4I0fm5q1BDYqxcBxNPSe85OHE3 + ucmKqvPozhQgYLPCregMIomC3yyANZnLCoGfCv9TpQl6 / + I182tST4WPNhVPxKxijoPU4Rh6xY34Ez8 + Jr8KdmzmYSNe4ukkIASplpvG7rKka824Hf8zI1BWnjWLDxb5IAxgUBbdr4x8d8C3kPfTf + 3 / 6 yC5wSOm9NSs0BA4OJNowtXZFryMzFfXzDzjl69kCAwEAAaOCAQAwgf0wHQYDVR0OBBYEFO + DkoP6qkysi9ZC74yTPuJVVg2yMA8GA1UdEwEB / wQFMAMBAf8wgcoGA1UdIwSBwjCBv4AU74OSg / qqTKyL1kLvjJM + 4 lVWDbKhgZakgZMwgZAxKDAmBgNVBAMMH1NlbGZTaWduZWRDZXJ0XzI0QXByMjAxN18xODAwNDQxGDAWBgNVBAsMDzAwRDZBMDAwMDAwMTd0ODEXMBUGA1UECgwOU2FsZXNmb3JjZS5jb20xFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xCzAJBgNVBAgMAkNBMQwwCgYDVQQGEwNVU0GCDgFboR91pAAAAAAeTabyMA0GCSqGSIb3DQEBCwUAA4IBAQAVhYBv5GJvhltks2j7Zc9wdFHW7yB4 / hPFo05y0yiOf71tLjOlBucSyxtmXLPjrECJvIJwKhsAIgYXnVp7ditxfauCcxczJgfeL1 / dxH / Ge8ePkmH6SdsO71cJL8dXEzOsoF + PAVQzUhqh8zxIipntL0wwNGTD0zIVQeTSozm0KF0SsSHIfbNy279uReGonC61i4Ouk5AMKA7Re9fVeUs6tqM2at22h9Zaj / r / OhXoDcZhzkd8Wq0ER / UKLZA1CyJHgwOC7REEZOuKrqgfWcYt4dGo5q6gqGHHPMv0N7s / MxqCvJCwGA8eJGvOO56I321vhWHQ6ZSJDWUqQFM / Ze7A < / ds : X509Certificate >
< / ds : X509Data >
< / ds : KeyInfo >
< / md : KeyDescriptor >
< md : NameIDFormat > urn : oasis : names : tc : SAML : 1.1 : nameid - format : unspecified < / md : NameIDFormat >
2021-06-06 23:58:23 +00:00
< md : SingleSignOnService Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location = "https://fleet-dev-ed.my.salesforce.com/idp/endpoint/HttpPost" / >
< md : SingleSignOnService Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location = "https://fleet-dev-ed.my.salesforce.com/idp/endpoint/HttpRedirect" / >
2017-05-09 00:43:48 +00:00
< / md : IDPSSODescriptor >
< / md : EntityDescriptor >
2021-03-30 19:56:20 +00:00
` ) , & metadata ) ; err != nil {
panic ( err )
}
return metadata
}
2017-05-09 00:43:48 +00:00
func TestNewValidator ( t * testing . T ) {
2021-03-30 19:56:20 +00:00
v , err := NewValidator ( testMetadata ( ) )
2017-05-09 00:43:48 +00:00
assert . Nil ( t , err )
assert . NotNil ( t , v )
}
var testResponse = ` PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvYXBpL3YxL2tvbGlkZS9zc28vY2FsbGJhY2siIElEPSJfYzgyMWM1MmUzZDJkN2NhMjFiMmJlNmJlOTQ4Y2RiYjAxNDkzNTkwMTA2NjM1IiBJblJlc3BvbnNlVG89IjM5MTY5NzllLTNhZTItNGU4My04N2I0LWZlMmViODg0Yjg5MSIgSXNzdWVJbnN0YW50PSIyMDE3LTA0LTMwVDIyOjA4OjI2LjYzNVoiIFZlcnNpb249IjIuMCI + PHNhbWw6SXNzdWVyIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL2tvbGlkZS1kZXYtZWQubXkuc2FsZXNmb3JjZS5jb208L3NhbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPgo8ZHM6U2lnbmVkSW5mbz4KPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz4KPGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSIvPgo8ZHM6UmVmZXJlbmNlIFVSST0iI19jODIxYzUyZTNkMmQ3Y2EyMWIyYmU2YmU5NDhjZGJiMDE0OTM1OTAxMDY2MzUiPgo8ZHM6VHJhbnNmb3Jtcz4KPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8 + CjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiPjxlYzpJbmNsdXNpdmVOYW1lc3BhY2VzIHhtbG5zOmVjPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiIFByZWZpeExpc3Q9ImRzIHNhbWwgc2FtbHAgeHMgeHNpIi8 + PC9kczpUcmFuc2Zvcm0 + CjwvZHM6VHJhbnNmb3Jtcz4KPGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8 + CjxkczpEaWdlc3RWYWx1ZT5PWnMxdHRQamtKYnF6Mk8yb3UraDJZK3FFYms9PC9kczpEaWdlc3RWYWx1ZT4KPC9kczpSZWZlcmVuY2U + CjwvZHM6U2lnbmVkSW5mbz4KPGRzOlNpZ25hdHVyZVZhbHVlPgpWMmlSWlRIdUpCajBnekYzYzFHVzBGY0JiRlR0QXlWUml4VWdtR3ZrR0xhRzBBeElBZkY4ejdxbUlMTkV4cDlEUjJJU1F5a2lCU3p6CkpBQllRREU2T0V6ak5XTnYyS2NsUTRjQ0VOOUdIbHh6bEo4dkFwQzRsdkV3aGlQL04zd0VKb3RGTlN2MVZRd0YvdWFmZ1Z6b1NIeVIKb3RYaEJ0akFjcktBV25kRWo5L3QvdWV0SkI4dHZ5OXdybzhtS3RIZVNiTmJoZ0dwVEgyVHpuUnFxRnhwS1lRT29adFExaEpOVSsvdApMWGVpbWxjc0QrSHFQejlIT0crN0JuQllZZTkyN1dZRWRqREFLODVmMDY3ekN5T1RmK3pnVFNJNCs5WUVsbUo1OVZ6RFRwR3kyZENVCkwvZHJrSjhDSUJKZzZ4ekc1aVAwbFVGay81TmFrclRxZG0wNkF3PT0KPC9kczpTaWduYXR1cmVWYWx1ZT4KPGRzOktleUluZm8 + PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU + TUlJRXJEQ0NBNVNnQXdJQkFnSU9BVnVoSDNXa0FBQUFBQjVOcHZJd0RRWUpLb1pJaHZjTkFRRUxCUUF3Z1pBeEtEQW1CZ05WQkFNTQpIMU5sYkdaVGFXZHVaV1JEWlhKMFh6STBRWEJ5TWpBeE4xOHhPREF3TkRReEdEQVdCZ05WQkFzTUR6QXdSRFpCTURBd01EQXdNVGQwCk9ERVhNQlVHQTFVRUNnd09VMkZzWlhObWIzSmpaUzVqYjIweEZqQVVCZ05WQkFjTURWTmhiaUJHY21GdVkybHpZMjh4Q3pBSkJnTlYKQkFnTUFrTkJNUXd3Q2dZRFZRUUdFd05WVTBFd0hoY05NVGN3TkRJME1UZ3dNRFExV2hjTk1UZ3dOREkwTVRJd01EQXdXakNCa0RFbwpNQ1lHQTFVRUF3d2ZVMlZzWmxOcFoyNWxaRU5sY25SZk1qUkJjSEl5TURFM1h6RTRNREEwTkRFWU1CWUdBMVVFQ3d3UE1EQkVOa0V3Ck1EQXdNREF4TjNRNE1SY3dGUVlEVlFRS0RBNVRZV3hsYzJadmNtTmxMbU52YlRFV01CUUdBMVVFQnd3TlUyRnVJRVp5WVc1amFYTmoKYnpFTE1Ba0dBMVVFQ0F3Q1EwRXhEREFLQmdOVkJBWVRBMVZUUVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQwpnZ0VCQUlPUjdoOEJGMmVGT2xRSGhWLzFTN3VPQk4yMkp2N1BEQ1hNejJmVTB1TGMrbXJ2OXhER2o2RWxmVys5ZFNkWGFDYlF6RDMrClhxNHJlUzRwWVJhZkpaLzI3T3R5Z1hsM3Jwb1BqU2xoUmlXK29ZVnVEY0NVUkpwdTBLdVo0STBmbTVxMUJEWXF4Y0J4TlBTZTg1T0gKRTMrdWNtS3F2UG96aFFnWUxQQ3JlZ01Jb21DM3l5QU5abkxDb0dmQ3Y5VHBRbDYvK0kxODJ0U1Q0V1BOaFZQeEt4aWpvUFU0Umg2eApZMzRFejgrSnI4S2Rtem1ZU05lNHVra0lBU3BscHZHN3JLa2E4MjRIZjh6STFCV25qV0xEeGI1SUF4Z1VCYmRyNHg4ZDhDM2tQZlRmCiszLzZ5QzV3U09tOU5TczBCQTRPSk5vd3RYWkZyeU16RmZYekR6amw2OWtDQXdFQUFhT0NBUUF3Z2Ywd0hRWURWUjBPQkJZRUZPK0QKa29QNnFreXNpOVpDNzR5VFB1SlZWZzJ5TUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3Z2NvR0ExVWRJd1NCd2pDQnY0QVU3NE9TZy9xcQpUS3lMMWtMdmpKTSs0bFZXRGJLaGdaYWtnWk13Z1pBeEtEQW1CZ05WQkFNTUgxTmxiR1pUYVdkdVpXUkRaWEowWHpJMFFYQnlNakF4Ck4xOHhPREF3TkRReEdEQVdCZ05WQkFzTUR6QXdSRFpCTURBd01EQXdNVGQwT0RFWE1CVUdBMVVFQ2d3T1UyRnNaWE5tYjNKalpTNWoKYjIweEZqQVVCZ05WQkFjTURWTmhiaUJHY21GdVkybHpZMjh4Q3pBSkJnTlZCQWdNQWtOQk1Rd3dDZ1lEVlFRR0V3TlZVMEdDRGdGYgpvUjkxcEFBQUFBQWVUYWJ5TUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBVmhZQnY1R0p2aGx0a3MyajdaYzl3ZEZIVzd5QjQvaFBGCm8wNXkweWlPZjcxdExqT2xCdWNTeXh0bVhMUGpyRUNKdkl
func TestValidate ( t * testing . T ) {
tm , err := time . Parse ( time . UnixDate , "Sun Apr 30 22:10:00 UTC 2017" )
require . Nil ( t , err )
2019-11-11 17:42:31 +00:00
2017-05-09 00:43:48 +00:00
clock := dsig . NewFakeClockAt ( tm )
2019-11-11 17:42:31 +00:00
2022-02-02 23:50:09 +00:00
testCases := [ ] struct {
audiences [ ] string
shouldFail bool
} {
{ audiences : [ ] string { "kolide" } , shouldFail : false } ,
{ audiences : [ ] string { "someotheraudience" } , shouldFail : true } ,
{ audiences : nil , shouldFail : true } ,
}
2019-11-11 17:42:31 +00:00
2022-02-02 23:50:09 +00:00
for _ , tt := range testCases {
validator , err := NewValidator ( testMetadata ( ) , Clock ( clock ) , WithExpectedAudience ( tt . audiences ... ) )
require . Nil ( t , err )
require . NotNil ( t , validator )
2017-05-09 00:43:48 +00:00
2022-02-02 23:50:09 +00:00
auth , err := DecodeAuthResponse ( testResponse )
require . Nil ( t , err )
signed , err := validator . ValidateSignature ( auth )
require . Nil ( t , err )
require . NotNil ( t , signed )
err = validator . ValidateResponse ( auth )
if tt . shouldFail {
require . Error ( t , err )
} else {
require . NoError ( t , err )
}
}
2017-05-09 00:43:48 +00:00
}
func tamperedResponse ( original string ) ( string , error ) {
decoded , err := base64 . StdEncoding . DecodeString ( original )
if err != nil {
return "" , err
}
var resp Response
rdr := bytes . NewBuffer ( decoded )
err = xml . NewDecoder ( rdr ) . Decode ( & resp )
if err != nil {
return "" , err
}
// change name
2021-06-06 22:07:29 +00:00
resp . Assertion . Subject . NameID . Value = "bob@fleet.co"
2017-05-09 00:43:48 +00:00
var wrtr bytes . Buffer
err = xml . NewEncoder ( & wrtr ) . Encode ( resp )
if err != nil {
return "" , err
}
return base64 . StdEncoding . EncodeToString ( wrtr . Bytes ( ) ) , nil
}
func TestVerfiyValidTamperedWithDocFails ( t * testing . T ) {
tampered , err := tamperedResponse ( testResponse )
require . Nil ( t , err )
2019-11-11 17:42:31 +00:00
2017-05-09 00:43:48 +00:00
tm , err := time . Parse ( time . UnixDate , "Sun Apr 30 22:10:00 UTC 2017" )
require . Nil ( t , err )
2019-11-11 17:42:31 +00:00
2017-05-09 00:43:48 +00:00
clock := dsig . NewFakeClockAt ( tm )
2021-03-30 19:56:20 +00:00
validator , err := NewValidator ( testMetadata ( ) , Clock ( clock ) )
2017-05-09 00:43:48 +00:00
require . Nil ( t , err )
require . NotNil ( t , validator )
2019-11-11 17:42:31 +00:00
2017-05-09 00:43:48 +00:00
auth , err := DecodeAuthResponse ( tampered )
2019-11-11 17:42:31 +00:00
require . Nil ( t , err )
2017-05-09 00:43:48 +00:00
_ , err = validator . ValidateSignature ( auth )
require . NotNil ( t , err )
}
// Message hasn't been tampered with but is stale
func TestVerfiyStaleMessageFails ( t * testing . T ) {
tm , err := time . Parse ( time . UnixDate , "Sun Apr 30 22:14:00 UTC 2017" )
require . Nil ( t , err )
clock := dsig . NewFakeClockAt ( tm )
2021-03-30 19:56:20 +00:00
validator , err := NewValidator ( testMetadata ( ) , Clock ( clock ) )
2017-05-09 00:43:48 +00:00
require . Nil ( t , err )
require . NotNil ( t , validator )
2019-11-11 17:42:31 +00:00
2017-05-09 00:43:48 +00:00
auth , err := DecodeAuthResponse ( testResponse )
2019-11-11 17:42:31 +00:00
require . Nil ( t , err )
2017-05-09 00:43:48 +00:00
signed , err := validator . ValidateSignature ( auth )
require . Nil ( t , err )
require . NotNil ( t , signed )
err = validator . ValidateResponse ( auth )
assert . NotNil ( t , err )
}
2017-07-18 20:28:35 +00:00
2021-03-30 19:56:20 +00:00
func testGoogleMetadata ( ) Metadata {
var metadata Metadata
if err := xml . Unmarshal ( [ ] byte ( `
2017-07-18 20:28:35 +00:00
< ? xml version = "1.0" encoding = "UTF-8" standalone = "no" ? >
< md : EntityDescriptor xmlns : md = "urn:oasis:names:tc:SAML:2.0:metadata" entityID = "https://accounts.google.com/o/saml2?idpid=C0171bstf" validUntil = "2022-07-16T20:07:43.000Z" >
< md : IDPSSODescriptor WantAuthnRequestsSigned = "false" protocolSupportEnumeration = "urn:oasis:names:tc:SAML:2.0:protocol" >
< md : KeyDescriptor use = "signing" >
< ds : KeyInfo xmlns : ds = "http://www.w3.org/2000/09/xmldsig#" >
< ds : X509Data >
< ds : X509Certificate > MIIDdDCCAlygAwIBAgIGAV1SKeijMA0GCSqGSIb3DQEBCwUAMHsxFDASBgNVBAoTC0dvb2dsZSBJ
bmMuMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQDEwZHb29nbGUxGDAWBgNVBAsTD0dv
b2dsZSBGb3IgV29yazELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEwHhcNMTcwNzE3
MjAwNzQzWhcNMjIwNzE2MjAwNzQzWjB7MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEWMBQGA1UEBxMN
TW91bnRhaW4gVmlldzEPMA0GA1UEAxMGR29vZ2xlMRgwFgYDVQQLEw9Hb29nbGUgRm9yIFdvcmsx
CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAzLXNn7VmJBkvVNYHffTzDoow / 8 eSklauVeYjhELY6dtFv56wAQsFNeMovFUPxPeG
7 Fci50 / KStvoNZOdKqZFCwYkfI2ssXuMpBP37x2iprV7moVwGdGJb52elMNe0DesgTPbJ / IWIvzF
3 GYxqYCHUlHuzJEzBYsdtvM8T / PClBxiLXRNbnjotzleFqb25w3XRfayOZg5GdQPeEmceWXDBhCa
eQyEPOrUTZ + //pZXSuKnOyaFfESNFNgvQJlYQQukjnhPtf674eWT6OdgZHyq8EBbZKfEhs5+KiAN
U43bDh9rpTJCB7rAKk1BFAW3r72pggwN9Z / sfp / C5B7uKAM5hwIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQAZXypikbbRzichNXLdK96M / do9nGS5Q3xVgA2uxTzm / 6 qNkAfOSGSk8OcLrppPonbohkeZ
WVnNB5VZZava4DoSZ6OZsvKc1FM0wKvPJd83KUb7Syk1bV7TkT8DPEclfsLnn5s5g0oHlhsqkNly
0 WPFTAoGHXYyOKGEARPoC / o + ZfgfvoMNyZkSQHiRboVVP2cT1ckJt4iCA65hNGXte29hSGmnX7QG
QyrBRp8n4UR9PjoeIy0tTCmG0tqu / NackFH4PkamY84Etxe9uH0StmkhID46QTT4Cv2 + jqCaklg +
7 VYqXbY64Wc / k0sK7WI1o3IVLWAPNb8ajV6Eo0Y8u + 1 N < / ds : X509Certificate >
< / ds : X509Data >
< / ds : KeyInfo >
< / md : KeyDescriptor >
< md : NameIDFormat > urn : oasis : names : tc : SAML : 1.1 : nameid - format : emailAddress < / md : NameIDFormat >
< md : SingleSignOnService Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location = "https://accounts.google.com/o/saml2/idp?idpid=C0171bstf" / >
< md : SingleSignOnService Binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location = "https://accounts.google.com/o/saml2/idp?idpid=C0171bstf" / >
< / md : IDPSSODescriptor >
< / md : EntityDescriptor >
2021-03-30 19:56:20 +00:00
` ) , & metadata ) ; err != nil {
panic ( err )
}
return metadata
}
2017-07-18 20:28:35 +00:00
func TestVerifyValidGoogleResponse ( t * testing . T ) {
samlResponse :=
` PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8 + PHNhbWwycDpSZXNwb25zZSB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvYXBpL3YxL2tvbGlkZS9zc28vY2FsbGJhY2siIElEPSJfODM1NzlhOTAwOGVmNzI2Zjg3YzUyYWFkNGI2ZGNjMDQiIEluUmVzcG9uc2VUbz0iU0dKaGkxZzVENC9ucE93WGF3OHQ2QT09IiBJc3N1ZUluc3RhbnQ9IjIwMTctMDctMThUMTQ6NDc6MDguMDM1WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9zYW1sMj9pZHBpZD1DMDE3MWJzdGY8L3NhbWwyOklzc3Vlcj48c2FtbDJwOlN0YXR1cz48c2FtbDJwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbDJwOlN0YXR1cz48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzUwMDA2MTk5MGFjYzAwNzIzMjg4ODMzYTMyN2NjOTg2IiBJc3N1ZUluc3RhbnQ9IjIwMTctMDctMThUMTQ6NDc6MDguMDM1WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyPmh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL3NhbWwyP2lkcGlkPUMwMTcxYnN0Zjwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8 + PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI181MDAwNjE5OTBhY2MwMDcyMzI4ODgzM2EzMjdjYzk4NiI + PGRzOlRyYW5zZm9ybXM + PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8 + PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8 + PGRzOkRpZ2VzdFZhbHVlPm5abWdLOVh0anlUN3NCQXBVMHR5WmJVRTRXV013Q3NEejhqNklaRTVJeHc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8 + PGRzOlNpZ25hdHVyZVZhbHVlPkRIZFUrTG5PWC91OEh1angrSXBEbW96dDl1MlJPRDlVVTJPYjVFbDBaakVwQUVTcXlZMlBqOVk0S2QwMUlzRFRmL2dGS0pXT3lWTXoKUFAzaW81UDRlaUE5NnArMGcwWU51TzZpY2tWRjlCSEFKeWpFVDM4QzNwQjk1cmdxVWI3ckxhRDZYZGZBWEZRN2wyZGFsSFM5eUxhLwpLQnRUM2YzeWtZUGI3NE5yQWhpaFY4WjBndlBweVdxQkRnMjNCNzZ0SWVyV24yNkxvb1prUE5YUFRHdi9zeThvY1k1b3o1NnBsS3ZaCk9tVmR3cHp3SDcvN2kvVUVuTnY2c2lzMy9lczBPbW01Z3hlS0xQNDB2V2I5bFRtMUhtdkxUVjNzWmlIWlFRbVV3bWZjc1pMNmd5VkUKZWFKTkRRUDR5T3crdlhLZGV5QWxWQzZqdHQwNk1nWTlWMHpqNWc9PTwvZHM6U2lnbmF0dXJlVmFsdWU + PGRzOktleUluZm8 + PGRzOlg1MDlEYXRhPjxkczpYNTA5U3ViamVjdE5hbWU + U1Q9Q2FsaWZvcm5pYSxDPVVTLE9VPUdvb2dsZSBGb3IgV29yayxDTj1Hb29nbGUsTD1Nb3VudGFpbiBWaWV3LE89R29vZ2xlIEluYy48L2RzOlg1MDlTdWJqZWN0TmFtZT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURkRENDQWx5Z0F3SUJBZ0lHQVYxU0tlaWpNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1Ic3hGREFTQmdOVkJBb1RDMGR2YjJkc1pTQkoKYm1NdU1SWXdGQVlEVlFRSEV3MU5iM1Z1ZEdGcGJpQldhV1YzTVE4d0RRWURWUVFERXdaSGIyOW5iR1V4R0RBV0JnTlZCQXNURDBkdgpiMmRzWlNCR2IzSWdWMjl5YXpFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V3SGhjTk1UY3dOekUzCk1qQXdOelF6V2hjTk1qSXdOekUyTWpBd056UXpXakI3TVJRd0VnWURWUVFLRXd0SGIyOW5iR1VnU1c1akxqRVdNQlFHQTFVRUJ4TU4KVFc5MWJuUmhhVzRnVm1sbGR6RVBNQTBHQTFVRUF4TUdSMjl2WjJ4bE1SZ3dGZ1lEVlFRTEV3OUhiMjluYkdVZ1JtOXlJRmR2Y21zeApDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBCk1JSUJDZ0tDQVFFQXpMWE5uN1ZtSkJrdlZOWUhmZlR6RG9vdy84ZVNrbGF1VmVZamhFTFk2ZHRGdjU2d0FRc0ZOZU1vdkZVUHhQZUcKN0ZjaTUwL0tTdHZvTlpPZEtxWkZDd1lrZkkyc3NYdU1wQlAzN3gyaXByVjdtb1Z3R2RHSmI1MmVsTU5lMERlc2dUUGJKL0lXSXZ6RgozR1l4cVlDSFVsSHV6SkV6QllzZHR2TThUL1BDbEJ4aUxYUk5ibmpvdHpsZUZxYjI1dzNYUmZheU9aZzVHZFFQZUVtY2VXWERCaENhCmVReUVQT3JVVForLy9wWlhTdUtuT3lhRmZFU05GTmd2UUpsWVFRdWtqbmhQdGY2NzRlV1Q2T2RnWkh5cThFQmJaS2ZFaHM1K0tpQU4KVTQzYkRoOXJwVEpDQjdyQUtrMUJGQVczcjcycGdnd045Wi9zZnAvQzVCN3VLQU01aHdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQQpBNElCQVFBWlh5cGlrYmJSemljaE5YTGRLOTZNL2RvOW5HUzVRM3hWZ0EydXhUem0vNnFOa0FmT1NHU2s4T2NMcnBwUG9uYm9oa2VaCldWbk5CNVZaWmF2YTREb1NaNk9ac3ZLYzFGTTB3S3ZQSmQ4M0tVYjdTeWsxYlY3VGtUOERQRWNsZnNMbm41czVnMG9IbGhzcWtObHkKMFdQRlRBb0dIWFl5T0tHRUFSUG9DL28rWmZnZnZvTU55WmtTUUhpUmJvVlZQMmNUMWNrSnQ0aUNBNjVoTkdYdGUyOWhTR21u
tm , err := time . Parse ( time . RFC3339 , "2017-07-18T14:47:08.035Z" )
require . Nil ( t , err )
clock := dsig . NewFakeClockAt ( tm )
2022-02-02 23:50:09 +00:00
validator , err := NewValidator ( testGoogleMetadata ( ) , Clock ( clock ) , WithExpectedAudience ( "kolide.edilok.net" ) )
2017-07-18 20:28:35 +00:00
require . Nil ( t , err )
require . NotNil ( t , validator )
auth , err := DecodeAuthResponse ( samlResponse )
require . Nil ( t , err )
require . NotNil ( t , auth )
signed , err := validator . ValidateSignature ( auth )
require . Nil ( t , err )
require . NotNil ( t , signed )
err = validator . ValidateResponse ( auth )
assert . Nil ( t , err )
}
2020-12-15 02:14:14 +00:00
func TestVerifyGoogleResponseCommentInjected ( t * testing . T ) {
2021-09-09 20:23:35 +00:00
t . Skip ( "this test now fails on Go 1.17 because of changes to xml parser - it use to fail roundtripping, now it passes and there is no signature so the validation ends without error" )
2020-12-15 02:14:14 +00:00
samlResponse :=
` PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8 + PHNhbWwycDpSZXNwb25zZSB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvYXBpL3YxL2tvbGlkZS9zc28vY2FsbGJhY2siIElEPSJfODM1NzlhOTAwOGVmNzI2Zjg3YzUyYWFkNGI2ZGNjMDQiIEluUmVzcG9uc2VUbz0iU0dKaGkxZzVENC9ucE93WGF3OHQ2QT09IiBJc3N1ZUluc3RhbnQ9IjIwMTctMDctMThUMTQ6NDc6MDguMDM1WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9zYW1sMj9pZHBpZD1DMDE3MWJzdGY8L3NhbWwyOklzc3Vlcj48c2FtbDJwOlN0YXR1cz48c2FtbDJwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbDJwOlN0YXR1cz48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzUwMDA2MTk5MGFjYzAwNzIzMjg4ODMzYTMyN2NjOTg2IiBJc3N1ZUluc3RhbnQ9IjIwMTctMDctMThUMTQ6NDc6MDguMDM1WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyPmh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL3NhbWwyP2lkcGlkPUMwMTcxYnN0Zjwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8 + PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI181MDAwNjE5OTBhY2MwMDcyMzI4ODgzM2EzMjdjYzk4NiI + PGRzOlRyYW5zZm9ybXM + PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8 + PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8 + PGRzOkRpZ2VzdFZhbHVlPm5abWdLOVh0anlUN3NCQXBVMHR5WmJVRTRXV013Q3NEejhqNklaRTVJeHc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8 + PGRzOlNpZ25hdHVyZVZhbHVlPkRIZFUrTG5PWC91OEh1angrSXBEbW96dDl1MlJPRDlVVTJPYjVFbDBaakVwQUVTcXlZMlBqOVk0S2QwMUlzRFRmL2dGS0pXT3lWTXoKUFAzaW81UDRlaUE5NnArMGcwWU51TzZpY2tWRjlCSEFKeWpFVDM4QzNwQjk1cmdxVWI3ckxhRDZYZGZBWEZRN2wyZGFsSFM5eUxhLwpLQnRUM2YzeWtZUGI3NE5yQWhpaFY4WjBndlBweVdxQkRnMjNCNzZ0SWVyV24yNkxvb1prUE5YUFRHdi9zeThvY1k1b3o1NnBsS3ZaCk9tVmR3cHp3SDcvN2kvVUVuTnY2c2lzMy9lczBPbW01Z3hlS0xQNDB2V2I5bFRtMUhtdkxUVjNzWmlIWlFRbVV3bWZjc1pMNmd5VkUKZWFKTkRRUDR5T3crdlhLZGV5QWxWQzZqdHQwNk1nWTlWMHpqNWc9PTwvZHM6U2lnbmF0dXJlVmFsdWU + PGRzOktleUluZm8 + PGRzOlg1MDlEYXRhPjxkczpYNTA5U3ViamVjdE5hbWU + U1Q9Q2FsaWZvcm5pYSxDPVVTLE9VPUdvb2dsZSBGb3IgV29yayxDTj1Hb29nbGUsTD1Nb3VudGFpbiBWaWV3LE89R29vZ2xlIEluYy48L2RzOlg1MDlTdWJqZWN0TmFtZT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURkRENDQWx5Z0F3SUJBZ0lHQVYxU0tlaWpNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1Ic3hGREFTQmdOVkJBb1RDMGR2YjJkc1pTQkoKYm1NdU1SWXdGQVlEVlFRSEV3MU5iM1Z1ZEdGcGJpQldhV1YzTVE4d0RRWURWUVFERXdaSGIyOW5iR1V4R0RBV0JnTlZCQXNURDBkdgpiMmRzWlNCR2IzSWdWMjl5YXpFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V3SGhjTk1UY3dOekUzCk1qQXdOelF6V2hjTk1qSXdOekUyTWpBd056UXpXakI3TVJRd0VnWURWUVFLRXd0SGIyOW5iR1VnU1c1akxqRVdNQlFHQTFVRUJ4TU4KVFc5MWJuUmhhVzRnVm1sbGR6RVBNQTBHQTFVRUF4TUdSMjl2WjJ4bE1SZ3dGZ1lEVlFRTEV3OUhiMjluYkdVZ1JtOXlJRmR2Y21zeApDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBCk1JSUJDZ0tDQVFFQXpMWE5uN1ZtSkJrdlZOWUhmZlR6RG9vdy84ZVNrbGF1VmVZamhFTFk2ZHRGdjU2d0FRc0ZOZU1vdkZVUHhQZUcKN0ZjaTUwL0tTdHZvTlpPZEtxWkZDd1lrZkkyc3NYdU1wQlAzN3gyaXByVjdtb1Z3R2RHSmI1MmVsTU5lMERlc2dUUGJKL0lXSXZ6RgozR1l4cVlDSFVsSHV6SkV6QllzZHR2TThUL1BDbEJ4aUxYUk5ibmpvdHpsZUZxYjI1dzNYUmZheU9aZzVHZFFQZUVtY2VXWERCaENhCmVReUVQT3JVVForLy9wWlhTdUtuT3lhRmZFU05GTmd2UUpsWVFRdWtqbmhQdGY2NzRlV1Q2T2RnWkh5cThFQmJaS2ZFaHM1K0tpQU4KVTQzYkRoOXJwVEpDQjdyQUtrMUJGQVczcjcycGdnd045Wi9zZnAvQzVCN3VLQU01aHdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQQpBNElCQVFBWlh5cGlrYmJSemljaE5YTGRLOTZNL2RvOW5HUzVRM3hWZ0EydXhUem0vNnFOa0FmT1NHU2s4T2NMcnBwUG9uYm9oa2VaCldWbk5CNVZaWmF2YTREb1NaNk9ac3ZLYzFGTTB3S3ZQSmQ4M0tVYjdTeWsxYlY3VGtUOERQRWNsZnNMbm41czVnMG9IbGhzcWtObHkKMFdQRlRBb0dIWFl5T0tHRUFSUG9DL28rWmZnZnZvTU55WmtTUUhpUmJvVlZQMmNUMWNrSnQ0aUNBNjVoTkdYdGUyOWhTR21u
decoded , err := base64 . StdEncoding . DecodeString ( samlResponse )
require . NoError ( t , err )
// Tamper with the valid response by injecting a comment
decoded = bytes . Replace ( decoded , [ ] byte ( "<saml2p:Response" ) , [ ] byte ( "<saml2p:Response ::foo=\"bar\"" ) , 1 )
samlResponse = base64 . StdEncoding . EncodeToString ( decoded )
tm , err := time . Parse ( time . RFC3339 , "2017-07-18T14:47:08.035Z" )
require . Nil ( t , err )
clock := dsig . NewFakeClockAt ( tm )
2021-03-30 19:56:20 +00:00
validator , err := NewValidator ( testGoogleMetadata ( ) , Clock ( clock ) )
2020-12-15 02:14:14 +00:00
require . Nil ( t , err )
require . NotNil ( t , validator )
auth , err := DecodeAuthResponse ( samlResponse )
require . Nil ( t , err )
require . NotNil ( t , auth )
_ , err = validator . ValidateSignature ( auth )
require . Error ( t , err )
}
func TestVerifyGoogleResponseDoubleColon ( t * testing . T ) {
2021-09-09 20:23:35 +00:00
t . Skip ( "this test now fails on Go 1.17 because of changes to xml parser - it use to fail roundtripping, now it passes and there is no signature so the validation ends without error" )
2020-12-15 02:14:14 +00:00
samlResponse := ` PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8 + PHNhbWwycDpSZXNwb25zZSB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvYXBpL3YxL2tvbGlkZS9zc28vY2FsbGJhY2siIElEPSJfODM1NzlhOTAwOGVmNzI2Zjg3YzUyYWFkNGI2ZGNjMDQiIEluUmVzcG9uc2VUbz0iU0dKaGkxZzVENC9ucE93WGF3OHQ2QT09IiBJc3N1ZUluc3RhbnQ9IjIwMTctMDctMThUMTQ6NDc6MDguMDM1WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9zYW1sMj9pZHBpZD1DMDE3MWJzdGY8L3NhbWwyOklzc3Vlcj48c2FtbDJwOlN0YXR1cz48c2FtbDJwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbDJwOlN0YXR1cz48OjpBc3NlcnRpb24geG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfNTAwMDYxOTkwYWNjMDA3MjMyODg4MzNhMzI3Y2M5ODYiIElzc3VlSW5zdGFudD0iMjAxNy0wNy0xOFQxNDo0NzowOC4wMzVaIiBWZXJzaW9uPSIyLjAiPjxzYW1sMjpJc3N1ZXI + aHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL28vc2FtbDI / aWRwaWQ9QzAxNzFic3RmPC9zYW1sMjpJc3N1ZXI + PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI + PGRzOlNpZ25lZEluZm8 + PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxkczpSZWZlcmVuY2UgVVJJPSIjXzUwMDA2MTk5MGFjYzAwNzIzMjg4ODMzYTMyN2NjOTg2Ij48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8 + PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48ZHM6RGlnZXN0VmFsdWU + blptZ0s5WHRqeVQ3c0JBcFUwdHlaYlVFNFdXTXdDc0R6OGo2SVpFNUl4dz08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU + REhkVStMbk9YL3U4SHVqeCtJcERtb3p0OXUyUk9EOVVVMk9iNUVsMFpqRXBBRVNxeVkyUGo5WTRLZDAxSXNEVGYvZ0ZLSldPeVZNegpQUDNpbzVQNGVpQTk2cCswZzBZTnVPNmlja1ZGOUJIQUp5akVUMzhDM3BCOTVyZ3FVYjdyTGFENlhkZkFYRlE3bDJkYWxIUzl5TGEvCktCdFQzZjN5a1lQYjc0TnJBaGloVjhaMGd2UHB5V3FCRGcyM0I3NnRJZXJXbjI2TG9vWmtQTlhQVEd2L3N5OG9jWTVvejU2cGxLdloKT21WZHdwendINy83aS9VRW5OdjZzaXMzL2VzME9tbTVneGVLTFA0MHZXYjlsVG0xSG12TFRWM3NaaUhaUVFtVXdtZmNzWkw2Z3lWRQplYUpORFFQNHlPdyt2WEtkZXlBbFZDNmp0dDA2TWdZOVYwemo1Zz09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE + PGRzOlg1MDlTdWJqZWN0TmFtZT5TVD1DYWxpZm9ybmlhLEM9VVMsT1U9R29vZ2xlIEZvciBXb3JrLENOPUdvb2dsZSxMPU1vdW50YWluIFZpZXcsTz1Hb29nbGUgSW5jLjwvZHM6WDUwOVN1YmplY3ROYW1lPjxkczpYNTA5Q2VydGlmaWNhdGU + TUlJRGREQ0NBbHlnQXdJQkFnSUdBVjFTS2Vpak1BMEdDU3FHU0liM0RRRUJDd1VBTUhzeEZEQVNCZ05WQkFvVEMwZHZiMmRzWlNCSgpibU11TVJZd0ZBWURWUVFIRXcxTmIzVnVkR0ZwYmlCV2FXVjNNUTh3RFFZRFZRUURFd1pIYjI5bmJHVXhHREFXQmdOVkJBc1REMGR2CmIyZHNaU0JHYjNJZ1YyOXlhekVMTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR2xtYjNKdWFXRXdIaGNOTVRjd056RTMKTWpBd056UXpXaGNOTWpJd056RTJNakF3TnpReldqQjdNUlF3RWdZRFZRUUtFd3RIYjI5bmJHVWdTVzVqTGpFV01CUUdBMVVFQnhNTgpUVzkxYm5SaGFXNGdWbWxsZHpFUE1BMEdBMVVFQXhNR1IyOXZaMnhsTVJnd0ZnWURWUVFMRXc5SGIyOW5iR1VnUm05eUlGZHZjbXN4CkN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlFd3BEWVd4cFptOXlibWxoTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEEKTUlJQkNnS0NBUUVBekxYTm43Vm1KQmt2Vk5ZSGZmVHpEb293LzhlU2tsYXVWZVlqaEVMWTZkdEZ2NTZ3QVFzRk5lTW92RlVQeFBlRwo3RmNpNTAvS1N0dm9OWk9kS3FaRkN3WWtmSTJzc1h1TXBCUDM3eDJpcHJWN21vVndHZEdKYjUyZWxNTmUwRGVzZ1RQYkovSVdJdnpGCjNHWXhxWUNIVWxIdXpKRXpCWXNkdHZNOFQvUENsQnhpTFhSTmJuam90emxlRnFiMjV3M1hSZmF5T1pnNUdkUVBlRW1jZVdYREJoQ2EKZVF5RVBPclVUWisvL3BaWFN1S25PeWFGZkVTTkZOZ3ZRSmxZUVF1a2puaFB0ZjY3NGVXVDZPZGdaSHlxOEVCYlpLZkVoczUrS2lBTgpVNDNiRGg5cnBUSkNCN3JBS2sxQkZBVzNyNzJwZ2d3TjlaL3NmcC9DNUI3dUtBTTVod0lEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBCkE0SUJBUUFaWHlwaWtiYlJ6aWNoTlhMZEs5Nk0vZG85bkdTNVEzeFZnQTJ1eFR6bS82cU5rQWZPU0dTazhPY0xycHBQb25ib2hrZVoKV1ZuTkI1VlpaYXZhNERvU1o2T1pzdktjMUZNMHdLdlBKZDgzS1ViN1N5azFiVjdUa1Q4RFBFY2xmc0xubjVzNWcwb0hsaHNxa05seQowV1BGVEFvR0hYWXlPS0dFQVJQb0MvbytaZmdmdm9NTnlaa1NRSGlSYm9WVlAyY1QxY2tKdDRpQ0E2NWhOR1h0Z
tm , err := time . Parse ( time . RFC3339 , "2017-07-18T14:47:08.035Z" )
require . Nil ( t , err )
clock := dsig . NewFakeClockAt ( tm )
2021-03-30 19:56:20 +00:00
validator , err := NewValidator ( testGoogleMetadata ( ) , Clock ( clock ) )
2020-12-15 02:14:14 +00:00
require . Nil ( t , err )
require . NotNil ( t , validator )
auth , err := DecodeAuthResponse ( samlResponse )
require . Nil ( t , err )
require . NotNil ( t , auth )
// Should fail due to the double colon in the response XML
_ , err = validator . ValidateSignature ( auth )
require . Error ( t , err )
}
2017-07-18 20:28:35 +00:00
func TestVerifyInvalidSignatureGoogleResponse ( t * testing . T ) {
samlResponse :=
` PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8 + PHNhbWwycDpSZXNwb25zZSB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgRGVzdGluYXRpb249Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvYXBpL3YxL2tvbGlkZS9zc28vY2FsbGJhY2siIElEPSJfODM1NzlhOTAwOGVmNzI2Zjg3YzUyYWFkNGI2ZGNjMDQiIEluUmVzcG9uc2VUbz0iU0dKaGkxZzVENC9ucE93WGF3OHQ2QT09IiBJc3N1ZUluc3RhbnQ9IjIwMTctMDctMThUMTQ6NDc6MDguMDM1WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vby9zYW1sMj9pZHBpZD1DMDE3MWJzdGY8L3NhbWwyOklzc3Vlcj48c2FtbDJwOlN0YXR1cz48c2FtbDJwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbDJwOlN0YXR1cz48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzUwMDA2MTk5MGFjYzAwNzIzMjg4ODMzYTMyN2NjOTg2IiBJc3N1ZUluc3RhbnQ9IjIwMTctMDctMThUMTQ6NDc6MDguMDM1WiIgVmVyc2lvbj0iMi4wIj48c2FtbDI6SXNzdWVyPmh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL3NhbWwyP2lkcGlkPUMwMTcxYnN0Zjwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8 + PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI181MDAwNjE5OTBhY2MwMDcyMzI4ODgzM2EzMjdjYzk4NiI + PGRzOlRyYW5zZm9ybXM + PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8 + PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8 + PGRzOkRpZ2VzdFZhbHVlPm5abWdLOVh0anlUN3NCQXBVMHR5WmJVRTRXV013Q3NEejhqNklaRTVJeHc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8 + PGRzOlNpZ25hdHVyZVZhbHVlPkRIZFUrTG5PWC91OEh1angrSXBEbW96dDl1MlJPRDlVVTJPYjVFbDBaakVwQUVTcXlZMlBqOVk0S2QwMUlzRFRmL2dGS0pXT3lWTXoKUFAzaW81UDRlaUE5NnArMGcwWU51TzZpY2tWRjlCSEFKeWpFVDM4QzNwQjk1cmdxVWI3ckxhRDZYZGZBWEZRN2wyZGFsSFM5eUxhLwpLQnRUM2YzeWtZUGI3NE5yQWhpaFY4WjBndlBweVdxQkRnMjNCNzZ0SWVyV24yNkxvb1prUE5YUFRHdi9zeThvY1k1b3o1NnBsS3ZaCk9tVmR3cHp3SDcvN2kvVUVuTnY2c2lzMy9lczBPbW01Z3hlS0xQNDB2V2I5bFRtMUhtdkxUVjNzWmlIWlFRbVV3bWZjc1pMNmd5VkUKZWFKTkRRUDR5T3crdlhLZGV5QWxWQzZqdHQwNk1nWTlWMHpqNWc9PTwvZHM6U2lnbmF0dXJlVmFsdWU + PGRzOktleUluZm8 + PGRzOlg1MDlEYXRhPjxkczpYNTA5U3ViamVjdE5hbWU + U1Q9Q2FsaWZvcm5pYSxDPVVTLE9VPUdvb2dsZSBGb3IgV29yayxDTj1Hb29nbGUsTD1Nb3VudGFpbiBWaWV3LE89R29vZ2xlIEluYy48L2RzOlg1MDlTdWJqZWN0TmFtZT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURkRENDQWx5Z0F3SUJBZ0lHQVYxU0tlaWpNQTBHQ1NxR1NJYjNEUUVCQ3dVQU1Ic3hGREFTQmdOVkJBb1RDMGR2YjJkc1pTQkoKYm1NdU1SWXdGQVlEVlFRSEV3MU5iM1Z1ZEdGcGJpQldhV1YzTVE4d0RRWURWUVFERXdaSGIyOW5iR1V4R0RBV0JnTlZCQXNURDBkdgpiMmRzWlNCR2IzSWdWMjl5YXpFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ1RDa05oYkdsbWIzSnVhV0V3SGhjTk1UY3dOekUzCk1qQXdOelF6V2hjTk1qSXdOekUyTWpBd056UXpXakI3TVJRd0VnWURWUVFLRXA0SGIyOW5iR1VnU1c1akxqRVdNQlFHQTFVRUJ4TU4KVFc5MWJuUmhhVzRnVm1sbGR6RVBNQTBHQTFVRUF4TUdSMjl2WjJ4bE1SZ3dGZ1lEVlFRTEV3OUhiMjluYkdVZ1JtOXlJRmR2Y21zeApDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBCk1JSUJDZ0tDQVFFQXpMWE5uN1ZtSkJrdlZOWUhmZlR6RG9vdy84ZVNrbGF1VmVZamhFTFk2ZHRGdjU2d0FRc0ZOZU1vdkZVUHhQZUcKN0ZjaTUwL0tTdHZvTlpPZEtxWkZDd1lrZkkyc3NYdU1wQlAzN3gyaXByVjdtb1Z3R2RHSmI1MmVsTU5lMERlc2dUUGJKL0lXSXZ6RgozR1l4cVlDSFVsSHV6SkV6QllzZHR2TThUL1BDbEJ4aUxYUk5ibmpvdHpsZUZxYjI1dzNYUmZheU9aZzVHZFFQZUVtY2VXWERCaENhCmVReUVQT3JVVForLy9wWlhTdUtuT3lhRmZFU05GTmd2UUpsWVFRdWtqbmhQdGY2NzRlV1Q2T2RnWkh5cThFQmJaS2ZFaHM1K0tpQU4KVTQzYkRoOXJwVEpDQjdyQUtrMUJGQVczcjcycGdnd045Wi9zZnAvQzVCN3VLQU01aHdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQQpBNElCQVFBWlh5cGlrYmJSemljaE5YTGRLOTZNL2RvOW5HUzVRM3hWZ0EydXhUem0vNnFOa0FmT1NHU2s4T2NMcnBwUG9uYm9oa2VaCldWbk5CNVZaWmF2YTREb1NaNk9ac3ZLYzFGTTB3S3ZQSmQ4M0tVYjdTeWsxYlY3VGtUOERQRWNsZnNMbm41czVnMG9IbGhzcWtObHkKMFdQRlRBb0dIWFl5T0tHRUFSUG9DL28rWmZnZnZvTU55WmtTUUhpUmJvVlZQMmNUMWNrSnQ0aUNBNjVoTkdYdGUyOWhTR21u
tm , err := time . Parse ( time . RFC3339 , "2017-07-18T14:47:08.035Z" )
require . Nil ( t , err )
clock := dsig . NewFakeClockAt ( tm )
2021-03-30 19:56:20 +00:00
validator , err := NewValidator ( testGoogleMetadata ( ) , Clock ( clock ) )
2017-07-18 20:28:35 +00:00
require . Nil ( t , err )
require . NotNil ( t , validator )
auth , err := DecodeAuthResponse ( samlResponse )
require . Nil ( t , err )
require . NotNil ( t , auth )
_ , err = validator . ValidateSignature ( auth )
require . NotNil ( t , err )
}
2017-08-01 02:48:42 +00:00
// validate id's are unique and that I didn't screw up my maths
func TestIDGenerator ( t * testing . T ) {
idTable := make ( map [ string ] struct { } )
for i := 0 ; i < 100 ; i ++ {
id , err := generateSAMLValidID ( )
require . Nil ( t , err )
assert . Subset ( t , [ ] byte ( idAlphabet ) , [ ] byte ( id ) )
_ , ok := idTable [ id ]
assert . False ( t , ok )
idTable [ id ] = struct { } { }
}
}
2019-05-16 20:51:42 +00:00
func TestIDPrefix ( t * testing . T ) {
// Ensure ID comes with the appropriate prefix
id , err := generateSAMLValidID ( )
require . Nil ( t , err )
assert . Equal ( t , idPrefix , id [ : 2 ] )
}