diff --git a/connector/saml/saml.go b/connector/saml/saml.go index 8b55252a..a24df1c8 100644 --- a/connector/saml/saml.go +++ b/connector/saml/saml.go @@ -130,9 +130,7 @@ func (c *Config) Open(logger logrus.FieldLogger) (connector.Connector, error) { return c.openConnector(logger) } -func (c *Config) openConnector(logger logrus.FieldLogger) (interface { - connector.SAMLConnector -}, error) { +func (c *Config) openConnector(logger logrus.FieldLogger) (*provider, error) { requiredFields := []struct { name, val string }{ @@ -274,8 +272,11 @@ func (p *provider) HandlePOST(s connector.Scopes, samlResponse, inResponseTo str if err != nil { return ident, fmt.Errorf("decode response: %v", err) } + + rootElementSigned := true if p.validator != nil { - if rawResp, err = verify(p.validator, rawResp); err != nil { + rawResp, rootElementSigned, err = verifyResponseSig(p.validator, rawResp) + if err != nil { return ident, fmt.Errorf("verify signature: %v", err) } } @@ -285,24 +286,26 @@ func (p *provider) HandlePOST(s connector.Scopes, samlResponse, inResponseTo str return ident, fmt.Errorf("unmarshal response: %v", err) } - if p.issuer != "" && resp.Issuer != nil && resp.Issuer.Issuer != p.issuer { - return ident, fmt.Errorf("expected Issuer value %s, got %s", p.issuer, resp.Issuer.Issuer) - } + if rootElementSigned { + if p.issuer != "" && resp.Issuer != nil && resp.Issuer.Issuer != p.issuer { + return ident, fmt.Errorf("expected Issuer value %s, got %s", p.issuer, resp.Issuer.Issuer) + } - // Verify InResponseTo value matches the expected ID associated with - // the RelayState. - if resp.InResponseTo != inResponseTo { - return ident, fmt.Errorf("expected InResponseTo value %s, got %s", inResponseTo, resp.InResponseTo) - } + // Verify InResponseTo value matches the expected ID associated with + // the RelayState. + if resp.InResponseTo != inResponseTo { + return ident, fmt.Errorf("expected InResponseTo value %s, got %s", inResponseTo, resp.InResponseTo) + } - // Destination is optional. - if resp.Destination != "" && resp.Destination != p.redirectURI { - return ident, fmt.Errorf("expected destination %q got %q", p.redirectURI, resp.Destination) + // Destination is optional. + if resp.Destination != "" && resp.Destination != p.redirectURI { + return ident, fmt.Errorf("expected destination %q got %q", p.redirectURI, resp.Destination) - } + } - if err = p.validateStatus(&resp); err != nil { - return ident, err + if err = p.validateStatus(&resp); err != nil { + return ident, err + } } assertion := resp.Assertion @@ -481,41 +484,57 @@ func (p *provider) validateConditions(assertion *assertion) error { return nil } -// verify checks the signature info of a XML document and returns -// the signed elements. -// The Validate function of the goxmldsig library only looks for -// signatures on the root element level. But a saml Response is valid -// if the complete message is signed, or only the Assertion is signed, -// or but elements are signed. Therefore we first check a possible -// signature of the Response than of the Assertion. If one of these -// is successful the Response is considered as valid. -func verify(validator *dsig.ValidationContext, data []byte) (signed []byte, err error) { +// verifyResponseSig attempts to verify the signature of a SAML response or +// the assertion. +// +// If the root element is properly signed, this method returns it. +// +// The SAML spec requires supporting responses where the root element is +// unverified, but the sub elements are signed. In these cases, +// this method returns rootVerified=false to indicate that the +// elements should be trusted, but all other elements MUST be ignored. +// +// Note: we still don't support multiple tags. If there are +// multiple present this code will only process the first. +func verifyResponseSig(validator *dsig.ValidationContext, data []byte) (signed []byte, rootVerified bool, err error) { doc := etree.NewDocument() if err = doc.ReadFromBytes(data); err != nil { - return nil, fmt.Errorf("parse document: %v", err) + return nil, false, fmt.Errorf("parse document: %v", err) } - verified := false + response := doc.Root() transformedResponse, err := validator.Validate(response) if err == nil { - verified = true + // Root element is verified, return it. doc.SetRoot(transformedResponse) + signed, err = doc.WriteToBytes() + return signed, true, err } + // Ensures xmlns are copied down to the assertion element when they are defined in the root + // + // TODO: Only select from child elements of the root. assertion, err := etreeutils.NSSelectOne(response, "urn:oasis:names:tc:SAML:2.0:assertion", "Assertion") if err != nil { - return nil, fmt.Errorf("response does not contain an Assertion element") + return nil, false, fmt.Errorf("response does not contain an Assertion element") } transformedAssertion, err := validator.Validate(assertion) - if err == nil { - verified = true - response.RemoveChild(assertion) - response.AddChild(transformedAssertion) + if err != nil { + return nil, false, fmt.Errorf("response does not contain a valid signature element: %v", err) } - if verified != true { - return nil, fmt.Errorf("response does not contain a valid Signature element") + + // Verified an assertion but not the response. Can't trust any child elements, + // except the assertion. Remove them all. + for _, el := range response.ChildElements() { + response.RemoveChild(el) } - return doc.WriteToBytes() + + // We still return the full element, even though it's unverified + // because the element is not a valid XML document on its own. + // It still requires the root element to define things like namespaces. + response.AddChild(transformedAssertion) + signed, err = doc.WriteToBytes() + return signed, false, err } func uuidv4() string { diff --git a/connector/saml/saml_test.go b/connector/saml/saml_test.go index cba0fe12..bb7fa1b2 100644 --- a/connector/saml/saml_test.go +++ b/connector/saml/saml_test.go @@ -6,24 +6,216 @@ import ( "encoding/pem" "errors" "io/ioutil" + "sort" "strings" "testing" "time" "github.com/Sirupsen/logrus" - + "github.com/kylelemons/godebug/pretty" dsig "github.com/russellhaering/goxmldsig" "github.com/coreos/dex/connector" ) -const ( - defaultIssuer = "http://www.okta.com/exk91cb99lKkKSYoy0h7" - defaultRedirectURI = "http://localhost:5556/dex/callback" +// responseTest maps a SAML 2.0 response object to a set of expected values. +// +// Tests are defined in the "testdata" directory and are self-signed using xmlsec1. +// +// To add a new test, define a new, unsigned SAML 2.0 response that exercises some +// case, then sign it using the "testdata/gen.sh" script. +// +// cp testdata/good-resp.tmpl testdata/( testname ).tmpl +// vim ( testname ).tmpl # Modify your template for your test case. +// vim testdata/gen.sh # Add a xmlsec1 command to the generation script. +// ./testdata/gen.sh # Sign your template. +// +// To install xmlsec1 on Fedora run: +// +// sudo dnf install xmlsec1 xmlsec1-openssl +// +// On mac: +// +// brew install Libxmlsec1 +// +type responseTest struct { + // CA file and XML file of the response. + caFile string + respFile string - // Response ID embedded in our testdata. - testDataResponseID = "_fd1b3ef9-ec09-44a7-a66b-0d39c250f6a0" -) + // Values that should be used to validate the signature. + now string + inResponseTo string + redirectURI string + + // Attribute customization. + usernameAttr string + emailAttr string + groupsAttr string + + // Expected outcome of the test. + wantErr bool + wantIdent connector.Identity +} + +func TestGoodResponse(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/good-resp.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantIdent: connector.Identity{ + UserID: "eric.chiang+okta@coreos.com", + Username: "Eric", + Email: "eric.chiang+okta@coreos.com", + EmailVerified: true, + }, + } + test.run(t) +} + +func TestGroups(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/good-resp.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + groupsAttr: "groups", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantIdent: connector.Identity{ + UserID: "eric.chiang+okta@coreos.com", + Username: "Eric", + Email: "eric.chiang+okta@coreos.com", + EmailVerified: true, + Groups: []string{"Admins", "Everyone"}, + }, + } + test.run(t) +} + +// TestOkta tests against an actual response from Okta. +func TestOkta(t *testing.T) { + test := responseTest{ + caFile: "testdata/okta-ca.pem", + respFile: "testdata/okta-resp.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantIdent: connector.Identity{ + UserID: "eric.chiang+okta@coreos.com", + Username: "Eric", + Email: "eric.chiang+okta@coreos.com", + EmailVerified: true, + }, + } + test.run(t) +} + +func TestBadStatus(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/bad-status.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantErr: true, + } + test.run(t) +} + +func TestInvalidCA(t *testing.T) { + test := responseTest{ + caFile: "testdata/bad-ca.crt", // Not the CA that signed this response. + respFile: "testdata/good-resp.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantErr: true, + } + test.run(t) +} + +func TestUnsignedResponse(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/good-resp.tmpl", // Use the unsigned template, not the signed document. + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantErr: true, + } + test.run(t) +} + +func TestExpiredAssertion(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/assertion-signed.xml", + now: "2020-04-04T04:34:59.330Z", // Assertion has expired. + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantErr: true, + } + test.run(t) +} + +// TestAssertionSignedNotResponse ensures the connector validates SAML 2.0 +// responses where the assertion is signed but the root element, the +// response, isn't. +func TestAssertionSignedNotResponse(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/assertion-signed.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantIdent: connector.Identity{ + UserID: "eric.chiang+okta@coreos.com", + Username: "Eric", + Email: "eric.chiang+okta@coreos.com", + EmailVerified: true, + }, + } + test.run(t) +} + +// TestTwoAssertionFirstSigned tries to catch an edge case where an attacker +// provides a second assertion that's not signed. +func TestTwoAssertionFirstSigned(t *testing.T) { + test := responseTest{ + caFile: "testdata/ca.crt", + respFile: "testdata/two-assertions-first-signed.xml", + now: "2017-04-04T04:34:59.330Z", + usernameAttr: "Name", + emailAttr: "email", + inResponseTo: "6zmm5mguyebwvajyf2sdwwcw6m", + redirectURI: "http://127.0.0.1:5556/dex/callback", + wantIdent: connector.Identity{ + UserID: "eric.chiang+okta@coreos.com", + Username: "Eric", + Email: "eric.chiang+okta@coreos.com", + EmailVerified: true, + }, + } + test.run(t) +} func loadCert(ca string) (*x509.Certificate, error) { data, err := ioutil.ReadFile(ca) @@ -37,6 +229,63 @@ func loadCert(ca string) (*x509.Certificate, error) { return x509.ParseCertificate(block.Bytes) } +func (r responseTest) run(t *testing.T) { + c := Config{ + CA: r.caFile, + UsernameAttr: r.usernameAttr, + EmailAttr: r.emailAttr, + GroupsAttr: r.groupsAttr, + RedirectURI: r.redirectURI, + // Never logging in, don't need this. + SSOURL: "http://foo.bar/", + } + now, err := time.Parse(timeFormat, r.now) + if err != nil { + t.Fatalf("parse test time: %v", err) + } + + conn, err := c.openConnector(logrus.New()) + if err != nil { + t.Fatal(err) + } + conn.now = func() time.Time { return now } + resp, err := ioutil.ReadFile(r.respFile) + if err != nil { + t.Fatal(err) + } + samlResp := base64.StdEncoding.EncodeToString(resp) + + scopes := connector.Scopes{ + OfflineAccess: false, + Groups: true, + } + ident, err := conn.HandlePOST(scopes, samlResp, r.inResponseTo) + if err != nil { + if !r.wantErr { + t.Fatalf("handle response: %v", err) + } + return + } + + if r.wantErr { + t.Fatalf("wanted error") + } + sort.Strings(ident.Groups) + sort.Strings(r.wantIdent.Groups) + if diff := pretty.Compare(ident, r.wantIdent); diff != "" { + t.Error(diff) + } +} + +const ( + defaultIssuer = "http://www.okta.com/exk91cb99lKkKSYoy0h7" + defaultRedirectURI = "http://localhost:5556/dex/callback" + + // Response ID embedded in our testdata. + testDataResponseID = "_fd1b3ef9-ec09-44a7-a66b-0d39c250f6a0" +) + +// Depricated: Use testing framework established above. func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) { cert, err := loadCert(ca) if err != nil { @@ -51,7 +300,7 @@ func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) { t.Fatal(err) } - if _, err := verify(validator, data); err != nil { + if _, _, err := verifyResponseSig(validator, data); err != nil { if shouldSucceed { t.Fatal(err) } @@ -62,6 +311,7 @@ func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) { } } +// Depricated: Use testing framework established above. func newProvider(issuer string, redirectURI string) *provider { if issuer == "" { issuer = defaultIssuer @@ -106,28 +356,6 @@ func TestVerifyUnsignedMessageAndUnsignedAssertion(t *testing.T) { runVerify(t, "testdata/idp-cert.pem", "testdata/idp-resp.xml", false) } -func TestHandlePOST(t *testing.T) { - p := newProvider("", "") - scopes := connector.Scopes{ - OfflineAccess: false, - Groups: true, - } - data, err := ioutil.ReadFile("testdata/idp-resp.xml") - if err != nil { - t.Fatal(err) - } - ident, err := p.HandlePOST(scopes, base64.StdEncoding.EncodeToString(data), testDataResponseID) - if err != nil { - t.Fatal(err) - } - if ident.UserID != "eric.chiang+okta@coreos.com" { - t.Fatalf("unexpected UserID %q", ident.UserID) - } - if ident.Username != "admin" { - t.Fatalf("unexpected Username: %q", ident.UserID) - } -} - func TestValidateStatus(t *testing.T) { p := newProvider("", "") var err error diff --git a/connector/saml/testdata/assertion-signed.tmpl b/connector/saml/testdata/assertion-signed.tmpl new file mode 100644 index 00000000..239bf271 --- /dev/null +++ b/connector/saml/testdata/assertion-signed.tmpl @@ -0,0 +1,56 @@ + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + + + + + + + + + + + + + + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + diff --git a/connector/saml/testdata/assertion-signed.xml b/connector/saml/testdata/assertion-signed.xml new file mode 100644 index 00000000..308676d4 --- /dev/null +++ b/connector/saml/testdata/assertion-signed.xml @@ -0,0 +1,79 @@ + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + + + + + + + + + + + kDdpmKMPp7zjUeMTuntXJFpT6cs= + + + Q12w9zPo9Bqn3W2OT7lbFbhfIDQrp7SXd/+9ZWpY4mv3ApgaOcNX2VtpSE0EjorU +1NyrktVOkCYueJm/HVQF7gyF85KRlPBDLBZOwxbnnmrRFoCk+U2kjIt8k8eZ7NsD +jLFGFgEveS359uvaHZR1Exbr0PBYwS7aXR3fpmjMjZ9T8f8Oe3Nt/9nWPgz/dFhb +Aa+AniWuupfq2v6YMLZ+9GLiO0sOr8UVkW8AYOm2Bin30epikXT1Axi/VxWz/fjP +nMUkgusFnhkgmIf/YncAv4S9GY6DcaV2iEj6cL70S7pcgaeRFi3iozigl+9a+lFo +dt3Jy8Jq/N3OAyDP2DxLEw== + + +MIIDGTCCAgGgAwIBAgIJAKLbLcQajEf8MA0GCSqGSIb3DQEBCwUAMCMxDDAKBgNV +BAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNvbTAeFw0xNzA0MDQwNzAwNTNaFw0z +NzAzMzAwNzAwNTNaMCMxDDAKBgNVBAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH3dKWbRqCIZD2m3aHI +4lfBT+u/4DECde74Ggq9WugdTucVQzDZUTaI7wzn17JM9hdPmXvaSRG9BaB1H3uO +ZCs/fmdhBERRhPvuEVfAZaFfQfR7vn7WvUzT7zwMLLB8+EHzL3fOSGM2QnCOMeUD +AB27Pb0fuBW43NXaTD9rwfFCHvo1UP+TBJIPnV65HMeMGIrtGLt7MZTPuPm3LnYA +faXLf2vWSzL5nAgnJvUgceZXmyuciBfXpt8c1jIsj4y3tBoRTRqaxuaW1Eo7WMKF +a7s6KvTBKErPKuzAoIcVB4ir6jm1ticAgB72SScKtPJJdEPemTXRNNzkiw7VbpY9 +QacCAwEAAaNQME4wHQYDVR0OBBYEFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MB8GA1Ud +IwQYMBaAFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAHVXB5QmZfki9QpKzoiBNfpQ/mo6XWhExLGBTJXEWJT3P7JP +oR4Z0+85bp0fUK338s+WjyqTn0U55Jtp0B65Qxy6ythkZat/6NPp/S7gto2De6pS +hSGygokQioVQnoYQeK0MXl2QbtrWwNiM4HC+9yohbUfjwv8yI7opwn/rjB6X/4De +oX2YzwTBJgoIXF7zMKYFF0DrKQjbTQr/a7kfNjq4930o7VhFph9Qpdv0EWM3svTd +esSffLKbWcabtyMtCr5QyEwZiozd567oWFWZYeHQyEtd+w6tAFmz9ZslipdQEa/j +1xUtrScuXt19sUfOgjUvA+VUNeMLDdpHUKHNW/Q= + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + diff --git a/connector/saml/testdata/bad-ca.crt b/connector/saml/testdata/bad-ca.crt new file mode 100644 index 00000000..e7843494 --- /dev/null +++ b/connector/saml/testdata/bad-ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGTCCAgGgAwIBAgIJAINei+KBx541MA0GCSqGSIb3DQEBCwUAMCMxDDAKBgNV +BAoMA0JBRDETMBEGA1UEAwwKY29yZW9zLmNvbTAeFw0xNzA0MDQwNzAwNTNaFw0z +NzAzMzAwNzAwNTNaMCMxDDAKBgNVBAoMA0JBRDETMBEGA1UEAwwKY29yZW9zLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKfSVQCQMJhwdeesQqZo +YHktgGjKA//p176kWoqVEX8+cVgKc1IEAzN73L0KsBcNkaItbZycQxkku8NGUYvt +inEK8V61vjK3IQBOV2+qKOeWvHPXd280I2JSGy768ELpZcaEmnA0CVbMaLdHLFQ/ +tcRocDcMKDhNexlsJ/cDPwzSkky6FU6UnaSih+I432UeJs/hRvAs1YJ3+G6uSVQ7 +xo2Fk2i+qd3IvRWOBagwEhEFcd/MfAu4+w+UYW4W1BC9zJoO2ETBgUVJzaiUGZ5z +rX/KNAX/+kAQWQLKW1sVgRKOI2yfyIVaUzF6V2uxwHrbeV75Pr3ClVdvuUWRcXKH +Wn8CAwEAAaNQME4wHQYDVR0OBBYEFLw+L3SLMIR2wfd7IQG1m3rlgGP7MB8GA1Ud +IwQYMBaAFLw+L3SLMIR2wfd7IQG1m3rlgGP7MAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBABH2mDQuf+JqjHtBCp9coi1WuX5xJuoSKyOAvlz7QJk0bb+W +oONg+ETQ7jT7KheiFQorghdulZerv+L1dmLU5ut/Zbf1zoaWLslOgVPpOy6LP0aS +uaa31jm7Qpig47+kTZEpPN6vUPpmAD70/uo3NgRNj8pztkWr08fEIbX/3ukHvFUE +XPxYxgF5tFj8EY6cdflzlC/0TYmJiHt/viv/yQfrvMBRvsVHfjfzNRxbNwfEdKuf +YIs5KeP2al7APsmF5d/UFGzoQGXaKEOpCRJ+Oj3spooLhhzWqV4gPZLVgU0DD6ja +GPb2XgLA9mdEmMukHU0RMeb8R+r8RvytWKvuJQE= +-----END CERTIFICATE----- diff --git a/connector/saml/testdata/bad-ca.key b/connector/saml/testdata/bad-ca.key new file mode 100644 index 00000000..e8282053 --- /dev/null +++ b/connector/saml/testdata/bad-ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCn0lUAkDCYcHXn +rEKmaGB5LYBoygP/6de+pFqKlRF/PnFYCnNSBAMze9y9CrAXDZGiLW2cnEMZJLvD +RlGL7YpxCvFetb4ytyEATldvqijnlrxz13dvNCNiUhsu+vBC6WXGhJpwNAlWzGi3 +RyxUP7XEaHA3DCg4TXsZbCf3Az8M0pJMuhVOlJ2koofiON9lHibP4UbwLNWCd/hu +rklUO8aNhZNovqndyL0VjgWoMBIRBXHfzHwLuPsPlGFuFtQQvcyaDthEwYFFSc2o +lBmec61/yjQF//pAEFkCyltbFYESjiNsn8iFWlMxeldrscB623le+T69wpVXb7lF +kXFyh1p/AgMBAAECggEAHh/PSk6XqoVlZLSzMhPCXX4hcq3wkdtz8rCl4AJqJaEb +z2Xw1WQK/w7YzMZCXaD951KoPlh+YuEJI0BYGvoEw83nDc0p2wisT9XANDcjKI8S +POkMc1W0lE2Qu5onzpr+vefHoSR2GLKQiXWpK2ZURnFI01jHT3P5CNM1SU2336ES +XT1GXlxTz59BS04bySS3s8PQZTtmFvQAjtjOWkg+nzTYgEO7xU5968Px+jdlO+xf +ZKtjlRKRNRmVlylUvCmIT6kIzIdyjuBqw4yx0bM1Av9QwpPuDkRWBeiT8o5xeY+L +yOSxUCg24CGgAl6mGVXWh+BC9Z3h8dXg9eMervT9gQKBgQDS6QffOBr+j19FiQwH +t+5h2klOR/mu8TX6oW8Dc6o5YsnLt0uQqa2jLq8kYRkOBVg68mMFvZXmhPoKv4hk +rOfDKjVfPz9ShrvuY301BAp/hdi/hNP+MAt683UlcnpwLOaASZMr+MjdnVVzfF6X +iNlV2RE3pAxSFkVlMPJJTmPPEQKBgQDLsxbYFj4JBKhMehdcsqjUtDuzLBPqisVa +cWKACxPAXIjztsEXF4F7sQk7q68uzLU80uPBVAJjf6lWwK9tcUdcBFHCXdqj8ZXB +77W4gZSkqHY0T6DJF+NZRF+z4cOg3qtDjTvqhetl5yyiY9IPyiSckNAz40pWD/0X +U/0nObuwjwKBgQCpWpUHmHWUkmtd2n3edMLlr/HM+d5zqxw89APAMdAt5DVFbxku +QBE9Ru87tvv3VjNSoe8BXQpQ39Yna0SKEozHGc1hfdfK3IVrFlgjieskGsXAg1f2 +c33EbFlUiGfoSyWLPYj/dfVUflFvOh56b1iUpog8tW1vPJLcfkEOu/NJAQKBgQCu +LAp7Z8FRarcQ9VAmhekQPq/RSv4YjOGkrNChVVdlInpDkV9XBFVF0yFm8SzQYl8R +i+0McG2+b/j2YbleZf6zMkpKXH/HsJjxg6qpAbt8c0LnBbMgXxmZSXpfT8o7MknU +b93scOfPcTRcAegqchiN+tDbnRwBrJgmqz0JnjbbBwKBgCXOWMgS8Azvvw+lUqua +yLdcAilAaqchgVBkI5ATZQodopEP+Gvevvzh6G8uQJp9fGrL/fR/tNg2viwCF/X8 +ROATx1z98/ItA3kyYhiNt/A6EqOb8SVOMq/eeMpvk+RB6gA9YdMf5H9XClW4vxLy +jaw+YQ6hOyMTmFfUI2/FumFE +-----END PRIVATE KEY----- diff --git a/connector/saml/testdata/bad-status.tmpl b/connector/saml/testdata/bad-status.tmpl new file mode 100644 index 00000000..093ae948 --- /dev/null +++ b/connector/saml/testdata/bad-status.tmpl @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + diff --git a/connector/saml/testdata/bad-status.xml b/connector/saml/testdata/bad-status.xml new file mode 100644 index 00000000..7de16ed5 --- /dev/null +++ b/connector/saml/testdata/bad-status.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + 96Mymeqjk6Mm0azcGKf6nD6SFWY= + + + AbzrvvisCPqcZ0OnkYNaFeuC8wIkivlIL479c3HJmFJycXLxm6LzS7wILw47huzP +/8r2FnZ3MT/qJdibz53zNFXBADu2af/lSx9bkuxZpYN5J91cgCjUt68xF8Xvo4d8 +jqOKq3H3C7DqU52QyF+XoPKHaBWUcefJoeLQEwUm9C+U6mSP5AZ82m1DoqyhOuWk +UYTjVUjVro+J1x9Bp/dyZ8OczaN+S9vIYm6AbsV5klYPQug951da5KJ/K8fvure9 +OIHaLnEb4BtQb7qDA8+3jPU7c88XvP+27FtSqiWM0vGGSc9pq4kS5hHmsrdbIkyl +Ajr+mNXxlNnXRQNEsqE+Gw== + + +MIIDGTCCAgGgAwIBAgIJAKLbLcQajEf8MA0GCSqGSIb3DQEBCwUAMCMxDDAKBgNV +BAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNvbTAeFw0xNzA0MDQwNzAwNTNaFw0z +NzAzMzAwNzAwNTNaMCMxDDAKBgNVBAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH3dKWbRqCIZD2m3aHI +4lfBT+u/4DECde74Ggq9WugdTucVQzDZUTaI7wzn17JM9hdPmXvaSRG9BaB1H3uO +ZCs/fmdhBERRhPvuEVfAZaFfQfR7vn7WvUzT7zwMLLB8+EHzL3fOSGM2QnCOMeUD +AB27Pb0fuBW43NXaTD9rwfFCHvo1UP+TBJIPnV65HMeMGIrtGLt7MZTPuPm3LnYA +faXLf2vWSzL5nAgnJvUgceZXmyuciBfXpt8c1jIsj4y3tBoRTRqaxuaW1Eo7WMKF +a7s6KvTBKErPKuzAoIcVB4ir6jm1ticAgB72SScKtPJJdEPemTXRNNzkiw7VbpY9 +QacCAwEAAaNQME4wHQYDVR0OBBYEFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MB8GA1Ud +IwQYMBaAFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAHVXB5QmZfki9QpKzoiBNfpQ/mo6XWhExLGBTJXEWJT3P7JP +oR4Z0+85bp0fUK338s+WjyqTn0U55Jtp0B65Qxy6ythkZat/6NPp/S7gto2De6pS +hSGygokQioVQnoYQeK0MXl2QbtrWwNiM4HC+9yohbUfjwv8yI7opwn/rjB6X/4De +oX2YzwTBJgoIXF7zMKYFF0DrKQjbTQr/a7kfNjq4930o7VhFph9Qpdv0EWM3svTd +esSffLKbWcabtyMtCr5QyEwZiozd567oWFWZYeHQyEtd+w6tAFmz9ZslipdQEa/j +1xUtrScuXt19sUfOgjUvA+VUNeMLDdpHUKHNW/Q= + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + diff --git a/connector/saml/testdata/ca.crt b/connector/saml/testdata/ca.crt new file mode 100644 index 00000000..00f1cf04 --- /dev/null +++ b/connector/saml/testdata/ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGTCCAgGgAwIBAgIJAKLbLcQajEf8MA0GCSqGSIb3DQEBCwUAMCMxDDAKBgNV +BAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNvbTAeFw0xNzA0MDQwNzAwNTNaFw0z +NzAzMzAwNzAwNTNaMCMxDDAKBgNVBAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH3dKWbRqCIZD2m3aHI +4lfBT+u/4DECde74Ggq9WugdTucVQzDZUTaI7wzn17JM9hdPmXvaSRG9BaB1H3uO +ZCs/fmdhBERRhPvuEVfAZaFfQfR7vn7WvUzT7zwMLLB8+EHzL3fOSGM2QnCOMeUD +AB27Pb0fuBW43NXaTD9rwfFCHvo1UP+TBJIPnV65HMeMGIrtGLt7MZTPuPm3LnYA +faXLf2vWSzL5nAgnJvUgceZXmyuciBfXpt8c1jIsj4y3tBoRTRqaxuaW1Eo7WMKF +a7s6KvTBKErPKuzAoIcVB4ir6jm1ticAgB72SScKtPJJdEPemTXRNNzkiw7VbpY9 +QacCAwEAAaNQME4wHQYDVR0OBBYEFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MB8GA1Ud +IwQYMBaAFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAHVXB5QmZfki9QpKzoiBNfpQ/mo6XWhExLGBTJXEWJT3P7JP +oR4Z0+85bp0fUK338s+WjyqTn0U55Jtp0B65Qxy6ythkZat/6NPp/S7gto2De6pS +hSGygokQioVQnoYQeK0MXl2QbtrWwNiM4HC+9yohbUfjwv8yI7opwn/rjB6X/4De +oX2YzwTBJgoIXF7zMKYFF0DrKQjbTQr/a7kfNjq4930o7VhFph9Qpdv0EWM3svTd +esSffLKbWcabtyMtCr5QyEwZiozd567oWFWZYeHQyEtd+w6tAFmz9ZslipdQEa/j +1xUtrScuXt19sUfOgjUvA+VUNeMLDdpHUKHNW/Q= +-----END CERTIFICATE----- diff --git a/connector/saml/testdata/ca.key b/connector/saml/testdata/ca.key new file mode 100644 index 00000000..05a43130 --- /dev/null +++ b/connector/saml/testdata/ca.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCh93Slm0agiGQ9 +pt2hyOJXwU/rv+AxAnXu+BoKvVroHU7nFUMw2VE2iO8M59eyTPYXT5l72kkRvQWg +dR97jmQrP35nYQREUYT77hFXwGWhX0H0e75+1r1M0+88DCywfPhB8y93zkhjNkJw +jjHlAwAduz29H7gVuNzV2kw/a8HxQh76NVD/kwSSD51euRzHjBiK7Ri7ezGUz7j5 +ty52AH2ly39r1ksy+ZwIJyb1IHHmV5srnIgX16bfHNYyLI+Mt7QaEU0amsbmltRK +O1jChWu7Oir0wShKzyrswKCHFQeIq+o5tbYnAIAe9kknCrTySXRD3pk10TTc5IsO +1W6WPUGnAgMBAAECggEBAJUJUDPHIwE7IAo/Drf9UpFvl2wWPmS6n+yKLeRuA0WN +Gnq27QH5Jqro7BdTCv7NpLEklNYLsar55UCWJacbCn9lSJo2Aqge3yC3GwxFRP9t +2RHwAAVU8hHM/tmhVkn8ZLDC5o32qlNorVBG+BCEZ0n0bsYlds2+Mq8x1XGSZX7q +Yyjt02q2VCEDPVUGqR2ONEE98Bv++mUfXzZjGohBPre67PuvEppEwo/uf4ILuyYB +lusSYcmPD2IBE/7FcRPefb2uDP9c6Tjo8PHXpK5hDBCtLz8lXheYMuTp9GqJmcOk +kw8af2jNkMUEpFho0RqnrJNQ3A7M5PXQiWxwYSL/2RkCgYEAz4Kg0qm4Oe5jl+4r +R986nElujo9g9Ad2sy9yT6fqceWoMKf68wh6bMx7HWXRqASS7bJ8wmS9EwgaWLBO +mjqZax99F1UiFk3+5lNEaYB1OlFaWRsZSapoX6b2JyfEbODqSgKVIaYVTYBHLip3 +3ab/EKNUrNbW9bLSXgbt3aT2kU0CgYEAx9BiErhZqkgmip+4omCWuTr6Lj/awftB +CVTfwLBYkh7SZcRAWc2bx7a1Bs1rvlczhGYsOlrZXnQRSM4fuUxUb+N5TCzZI9V/ +Prc2r2Lps3AB5CDPLZoyv0efBjSLqAA1tYKTvAHREi9Wfe5PNdfKiwrz6KmIwV3c ++s2YSWcU5MMCgYEArmzvIiTnZkqsDJl2aAOMELLo64w5wuZDMHtBaxOKThLtPXj1 +yDPoNGvtUNi1UrYFiyftFrn29HhrLQGGEL4RF6pwS5yT+ou1J4X2i3gfEdYwS5Yr +u3AyK7T8VA1pXtvwFCX3lUE1xt989aFdAEPPQv0HwAEWz5Bwo/jPGPABEkECgYBy +vDWUikbygHuhHhXnJ49kzXjbFc+Hk77EnPferWQug4RM62QILQhGpaNNRKeZpHjw +jbrXx1MJ6ZwDMlkFDc9ucDA2jYoiCXYHjSzZiPKpFqf/VtegV+rL61RlO8b1sSkm +ENTEIEbtKkGADldtk3u6W4+zCaZ9YmiBm4zWmVpmAQKBgHvNRcbITib+sbQE+cJM +4TtrAHFTLWtGCd+n6rKrE8gjt7ypbBOMlOau60LZ2Pbt3DrqOLtDoOalvZhYraOb +rkoPbDAVaXAmUJ8tw2M07PPLpJuruLSFw16VrBaDiyubO8H/hvnuF4kKpRvt8ty0 +DBogMo9McFczyisRKebmANLw +-----END PRIVATE KEY----- diff --git a/connector/saml/testdata/gen.sh b/connector/saml/testdata/gen.sh new file mode 100755 index 00000000..dec6b158 --- /dev/null +++ b/connector/saml/testdata/gen.sh @@ -0,0 +1,47 @@ +#!/bin/bash -ex + +# Always run from the testdata directory +cd "$(dirname "$0")" + +# Uncomment these commands to regenerate the CA files. +# +# openssl req \ +# -nodes \ +# -newkey rsa:2048 \ +# -keyout ca.key \ +# -new -x509 -days 7300 \ +# -extensions v3_ca \ +# -out ca.crt \ +# -subj "/O=DEX/CN=coreos.com" +# +# openssl req \ +# -nodes \ +# -newkey rsa:2048 \ +# -keyout bad-ca.key \ +# -new -x509 -days 7300 \ +# -extensions v3_ca \ +# -out bad-ca.crt \ +# -subj "/O=BAD/CN=coreos.com" + +# Sign these files using xmlsec1. +# +# Templates MUST have a element already embedded in them so +# xmlsec1 can know where to embed the signature. +# +# See: https://sgros.blogspot.com/2013/01/signing-xml-document-using-xmlsec1.html + +xmlsec1 --sign --privkey-pem ca.key,ca.crt --output good-resp.xml good-resp.tmpl +xmlsec1 --sign --privkey-pem ca.key,ca.crt --output bad-status.xml bad-status.tmpl + +# Sign a specific sub element, not just the root. +# +# Values match up to the element in the documents. +xmlsec1 --sign --privkey-pem ca.key,ca.crt \ + --id-attr:ID Assertion \ + --output assertion-signed.xml assertion-signed.tmpl + +xmlsec1 --sign --privkey-pem ca.key,ca.crt \ + --id-attr:ID Assertion \ + --output two-assertions-first-signed.xml \ + two-assertions-first-signed.tmpl + diff --git a/connector/saml/testdata/good-resp.tmpl b/connector/saml/testdata/good-resp.tmpl new file mode 100644 index 00000000..b3c3c55e --- /dev/null +++ b/connector/saml/testdata/good-resp.tmpl @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + diff --git a/connector/saml/testdata/good-resp.xml b/connector/saml/testdata/good-resp.xml new file mode 100644 index 00000000..3e9b3416 --- /dev/null +++ b/connector/saml/testdata/good-resp.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + ew38E1LGMwYT+0gUZNq0RacD3GM= + + + TQ84pCaZAyEDBGkNafTMfwPUWujFvmdoXzyYMXZURIlKhA8Pv1bIZfzQ5MgbQr1W +z2Ye99/hss24Y4ueNT9nS+53LvDekhNctFGYfgdMjrbxs8Awo3KnbvveDib5zGvk +fWd/0/QLvlbFd/3670QGb5JQE1nD9mlAqPonyQgoufk63gEM84+tU71cAM7XKiy6 +09MC0y4s967qRAiLAtfgKbvi+46HkF/g+WsS74Wa8cu/A863URt56W0cogRjHWpQ +B+q8/FyVeJRE0NlrOjhnsgTU2QJtvkxYYvqIpRDbMv53NLKeAFvRhOcyJxhFXtSj +LF/oPMjbmHji4ylFiAlQWw== + + +MIIDGTCCAgGgAwIBAgIJAKLbLcQajEf8MA0GCSqGSIb3DQEBCwUAMCMxDDAKBgNV +BAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNvbTAeFw0xNzA0MDQwNzAwNTNaFw0z +NzAzMzAwNzAwNTNaMCMxDDAKBgNVBAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH3dKWbRqCIZD2m3aHI +4lfBT+u/4DECde74Ggq9WugdTucVQzDZUTaI7wzn17JM9hdPmXvaSRG9BaB1H3uO +ZCs/fmdhBERRhPvuEVfAZaFfQfR7vn7WvUzT7zwMLLB8+EHzL3fOSGM2QnCOMeUD +AB27Pb0fuBW43NXaTD9rwfFCHvo1UP+TBJIPnV65HMeMGIrtGLt7MZTPuPm3LnYA +faXLf2vWSzL5nAgnJvUgceZXmyuciBfXpt8c1jIsj4y3tBoRTRqaxuaW1Eo7WMKF +a7s6KvTBKErPKuzAoIcVB4ir6jm1ticAgB72SScKtPJJdEPemTXRNNzkiw7VbpY9 +QacCAwEAAaNQME4wHQYDVR0OBBYEFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MB8GA1Ud +IwQYMBaAFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAHVXB5QmZfki9QpKzoiBNfpQ/mo6XWhExLGBTJXEWJT3P7JP +oR4Z0+85bp0fUK338s+WjyqTn0U55Jtp0B65Qxy6ythkZat/6NPp/S7gto2De6pS +hSGygokQioVQnoYQeK0MXl2QbtrWwNiM4HC+9yohbUfjwv8yI7opwn/rjB6X/4De +oX2YzwTBJgoIXF7zMKYFF0DrKQjbTQr/a7kfNjq4930o7VhFph9Qpdv0EWM3svTd +esSffLKbWcabtyMtCr5QyEwZiozd567oWFWZYeHQyEtd+w6tAFmz9ZslipdQEa/j +1xUtrScuXt19sUfOgjUvA+VUNeMLDdpHUKHNW/Q= + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + diff --git a/connector/saml/testdata/idp-resp-signed-assertion0.xml b/connector/saml/testdata/idp-resp-signed-assertion0.xml new file mode 100644 index 00000000..01feb1ca --- /dev/null +++ b/connector/saml/testdata/idp-resp-signed-assertion0.xml @@ -0,0 +1,57 @@ + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + HFNooGfpAONF7T96W3bFsXkH51k=dI0QBihhNT5rtRYE9iB0lEKXkE7Yr4+QueOItRH2RcKwAXJ6DA/m3D/S7qwXk00Hn8ZpHu48ZO+HJpyweEEh2UuUWJCCTwwggagKybbSoRx3UTnSuNAFTdoDWTGt89z8j4+gRMC0sepYwppF3u87vJKRVBh8HjFfrHmWsZKwNtfoeXOOFCeatwxcI1sKCoBs2fTn78683ThoAJe3pygipSHY5WPt4dfT/yAY5Ars+OPY/N02M80OfIygZXdJwND0tVPJIF3M9DaehSkvCBHs7QA7DARsRXcuXdsYY7R8wHzqDVJZ4OvcsprONamm5AgUIpql1CjT94rFwWOFyxF2tg== +MIIEUTCCAzmgAwIBAgIJAJdmunb39nFKMA0GCSqGSIb3DQEBCwUAMHgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQKEwNJRFAxFDASBgNVBAsTC1NTT1Byb3ZpZGVyMRMwEQYDVQQDEwpkZXYtOTY5MjQ0MRswGQYJKoZIhvcNAQkBFgxpbmZvQGlkcC5vcmcwHhcNMTcwMTI0MTczMTI3WhcNMjcwMTIyMTczMTI3WjB4MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEChMDSURQMRQwEgYDVQQLEwtTU09Qcm92aWRlcjETMBEGA1UEAxMKZGV2LTk2OTI0NDEbMBkGCSqGSIb3DQEJARYMaW5mb0BpZHAub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0X/AE1tmDmhGRROAWaJ82XSORivRfgNt9Fb4rLrf6nIJsQN3vNb1Nk4DSUEDdQuvHNaEemSVkSPgfq5qnhh37bJaghr0728J8dOyYzV5eArPvsbyCRcnhXQzpCK2zvHwjgxNJMsNJLbnYpG/U+dCdCtcOOn9JEhKO8wKn06y2tcrvC1uuVs7bodukPUNq82KJTyvCQP8jh1hEZXeR2siJFDeJj1n2FNTMeCKIqOb42J/i+sBTlyK3mV5Ni++hI/ssIYVbPwrMIBd6sKLVAgInshBHOj/7XcXW/rMf468YtBKs4XnXsE3hLoU02aWCRDlVHa4hm3jfIAqEADOUumklQIDAQABo4HdMIHaMB0GA1UdDgQWBBRjN/dQSvhZxIsHTXmDKQJkPrjp0TCBqgYDVR0jBIGiMIGfgBRjN/dQSvhZxIsHTXmDKQJkPrjp0aF8pHoweDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAoTA0lEUDEUMBIGA1UECxMLU1NPUHJvdmlkZXIxEzARBgNVBAMTCmRldi05NjkyNDQxGzAZBgkqhkiG9w0BCQEWDGluZm9AaWRwLm9yZ4IJAJdmunb39nFKMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIqHUglIUAA+BKMW6B0Q+cqIgDr9fWlsvDwIVK7/cvUeGIH3icSsje9AVZ4nQOJpxmC/E06HfuDXmbT1wG16jNo01mPW9qaOGRJuQqlZdegCSF385o/OHcbaEKBRwyYuvLfu80EREj8wcMUKFpExoaxK7K8DS7hh3w7exLB80jyhIaDEYc1hdyAl+206XpOXSYBetsg7I622R2+ajSL7ygUxQjmKQ5DyInPdXzCFCL6Ew/BN0dwzfnBEEK223ruOWBLpj13zMC077dor/NgYyHZU6iqiDS2eYO5jhVMve/mP9734+6N34seQRmekfmsf2dJcEQhPVYr/j0DeJc3men4= + + eric.chiang+okta@coreos.com + + + + + + + http://localhost:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+attacker@coreos.com + + + + + + + http://localhost:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + attacker + + + eric.chiang+attacker@coreos.com + + + + diff --git a/connector/saml/testdata/okta-resp.xml b/connector/saml/testdata/okta-resp.xml index 9dff8e10..8b4955b0 100644 --- a/connector/saml/testdata/okta-resp.xml +++ b/connector/saml/testdata/okta-resp.xml @@ -1,4 +1,4 @@ -http://www.okta.com/exk91cb99lKkKSYoy0h7Phu93l0D97JSMIYDZBdVeNLN0pwBVHhzUDWxbh4sc6g=M2gMHOmnMAFgh2apq/2jHwDYmisUkYMUqxrWkQJf3RHFotl4EeDlcqq/FzOboJc3NcbKBqQY3CWsWhWh5cNWHDgNneaahW4czww+9DCM0R/zz5c6GuMYFEh5df2sDn/dWk/jbKMiAMgPdKJ2x/+5Xk9q4axC52TdQrrbZtzAAAn4CgrT6Kf11qfMl5wpDarg3qPw7ANxWn2DKzCsvCkOIwM2+AXh+sEXmTvvZIQ0vpv098FH/ZTGt4sCwb1bmRZ3UZLhBcxVc/sjuEW/sQ6pbQHkjrXIR5bxXzGNUxYpcGjrp9HGF+In0BAc+Ds/A0H142e1rgtcX8LH2pbG8URJSQ==MIIDpDCCAoygAwIBAgIGAVjgvNroMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG +http://www.okta.com/exk91cb99lKkKSYoy0h7/jttoTHVc1zHB8tgDVQtiNLAhKAiL24V5Np/SNViPag=y1v4Q0No1l82Y32SHL8weC4mXPWRmhy0SdWPd4Dw1gMWW2aGdnMt11VGom4z1/42HxKB0EBje/UPJeagcpEgJ2JQTdb1SvZrQaxwcWexH0Qyw2Tim9kv66dgr0Uo6PRmkYw/ewcimgdNZUOieffUG1Wc+YWtllmE4nz6NR3aLT9WScbC5smbXk2HwWP9xSg3loKMYTUSH32sRePw76QdGbVExUYyFjnB+oY9mIzBHvCTjZw6JGqEaMBmzReCgLZEBdeo0BuitTWCJY5bayJEpasJCQE4iurcKsz6wMheBbEAcQBqiExSUU8dJgQPhD9y5nMBEGC4cvdq4xbvWBKfVQ==MIIDpDCCAoygAwIBAgIGAVjgvNroMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi05NjkyNDQxHDAaBgkqhkiG9w0BCQEW DWluZm9Ab2t0YS5jb20wHhcNMTYxMjA4MjMxOTIzWhcNMjYxMjA4MjMyMDIzWjCBkjELMAkGA1UE @@ -14,7 +14,7 @@ eg2DRW6I9/v/mfN2KAQEDqF9aSNlNFWZWmb52kukMv3tLWw0puaevicIZ/nZrW+D3CLDVVfWHeVt u/Jh63cVya/VEoP1SVa0XQLf/ial+XuwdBBL1yc+7o2XHOfluDaXw/v2FWYpZtICf3a39giGaNWp eCT4g2TDWM4Jf/X7/mRbLX9tQO7XRural1CXx8VIMcmbKNbUtQiO8yEtVQ+FJKOsl7KOSzkgqNiL rJy+Y0D9biLZVKp07KWAY2FPCEtCkBrvo8BhvWbxWMA8CVQNAiTylM27Pc6kbc64pNr7C1Jx1wuE -mVy9Fgb4PA2N3hPeD7mBmGGp7CfDbGcyhttp://www.okta.com/exk91cb99lKkKSYoy0h7ufwWUjecX6I/aQb4WW9P9ZMLG3C8hN6LaZyyb/EATIs=jKtNBzxAL67ssuzWkkbf0yzqRyZ51y2JjBQ9C6bW8io/JOYQB2v7Bix7Eu/RjJslO7OBqD+3tPrK7ZBOy2+LFuAh3cDNa3U5NhO0raLrn/2YoJXfjj3XX3hyQv6GVxo0EY1KJNXOzWxjp9RVDpHslPTIL1yDC/oy0Mlzxu6pXBEerz9J2/Caenq66Skb5/DAT8FvrJ2s1bxuMagShs3APhC1hD8mvktZ+ZcN8ujs2SebteGK4IoOCx+e8+v2CyycBv1l5l+v5I+D2HnbAw4LfvHnW4rZOJT2AvoI47p1YBK1qDsJutG3jUPKy4Yx5YF73Xi1oytr+rrHyx/lfFPd2A==MIIDpDCCAoygAwIBAgIGAVjgvNroMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG +mVy9Fgb4PA2N3hPeD7mBmGGp7CfDbGcyhttp://www.okta.com/exk91cb99lKkKSYoy0h7W9osU1+7JHYa6E3Y3tvOCBN/jAGVTl39Wngwkq+4jKI=OWa1WvK9+/HOgfm37RwpzUYryJl3ryzdqRUEMlV3ZdLcCz7ZnQ26PCoZD7KxdxUjRci81Ev3OsT8pMCj+sDbFbvBhdRrVvS0sJEgqIFftgD3CYH6OaNGmahSum5Cz+p7xNow/XNQcxjEI2luAtMs+l9JlH8eNPvVVE8RSnXdq9G+y6Iu6RKBVESN9Lgwc6+L2XpqzalZv4d3D+c5dyFCjtNXLOLCJtu3F5w+dYM3KuYJ913S7fbXB2Tv7yRioc9Ssuehft5YacPY9ACsi0PZYAs9Gh4wlzu2yI+7cBfA6hn+h3T/uLu3DMWtHelKtkyOvJS2kFYJlFDio+h7uUbi9A==MIIDpDCCAoygAwIBAgIGAVjgvNroMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi05NjkyNDQxHDAaBgkqhkiG9w0BCQEW DWluZm9Ab2t0YS5jb20wHhcNMTYxMjA4MjMxOTIzWhcNMjYxMjA4MjMyMDIzWjCBkjELMAkGA1UE @@ -30,4 +30,4 @@ eg2DRW6I9/v/mfN2KAQEDqF9aSNlNFWZWmb52kukMv3tLWw0puaevicIZ/nZrW+D3CLDVVfWHeVt u/Jh63cVya/VEoP1SVa0XQLf/ial+XuwdBBL1yc+7o2XHOfluDaXw/v2FWYpZtICf3a39giGaNWp eCT4g2TDWM4Jf/X7/mRbLX9tQO7XRural1CXx8VIMcmbKNbUtQiO8yEtVQ+FJKOsl7KOSzkgqNiL rJy+Y0D9biLZVKp07KWAY2FPCEtCkBrvo8BhvWbxWMA8CVQNAiTylM27Pc6kbc64pNr7C1Jx1wuE -mVy9Fgb4PA2N3hPeD7mBmGGp7CfDbGcyeric.chiang+okta@coreos.comhttp://localhost:5556/dex/callbackurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport +mVy9Fgb4PA2N3hPeD7mBmGGp7CfDbGcyeric.chiang+okta@coreos.comhttp://127.0.0.1:5556/dex/callbackurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransporteric.chiang+okta@coreos.comEricEveryoneAdmins diff --git a/connector/saml/testdata/two-assertions-first-signed.tmpl b/connector/saml/testdata/two-assertions-first-signed.tmpl new file mode 100644 index 00000000..22f07cda --- /dev/null +++ b/connector/saml/testdata/two-assertions-first-signed.tmpl @@ -0,0 +1,99 @@ + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + + + + + + + + + + + + + + + + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + + + I AM AN ATTACKER TRYING TO GET YOU TO USE THIS ASSERTION!!! + + + + + Everyone + Admins + + + + diff --git a/connector/saml/testdata/two-assertions-first-signed.xml b/connector/saml/testdata/two-assertions-first-signed.xml new file mode 100644 index 00000000..ccc363b4 --- /dev/null +++ b/connector/saml/testdata/two-assertions-first-signed.xml @@ -0,0 +1,122 @@ + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + + + + + + + + + + + + + + + + kDdpmKMPp7zjUeMTuntXJFpT6cs= + + + Q12w9zPo9Bqn3W2OT7lbFbhfIDQrp7SXd/+9ZWpY4mv3ApgaOcNX2VtpSE0EjorU +1NyrktVOkCYueJm/HVQF7gyF85KRlPBDLBZOwxbnnmrRFoCk+U2kjIt8k8eZ7NsD +jLFGFgEveS359uvaHZR1Exbr0PBYwS7aXR3fpmjMjZ9T8f8Oe3Nt/9nWPgz/dFhb +Aa+AniWuupfq2v6YMLZ+9GLiO0sOr8UVkW8AYOm2Bin30epikXT1Axi/VxWz/fjP +nMUkgusFnhkgmIf/YncAv4S9GY6DcaV2iEj6cL70S7pcgaeRFi3iozigl+9a+lFo +dt3Jy8Jq/N3OAyDP2DxLEw== + + +MIIDGTCCAgGgAwIBAgIJAKLbLcQajEf8MA0GCSqGSIb3DQEBCwUAMCMxDDAKBgNV +BAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNvbTAeFw0xNzA0MDQwNzAwNTNaFw0z +NzAzMzAwNzAwNTNaMCMxDDAKBgNVBAoMA0RFWDETMBEGA1UEAwwKY29yZW9zLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKH3dKWbRqCIZD2m3aHI +4lfBT+u/4DECde74Ggq9WugdTucVQzDZUTaI7wzn17JM9hdPmXvaSRG9BaB1H3uO +ZCs/fmdhBERRhPvuEVfAZaFfQfR7vn7WvUzT7zwMLLB8+EHzL3fOSGM2QnCOMeUD +AB27Pb0fuBW43NXaTD9rwfFCHvo1UP+TBJIPnV65HMeMGIrtGLt7MZTPuPm3LnYA +faXLf2vWSzL5nAgnJvUgceZXmyuciBfXpt8c1jIsj4y3tBoRTRqaxuaW1Eo7WMKF +a7s6KvTBKErPKuzAoIcVB4ir6jm1ticAgB72SScKtPJJdEPemTXRNNzkiw7VbpY9 +QacCAwEAAaNQME4wHQYDVR0OBBYEFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MB8GA1Ud +IwQYMBaAFNHyGYyY2+eZ1l7ZLPZsnc3GOtj/MAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAHVXB5QmZfki9QpKzoiBNfpQ/mo6XWhExLGBTJXEWJT3P7JP +oR4Z0+85bp0fUK338s+WjyqTn0U55Jtp0B65Qxy6ythkZat/6NPp/S7gto2De6pS +hSGygokQioVQnoYQeK0MXl2QbtrWwNiM4HC+9yohbUfjwv8yI7opwn/rjB6X/4De +oX2YzwTBJgoIXF7zMKYFF0DrKQjbTQr/a7kfNjq4930o7VhFph9Qpdv0EWM3svTd +esSffLKbWcabtyMtCr5QyEwZiozd567oWFWZYeHQyEtd+w6tAFmz9ZslipdQEa/j +1xUtrScuXt19sUfOgjUvA+VUNeMLDdpHUKHNW/Q= + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + Eric + + + Everyone + Admins + + + + + + http://www.okta.com/exk91cb99lKkKSYoy0h7 + + eric.chiang+okta@coreos.com + + + + + + + http://127.0.0.1:5556/dex/callback + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + eric.chiang+okta@coreos.com + + + + + I AM AN ATTACKER TRYING TO GET YOU TO USE THIS ASSERTION!!! + + + + + Everyone + Admins + + + +