diff --git a/docs/docs/apis/actions/customize-samlresponse.md b/docs/docs/apis/actions/customize-samlresponse.md new file mode 100644 index 0000000000..33183b7ac8 --- /dev/null +++ b/docs/docs/apis/actions/customize-samlresponse.md @@ -0,0 +1,28 @@ +--- +title: Complement SAMLResponse +--- + +This flow is executed before the return of the SAMLResponse. + +## Pre SAMLResponse creation + +This trigger is called before attributes are set in the SAMLResponse. + +### Parameters of Pre SAMLResponse creation + +- `ctx` + The first parameter contains the following fields: + - `v1` + - `getUser()` [*User*](./objects#user) + - `user` + - `getMetadata()` [*metadataResult*](./objects#metadata-result) + - `grants` [*UserGrantList*](./objects#user-grant-list) +- `api` + The second parameter contains the following fields: + - `v1` + - `attributes` + - `setCustomAttribute(string, string, ...string)` + Sets any value as attribute in addition to the default attributes, if the key is not already present. The parameters represent the key, nameFormat and the attributeValue(s). + - `user` + - `setMetadata(string, Any)` + Key of the metadata and any value diff --git a/docs/sidebars.js b/docs/sidebars.js index 571da0de6d..ac5584e0f3 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -566,6 +566,7 @@ module.exports = { "apis/actions/internal-authentication", "apis/actions/external-authentication", "apis/actions/complement-token", + "apis/actions/customize-samlresponse", "apis/actions/objects", ] }, diff --git a/go.mod b/go.mod index bd62f2bd35..07620215d8 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( github.com/zitadel/logging v0.3.4 github.com/zitadel/oidc/v2 v2.7.0 github.com/zitadel/passwap v0.3.0 - github.com/zitadel/saml v0.0.11 + github.com/zitadel/saml v0.1.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.40.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.40.0 go.opentelemetry.io/otel v1.14.0 @@ -115,7 +115,7 @@ require ( cloud.google.com/go/trace v1.9.0 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect github.com/amdonov/xmlsig v0.1.0 // indirect - github.com/beevik/etree v1.1.0 // indirect + github.com/beevik/etree v1.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -181,7 +181,7 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rs/xid v1.4.0 // indirect - github.com/russellhaering/goxmldsig v1.3.0 // indirect + github.com/russellhaering/goxmldsig v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.0 // indirect diff --git a/go.sum b/go.sum index 2edc2dd911..c061a1206a 100644 --- a/go.sum +++ b/go.sum @@ -105,8 +105,9 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= +github.com/beevik/etree v1.2.0 h1:l7WETslUG/T+xOPs47dtd6jov2Ii/8/OjCldk5fYfQw= +github.com/beevik/etree v1.2.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -280,6 +281,7 @@ github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXg github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -789,8 +791,8 @@ github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russellhaering/goxmldsig v1.3.0 h1:DllIWUgMy0cRUMfGiASiYEa35nsieyD3cigIwLonTPM= -github.com/russellhaering/goxmldsig v1.3.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= +github.com/russellhaering/goxmldsig v1.4.0 h1:8UcDh/xGyQiyrW+Fq5t8f+l2DLB1+zlhYzkPUJ7Qhys= +github.com/russellhaering/goxmldsig v1.4.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -900,8 +902,10 @@ github.com/zitadel/oidc/v2 v2.7.0 h1:IGX4EDk6tegTjUSsZDWeTfLseFU0BdJ/Glf1tgys2lU github.com/zitadel/oidc/v2 v2.7.0/go.mod h1:zkUkVJS0sDVy9m0UA9RgO3f8i/C0rtjvXU36UJj7T+0= github.com/zitadel/passwap v0.3.0 h1:kC/vzN9xQlEQjUAZs0z2P5nKrZs9AuTqprteSQ2S4Ag= github.com/zitadel/passwap v0.3.0/go.mod h1:sIpG6HfmnP28qwxu8kf+ot53ERbLwU9fOITstAwZSms= -github.com/zitadel/saml v0.0.11 h1:kObucnBrcu1PHCO7RGT0iVeuJL/5I50gUgr40S41nMs= -github.com/zitadel/saml v0.0.11/go.mod h1:YGWAvPZRv4DbEZ78Ht/2P0AWzGn+6WGhFf90PMXl0Po= +github.com/zitadel/saml v0.0.12-0.20230809152136-3bdfd7ad13fe h1:mcdiFREwddgcJjK+KDl/J29Cikr0nymiFhYdp3DBKB4= +github.com/zitadel/saml v0.0.12-0.20230809152136-3bdfd7ad13fe/go.mod h1:M+X+3vMUulpoLofKeH/W1/qjQQ3owitc2GuGDu3oYpM= +github.com/zitadel/saml v0.1.0 h1:FZKKFRCamoKmFH3kGOW0ObcDozaJz7NdHn+WPm8PcXc= +github.com/zitadel/saml v0.1.0/go.mod h1:M+X+3vMUulpoLofKeH/W1/qjQQ3owitc2GuGDu3oYpM= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= @@ -1009,6 +1013,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= diff --git a/internal/api/grpc/action/action.go b/internal/api/grpc/action/action.go index bc29f6e119..be59e09579 100644 --- a/internal/api/grpc/action/action.go +++ b/internal/api/grpc/action/action.go @@ -19,6 +19,8 @@ func FlowTypeToDomain(flowType string) domain.FlowType { return domain.FlowTypeCustomiseToken case domain.FlowTypeInternalAuthentication.ID(): return domain.FlowTypeInternalAuthentication + case domain.FlowTypeCustomizeSAMLResponse.ID(): + return domain.FlowTypeCustomizeSAMLResponse default: return domain.FlowTypeUnspecified } @@ -47,6 +49,8 @@ func TriggerTypeToDomain(triggerType string) domain.TriggerType { return domain.TriggerTypePreAccessTokenCreation case domain.TriggerTypePreUserinfoCreation.ID(): return domain.TriggerTypePreUserinfoCreation + case domain.TriggerTypePreSAMLResponseCreation.ID(): + return domain.TriggerTypePreSAMLResponseCreation default: return domain.TriggerTypeUnspecified } diff --git a/internal/api/grpc/management/flow.go b/internal/api/grpc/management/flow.go index 3e3ed25f81..33f0739bad 100644 --- a/internal/api/grpc/management/flow.go +++ b/internal/api/grpc/management/flow.go @@ -18,6 +18,7 @@ func (s *Server) ListFlowTypes(ctx context.Context, _ *mgmt_pb.ListFlowTypesRequ action_grpc.FlowTypeToPb(domain.FlowTypeExternalAuthentication), action_grpc.FlowTypeToPb(domain.FlowTypeCustomiseToken), action_grpc.FlowTypeToPb(domain.FlowTypeInternalAuthentication), + action_grpc.FlowTypeToPb(domain.FlowTypeCustomizeSAMLResponse), }, }, nil } diff --git a/internal/api/oidc/client.go b/internal/api/oidc/client.go index 09475f1dec..8ce41d747b 100644 --- a/internal/api/oidc/client.go +++ b/internal/api/oidc/client.go @@ -386,7 +386,7 @@ func (o *OPStorage) setUserinfo(ctx context.Context, userInfo *oidc.UserInfo, us } o.setUserInfoRoleClaims(userInfo, projectRoles) - return o.userinfoFlows(ctx, user.ResourceOwner, userGrants, userInfo) + return o.userinfoFlows(ctx, user, userGrants, userInfo) } func (o *OPStorage) setUserInfoProfile(ctx context.Context, userInfo *oidc.UserInfo, user *query.User) { @@ -457,8 +457,8 @@ func (o *OPStorage) setUserInfoRoleClaims(userInfo *oidc.UserInfo, roles *projec } } -func (o *OPStorage) userinfoFlows(ctx context.Context, resourceOwner string, userGrants *query.UserGrants, userInfo *oidc.UserInfo) error { - queriedActions, err := o.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeCustomiseToken, domain.TriggerTypePreUserinfoCreation, resourceOwner, false) +func (o *OPStorage) userinfoFlows(ctx context.Context, user *query.User, userGrants *query.UserGrants, userInfo *oidc.UserInfo) error { + queriedActions, err := o.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeCustomiseToken, domain.TriggerTypePreUserinfoCreation, user.ResourceOwner, false) if err != nil { return err } @@ -468,17 +468,13 @@ func (o *OPStorage) userinfoFlows(ctx context.Context, resourceOwner string, use actions.SetFields("claims", userinfoClaims(userInfo)), actions.SetFields("getUser", func(c *actions.FieldConfig) interface{} { return func(call goja.FunctionCall) goja.Value { - user, err := o.query.GetUserByID(ctx, true, userInfo.Subject, false) - if err != nil { - panic(err) - } return object.UserFromQuery(c, user) } }), actions.SetFields("user", actions.SetFields("getMetadata", func(c *actions.FieldConfig) interface{} { return func(goja.FunctionCall) goja.Value { - resourceOwnerQuery, err := query.NewUserMetadataResourceOwnerSearchQuery(resourceOwner) + resourceOwnerQuery, err := query.NewUserMetadataResourceOwnerSearchQuery(user.ResourceOwner) if err != nil { logging.WithError(err).Debug("unable to create search query") panic(err) @@ -552,7 +548,7 @@ func (o *OPStorage) userinfoFlows(ctx context.Context, resourceOwner string, use Key: key, Value: value, } - if _, err = o.command.SetUserMetadata(ctx, metadata, userInfo.Subject, resourceOwner); err != nil { + if _, err = o.command.SetUserMetadata(ctx, metadata, userInfo.Subject, user.ResourceOwner); err != nil { logging.WithError(err).Info("unable to set md in action") panic(err) } @@ -665,10 +661,6 @@ func (o *OPStorage) privateClaimsFlows(ctx context.Context, userID string, userG }), actions.SetFields("getUser", func(c *actions.FieldConfig) interface{} { return func(call goja.FunctionCall) goja.Value { - user, err := o.query.GetUserByID(ctx, true, userID, false) - if err != nil { - panic(err) - } return object.UserFromQuery(c, user) } }), @@ -807,7 +799,7 @@ func (o *OPStorage) assertRoles(ctx context.Context, userID, applicationID strin } return grants, roles, nil } - // now specific roles were requested, so convert any grants into roles + // no specific roles were requested, so convert any grants into roles for _, grant := range grants.UserGrants { for _, role := range grant.Roles { roles.Add(grant.ProjectID, role, grant.ResourceOwner, grant.OrgPrimaryDomain, grant.ProjectID == projectID) diff --git a/internal/api/saml/storage.go b/internal/api/saml/storage.go index 45686d6ad3..7a0d10f56c 100644 --- a/internal/api/saml/storage.go +++ b/internal/api/saml/storage.go @@ -2,14 +2,19 @@ package saml import ( "context" + "encoding/json" "time" + "github.com/dop251/goja" + "github.com/zitadel/logging" "github.com/zitadel/saml/pkg/provider" "github.com/zitadel/saml/pkg/provider/key" "github.com/zitadel/saml/pkg/provider/models" "github.com/zitadel/saml/pkg/provider/serviceprovider" "github.com/zitadel/saml/pkg/provider/xml/samlp" + "github.com/zitadel/zitadel/internal/actions" + "github.com/zitadel/zitadel/internal/actions/object" "github.com/zitadel/zitadel/internal/api/http/middleware" "github.com/zitadel/zitadel/internal/auth/repository" "github.com/zitadel/zitadel/internal/command" @@ -124,7 +129,7 @@ func (p *Storage) AuthRequestByID(ctx context.Context, id string) (_ models.Auth return AuthRequestFromBusiness(resp) } -func (p *Storage) SetUserinfoWithUserID(ctx context.Context, userinfo models.AttributeSetter, userID string, attributes []int) (err error) { +func (p *Storage) SetUserinfoWithUserID(ctx context.Context, applicationID string, userinfo models.AttributeSetter, userID string, attributes []int) (err error) { ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() user, err := p.query.GetUserByID(ctx, true, userID, false) @@ -132,7 +137,17 @@ func (p *Storage) SetUserinfoWithUserID(ctx context.Context, userinfo models.Att return err } - setUserinfo(user, userinfo, attributes) + userGrants, err := p.getGrants(ctx, userID, applicationID) + if err != nil { + return err + } + + customAttributes, err := p.getCustomAttributes(ctx, user, userGrants) + if err != nil { + return err + } + + setUserinfo(user, userinfo, attributes, customAttributes) return nil } @@ -149,11 +164,14 @@ func (p *Storage) SetUserinfoWithLoginName(ctx context.Context, userinfo models. return err } - setUserinfo(user, userinfo, attributes) + setUserinfo(user, userinfo, attributes, map[string]*customAttribute{}) return nil } -func setUserinfo(user *query.User, userinfo models.AttributeSetter, attributes []int) { +func setUserinfo(user *query.User, userinfo models.AttributeSetter, attributes []int, customAttributes map[string]*customAttribute) { + for name, attr := range customAttributes { + userinfo.SetCustomAttribute(name, "", attr.nameFormat, attr.attributeValue) + } if len(attributes) == 0 { userinfo.SetUsername(user.PreferredLoginName) userinfo.SetUserID(user.ID) @@ -191,3 +209,139 @@ func setUserinfo(user *query.User, userinfo models.AttributeSetter, attributes [ } } } + +func (p *Storage) getCustomAttributes(ctx context.Context, user *query.User, userGrants *query.UserGrants) (map[string]*customAttribute, error) { + customAttributes := make(map[string]*customAttribute, 0) + queriedActions, err := p.query.GetActiveActionsByFlowAndTriggerType(ctx, domain.FlowTypeCustomizeSAMLResponse, domain.TriggerTypePreSAMLResponseCreation, user.ResourceOwner, false) + if err != nil { + return nil, err + } + ctxFields := actions.SetContextFields( + actions.SetFields("v1", + actions.SetFields("getUser", func(c *actions.FieldConfig) interface{} { + return func(call goja.FunctionCall) goja.Value { + return object.UserFromQuery(c, user) + } + }), + actions.SetFields("user", + actions.SetFields("getMetadata", func(c *actions.FieldConfig) interface{} { + return func(goja.FunctionCall) goja.Value { + resourceOwnerQuery, err := query.NewUserMetadataResourceOwnerSearchQuery(user.ResourceOwner) + if err != nil { + logging.WithError(err).Debug("unable to create search query") + panic(err) + } + metadata, err := p.query.SearchUserMetadata( + ctx, + true, + user.ID, + &query.UserMetadataSearchQueries{Queries: []query.SearchQuery{resourceOwnerQuery}}, + false, + ) + if err != nil { + logging.WithError(err).Info("unable to get md in action") + panic(err) + } + return object.UserMetadataListFromQuery(c, metadata) + } + }), + actions.SetFields("grants", func(c *actions.FieldConfig) interface{} { + return object.UserGrantsFromQuery(c, userGrants) + }), + ), + ), + ) + + for _, action := range queriedActions { + actionCtx, cancel := context.WithTimeout(ctx, action.Timeout()) + + apiFields := actions.WithAPIFields( + actions.SetFields("v1", + actions.SetFields("attributes", + actions.SetFields("setCustomAttribute", func(name string, nameFormat string, attributeValue ...string) { + if _, ok := customAttributes[name]; !ok { + customAttributes = appendCustomAttribute(customAttributes, name, nameFormat, attributeValue) + return + } + }), + ), + actions.SetFields("user", + actions.SetFields("setMetadata", func(call goja.FunctionCall) { + if len(call.Arguments) != 2 { + panic("exactly 2 (key, value) arguments expected") + } + key := call.Arguments[0].Export().(string) + val := call.Arguments[1].Export() + + value, err := json.Marshal(val) + if err != nil { + logging.WithError(err).Debug("unable to marshal") + panic(err) + } + + metadata := &domain.Metadata{ + Key: key, + Value: value, + } + if _, err = p.command.SetUserMetadata(ctx, metadata, user.ID, user.ResourceOwner); err != nil { + logging.WithError(err).Info("unable to set md in action") + panic(err) + } + }), + ), + ), + ) + + err = actions.Run( + actionCtx, + ctxFields, + apiFields, + action.Script, + action.Name, + append(actions.ActionToOptions(action), actions.WithHTTP(actionCtx))..., + ) + cancel() + if err != nil { + return nil, err + } + } + return customAttributes, nil +} + +func (p *Storage) getGrants(ctx context.Context, userID, applicationID string) (*query.UserGrants, error) { + projectID, err := p.query.ProjectIDFromClientID(ctx, applicationID, false) + if err != nil { + return nil, err + } + + projectQuery, err := query.NewUserGrantProjectIDSearchQuery(projectID) + if err != nil { + return nil, err + } + userIDQuery, err := query.NewUserGrantUserIDSearchQuery(userID) + if err != nil { + return nil, err + } + return p.query.UserGrants(ctx, &query.UserGrantsQueries{ + Queries: []query.SearchQuery{ + projectQuery, + userIDQuery, + }, + }, true, false) +} + +type customAttribute struct { + nameFormat string + attributeValue []string +} + +func appendCustomAttribute(customAttributes map[string]*customAttribute, name string, nameFormat string, attributeValue []string) map[string]*customAttribute { + if customAttributes == nil { + customAttributes = make(map[string]*customAttribute) + } + customAttributes[name] = &customAttribute{ + nameFormat: nameFormat, + attributeValue: attributeValue, + } + return customAttributes +} diff --git a/internal/domain/flow.go b/internal/domain/flow.go index c54436af1a..e8fcfbccb7 100644 --- a/internal/domain/flow.go +++ b/internal/domain/flow.go @@ -21,6 +21,7 @@ const ( FlowTypeExternalAuthentication FlowTypeCustomiseToken FlowTypeInternalAuthentication + FlowTypeCustomizeSAMLResponse flowTypeCount ) @@ -56,6 +57,10 @@ func (s FlowType) TriggerTypes() []TriggerType { TriggerTypePreCreation, TriggerTypePostCreation, } + case FlowTypeCustomizeSAMLResponse: + return []TriggerType{ + TriggerTypePreSAMLResponseCreation, + } default: return nil } @@ -80,6 +85,8 @@ func (s FlowType) LocalizationKey() string { return "Action.Flow.Type.CustomiseToken" case FlowTypeInternalAuthentication: return "Action.Flow.Type.InternalAuthentication" + case FlowTypeCustomizeSAMLResponse: + return "Action.Flow.Type.CustomizeSAMLResponse" default: return "Action.Flow.Type.Unspecified" } @@ -94,6 +101,7 @@ const ( TriggerTypePostCreation TriggerTypePreUserinfoCreation TriggerTypePreAccessTokenCreation + TriggerTypePreSAMLResponseCreation triggerTypeCount ) @@ -124,6 +132,8 @@ func (s TriggerType) LocalizationKey() string { return "Action.TriggerType.PreUserinfoCreation" case TriggerTypePreAccessTokenCreation: return "Action.TriggerType.PreAccessTokenCreation" + case TriggerTypePreSAMLResponseCreation: + return "Action.TriggerType.PreSAMLResponseCreation" default: return "Action.TriggerType.Unspecified" } diff --git a/internal/static/i18n/bg.yaml b/internal/static/i18n/bg.yaml index 319d4af86f..2e06279675 100644 --- a/internal/static/i18n/bg.yaml +++ b/internal/static/i18n/bg.yaml @@ -1266,6 +1266,7 @@ Action: ExternalAuthentication: Външно удостоверяване CustomiseToken: Токен за допълнение InternalAuthentication: Вътрешно удостоверяване + CustomizeSAMLResponse: Допълнение на SAMLResponse TriggerType: Unspecified: Неуточнено PostAuthentication: Публикуване на автентификация @@ -1273,3 +1274,4 @@ Action: PostCreation: Създаване на публикации PreUserinfoCreation: Предварително създаване на потребителска информация PreAccessTokenCreation: Създаване на маркер за предварителен достъп + PreSAMLResponseCreation: Предварително създаване на SAMLResponse diff --git a/internal/static/i18n/de.yaml b/internal/static/i18n/de.yaml index 774f87f7dd..04fd3a3eac 100644 --- a/internal/static/i18n/de.yaml +++ b/internal/static/i18n/de.yaml @@ -1216,6 +1216,7 @@ Action: ExternalAuthentication: Externe Authentifizierung CustomiseToken: Token ergänzen InternalAuthentication: Interne Authentifizierung + CustomizeSAMLResponse: SAMLResponse ergänzen TriggerType: Unspecified: Unspezifiziert PostAuthentication: Nach Authentifizierung @@ -1223,3 +1224,4 @@ Action: PostCreation: Nach Erstellung PreUserinfoCreation: Vor Userinfo Erstellung PreAccessTokenCreation: Vor Access Token Erstellung + PreSAMLResponseCreation: Vor SAMLResponse Erstellung diff --git a/internal/static/i18n/en.yaml b/internal/static/i18n/en.yaml index d6e84e5814..43ef6e043b 100644 --- a/internal/static/i18n/en.yaml +++ b/internal/static/i18n/en.yaml @@ -1216,6 +1216,7 @@ Action: ExternalAuthentication: External Authentication CustomiseToken: Complement Token InternalAuthentication: Internal Authentication + CustomizeSAMLResponse: Complement SAMLResponse TriggerType: Unspecified: Unspecified PostAuthentication: Post Authentication @@ -1223,3 +1224,4 @@ Action: PostCreation: Post Creation PreUserinfoCreation: Pre Userinfo creation PreAccessTokenCreation: Pre access token creation + PreSAMLResponseCreation: Pre SAMLResponse creation diff --git a/internal/static/i18n/es.yaml b/internal/static/i18n/es.yaml index 95af0e0714..825ea9ec62 100644 --- a/internal/static/i18n/es.yaml +++ b/internal/static/i18n/es.yaml @@ -1216,6 +1216,7 @@ Action: ExternalAuthentication: Autenticación externa CustomiseToken: Token complementario InternalAuthentication: Autenticación interna + CustomizeSAMLResponse: SAMLResponse complementario TriggerType: Unspecified: No especificado PostAuthentication: Post Autenticación @@ -1223,3 +1224,4 @@ Action: PostCreation: Post Creación PreUserinfoCreation: Pre creación de Userinfo PreAccessTokenCreation: Pre creación de token de acceso + PreSAMLResponseCreation: Creación previa de SAMLResponse diff --git a/internal/static/i18n/fr.yaml b/internal/static/i18n/fr.yaml index f0a1b1df45..3933e4d64c 100644 --- a/internal/static/i18n/fr.yaml +++ b/internal/static/i18n/fr.yaml @@ -1045,6 +1045,7 @@ Action: ExternalAuthentication: Authentification externe CustomiseToken: Compléter Token InternalAuthentication: Authentification interne + CustomizeSAMLResponse: Compléter SAMLResponse TriggerType: Unspecified: Non spécifié PostAuthentication: Authentification postérieure @@ -1052,3 +1053,4 @@ Action: PostCreation: Post-création PreUserinfoCreation: Pré Userinfo création PreAccessTokenCreation: Pré access token création + PreSAMLResponseCreation: Création préalable de la réponse SAMLResponse diff --git a/internal/static/i18n/it.yaml b/internal/static/i18n/it.yaml index 3e70d4f6a8..7f73063c8e 100644 --- a/internal/static/i18n/it.yaml +++ b/internal/static/i18n/it.yaml @@ -1045,6 +1045,7 @@ Action: ExternalAuthentication: Autenticazione esterna CustomiseToken: Completare Token InternalAuthentication: Autenticazione interna + CustomizeSAMLResponse: Completare SAMLResponse TriggerType: Unspecified: Non specificato PostAuthentication: Post-autenticazione @@ -1052,3 +1053,4 @@ Action: PostCreation: Creazione successiva PreUserinfoCreation: Pre userinfo creazione PreAccessTokenCreation: Pre access token creazione + PreSAMLResponseCreation: Pre SAMLResponse creazione diff --git a/internal/static/i18n/ja.yaml b/internal/static/i18n/ja.yaml index d1e5cdfa47..d0e2279ece 100644 --- a/internal/static/i18n/ja.yaml +++ b/internal/static/i18n/ja.yaml @@ -1205,6 +1205,7 @@ Action: ExternalAuthentication: 外部認証 CustomiseToken: トークンを補完 InternalAuthentication: 内部認証 + CustomizeSAMLResponse: SAMLResponse の補完 TriggerType: Unspecified: 未定義 PostAuthentication: 認証後 @@ -1212,3 +1213,4 @@ Action: PostCreation: 作成後 PreUserinfoCreation: ユーザー情報作成前 PreAccessTokenCreation: アクセストークン作成前 + PreSAMLResponseCreation: SAMLResponse の作成前 diff --git a/internal/static/i18n/mk.yaml b/internal/static/i18n/mk.yaml index 4d2afce3c6..c4075da9c8 100644 --- a/internal/static/i18n/mk.yaml +++ b/internal/static/i18n/mk.yaml @@ -1215,6 +1215,7 @@ Action: ExternalAuthentication: Надворешна автентикација CustomiseToken: Комплемент на токенот InternalAuthentication: Внатрешна автентикација + CustomizeSAMLResponse: Дополнете го SAMLResponse TriggerType: Unspecified: Неодредено PostAuthentication: По автентикација @@ -1222,3 +1223,4 @@ Action: PostCreation: По креирање PreUserinfoCreation: Пред креирање на кориснички информации PreAccessTokenCreation: Пред креирање на токен за пристап + PreSAMLResponseCreation: Пред создавање на SAMLResponse diff --git a/internal/static/i18n/pl.yaml b/internal/static/i18n/pl.yaml index adde4501aa..07a00e3149 100644 --- a/internal/static/i18n/pl.yaml +++ b/internal/static/i18n/pl.yaml @@ -1216,6 +1216,7 @@ Action: ExternalAuthentication: Autentykacja zewnętrzna CustomiseToken: Uzupełnienie tokenu InternalAuthentication: Autentykacja wewnętrzna + CustomizeSAMLResponse: Uzupełnienie SAMLResponse TriggerType: Unspecified: Nieokreślony PostAuthentication: Po autentykacji @@ -1223,3 +1224,4 @@ Action: PostCreation: Po utworzeniu PreUserinfoCreation: Przed tworzeniem informacji o użytkowniku PreAccessTokenCreation: Przed tworzeniem tokenu dostępu + PreSAMLResponseCreation: Wstępne tworzenie odpowiedzi SAMLResponse diff --git a/internal/static/i18n/pt.yaml b/internal/static/i18n/pt.yaml index 00f3f1a055..a2e9754495 100644 --- a/internal/static/i18n/pt.yaml +++ b/internal/static/i18n/pt.yaml @@ -1211,6 +1211,7 @@ Action: ExternalAuthentication: Autenticação externa CustomiseToken: Complementar Token InternalAuthentication: Autenticação interna + CustomizeSAMLResponse: Complementar SAMLResponse TriggerType: Unspecified: Não especificado PostAuthentication: Pós-autenticação @@ -1218,3 +1219,4 @@ Action: PostCreation: Póscriação PreUserinfoCreation: Pré-criação de informações do usuário PreAccessTokenCreation: Pré-criação de access token + PreSAMLResponseCreation: Pré-criação de SAMLResponse diff --git a/internal/static/i18n/zh.yaml b/internal/static/i18n/zh.yaml index fb1d158c62..3418a7dcc4 100644 --- a/internal/static/i18n/zh.yaml +++ b/internal/static/i18n/zh.yaml @@ -1045,6 +1045,7 @@ Action: ExternalAuthentication: 外部认证 CustomiseToken: 自定义令牌 InternalAuthentication: 内部认证 + CustomizeSAMLResponse: 补充 SAMLResponse TriggerType: Unspecified: 未指定的 PostAuthentication: 后期认证 @@ -1052,3 +1053,4 @@ Action: PostCreation: 创建后 PreUserinfoCreation: 用户信息创建前 PreAccessTokenCreation: access 令牌创建前 + PreSAMLResponseCreation: 创建 SAMLResponse 前