diff --git a/authnresponse.go b/authnresponse.go index 3064412..98e36d3 100644 --- a/authnresponse.go +++ b/authnresponse.go @@ -59,7 +59,7 @@ func (r *Response) Validate(s *ServiceProviderSettings) error { return errors.New("no Assertions") } - if len(r.Signature.SignatureValue.Value) == 0 { + if len(r.Signature.SignatureValue.Value) == 0 && len(r.Assertion.Signature.SignatureValue.Value) == 0 { return errors.New("no signature") } @@ -75,7 +75,12 @@ func (r *Response) Validate(s *ServiceProviderSettings) error { return errors.New("subject recipient mismatch, expected: " + s.AssertionConsumerServiceURL + " not " + r.Assertion.Subject.SubjectConfirmation.SubjectConfirmationData.Recipient) } - err := VerifyResponseSignature(r.originalString, s.IDPPublicCertPath) + var err error + if s.SignaturesInAssertion { + err = VerifyAssertionSignature(r.originalString, s.IDPPublicCertPath) + } else { + err = VerifyResponseSignature(r.originalString, s.IDPPublicCertPath) + } if err != nil { return err } diff --git a/saml.go b/saml.go index 71feac5..5eaed98 100644 --- a/saml.go +++ b/saml.go @@ -13,6 +13,7 @@ type ServiceProviderSettings struct { IDPPublicCertPath string AssertionConsumerServiceURL string SPSignRequest bool + SignaturesInAssertion bool hasInit bool publicCert string diff --git a/types.go b/types.go index 217340f..13b092e 100644 --- a/types.go +++ b/types.go @@ -203,6 +203,7 @@ type Assertion struct { SAML string `xml:"saml,attr"` IssueInstant string `xml:"IssueInstant,attr"` Issuer Issuer `xml:"Issuer"` + Signature Signature Subject Subject Conditions Conditions AttributeStatement AttributeStatement diff --git a/xmlsec.go b/xmlsec.go index 484a940..ff3464d 100644 --- a/xmlsec.go +++ b/xmlsec.go @@ -9,8 +9,9 @@ import ( ) const ( - xmlResponseID = "urn:oasis:names:tc:SAML:2.0:protocol:Response" - xmlRequestID = "urn:oasis:names:tc:SAML:2.0:protocol:AuthnRequest" + xmlResponseID = "urn:oasis:names:tc:SAML:2.0:protocol:Response" + xmlRequestID = "urn:oasis:names:tc:SAML:2.0:protocol:AuthnRequest" + xmlAssertionID = "urn:oasis:names:tc:SAML:2.0:assertion:Assertion" ) // SignRequest sign a SAML 2.0 AuthnRequest @@ -77,6 +78,13 @@ func VerifyRequestSignature(xml string, publicCertPath string) error { return verify(xml, publicCertPath, xmlRequestID) } +// VerifyAssertionSignature verify signature of a SAML 2.0 Response document +// `publicCertPath` must be a path on the filesystem, xmlsec1 is run out of process +// through `exec` +func VerifyAssertionSignature(xml string, publicCertPath string) error { + return verify(xml, publicCertPath, xmlAssertionID) +} + func verify(xml string, publicCertPath string, id string) error { //Write saml to samlXmlsecInput, err := ioutil.TempFile(os.TempDir(), "tmpgs")