Repository: Nerzal/gocloak
Pull request #327 (2021-12-08 07:49:33)

feat: add CreateAuthenticationExecutionFlow
Thanks for your contribution!
Hi, if there is an issue, that your PR adresses, please link it! 


Nerzal: Hi, could you please resolve the merge conflicts?
weixiao-huang: All conflicts have been resolved
codecov[bot]: # [Codecov](https://codecov.io/gh/Nerzal/gocloak/pull/327?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal) Report
> Merging [#327](https://codecov.io/gh/Nerzal/gocloak/pull/327?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal) (52627eb) into [main](https://codecov.io/gh/Nerzal/gocloak/commit/392e397a4023a2be4728f6e355994a67af380039?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal) (392e397) will **decrease** coverage by `0.15%`.
> The diff coverage is `0.00%`.

[![Impacted file tree graph](https://codecov.io/gh/Nerzal/gocloak/pull/327/graphs/tree.svg?width=650&height=150&src=pr&token=gB52LSVNIV&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal)](https://codecov.io/gh/Nerzal/gocloak/pull/327?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal)

```diff
@@            Coverage Diff             @@
##             main     #327      +/-   ##
==========================================
- Coverage   76.60%   76.44%   -0.16%     
==========================================
  Files           4        4              
  Lines        1962     1966       +4     
==========================================
  Hits         1503     1503              
- Misses        319      323       +4     
  Partials      140      140              
```


| [Impacted Files](https://codecov.io/gh/Nerzal/gocloak/pull/327?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal) | Coverage Δ | |
|---|---|---|
| [client.go](https://codecov.io/gh/Nerzal/gocloak/pull/327/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal#diff-Y2xpZW50Lmdv) | `74.63% <0.00%> (-0.17%)` | :arrow_down: |
| [models.go](https://codecov.io/gh/Nerzal/gocloak/pull/327/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal#diff-bW9kZWxzLmdv) | `92.80% <ø> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/Nerzal/gocloak/pull/327?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/Nerzal/gocloak/pull/327?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal). Last update [392e397...52627eb](https://codecov.io/gh/Nerzal/gocloak/pull/327?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nerzal).

Nerzal: Hi again :) 

The code looks good so far. 
Could you please also add a test for that function? :) 
weixiao-huang: I added tests but I cannot test it in my local machine, so please approve the test ci, thanks
weixiao-huang: Hello, could you please approve the ci to test?

Patch:
diff --git a/client.go b/client.go
index 71c0319..231acaa 100644
--- a/client.go
+++ b/client.go
@@ -2204,6 +2204,15 @@ func (client *gocloak) DeleteAuthenticationExecution(ctx context.Context, token,
 	return checkForError(resp, err, errMessage)
 }
 
+//CreateAuthenticationExecutionFlow creates a new execution for the given flow name in the given realm
+func (client *gocloak) CreateAuthenticationExecutionFlow(ctx context.Context, token, realm, flow string, executionFlow CreateAuthenticationExecutionFlowRepresentation) error {
+	const errMessage = "could not create authentication execution flow"
+	resp, err := client.getRequestWithBearerAuth(ctx, token).SetBody(executionFlow).
+		Post(client.getAdminRealmURL(realm, "authentication", "flows", flow, "executions", "flow"))
+
+	return checkForError(resp, err, errMessage)
+}
+
 // -----
 // Users
 // -----
@@ -3683,3 +3692,17 @@ func (client *gocloak) CreateClientScopesScopeMappingsRealmRoles(ctx context.Con
 
 	return checkForError(resp, err, errMessage)
 }
+
+// UpdateRequiredAction updates a required action for a given realm
+func (client *gocloak) UpdateRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error {
+	const errMessage = "could not update required action"
+
+	if NilOrEmpty(requiredAction.ProviderID) {
+		return errors.New("providerId is required for updating a required action")
+	}
+	_, err := client.getRequestWithBearerAuth(ctx, token).
+		SetBody(requiredAction).
+		Put(client.getAdminRealmURL(realm, "authentication", "required-actions", *requiredAction.ProviderID))
+
+	return err
+}
diff --git a/go.sum b/go.sum
index 1a7b4fd..08d51aa 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,5 @@
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=
-github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU=
 github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4=
 github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q=
 github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
@@ -12,47 +10,28 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/segmentio/ksuid v1.0.3 h1:FoResxvleQwYiPAVKe1tMUlEirodZqlqglIuFsdDntY=
-github.com/segmentio/ksuid v1.0.3/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
 github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
 github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
-github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
 golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/gocloak.go b/gocloak.go
index d09bdf9..8afb130 100644
--- a/gocloak.go
+++ b/gocloak.go
@@ -316,6 +316,9 @@ type GoCloak interface {
 	// DeleteAuthenticationExecution delete a single execution with the given ID
 	DeleteAuthenticationExecution(ctx context.Context, token, realm, executionID string) error
 
+	//CreateAuthenticationExecutionFlow creates a new flow execution for the given flow name in the given realm
+	CreateAuthenticationExecutionFlow(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionFlowRepresentation) error
+
 	// *** Users ***
 	// CreateUser creates a new user
 	CreateUser(ctx context.Context, token, realm string, user User) (string, error)
@@ -493,6 +496,14 @@ type GoCloak interface {
 	// ---------------
 	// Events API
 	// ---------------
+
 	// GetEvents returns events
 	GetEvents(ctx context.Context, token string, realm string, params GetEventsParams) ([]*EventRepresentation, error)
+
+	// -------------------
+	// RequiredActions API
+	// -------------------
+
+	// UpdateRequiredAction updates a required action for a given realm
+	UpdateRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error
 }
diff --git a/models.go b/models.go
index f4ff195..551b829 100644
--- a/models.go
+++ b/models.go
@@ -197,19 +197,13 @@ type SetPasswordRequest struct {
 
 // Component is a component
 type Component struct {
-	ID              *string          `json:"id,omitempty"`
-	Name            *string          `json:"name,omitempty"`
-	ProviderID      *string          `json:"providerId,omitempty"`
-	ProviderType    *string          `json:"providerType,omitempty"`
-	ParentID        *string          `json:"parentId,omitempty"`
-	ComponentConfig *ComponentConfig `json:"config,omitempty"`
-	SubType         *string          `json:"subType,omitempty"`
-}
-
-// ComponentConfig is a componentconfig
-type ComponentConfig struct {
-	Priority  *[]string `json:"priority,omitempty"`
-	Algorithm *[]string `json:"algorithm,omitempty"`
+	ID              *string              `json:"id,omitempty"`
+	Name            *string              `json:"name,omitempty"`
+	ProviderID      *string              `json:"providerId,omitempty"`
+	ProviderType    *string              `json:"providerType,omitempty"`
+	ParentID        *string              `json:"parentId,omitempty"`
+	ComponentConfig *map[string][]string `json:"config,omitempty"`
+	SubType         *string              `json:"subType,omitempty"`
 }
 
 // KeyStoreConfig holds the keyStoreConfig
@@ -263,6 +257,7 @@ type UserGroup struct {
 type GetUsersParams struct {
 	BriefRepresentation *bool   `json:"briefRepresentation,string,omitempty"`
 	Email               *string `json:"email,omitempty"`
+	EmailVerified       *bool   `json:"emailVerified,string,omitempty"`
 	Enabled             *bool   `json:"enabled,string,omitempty"`
 	Exact               *bool   `json:"exact,string,omitempty"`
 	First               *int    `json:"first,string,omitempty"`
@@ -271,6 +266,7 @@ type GetUsersParams struct {
 	IDPUserID           *string `json:"idpUserId,omitempty"`
 	LastName            *string `json:"lastName,omitempty"`
 	Max                 *int    `json:"max,string,omitempty"`
+	Q                   *string `json:"q,omitempty"`
 	Search              *string `json:"search,omitempty"`
 	Username            *string `json:"username,omitempty"`
 }
@@ -797,6 +793,14 @@ type CreateAuthenticationExecutionRepresentation struct {
 	Provider *string `json:"provider,omitempty"`
 }
 
+// CreateAuthenticationExecutionFlowRepresentation contains the provider to be used for a new authentication representation
+type CreateAuthenticationExecutionFlowRepresentation struct {
+	Alias       *string `json:"alias,omitempty"`
+	Description *string `json:"description,omitempty"`
+	Provider    *string `json:"provider,omitempty"`
+	Type        *string `json:"type,omitempty"`
+}
+
 // ModifyAuthenticationExecutionRepresentation is the payload for updating an execution representation
 type ModifyAuthenticationExecutionRepresentation struct {
 	ID                   *string   `json:"id,omitempty"`
@@ -1234,6 +1238,18 @@ type CredentialRepresentation struct {
 	UserLabel      *string `json:"userLabel,omitempty"`
 }
 
+// RequiredActionProviderRepresentation is a representation of required actions
+// v15: https://www.keycloak.org/docs-api/15.0/rest-api/index.html#_requiredactionproviderrepresentation
+type RequiredActionProviderRepresentation struct {
+	Alias         *string            `json:"alias,omitempty"`
+	Config        *map[string]string `json:"config,omitempty"`
+	DefaultAction *bool              `json:"defaultAction,omitempty"`
+	Enabled       *bool              `json:"enabled,omitempty"`
+	Name          *string            `json:"name,omitempty"`
+	Priority      *int32             `json:"priority,omitempty"`
+	ProviderID    *string            `json:"providerId,omitempty"`
+}
+
 // prettyStringStruct returns struct formatted into pretty string
 func prettyStringStruct(t interface{}) string {
 
@@ -1256,7 +1272,6 @@ func (v *RetrospecTokenResult) String() string                      { return pre
 func (v *User) String() string                                      { return prettyStringStruct(v) }
 func (v *SetPasswordRequest) String() string                        { return prettyStringStruct(v) }
 func (v *Component) String() string                                 { return prettyStringStruct(v) }
-func (v *ComponentConfig) String() string                           { return prettyStringStruct(v) }
 func (v *KeyStoreConfig) String() string                            { return prettyStringStruct(v) }
 func (v *ActiveKeys) String() string                                { return prettyStringStruct(v) }
 func (v *Key) String() string                                       { return prettyStringStruct(v) }
@@ -1326,3 +1341,4 @@ func (v *GetUserPermissionParams) String() string                   { return pre
 func (v *ResourcePolicyRepresentation) String() string              { return prettyStringStruct(v) }
 func (v *GetResourcePoliciesParams) String() string                 { return prettyStringStruct(v) }
 func (v *CredentialRepresentation) String() string                  { return prettyStringStruct(v) }
+func (v *RequiredActionProviderRepresentation) String() string      { return prettyStringStruct(v) }


Test patch:
diff --git a/client_test.go b/client_test.go
index a222279..7f694e7 100644
--- a/client_test.go
+++ b/client_test.go
@@ -6149,7 +6149,7 @@ func TestGocloak_GetAuthenticationFlows(t *testing.T) {
 	require.Error(t, err)
 }
 
-func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecution(t *testing.T) {
+func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecutionAndFlow(t *testing.T) {
 	t.Parallel()
 	cfg := GetConfig(t)
 	client := NewClientWithDebug(t)
@@ -6166,6 +6166,13 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecution(t *te
 		ProviderID:  gocloak.StringP("basic-flow"),
 	}
 
+	authExecFlow := gocloak.CreateAuthenticationExecutionFlowRepresentation{
+		Alias:       gocloak.StringP("testauthexecflow"),
+		Description: gocloak.StringP("test"),
+		Provider:    gocloak.StringP("basic-flow"),
+		Type:        gocloak.StringP("basic-flow"),
+	}
+
 	err := client.CreateAuthenticationFlow(
 		context.Background(),
 		token.AccessToken,
@@ -6184,25 +6191,40 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecution(t *te
 	)
 	require.NoError(t, err, "Failed to create authentication execution")
 
-	authExecs, err := client.GetAuthenticationExecutions(
+	err = client.CreateAuthenticationExecutionFlow(
 		context.Background(),
 		token.AccessToken,
 		cfg.GoCloak.Realm,
 		*authFlow.Alias,
+		authExecFlow,
 	)
+	require.NoError(t, err, "Failed to create authentication execution flow")
 
-	t.Logf("authentication executions: %+v", authExecs)
-	require.NoError(t, err, "Failed to get authentication executions")
-
-	authExecs[0].Requirement = gocloak.StringP("ALTERNATIVE")
-	err = client.UpdateAuthenticationExecution(
+	authExecs, err := client.GetAuthenticationExecutions(
 		context.Background(),
 		token.AccessToken,
 		cfg.GoCloak.Realm,
 		*authFlow.Alias,
-		*authExecs[0],
 	)
-	require.NoError(t, err, "Failed to update authentication executions")
+
+	t.Logf("authentication executions: %+v", authExecs)
+	require.NoError(t, err, "Failed to get authentication executions")
+
+	// UpdateAuthenticationExecution
+	for _, execution := range authExecs {
+		if execution.ProviderID != nil && *execution.ProviderID == *authExec.Provider {
+			execution.Requirement = gocloak.StringP("ALTERNATIVE")
+			err = client.UpdateAuthenticationExecution(
+				context.Background(),
+				token.AccessToken,
+				cfg.GoCloak.Realm,
+				*authFlow.Alias,
+				*execution,
+			)
+			require.NoError(t, err, fmt.Sprintf("Failed to update authentication executions, realm: %+v, flow: %+v, execution: %+v", cfg.GoCloak.Realm, *authFlow.Alias, *execution.ProviderID))
+			break
+		}
+	}
 	authExecs, err = client.GetAuthenticationExecutions(
 		context.Background(),
 		token.AccessToken,
@@ -6212,6 +6234,34 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecution(t *te
 	require.NoError(t, err, "Failed to get authentication executions second time")
 	t.Logf("authentication executions after update: %+v", authExecs)
 
+	var (
+		execDeleted   bool
+		execFlowFound bool
+	)
+	for _, execution := range authExecs {
+		if execution.DisplayName != nil && *execution.DisplayName == *authExecFlow.Alias {
+			execFlowFound = true
+			continue
+		}
+		if execution.ProviderID != nil && *execution.ProviderID == *authExec.Provider {
+			require.NotNil(t, execution.Requirement)
+			require.Equal(t, *execution.Requirement, "ALTERNATIVE")
+			err = client.DeleteAuthenticationExecution(
+				context.Background(),
+				token.AccessToken,
+				cfg.GoCloak.Realm,
+				*execution.ID,
+			)
+			require.NoError(t, err, "Failed to delete authentication execution")
+			execDeleted = true
+		}
+		if execDeleted && execFlowFound {
+			break
+		}
+	}
+	require.True(t, execDeleted, "Failed to delete authentication execution, no execution was deleted")
+	require.True(t, execFlowFound, "Failed to find authentication execution flow")
+
 	flows, err := client.GetAuthenticationFlows(context.Background(), token.AccessToken, cfg.GoCloak.Realm)
 	require.NoError(t, err, "Failed to get authentication flows")
 	deleted := false
@@ -6230,3 +6280,21 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecution(t *te
 	}
 	require.True(t, deleted, "Failed to delete authentication flow, no flow was deleted")
 }
+
+func TestGocloak_UpdateRequiredAction(t *testing.T) {
+	t.Parallel()
+	cfg := GetConfig(t)
+	client := NewClientWithDebug(t)
+	token := GetAdminToken(t, client)
+	requiredAction := gocloak.RequiredActionProviderRepresentation{
+		Alias:         gocloak.StringP("VERIFY_EMAIL"),
+		Config:        nil,
+		DefaultAction: gocloak.BoolP(false),
+		Enabled:       gocloak.BoolP(true),
+		Name:          gocloak.StringP("Verify Email"),
+		Priority:      gocloak.Int32P(50),
+		ProviderID:    gocloak.StringP("VERIFY_EMAIL"),
+	}
+	err := client.UpdateRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, requiredAction)
+	require.NoError(t, err, "Failed to update required action")
+}
diff --git a/model_test.go b/model_test.go
index 88458df..92fd334 100644
--- a/model_test.go
+++ b/model_test.go
@@ -222,7 +222,6 @@ func TestStringerOmitEmpty(t *testing.T) {
 		&gocloak.User{},
 		&gocloak.SetPasswordRequest{},
 		&gocloak.Component{},
-		&gocloak.ComponentConfig{},
 		&gocloak.KeyStoreConfig{},
 		&gocloak.ActiveKeys{},
 		&gocloak.Key{},
diff --git a/run-tests.sh b/run-tests.sh
index 9bb7dc5..ed2de6c 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -13,4 +13,4 @@ fi
 
 go test -failfast -race -cover -coverprofile=coverage.out -covermode=atomic -p 10 -cpu 1,2 -bench . -benchmem ${ARGS[@]}
 
-docker-compose down
+docker-compose down
\ No newline at end of file