forked from mystiq/dex
		
	Fixes #1304, if we want to be harsh. However, I think if it was the user's intention to pass two certs, and the second one couldn't be read, that shouldn't just disappear. After all, when attempting to login later, that might fail because the expected IdP cert data isn't there. Signed-off-by: Stephan Renatus <srenatus@chef.io>
		
			
				
	
	
		
			504 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			504 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package saml
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/x509"
 | 
						|
	"encoding/base64"
 | 
						|
	"encoding/pem"
 | 
						|
	"errors"
 | 
						|
	"io/ioutil"
 | 
						|
	"sort"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/kylelemons/godebug/pretty"
 | 
						|
	dsig "github.com/russellhaering/goxmldsig"
 | 
						|
	"github.com/sirupsen/logrus"
 | 
						|
 | 
						|
	"github.com/dexidp/dex/connector"
 | 
						|
)
 | 
						|
 | 
						|
// 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
 | 
						|
 | 
						|
	// Values that should be used to validate the signature.
 | 
						|
	now          string
 | 
						|
	inResponseTo string
 | 
						|
	redirectURI  string
 | 
						|
	entityIssuer 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)
 | 
						|
}
 | 
						|
 | 
						|
func TestInvalidSubjectInResponseTo(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: "invalid-id", // Bad InResponseTo value.
 | 
						|
		redirectURI:  "http://127.0.0.1:5556/dex/callback",
 | 
						|
		wantErr:      true,
 | 
						|
	}
 | 
						|
	test.run(t)
 | 
						|
}
 | 
						|
 | 
						|
func TestInvalidSubjectRecipient(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://bad.com/dex/callback", // Doesn't match Recipient value.
 | 
						|
		wantErr:      true,
 | 
						|
	}
 | 
						|
	test.run(t)
 | 
						|
}
 | 
						|
 | 
						|
