mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 20:57:31 +00:00
fix(saml): improve error handling (#8928)
# Which Problems Are Solved
There are multiple issues with the metadata and error handling of SAML:
- When providing a SAML metadata for an IdP, which cannot be processed,
the error will only be noticed once a user tries to use the IdP.
- Parsing for metadata with any other encoding than UTF-8 fails.
- Metadata containing an enclosing EntitiesDescriptor around
EntityDescriptor cannot be parsed.
- Metadata's `validUntil` value is always set to 48 hours, which causes
issues on external providers, if processed from a manual down/upload.
- If a SAML response cannot be parsed, only a generic "Authentication
failed" error is returned, the cause is hidden to the user and also to
actions.
# How the Problems Are Solved
- Return parsing errors after create / update and retrieval of an IdP in
the API.
- Prevent the creation and update of an IdP in case of a parsing
failure.
- Added decoders for encodings other than UTF-8 (including ASCII,
windows and ISO, [currently
supported](efd25daf28/encoding/ianaindex/ianaindex.go (L156)
))
- Updated parsing to handle both `EntitiesDescriptor` and
`EntityDescriptor` as root element
- `validUntil` will automatically set to the certificate's expiration
time
- Unwrapped the hidden error to be returned. The Login UI will still
only provide a mostly generic error, but action can now access the
underlying error.
# Additional Changes
None
# Additional Context
reported by a customer
This commit is contained in:
@@ -5348,7 +5348,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
provider SAMLProvider
|
||||
provider *SAMLProvider
|
||||
}
|
||||
type res struct {
|
||||
id string
|
||||
@@ -5370,7 +5370,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@@ -5379,7 +5379,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata",
|
||||
"no metadata",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
@@ -5387,7 +5387,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
@@ -5397,6 +5397,26 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata, fail on error",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ok",
|
||||
fields: fields{
|
||||
@@ -5406,7 +5426,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@@ -5428,9 +5448,9 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -5447,7 +5467,7 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@@ -5475,9 +5495,9 @@ func TestCommandSide_AddOrgSAMLIDP(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
Binding: "binding",
|
||||
WithSignedRequest: true,
|
||||
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
||||
@@ -5528,7 +5548,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx context.Context
|
||||
resourceOwner string
|
||||
id string
|
||||
provider SAMLProvider
|
||||
provider *SAMLProvider
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@@ -5548,7 +5568,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@@ -5565,7 +5585,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{},
|
||||
provider: &SAMLProvider{},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@@ -5574,7 +5594,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata",
|
||||
"no metadata",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
@@ -5582,7 +5602,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
@@ -5592,6 +5612,26 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"invalid metadata, error",
|
||||
fields{
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
return errors.Is(err, zerrors.ThrowInvalidArgument(nil, "ORG-SFqqh42", "Errors.Project.App.SAMLMetadataFormat"))
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
fields: fields{
|
||||
@@ -5603,9 +5643,9 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -5623,7 +5663,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
org.NewSAMLIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||
"id1",
|
||||
"name",
|
||||
[]byte("metadata"),
|
||||
validSAMLMetadata,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
@@ -5644,9 +5684,9 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "name",
|
||||
Metadata: []byte("metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@@ -5684,7 +5724,7 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
"id1",
|
||||
[]idp.SAMLIDPChanges{
|
||||
idp.ChangeSAMLName("new name"),
|
||||
idp.ChangeSAMLMetadata([]byte("new metadata")),
|
||||
idp.ChangeSAMLMetadata(validSAMLMetadata),
|
||||
idp.ChangeSAMLBinding("new binding"),
|
||||
idp.ChangeSAMLWithSignedRequest(true),
|
||||
idp.ChangeSAMLNameIDFormat(gu.Ptr(domain.SAMLNameIDFormatTransient)),
|
||||
@@ -5707,9 +5747,9 @@ func TestCommandSide_UpdateOrgSAMLIDP(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
id: "id1",
|
||||
provider: SAMLProvider{
|
||||
provider: &SAMLProvider{
|
||||
Name: "new name",
|
||||
Metadata: []byte("new metadata"),
|
||||
Metadata: validSAMLMetadata,
|
||||
Binding: "new binding",
|
||||
WithSignedRequest: true,
|
||||
NameIDFormat: gu.Ptr(domain.SAMLNameIDFormatTransient),
|
||||
|
Reference in New Issue
Block a user