Skip to content

Commit e1e76fd

Browse files
fix missing verification of detached signatures in responses
Applied long-open PR crewjam#449 plus https://github.com/crewjam/saml/pull/449/files#r1654477177 to make embedded signature optional when a good detached signature is seen.
1 parent 401536d commit e1e76fd

File tree

4 files changed

+381
-19
lines changed

4 files changed

+381
-19
lines changed

service_provider.go

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -264,29 +264,23 @@ func (r *AuthnRequest) Redirect(relayState string, sp *ServiceProvider) (*url.UR
264264

265265
rv, _ := url.Parse(r.Destination)
266266
// We can't depend on Query().set() as order matters for signing
267+
reqString := string(w.Bytes())
267268
query := rv.RawQuery
268269
if len(query) > 0 {
269-
query += "&SAMLRequest=" + url.QueryEscape(w.String())
270+
query += "&" + string(samlRequest) + "=" + url.QueryEscape(reqString)
270271
} else {
271-
query += "SAMLRequest=" + url.QueryEscape(w.String())
272+
query += string(samlRequest) + "=" + url.QueryEscape(reqString)
272273
}
273274

274275
if relayState != "" {
275-
query += "&RelayState=" + relayState
276+
query += "&RelayState=" + url.QueryEscape(relayState)
276277
}
277278
if len(sp.SignatureMethod) > 0 {
278-
query += "&SigAlg=" + url.QueryEscape(sp.SignatureMethod)
279-
signingContext, err := GetSigningContext(sp)
280-
281-
if err != nil {
282-
return nil, err
283-
}
284-
285-
sig, err := signingContext.SignString(query)
286-
if err != nil {
287-
return nil, err
279+
var errSig error
280+
query, errSig = sp.signQuery(samlRequest, query, reqString, relayState)
281+
if errSig != nil {
282+
return nil, errSig
288283
}
289-
query += "&Signature=" + url.QueryEscape(base64.StdEncoding.EncodeToString(sig))
290284
}
291285

292286
rv.RawQuery = query
@@ -1475,8 +1469,9 @@ func (sp *ServiceProvider) nameIDFormat() string {
14751469

14761470
// ValidateLogoutResponseRequest validates the LogoutResponse content from the request
14771471
func (sp *ServiceProvider) ValidateLogoutResponseRequest(req *http.Request) error {
1478-
if data := req.URL.Query().Get("SAMLResponse"); data != "" {
1479-
return sp.ValidateLogoutResponseRedirect(data)
1472+
query := req.URL.Query()
1473+
if data := query.Get("SAMLResponse"); data != "" {
1474+
return sp.ValidateLogoutResponseRedirect(query)
14801475
}
14811476

14821477
err := req.ParseForm()
@@ -1528,7 +1523,9 @@ func (sp *ServiceProvider) ValidateLogoutResponseForm(postFormData string) error
15281523
//
15291524
// URL Binding appears to be gzip / flate encoded
15301525
// See https://www.oasis-open.org/committees/download.php/20645/sstc-saml-tech-overview-2%200-draft-10.pdf 6.6
1531-
func (sp *ServiceProvider) ValidateLogoutResponseRedirect(queryParameterData string) error {
1526+
func (sp *ServiceProvider) ValidateLogoutResponseRedirect(query url.Values) error {
1527+
queryParameterData := query.Get("SAMLResponse")
1528+
15321529
retErr := &InvalidResponseError{
15331530
Now: TimeNow(),
15341531
}
@@ -1550,15 +1547,26 @@ func (sp *ServiceProvider) ValidateLogoutResponseRedirect(queryParameterData str
15501547
return err
15511548
}
15521549

1550+
querySig := false
1551+
if query.Get("Signature") != "" && query.Get("SigAlg") != "" {
1552+
if err := sp.validateQuerySig(query); err != nil {
1553+
retErr.PrivateErr = err
1554+
return retErr
1555+
}
1556+
querySig = true
1557+
}
1558+
15531559
doc := etree.NewDocument()
15541560
if err := doc.ReadFromBytes(gr); err != nil {
15551561
retErr.PrivateErr = err
15561562
return retErr
15571563
}
15581564

15591565
if err := sp.validateSignature(doc.Root()); err != nil {
1560-
retErr.PrivateErr = err
1561-
return retErr
1566+
if err != errSignatureElementNotPresent || !querySig {
1567+
retErr.PrivateErr = err
1568+
return retErr
1569+
}
15621570
}
15631571

15641572
var resp LogoutResponse

service_provider_signed.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package saml
2+
3+
import (
4+
"crypto"
5+
"crypto/rsa"
6+
"crypto/sha1" // #nosec G505
7+
"crypto/sha256"
8+
"crypto/sha512"
9+
"crypto/x509"
10+
"encoding/base64"
11+
"errors"
12+
"fmt"
13+
"net/url"
14+
15+
dsig "github.com/russellhaering/goxmldsig"
16+
)
17+
18+
type reqType string
19+
20+
const (
21+
samlRequest reqType = "SAMLRequest"
22+
samlResponse reqType = "SAMLResponse"
23+
)
24+
25+
var (
26+
// ErrInvalidQuerySignature is returned when the query signature is invalid
27+
ErrInvalidQuerySignature = errors.New("invalid query signature")
28+
// ErrNoQuerySignature is returned when the query does not contain a signature
29+
ErrNoQuerySignature = errors.New("query Signature or SigAlg not found")
30+
)
31+
32+
// Sign Query with the SP private key.
33+
// Returns provided query with the SigAlg and Signature parameters added.
34+
func (sp *ServiceProvider) signQuery(reqT reqType, query, body, relayState string) (string, error) {
35+
signingContext, err := GetSigningContext(sp)
36+
37+
// Encode Query as standard demands. query.Encode() is not standard compliant
38+
toHash := string(reqT) + "=" + url.QueryEscape(body)
39+
if relayState != "" {
40+
toHash += "&RelayState=" + url.QueryEscape(relayState)
41+
}
42+
43+
toHash += "&SigAlg=" + url.QueryEscape(sp.SignatureMethod)
44+
45+
if err != nil {
46+
return "", err
47+
}
48+
49+
sig, err := signingContext.SignString(toHash)
50+
if err != nil {
51+
return "", err
52+
}
53+
54+
query += "&SigAlg=" + url.QueryEscape(sp.SignatureMethod)
55+
query += "&Signature=" + url.QueryEscape(base64.StdEncoding.EncodeToString(sig))
56+
57+
return query, nil
58+
}
59+
60+
// validateSig validation of the signature of the Redirect Binding in query values
61+
// Query is valid if return is nil
62+
func (sp *ServiceProvider) validateQuerySig(query url.Values) error {
63+
sig := query.Get("Signature")
64+
alg := query.Get("SigAlg")
65+
if sig == "" || alg == "" {
66+
return ErrNoQuerySignature
67+
}
68+
69+
certs, err := sp.getIDPSigningCerts()
70+
if err != nil {
71+
return err
72+
}
73+
74+
respType := ""
75+
if query.Get("SAMLResponse") != "" {
76+
respType = "SAMLResponse"
77+
} else if query.Get("SAMLRequest") != "" {
78+
respType = "SAMLRequest"
79+
} else {
80+
return fmt.Errorf("No SAMLResponse or SAMLRequest found in query")
81+
}
82+
83+
// Encode Query as standard demands.
84+
// query.Encode() is not standard compliant
85+
// as query encoding order matters
86+
res := respType + "=" + url.QueryEscape(query.Get(respType))
87+
88+
relayState := query.Get("RelayState")
89+
if relayState != "" {
90+
res += "&RelayState=" + url.QueryEscape(relayState)
91+
}
92+
93+
res += "&SigAlg=" + url.QueryEscape(alg)
94+
95+
// Signature is base64 encoded
96+
sigBytes, err := base64.StdEncoding.DecodeString(sig)
97+
if err != nil {
98+
return fmt.Errorf("failed to decode signature: %w", err)
99+
}
100+
101+
var (
102+
hashed []byte
103+
hashAlg crypto.Hash
104+
sigAlg x509.SignatureAlgorithm
105+
)
106+
107+
// Hashed Query
108+
switch alg {
109+
case dsig.RSASHA256SignatureMethod:
110+
hashed256 := sha256.Sum256([]byte(res))
111+
hashed = hashed256[:]
112+
hashAlg = crypto.SHA256
113+
sigAlg = x509.SHA256WithRSA
114+
case dsig.RSASHA512SignatureMethod:
115+
hashed512 := sha512.Sum512([]byte(res))
116+
hashed = hashed512[:]
117+
hashAlg = crypto.SHA512
118+
sigAlg = x509.SHA512WithRSA
119+
case dsig.RSASHA1SignatureMethod:
120+
hashed1 := sha1.Sum([]byte(res)) // #nosec G401
121+
hashed = hashed1[:]
122+
hashAlg = crypto.SHA1
123+
sigAlg = x509.SHA1WithRSA
124+
default:
125+
return fmt.Errorf("unsupported signature algorithm: %s", alg)
126+
}
127+
128+
// validate signature
129+
for _, cert := range certs {
130+
// verify cert is RSA
131+
if cert.SignatureAlgorithm != sigAlg {
132+
continue
133+
}
134+
135+
if err := rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), hashAlg, hashed, sigBytes); err == nil {
136+
return nil
137+
}
138+
}
139+
140+
return ErrInvalidQuerySignature
141+
}

service_provider_signed_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package saml
2+
3+
import (
4+
"crypto/rsa"
5+
"encoding/base64"
6+
"encoding/xml"
7+
"net/url"
8+
"testing"
9+
10+
dsig "github.com/russellhaering/goxmldsig"
11+
"gotest.tools/assert"
12+
"gotest.tools/golden"
13+
)
14+
15+
// Given a SAMLRequest query string, sign the query and validate signature
16+
// Using same Cert for SP and IdP in order to test
17+
func TestSigningAndValidation(t *testing.T) {
18+
type testCase struct {
19+
desc string
20+
relayState string
21+
requestType reqType
22+
wantErr bool
23+
wantRawQuery string
24+
}
25+
26+
testCases := []testCase{
27+
{
28+
desc: "validate signature of SAMLRequest with relayState",
29+
relayState: "AAAAAAAAAAAA",
30+
requestType: samlRequest,
31+
wantRawQuery: "SAMLRequest=PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJRD0iaWQtMDAwMjA0MDYwODBhMGMwZTEwMTIxNDE2MTgxYTFjMWUyMDIyMjQyNiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTUtMTItMDFUMDE6NTc6MDlaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9pZHAuZXhhbXBsZS5jb20vc2FtbC9zc28iIEFzc2VydGlvbkNvbnN1bWVyU2VydmljZVVSTD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9zYW1sMi9hY3MiIFByb3RvY29sQmluZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmJpbmRpbmdzOkhUVFAtUE9TVCI%2BPHNhbWw6SXNzdWVyIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL3NwLmV4YW1wbGUuY29tL3NhbWwyL21ldGFkYXRhPC9zYW1sOklzc3Vlcj48c2FtbHA6TmFtZUlEUG9saWN5IEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50IiBBbGxvd0NyZWF0ZT0idHJ1ZSIvPjwvc2FtbHA6QXV0aG5SZXF1ZXN0Pg%3D%3D&RelayState=AAAAAAAAAAAA&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=zWAF4S%2FIs7tfmEriOsT5Fm8EFOGS3iCq6OxP5i7hM%2BMPwAoXwdDz6fKH8euS1gQ3sGOZBdHD588FZLvnO1OeCxLaEsxHMVKsAZSZFLBmPPwqB6e%2B84cCwX2szOeoMROaR%2B36mdoBDRQz36JIvyBBG%2FND9x41k%2FGQuAuwk%2B9fkuE%3D",
32+
},
33+
{
34+
desc: "validate signature of SAML request without relay state",
35+
relayState: "",
36+
requestType: samlRequest,
37+
wantRawQuery: "SAMLRequest=PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJRD0iaWQtMDAwMjA0MDYwODBhMGMwZTEwMTIxNDE2MTgxYTFjMWUyMDIyMjQyNiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTUtMTItMDFUMDE6NTc6MDlaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9pZHAuZXhhbXBsZS5jb20vc2FtbC9zc28iIEFzc2VydGlvbkNvbnN1bWVyU2VydmljZVVSTD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9zYW1sMi9hY3MiIFByb3RvY29sQmluZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmJpbmRpbmdzOkhUVFAtUE9TVCI%2BPHNhbWw6SXNzdWVyIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL3NwLmV4YW1wbGUuY29tL3NhbWwyL21ldGFkYXRhPC9zYW1sOklzc3Vlcj48c2FtbHA6TmFtZUlEUG9saWN5IEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50IiBBbGxvd0NyZWF0ZT0idHJ1ZSIvPjwvc2FtbHA6QXV0aG5SZXF1ZXN0Pg%3D%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=HDdoHJSdkYh9%2BmE7RZ1LXcsAWIMJ6LuzKJgwLxH%2BQ4sKFlh8b5moFuQ%2B7rPEwoTcg9SjgCGV5rW9v8PrSU7WGKcLfAbeVwXWyU94ghjFZHEj%2BFCDpsfTD750ZPAPVnhVr0GogFZZ7c%2BEWX4NAqL4CYxDvsg56o%2BpOjw62G%2FyPDc%3D",
38+
},
39+
{
40+
desc: "validate signature of SAML response with relay state",
41+
relayState: "AAAAAAAAAAAA",
42+
requestType: samlResponse,
43+
wantRawQuery: "SAMLResponse=PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJRD0iaWQtMDAwMjA0MDYwODBhMGMwZTEwMTIxNDE2MTgxYTFjMWUyMDIyMjQyNiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTUtMTItMDFUMDE6NTc6MDlaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9pZHAuZXhhbXBsZS5jb20vc2FtbC9zc28iIEFzc2VydGlvbkNvbnN1bWVyU2VydmljZVVSTD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9zYW1sMi9hY3MiIFByb3RvY29sQmluZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmJpbmRpbmdzOkhUVFAtUE9TVCI%2BPHNhbWw6SXNzdWVyIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL3NwLmV4YW1wbGUuY29tL3NhbWwyL21ldGFkYXRhPC9zYW1sOklzc3Vlcj48c2FtbHA6TmFtZUlEUG9saWN5IEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50IiBBbGxvd0NyZWF0ZT0idHJ1ZSIvPjwvc2FtbHA6QXV0aG5SZXF1ZXN0Pg%3D%3D&RelayState=AAAAAAAAAAAA&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1&Signature=JDeiWfLgV7SZqgqU64wgtAHS%2FqtF2c3c%2B9g1vdfRHn03tm5jrgsvJtIYg1BD8HoejCoyruH3xgDz1i2qqecVcUiAdaVgVvhn0JWJ%2BzeN9YpUFTEQ4Ah1pwezlSArzuz5esgYzSkemViox313HePWZ%2Fd0FAmtdXuGHA8O0Lp%2F4Ws%3D",
44+
},
45+
}
46+
47+
idpMetadata := golden.Get(t, "SP_IDPMetadata_signing")
48+
s := ServiceProvider{
49+
Key: mustParsePrivateKey(golden.Get(t, "idp_key.pem")).(*rsa.PrivateKey),
50+
Certificate: mustParseCertificate(golden.Get(t, "idp_cert.pem")),
51+
MetadataURL: mustParseURL("https://15661444.ngrok.io/saml2/metadata"),
52+
AcsURL: mustParseURL("https://15661444.ngrok.io/saml2/acs"),
53+
SignatureMethod: dsig.RSASHA1SignatureMethod,
54+
}
55+
56+
err := xml.Unmarshal(idpMetadata, &s.IDPMetadata)
57+
idpCert, err := s.getIDPSigningCerts()
58+
59+
assert.Check(t, err == nil)
60+
assert.Check(t,
61+
s.Certificate.Issuer.CommonName == idpCert[0].Issuer.CommonName, "expected %s, got %s",
62+
s.Certificate.Issuer.CommonName, idpCert[0].Issuer.CommonName)
63+
64+
req := golden.Get(t, "idp_authn_request.xml")
65+
reqString := base64.StdEncoding.EncodeToString(req)
66+
67+
for _, tc := range testCases {
68+
t.Run(tc.desc, func(t *testing.T) {
69+
relayState := tc.relayState
70+
71+
rawQuery := string(tc.requestType) + "=" + url.QueryEscape(reqString)
72+
73+
if relayState != "" {
74+
rawQuery += "&RelayState=" + relayState
75+
}
76+
77+
rawQuery, err = s.signQuery(tc.requestType, rawQuery, reqString, relayState)
78+
assert.NilError(t, err, "error signing query: %s", err)
79+
80+
assert.Equal(t, tc.wantRawQuery, rawQuery)
81+
82+
query, err := url.ParseQuery(rawQuery)
83+
assert.NilError(t, err, "error parsing query: %s", err)
84+
85+
err = s.validateQuerySig(query)
86+
assert.NilError(t, err, "error validating query: %s", err)
87+
})
88+
}
89+
}
90+
91+
// Given a raw query with an unsupported signature method, the signature should be rejected.
92+
func TestInvalidSignatureAlgorithm(t *testing.T) {
93+
rawQuery := "SAMLRequest=PHNhbWxwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJRD0iaWQtMDAwMjA0MDYwODBhMGMwZTEwMTIxNDE2MTgxYTFjMWUyMDIyMjQyNiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTUtMTItMDFUMDE6NTc6MDlaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9pZHAuZXhhbXBsZS5jb20vc2FtbC9zc28iIEFzc2VydGlvbkNvbnN1bWVyU2VydmljZVVSTD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9zYW1sMi9hY3MiIFByb3RvY29sQmluZGluZz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmJpbmRpbmdzOkhUVFAtUE9TVCI%2BPHNhbWw6SXNzdWVyIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL3NwLmV4YW1wbGUuY29tL3NhbWwyL21ldGFkYXRhPC9zYW1sOklzc3Vlcj48c2FtbHA6TmFtZUlEUG9saWN5IEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6dHJhbnNpZW50IiBBbGxvd0NyZWF0ZT0idHJ1ZSIvPjwvc2FtbHA6QXV0aG5SZXF1ZXN0Pg%3D%3D&RelayState=AAAAAAAAAAAA&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha384&Signature=zWAF4S%2FIs7tfmEriOsT5Fm8EFOGS3iCq6OxP5i7hM%2BMPwAoXwdDz6fKH8euS1gQ3sGOZBdHD588FZLvnO1OeCxLaEsxHMVKsAZSZFLBmPPwqB6e%2B84cCwX2szOeoMROaR%2B36mdoBDRQz36JIvyBBG%2FND9x41k%2FGQuAuwk%2B9fkuE%3D"
94+
95+
idpMetadata := golden.Get(t, "SP_IDPMetadata_signing")
96+
s := ServiceProvider{
97+
Key: mustParsePrivateKey(golden.Get(t, "idp_key.pem")).(*rsa.PrivateKey),
98+
Certificate: mustParseCertificate(golden.Get(t, "idp_cert.pem")),
99+
MetadataURL: mustParseURL("https://15661444.ngrok.io/saml2/metadata"),
100+
AcsURL: mustParseURL("https://15661444.ngrok.io/saml2/acs"),
101+
SignatureMethod: dsig.RSASHA1SignatureMethod,
102+
}
103+
104+
err := xml.Unmarshal(idpMetadata, &s.IDPMetadata)
105+
idpCert, err := s.getIDPSigningCerts()
106+
107+
assert.Check(t, err == nil)
108+
assert.Check(t,
109+
s.Certificate.Issuer.CommonName == idpCert[0].Issuer.CommonName, "expected %s, got %s",
110+
s.Certificate.Issuer.CommonName, idpCert[0].Issuer.CommonName)
111+
112+
query, err := url.ParseQuery(rawQuery)
113+
assert.NilError(t, err, "error parsing query: %s", err)
114+
115+
err = s.validateQuerySig(query)
116+
assert.Error(t, err, "unsupported signature algorithm: http://www.w3.org/2000/09/xmldsig#rsa-sha384")
117+
}

0 commit comments

Comments
 (0)