Merge pull request #885 from Calpicow/saml_issuer_fix
Add ssoIssuer to fix Response issuer checking
This commit is contained in:
commit
40f0265ab4
@ -30,17 +30,23 @@ connectors:
|
|||||||
# CA to use when validating the SAML response.
|
# CA to use when validating the SAML response.
|
||||||
ca: /path/to/ca.pem
|
ca: /path/to/ca.pem
|
||||||
|
|
||||||
# CA's can also be provided inline as a base64'd blob.
|
# CA's can also be provided inline as a base64'd blob.
|
||||||
#
|
#
|
||||||
# caData: ( RAW base64'd PEM encoded CA )
|
# caData: ( RAW base64'd PEM encoded CA )
|
||||||
|
|
||||||
# To skip signature validation, uncomment the following field. This should
|
# To skip signature validation, uncomment the following field. This should
|
||||||
# only be used during testing and may be removed in the future.
|
# only be used during testing and may be removed in the future.
|
||||||
#
|
#
|
||||||
# insucreSkipSignatureValidation: true
|
# insecureSkipSignatureValidation: true
|
||||||
|
|
||||||
|
# Optional: Issuer value for AuthnRequest
|
||||||
|
entityIssuer: https://dex.example.com/callback
|
||||||
|
|
||||||
|
# Optional: Issuer value for SAML Response
|
||||||
|
ssoIssuer: https://saml.example.com/sso
|
||||||
|
|
||||||
# Dex's callback URL. Must match the "Destination" attribute of all responses
|
# Dex's callback URL. Must match the "Destination" attribute of all responses
|
||||||
# exactly.
|
# exactly.
|
||||||
redirectURI: https://dex.example.com/callback
|
redirectURI: https://dex.example.com/callback
|
||||||
|
|
||||||
# Name of attributes in the returned assertions to map to ID token claims.
|
# Name of attributes in the returned assertions to map to ID token claims.
|
||||||
|
@ -81,8 +81,9 @@ type Config struct {
|
|||||||
//
|
//
|
||||||
// https://www.oasis-open.org/committees/download.php/35391/sstc-saml-metadata-errata-2.0-wd-04-diff.pdf
|
// https://www.oasis-open.org/committees/download.php/35391/sstc-saml-metadata-errata-2.0-wd-04-diff.pdf
|
||||||
|
|
||||||
Issuer string `json:"issuer"`
|
EntityIssuer string `json:"entityIssuer"`
|
||||||
SSOURL string `json:"ssoURL"`
|
SSOIssuer string `json:"ssoIssuer"`
|
||||||
|
SSOURL string `json:"ssoURL"`
|
||||||
|
|
||||||
// X509 CA file or raw data to verify XML signatures.
|
// X509 CA file or raw data to verify XML signatures.
|
||||||
CA string `json:"ca"`
|
CA string `json:"ca"`
|
||||||
@ -154,7 +155,8 @@ func (c *Config) openConnector(logger logrus.FieldLogger) (*provider, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p := &provider{
|
p := &provider{
|
||||||
issuer: c.Issuer,
|
entityIssuer: c.EntityIssuer,
|
||||||
|
ssoIssuer: c.SSOIssuer,
|
||||||
ssoURL: c.SSOURL,
|
ssoURL: c.SSOURL,
|
||||||
now: time.Now,
|
now: time.Now,
|
||||||
usernameAttr: c.UsernameAttr,
|
usernameAttr: c.UsernameAttr,
|
||||||
@ -217,8 +219,9 @@ func (c *Config) openConnector(logger logrus.FieldLogger) (*provider, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
issuer string
|
entityIssuer string
|
||||||
ssoURL string
|
ssoIssuer string
|
||||||
|
ssoURL string
|
||||||
|
|
||||||
now func() time.Time
|
now func() time.Time
|
||||||
|
|
||||||
@ -251,10 +254,10 @@ func (p *provider) POSTData(s connector.Scopes, id string) (action, value string
|
|||||||
},
|
},
|
||||||
AssertionConsumerServiceURL: p.redirectURI,
|
AssertionConsumerServiceURL: p.redirectURI,
|
||||||
}
|
}
|
||||||
if p.issuer != "" {
|
if p.entityIssuer != "" {
|
||||||
// Issuer for the request is optional. For example, okta always ignores
|
// Issuer for the request is optional. For example, okta always ignores
|
||||||
// this value.
|
// this value.
|
||||||
r.Issuer = &issuer{Issuer: p.issuer}
|
r.Issuer = &issuer{Issuer: p.entityIssuer}
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := xml.MarshalIndent(r, "", " ")
|
data, err := xml.MarshalIndent(r, "", " ")
|
||||||
@ -287,8 +290,8 @@ func (p *provider) HandlePOST(s connector.Scopes, samlResponse, inResponseTo str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rootElementSigned {
|
if rootElementSigned {
|
||||||
if p.issuer != "" && resp.Issuer != nil && resp.Issuer.Issuer != p.issuer {
|
if p.ssoIssuer != "" && resp.Issuer != nil && resp.Issuer.Issuer != p.ssoIssuer {
|
||||||
return ident, fmt.Errorf("expected Issuer value %s, got %s", p.issuer, resp.Issuer.Issuer)
|
return ident, fmt.Errorf("expected Issuer value %s, got %s", p.entityIssuer, resp.Issuer.Issuer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify InResponseTo value matches the expected ID associated with
|
// Verify InResponseTo value matches the expected ID associated with
|
||||||
|
@ -278,14 +278,14 @@ func (r responseTest) run(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultIssuer = "http://www.okta.com/exk91cb99lKkKSYoy0h7"
|
defaultSSOIssuer = "http://www.okta.com/exk91cb99lKkKSYoy0h7"
|
||||||
defaultRedirectURI = "http://localhost:5556/dex/callback"
|
defaultRedirectURI = "http://localhost:5556/dex/callback"
|
||||||
|
|
||||||
// Response ID embedded in our testdata.
|
// Response ID embedded in our testdata.
|
||||||
testDataResponseID = "_fd1b3ef9-ec09-44a7-a66b-0d39c250f6a0"
|
testDataResponseID = "_fd1b3ef9-ec09-44a7-a66b-0d39c250f6a0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Depricated: Use testing framework established above.
|
// Deprecated: Use testing framework established above.
|
||||||
func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) {
|
func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) {
|
||||||
cert, err := loadCert(ca)
|
cert, err := loadCert(ca)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -311,10 +311,10 @@ func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depricated: Use testing framework established above.
|
// Deprecated: Use testing framework established above.
|
||||||
func newProvider(issuer string, redirectURI string) *provider {
|
func newProvider(ssoIssuer string, redirectURI string) *provider {
|
||||||
if issuer == "" {
|
if ssoIssuer == "" {
|
||||||
issuer = defaultIssuer
|
ssoIssuer = defaultSSOIssuer
|
||||||
}
|
}
|
||||||
if redirectURI == "" {
|
if redirectURI == "" {
|
||||||
redirectURI = defaultRedirectURI
|
redirectURI = defaultRedirectURI
|
||||||
@ -322,7 +322,7 @@ func newProvider(issuer string, redirectURI string) *provider {
|
|||||||
now, _ := time.Parse(time.RFC3339, "2017-01-24T20:48:41Z")
|
now, _ := time.Parse(time.RFC3339, "2017-01-24T20:48:41Z")
|
||||||
timeFunc := func() time.Time { return now }
|
timeFunc := func() time.Time { return now }
|
||||||
return &provider{
|
return &provider{
|
||||||
issuer: issuer,
|
ssoIssuer: ssoIssuer,
|
||||||
ssoURL: "http://idp.org/saml/sso",
|
ssoURL: "http://idp.org/saml/sso",
|
||||||
now: timeFunc,
|
now: timeFunc,
|
||||||
usernameAttr: "user",
|
usernameAttr: "user",
|
||||||
|
Reference in New Issue
Block a user