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:
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/idp/providers/saml"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@@ -511,10 +512,10 @@ func (c *Commands) UpdateInstanceAppleProvider(ctx context.Context, id string, p
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) AddInstanceSAMLProvider(ctx context.Context, provider SAMLProvider) (string, *domain.ObjectDetails, error) {
|
||||
func (c *Commands) AddInstanceSAMLProvider(ctx context.Context, provider *SAMLProvider) (id string, details *domain.ObjectDetails, err error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
id, err := c.idGenerator.Next()
|
||||
id, err = c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@@ -530,7 +531,7 @@ func (c *Commands) AddInstanceSAMLProvider(ctx context.Context, provider SAMLPro
|
||||
return id, pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) UpdateInstanceSAMLProvider(ctx context.Context, id string, provider SAMLProvider) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) UpdateInstanceSAMLProvider(ctx context.Context, id string, provider *SAMLProvider) (details *domain.ObjectDetails, err error) {
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
instanceAgg := instance.NewAggregate(instanceID)
|
||||
writeModel := NewSAMLInstanceIDPWriteModel(instanceID, id)
|
||||
@@ -1719,7 +1720,7 @@ func (c *Commands) prepareUpdateInstanceAppleProvider(a *instance.Aggregate, wri
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider SAMLProvider) preparation.Validation {
|
||||
func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider *SAMLProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-o07zjotgnd", "Errors.Invalid.Argument")
|
||||
@@ -1734,6 +1735,9 @@ func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeMo
|
||||
if len(provider.Metadata) == 0 {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-3bi3esi16t", "Errors.Invalid.Argument")
|
||||
}
|
||||
if _, err := saml.ParseMetadata(provider.Metadata); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "INST-SF3rwhgh", "Errors.Project.App.SAMLMetadataFormat")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
@@ -1772,7 +1776,7 @@ func (c *Commands) prepareAddInstanceSAMLProvider(a *instance.Aggregate, writeMo
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) prepareUpdateInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider SAMLProvider) preparation.Validation {
|
||||
func (c *Commands) prepareUpdateInstanceSAMLProvider(a *instance.Aggregate, writeModel *InstanceSAMLIDPWriteModel, provider *SAMLProvider) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "INST-7o3rq1owpm", "Errors.Invalid.Argument")
|
||||
@@ -1790,6 +1794,9 @@ func (c *Commands) prepareUpdateInstanceSAMLProvider(a *instance.Aggregate, writ
|
||||
}
|
||||
provider.Metadata = data
|
||||
}
|
||||
if _, err := saml.ParseMetadata(provider.Metadata); err != nil {
|
||||
return nil, zerrors.ThrowInvalidArgument(err, "INST-dsfj3kl2", "Errors.Project.App.SAMLMetadataFormat")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
events, err := filter(ctx, writeModel.Query())
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user