func TestInvalidAssertionAudience(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",
 | 
						|
		// EntityIssuer overrides RedirectURI when determining the expected
 | 
						|
		// audience. In this case, ensure the audience is invalid.
 | 
						|
		entityIssuer: "http://localhost:5556/dex/callback",
 | 
						|
		wantErr:      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 TestTamperedResponseNameID(t *testing.T) {
 | 
						|
	test := responseTest{
 | 
						|
		caFile:       "testdata/ca.crt",
 | 
						|
		respFile:     "testdata/tampered-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 loadCert(ca string) (*x509.Certificate, error) {
 | 
						|
	data, err := ioutil.ReadFile(ca)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	block, _ := pem.Decode(data)
 | 
						|
	if block == nil {
 | 
						|
		return nil, errors.New("ca file didn't contain any PEM data")
 | 
						|
	}
 | 
						|
	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,
 | 
						|
		EntityIssuer: r.entityIssuer,
 | 
						|
		// 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)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestConfigCAData(t *testing.T) {
 | 
						|
	logger := logrus.New()
 | 
						|
	validPEM, err := ioutil.ReadFile("testdata/ca.crt")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	valid2ndPEM, err := ioutil.ReadFile("testdata/okta-ca.pem")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	// copy helper, avoid messing with the byte slice among different cases
 | 
						|
	c := func(bs []byte) []byte {
 | 
						|
		return append([]byte(nil), bs...)
 | 
						|
	}
 | 
						|
 | 
						|
	tests := []struct {
 | 
						|
		name    string
 | 
						|
		caData  []byte
 | 
						|
		wantErr bool
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name:   "one valid PEM entry",
 | 
						|
			caData: c(validPEM),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "one valid PEM entry with trailing newline",
 | 
						|
			caData: append(c(validPEM), []byte("\n")...),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "one valid PEM entry with trailing spaces",
 | 
						|
			caData: append(c(validPEM), []byte("   ")...),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "one valid PEM entry with two trailing newlines",
 | 
						|
			caData: append(c(validPEM), []byte("\n\n")...),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "two valid PEM entries",
 | 
						|
			caData: append(c(validPEM), c(valid2ndPEM)...),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "two valid PEM entries with newline in between",
 | 
						|
			caData: append(append(c(validPEM), []byte("\n")...), c(valid2ndPEM)...),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "two valid PEM entries with trailing newline",
 | 
						|
			caData: append(c(valid2ndPEM), append(c(validPEM), []byte("\n")...)...),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:    "empty",
 | 
						|
			caData:  []byte{},
 | 
						|
			wantErr: true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:    "one valid PEM entry with trailing data",
 | 
						|
			caData:  append(c(validPEM), []byte("yaddayadda")...),
 | 
						|
			wantErr: true,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:    "one valid PEM entry with bad data before",
 | 
						|
			caData:  append([]byte("yaddayadda"), c(validPEM)...),
 | 
						|
			wantErr: true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tc := range tests {
 | 
						|
		t.Run(tc.name, func(t *testing.T) {
 | 
						|
			c := Config{
 | 
						|
				CAData:       tc.caData,
 | 
						|
				UsernameAttr: "user",
 | 
						|
				EmailAttr:    "email",
 | 
						|
				RedirectURI:  "http://127.0.0.1:5556/dex/callback",
 | 
						|
				SSOURL:       "http://foo.bar/",
 | 
						|
			}
 | 
						|
			_, err := (&c).Open("samltest", logger)
 | 
						|
			if tc.wantErr {
 | 
						|
				if err == nil {
 | 
						|
					t.Error("expected error, got nil")
 | 
						|
				}
 | 
						|
			} else if err != nil {
 | 
						|
				t.Errorf("expected no error, got %v", err)
 | 
						|
			}
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	defaultSSOIssuer   = "http://www.okta.com/exk91cb99lKkKSYoy0h7"
 | 
						|
	defaultRedirectURI = "http://localhost:5556/dex/callback"
 | 
						|
 | 
						|
	// Response ID embedded in our testdata.
 | 
						|
	testDataResponseID = "_fd1b3ef9-ec09-44a7-a66b-0d39c250f6a0"
 | 
						|
)
 | 
						|
 | 
						|
// Deprecated: Use testing framework established above.
 | 
						|
func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) {
 | 
						|
	cert, err := loadCert(ca)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	s := certStore{[]*x509.Certificate{cert}}
 | 
						|
 | 
						|
	validator := dsig.NewDefaultValidationContext(s)
 | 
						|
 | 
						|
	data, err := ioutil.ReadFile(resp)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if _, _, err := verifyResponseSig(validator, data); err != nil {
 | 
						|
		if shouldSucceed {
 | 
						|
			t.Fatal(err)
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if !shouldSucceed {
 | 
						|
			t.Fatalf("expected an invalid signatrue but verification has been successful")
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Deprecated: Use testing framework established above.
 | 
						|
func newProvider(ssoIssuer string, redirectURI string) *provider {
 | 
						|
	if ssoIssuer == "" {
 | 
						|
		ssoIssuer = defaultSSOIssuer
 | 
						|
	}
 | 
						|
	if redirectURI == "" {
 | 
						|
		redirectURI = defaultRedirectURI
 | 
						|
	}
 | 
						|
	now, _ := time.Parse(time.RFC3339, "2017-01-24T20:48:41Z")
 | 
						|
	timeFunc := func() time.Time { return now }
 | 
						|
	return &provider{
 | 
						|
		ssoIssuer:    ssoIssuer,
 | 
						|
		ssoURL:       "http://idp.org/saml/sso",
 | 
						|
		now:          timeFunc,
 | 
						|
		usernameAttr: "user",
 | 
						|
		emailAttr:    "email",
 | 
						|
		redirectURI:  redirectURI,
 | 
						|
		logger:       logrus.New(),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestVerify(t *testing.T) {
 | 
						|
	runVerify(t, "testdata/okta-ca.pem", "testdata/okta-resp.xml", true)
 | 
						|
}
 | 
						|
 | 
						|
func TestVerifyUnsignedMessageAndSignedAssertionWithRootXmlNs(t *testing.T) {
 | 
						|
	runVerify(t, "testdata/oam-ca.pem", "testdata/oam-resp.xml", true)
 | 
						|
}
 | 
						|
 | 
						|
func TestVerifySignedMessageAndUnsignedAssertion(t *testing.T) {
 | 
						|
	runVerify(t, "testdata/idp-cert.pem", "testdata/idp-resp-signed-message.xml", true)
 | 
						|
}
 | 
						|
 | 
						|
func TestVerifyUnsignedMessageAndSignedAssertion(t *testing.T) {
 | 
						|
	runVerify(t, "testdata/idp-cert.pem", "testdata/idp-resp-signed-assertion.xml", true)
 | 
						|
}
 | 
						|
 | 
						|
func TestVerifySignedMessageAndSignedAssertion(t *testing.T) {
 | 
						|
	runVerify(t, "testdata/idp-cert.pem", "testdata/idp-resp-signed-message-and-assertion.xml", true)
 | 
						|
}
 | 
						|
 | 
						|
func TestVerifyUnsignedMessageAndUnsignedAssertion(t *testing.T) {
 | 
						|
	runVerify(t, "testdata/idp-cert.pem", "testdata/idp-resp.xml", false)
 | 
						|
}
 |