From 76b1bd1e3b71ab7f376d5ec41650620c207404af Mon Sep 17 00:00:00 2001 From: Dave Sirockin Date: Mon, 24 Jan 2022 11:39:20 +0100 Subject: [PATCH 01/60] add `Q` and `EmailVerified` to GetUsersParams (#337) Co-authored-by: Dave Sirockin --- models.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/models.go b/models.go index f4ff1950..045c0403 100644 --- a/models.go +++ b/models.go @@ -263,6 +263,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 +272,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"` } From 7fa5389b9f83a2be4ee2d372b9d7cbaf54402154 Mon Sep 17 00:00:00 2001 From: Christian Rebischke Date: Thu, 17 Feb 2022 14:24:22 +0100 Subject: [PATCH 02/60] feat: add requiredActionProviderRepresentation (#339) This commit adds the requiredActionProviderRepresentation and a function for updating required actions --- client.go | 14 ++++++++++++++ client_test.go | 18 ++++++++++++++++++ gocloak.go | 8 ++++++++ models.go | 13 +++++++++++++ 4 files changed, 53 insertions(+) diff --git a/client.go b/client.go index 71c0319f..918ed95f 100644 --- a/client.go +++ b/client.go @@ -3683,3 +3683,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/client_test.go b/client_test.go index a2222798..a3d36b7a 100644 --- a/client_test.go +++ b/client_test.go @@ -6230,3 +6230,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/gocloak.go b/gocloak.go index d09bdf9f..f8401806 100644 --- a/gocloak.go +++ b/gocloak.go @@ -493,6 +493,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 045c0403..089e7afc 100644 --- a/models.go +++ b/models.go @@ -1236,6 +1236,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 { @@ -1328,3 +1340,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) } From 4716d38a7db252adb5f3b3b5ebaeb89166538927 Mon Sep 17 00:00:00 2001 From: Merlin Dienst Date: Thu, 17 Feb 2022 14:26:26 +0100 Subject: [PATCH 03/60] Changed ComponentConfig to be a map[string][]string instead of its own struct (#325) * Feature: #321 ComponentConfig now is a map[string]string to generalize it's usage * changed module name * changed all nerzal to doktormerlin * added replacement directive * Added newline to end of file * removed replacement directive * map[string]string now map[string][]string in ComponentConfig * Changed ComponentConfig to be a map[string][]string instead of its own struct * Fixed issues caused by renaming. Go and forking just doesnt go well together * Renamed some stuff from Nerzal to nerzal * tests sleeping 10 seconds again * reverted tests Co-authored-by: merl_umlaut --- go.sum | 21 --------------------- model_test.go | 1 - models.go | 21 +++++++-------------- run-tests.sh | 2 +- 4 files changed, 8 insertions(+), 37 deletions(-) diff --git a/go.sum b/go.sum index 1a7b4fd5..08d51aa9 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/model_test.go b/model_test.go index 88458df4..92fd334f 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/models.go b/models.go index 089e7afc..6635d098 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 @@ -1270,7 +1264,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) } diff --git a/run-tests.sh b/run-tests.sh index 9bb7dc51..ed2de6ce 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 From 08df6c5e6d4d6227a8ada3c1eac0179b38e173bd Mon Sep 17 00:00:00 2001 From: Weixiao Huang Date: Thu, 17 Feb 2022 21:28:58 +0800 Subject: [PATCH 04/60] feat: add CreateAuthenticationExecutionFlow (#327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add CreateAuthenticationExecutionFlow * test: add test for GetAuthenticationExecutions, DeleteAuthenticationExecution and CreateAuthenticationExecutionFlow * test: improve authExecs check Co-authored-by: 黄维啸 --- client.go | 9 +++++++ client_test.go | 68 +++++++++++++++++++++++++++++++++++++++++++------- gocloak.go | 3 +++ models.go | 8 ++++++ 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/client.go b/client.go index 918ed95f..231acaa0 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 // ----- diff --git a/client_test.go b/client_test.go index a3d36b7a..7f694e76 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 diff --git a/gocloak.go b/gocloak.go index f8401806..8afb1309 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) diff --git a/models.go b/models.go index 6635d098..551b8298 100644 --- a/models.go +++ b/models.go @@ -793,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"` From b55ab25c3e22f9da84028faeb254a9375502c093 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 22 Feb 2022 17:07:18 +0100 Subject: [PATCH 05/60] ignore gocognit in test files --- .golangci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.yml b/.golangci.yml index 5922af33..c5424555 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -40,5 +40,6 @@ issues: - gocyclo - dupl - gosec + - gocognit exclude: - should have a package comment From 44d3a1f80082495a5bc11e23f806cb0541741feb Mon Sep 17 00:00:00 2001 From: Tjark Meyer <77924577+tjarkmeyer@users.noreply.github.com> Date: Tue, 1 Mar 2022 10:31:56 +0100 Subject: [PATCH 06/60] fix: json tags in GetEventsParams (#335) (#340) Co-authored-by: Tjark Meyer --- models.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models.go b/models.go index 551b8298..bd5b2aed 100644 --- a/models.go +++ b/models.go @@ -1190,9 +1190,9 @@ type GetEventsParams struct { Client *string `json:"client,omitempty"` DateFrom *string `json:"dateFrom,omitempty"` DateTo *string `json:"dateTo,omitempty"` - First *int32 `json:"first,omitempty"` + First *int32 `json:"first,string,omitempty"` IPAddress *string `json:"ipAddress,omitempty"` - Max *int32 `json:"max,omitempty"` + Max *int32 `json:"max,string,omitempty"` Type []string `json:"type,omitempty"` UserID *string `json:"user,omitempty"` } From c0c3fdca4d0b0c5cecac477552066b50cfbd14c8 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 1 Mar 2022 10:34:58 +0100 Subject: [PATCH 07/60] upgrade to V11 --- README.md | 4 ++-- client.go | 2 +- client_benchmark_test.go | 2 +- client_test.go | 2 +- go.mod | 2 +- model_test.go | 2 +- utils_test.go | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f2cb3d72..e5704e72 100644 --- a/README.md +++ b/README.md @@ -130,13 +130,13 @@ There are a lot of backward incompatible changes: ### Installation ```shell -go get github.com/Nerzal/gocloak/v10 +go get github.com/Nerzal/gocloak/v11 ``` ### Importing ```go - import "github.com/Nerzal/gocloak/v10" + import "github.com/Nerzal/gocloak/v11" ``` ### Create New User diff --git a/client.go b/client.go index 231acaa0..1d1b03d3 100644 --- a/client.go +++ b/client.go @@ -17,7 +17,7 @@ import ( "github.com/pkg/errors" "github.com/segmentio/ksuid" - "github.com/Nerzal/gocloak/v10/pkg/jwx" + "github.com/Nerzal/gocloak/v11/pkg/jwx" ) type gocloak struct { diff --git a/client_benchmark_test.go b/client_benchmark_test.go index c5265097..e097fbd8 100644 --- a/client_benchmark_test.go +++ b/client_benchmark_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/Nerzal/gocloak/v10" + "github.com/Nerzal/gocloak/v11" "github.com/stretchr/testify/assert" ) diff --git a/client_test.go b/client_test.go index 7f694e76..44774853 100644 --- a/client_test.go +++ b/client_test.go @@ -26,7 +26,7 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/pkcs12" - "github.com/Nerzal/gocloak/v10" + "github.com/Nerzal/gocloak/v11" ) type configAdmin struct { diff --git a/go.mod b/go.mod index 02cbd14c..f6eeb956 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/Nerzal/gocloak/v10 +module github.com/Nerzal/gocloak/v11 go 1.15 diff --git a/model_test.go b/model_test.go index 92fd334f..cb9fea0a 100644 --- a/model_test.go +++ b/model_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - "github.com/Nerzal/gocloak/v10" + "github.com/Nerzal/gocloak/v11" "github.com/stretchr/testify/assert" ) diff --git a/utils_test.go b/utils_test.go index c1db3faf..92cfa212 100644 --- a/utils_test.go +++ b/utils_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/Nerzal/gocloak/v10" + "github.com/Nerzal/gocloak/v11" ) func TestStringP(t *testing.T) { From 30870aa195a7975adfcb929c5b90a4100c675a18 Mon Sep 17 00:00:00 2001 From: Nerzal Date: Tue, 1 Mar 2022 13:02:15 +0100 Subject: [PATCH 08/60] Update README.md --- README.md | 100 +----------------------------------------------------- 1 file changed, 1 insertion(+), 99 deletions(-) diff --git a/README.md b/README.md index e5704e72..c7b2c6ac 100644 --- a/README.md +++ b/README.md @@ -24,106 +24,8 @@ Benchmarks can be found [here](https://nerzal.github.io/gocloak/dev/bench/) ## Changelog -### V10 +For release notes please consult the specific releases [here](https://github.com/Nerzal/gocloak/releases) -#### V10.0.1 - -We introduced 2 breaking changes. - -We switched the internal used JWT library, because the old one was no longer supported. - -Instead of passing the expected audience into the DecodeToken functions, we can validate the expected audience with a call to VerifyAudience: https://pkg.go.dev/github.com/golang-jwt/jwt#MapClaims.VerifyAudience - -When using custom claims, you'd have to implement the audience check for yourself for now. -I'm open for better ideas regarding the audience validation. - -The second breaking change is we switched the type of enum PolicyEnforcementMode from int to string. - -* Feature: #315 change type of enum PolicyEnforcementMode from int to string -* Feature: #307 switch jwt lib -* Feature: #310 type are added to the path of update policy and update permission fix #308 -* Feature: #315 change type of enum PolicyEnforcementMode from int to string -* Feature: #318 Auth flows and executions -* Feature: #319 defaults for P* utils -* Feature: #320 add password policies to server info - -### V9 - -#### V9.0.4 - -* Feature: #314 Add query parameter search to model GetClientsParams -* Feature: #313 Added ExactName param to GetSourceParams -* Feature: #312 Add support for client registration API -* Feature: #311 Add defaultRole to RealmRepresentation - - -#### V9.0.2 - -Bugfix: #305 Fix function signature of LoginClientTokenExchange function - - -#### V9.0.1 - -Breaking changes were introduced in #285 -See: https://github.com/Nerzal/gocloak/pull/285/files - -New Features: -- #301 adding APIs handler to fetch policy resources -- #299 GroupList Retrieval by RoleName -- #296 Fixed incorrect json representation of ResourceType in PermissionRepresentation -- #294 Remove duplicate quotes in README.md -- #293 add IDPAlias IDPUserID query parameter to GetUsersParams -- #290 Consent revocation endpoint -- #288 Add support for token exchange login method - -Bugifxes: -- #287 bugfix: clear up id of client and client_id confusion - -### v8 - -Features: - -- Add DeleteIdentityProviderMapper and GetIdentityProviderMappers #273 -- Adding search by attributes client param #272 -- Add CreateIdentityProviderMapper call #268 -- Add ImportIdentityProviderConfig method #267 -- Added endpoint to support exporting public broker config info #266 - -Fixes: - -- adding "DecisionStrategy" to "ResourceServerRepresentation" #264 - -### v7 - -Breaking Change - -- Added support for array values in aud claim -- When decoding an access Token, it is now needed to provide the audience to check -- Add member "MatchingURI" to GetResourceParams -- Add resource policy functions (thanks to timdrysdale) -- Add type field to APIError -- Most of the protection API should now be implemented (thanks to timdrysdale) - -### v6 - -There are several backward incompatible changes - -- all client functions now take `context.Context` as first argument. -- `UserAttributeContains` was moved from client method to package function. -- all structures now use pointers for the array types ([]string -> *[]string) - -### v5 - -There is only one change, but it's backward incompatible: - -- Wrap Errors and use APIError struct to also provide the httpstatus code. ([#146](https://github.com/Nerzal/gocloak/pull/146)) - -### v4 - -There are a lot of backward incompatible changes: - -- all functions what create an object now return an ID of the created object. The return statement of those functions has been changed from (error) to (string, error) -- All structures now use pointers instead of general types (bool -> *bool, string ->*string). It has been done to properly use omitempty tag, otherwise it was impossible to set a false value for any of the bool propertires. ## Usage From 4f92e9c55399685d71f96f3645f802de3d2ca350 Mon Sep 17 00:00:00 2001 From: quantonganh Date: Tue, 8 Mar 2022 14:54:33 +0700 Subject: [PATCH 09/60] token exchange: make requested_subject optional (#343) --- client.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client.go b/client.go index 1d1b03d3..497c768c 100644 --- a/client.go +++ b/client.go @@ -522,7 +522,7 @@ func (client *gocloak) LoginAdmin(ctx context.Context, username, password, realm }) } -// Login performs a login with client credentials +// LoginClient performs a login with client credentials func (client *gocloak) LoginClient(ctx context.Context, clientID, clientSecret, realm string) (*JWT, error) { return client.GetToken(ctx, realm, TokenOptions{ ClientID: &clientID, @@ -534,15 +534,18 @@ func (client *gocloak) LoginClient(ctx context.Context, clientID, clientSecret, // LoginClientTokenExchange will exchange the presented token for a user's token // Requires Token-Exchange is enabled: https://www.keycloak.org/docs/latest/securing_apps/index.html#_token-exchange func (client *gocloak) LoginClientTokenExchange(ctx context.Context, clientID, token, clientSecret, realm, targetClient, userID string) (*JWT, error) { - return client.GetToken(ctx, realm, TokenOptions{ + tokenOptions := TokenOptions{ ClientID: &clientID, ClientSecret: &clientSecret, GrantType: StringP("urn:ietf:params:oauth:grant-type:token-exchange"), SubjectToken: &token, RequestedTokenType: StringP("urn:ietf:params:oauth:token-type:refresh_token"), Audience: &targetClient, - RequestedSubject: &userID, - }) + } + if userID != "" { + tokenOptions.RequestedSubject = &userID + } + return client.GetToken(ctx, realm, tokenOptions) } // LoginClientSignedJWT performs a login with client credentials and signed jwt claims From fec776484b690e0823d4318415cbeff02387badf Mon Sep 17 00:00:00 2001 From: Bastian Date: Fri, 11 Mar 2022 10:22:28 +0100 Subject: [PATCH 10/60] fix(client): remove unnecessary fmt.Print (#344) --- client.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/client.go b/client.go index 497c768c..0eaa9316 100644 --- a/client.go +++ b/client.go @@ -3631,8 +3631,6 @@ func (client *gocloak) GetEvents(ctx context.Context, token string, realm string SetQueryParams(queryParams). Get(client.getAdminRealmURL(realm, "events")) - fmt.Printf("%v+", result) - if err := checkForError(resp, err, errMessage); err != nil { return nil, err } From 47fc5dcaa2b2213ef310c2b1e72758f14858601a Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 4 May 2022 18:34:28 +0200 Subject: [PATCH 11/60] exchange deprecated linter --- .golangci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index c5424555..9e1d67ac 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -11,7 +11,7 @@ linters: - gosec - maligned - unconvert - - golint + - revive - gocognit - gocyclo fast: true From 94b56cad73b9be260a44601a6bb560d6f7ab4a64 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 4 May 2022 18:35:56 +0200 Subject: [PATCH 12/60] update github actions --- .github/workflows/go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 9dd3440f..10f85449 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -9,13 +9,13 @@ jobs: - name: Install Go uses: actions/setup-go@v2.1.3 with: - go-version: 1.17 + go-version: 1.18 - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint uses: golangci/golangci-lint-action@v2.3.0 with: - version: v1.28.3 + version: v1.45.2 - name: WriteGoList run: go list -json -m all > go.list - name: nancy From e32d443550835cf2be738f9886884d5cd6d348de Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 4 May 2022 18:38:01 +0200 Subject: [PATCH 13/60] update direct dependencies --- go.mod | 10 +++++----- go.sum | 29 +++++++++++++++-------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index f6eeb956..d3a67f2f 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/Nerzal/gocloak/v11 go 1.15 require ( - github.com/go-resty/resty/v2 v2.6.0 - github.com/golang-jwt/jwt/v4 v4.1.0 + github.com/go-resty/resty/v2 v2.7.0 + github.com/golang-jwt/jwt/v4 v4.4.1 github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 github.com/segmentio/ksuid v1.0.4 - github.com/stretchr/testify v1.7.0 - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 - golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b // indirect + github.com/stretchr/testify v1.7.1 + golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 08d51aa9..7f4ec501 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ 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.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= -github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= +github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ= +github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -14,21 +14,22 @@ 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -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-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-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= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 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/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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= From b2d9f950b45dec1393bbcc44850bb8e624d86a59 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 4 May 2022 18:39:36 +0200 Subject: [PATCH 14/60] update golang-ci lint action to newest version --- .github/workflows/go.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 10f85449..e84bd2a1 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -13,9 +13,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2.3.0 - with: - version: v1.45.2 + uses: golangci/golangci-lint-action@v3.1.0 - name: WriteGoList run: go list -json -m all > go.list - name: nancy From 3348765652e493e9b2110d27bd54113d75908b89 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 4 May 2022 18:40:12 +0200 Subject: [PATCH 15/60] update install go action to newest version --- .github/workflows/go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e84bd2a1..0fbb1b27 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -6,8 +6,8 @@ jobs: tests: runs-on: ubuntu-latest steps: - - name: Install Go - uses: actions/setup-go@v2.1.3 + - name: Setup Go environment + uses: actions/setup-go@v3.0.0 with: go-version: 1.18 - name: Checkout code From 289eed6740763c589dc44bee0a0ba16178371fec Mon Sep 17 00:00:00 2001 From: Marcin Pawlowski Date: Wed, 4 May 2022 12:53:08 -0700 Subject: [PATCH 16/60] update GetResourcePoliciesParams to use correct filter key (#350) --- models.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models.go b/models.go index bd5b2aed..a9a140fd 100644 --- a/models.go +++ b/models.go @@ -1178,7 +1178,7 @@ type PolicyResourceRepresentation struct { // GetResourcePoliciesParams is a representation of the query params for getting policies type GetResourcePoliciesParams struct { - ResourceID *string `json:"resource_id,omitempty"` + ResourceID *string `json:"resource,omitempty"` Name *string `json:"name,omitempty"` Scope *string `json:"scope,omitempty"` First *int `json:"first,string,omitempty"` From 47ca5d67f90cab8d2efc262f5fa1f6e53054f1b3 Mon Sep 17 00:00:00 2001 From: Himanshu Malpande Date: Thu, 5 May 2022 13:30:17 +0530 Subject: [PATCH 17/60] Added ClientScope ProtocolMappers CRUD (#351) --- client.go | 70 ++++++++++++++++++++++++++++++++++ client_test.go | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ gocloak.go | 10 +++++ 3 files changed, 181 insertions(+) diff --git a/client.go b/client.go index 0eaa9316..98c7c1a4 100644 --- a/client.go +++ b/client.go @@ -779,6 +779,21 @@ func (client *gocloak) CreateClientScope(ctx context.Context, token, realm strin return getID(resp), nil } +// CreateClientScopeProtocolMapper creates a new protocolMapper under the given client scope +func (client *gocloak) CreateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) (string, error) { + const errMessage = "could not create client scope protocol mapper" + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetBody(protocolMapper). + Post(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) + + if err := checkForError(resp, err, errMessage); err != nil { + return "", err + } + + return getID(resp), nil +} + func (client *gocloak) UpdateGroup(ctx context.Context, token, realm string, updatedGroup Group) error { const errMessage = "could not update group" @@ -849,6 +864,17 @@ func (client *gocloak) UpdateClientScope(ctx context.Context, token, realm strin return checkForError(resp, err, errMessage) } +// UpdateClientScopeProtocolMapper updates the given protocol mapper for a client scope +func (client *gocloak) UpdateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) error { + const errMessage = "could not update client scope" + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetBody(protocolMapper). + Put(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", PString(protocolMapper.ID))) + + return checkForError(resp, err, errMessage) +} + func (client *gocloak) DeleteGroup(ctx context.Context, token, realm, groupID string) error { const errMessage = "could not delete group" @@ -906,6 +932,16 @@ func (client *gocloak) DeleteClientScope(ctx context.Context, token, realm, scop return checkForError(resp, err, errMessage) } +// DeleteClientScopeProtocolMapper deletes the given protocol mapper from the client scope +func (client *gocloak) DeleteClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) error { + const errMessage = "could not delete client scope" + + resp, err := client.getRequestWithBearerAuth(ctx, token). + Delete(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) + + return checkForError(resp, err, errMessage) +} + // GetClient returns a client func (client *gocloak) GetClient(ctx context.Context, token, realm, idOfClient string) (*Client, error) { const errMessage = "could not get client" @@ -1099,6 +1135,40 @@ func (client *gocloak) GetClientScopes(ctx context.Context, token, realm string) return result, nil } +// GetClientScopeProtocolMappers returns all protocol mappers of a client scope +func (client *gocloak) GetClientScopeProtocolMappers(ctx context.Context, token, realm, scopeID string) ([]*ProtocolMappers, error) { + const errMessage = "could not get client scope protocol mappers" + + var result []*ProtocolMappers + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// GetClientScopeProtocolMapper returns a protocol mapper of a client scope +func (client *gocloak) GetClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) (*ProtocolMappers, error) { + const errMessage = "could not get client scope protocol mappers" + + var result *ProtocolMappers + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + // GetClientScopeMappings returns all scope mappings for the client func (client *gocloak) GetClientScopeMappings(ctx context.Context, token, realm, idOfClient string) (*MappingsRepresentation, error) { const errMessage = "could not get all scope mappings for the client" diff --git a/client_test.go b/client_test.go index 44774853..6d94ff0d 100644 --- a/client_test.go +++ b/client_test.go @@ -1309,6 +1309,87 @@ func Test_CreateClientScope_DeleteClientScope(t *testing.T) { tearDown() } +func CreateUpdateClientScopeProtocolMapper(t *testing.T, client gocloak.GoCloak, scopeID string, protocolMapper *gocloak.ProtocolMappers) (func(), string) { + cfg := GetConfig(t) + token := GetAdminToken(t, client) + + if protocolMapper == nil { + protocolMapper = &gocloak.ProtocolMappers{ + ID: GetRandomNameP("proto-map-"), + Name: GetRandomNameP("proto-map-"), + Protocol: GetRandomNameP("openid-connect"), + ProtocolMapper: gocloak.StringP("oidc-usermodel-realm-role-mapper"), + ProtocolMappersConfig: &gocloak.ProtocolMappersConfig{ + UserAttribute: gocloak.StringP("foo"), + IDTokenClaim: gocloak.StringP("true"), + UserinfoTokenClaim: gocloak.StringP("true"), + AccessTokenClaim: gocloak.StringP("true"), + ClaimName: gocloak.StringP("realm.roles"), + JSONTypeLabel: gocloak.StringP("String"), + Multivalued: gocloak.StringP("true"), + }, + } + } + + t.Logf("Creating Client Scope Protocol Mapper: %+v", protocolMapper) + protocolMapperID, err := client.CreateClientScopeProtocolMapper( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + *protocolMapper, + ) + require.NoError(t, err, "CreateClientScopeProtocolMapper failed") + if !gocloak.NilOrEmpty(protocolMapper.ID) { + require.Equal(t, protocolMapperID, *protocolMapper.ID) + } + + protocolMapper.Name = GetRandomNameP("proto-map2-") + protocolMapper.ProtocolMappersConfig.AccessTokenClaim = gocloak.StringP("false") + err = client.UpdateClientScopeProtocolMapper( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + *protocolMapper, + ) + require.NoError(t, err, "UpdateClientScopeProtocolMapper failed") + + tearDown := func() { + err := client.DeleteClientScopeProtocolMapper( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + protocolMapperID, + ) + require.NoError(t, err, "DeleteClientScopeProtocolMapper failed") + } + return tearDown, protocolMapperID +} + +func Test_CreateClientScopeProtocolMapper_DeleteClientScopeProtocolMapper(t *testing.T) { + // t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + tearDown1, scopeID := CreateClientScope(t, client, nil) + tearDown2, protocolMapperID := CreateUpdateClientScopeProtocolMapper(t, client, scopeID, nil) + protocolMapper, err := client.GetClientScopeProtocolMapper( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + protocolMapperID, + ) + require.NoError(t, err) + require.NotEmpty(t, protocolMapper) + require.Equal(t, protocolMapper.ProtocolMappersConfig.AccessTokenClaim, gocloak.StringP("false")) + tearDown2() + tearDown1() +} + func Test_ListAddRemoveDefaultClientScopes(t *testing.T) { // t.Parallel() cfg := GetConfig(t) @@ -1501,6 +1582,26 @@ func Test_GetClientScopes(t *testing.T) { require.NotZero(t, len(scopes), "there should be client scopes") } +func Test_GetClientScopeProtocolMappers(t *testing.T) { + // t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + tearDown, scopeID := CreateClientScope(t, client, nil) + defer tearDown() + + // Getting client scope protocol mappers + protocolMappers, err := client.GetClientScopeProtocolMappers( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + ) + require.NoError(t, err, "GetClientScopeProtocolMappers failed") + // Checking that GetClientScopeProtocolMappers returns something + require.NotNil(t, protocolMappers) +} + func CreateClientScopeMappingsRealmRoles(t *testing.T, client gocloak.GoCloak, idOfClient string, roles []gocloak.Role) func() { token := GetAdminToken(t, client) cfg := GetConfig(t) diff --git a/gocloak.go b/gocloak.go index 8afb1309..a4788548 100644 --- a/gocloak.go +++ b/gocloak.go @@ -76,6 +76,8 @@ type GoCloak interface { CreateClient(ctx context.Context, accessToken, realm string, newClient Client) (string, error) // CreateClientScope creates a new clientScope CreateClientScope(ctx context.Context, accessToken, realm string, scope ClientScope) (string, error) + // CreateClientScopeProtocolMapper creates a new protocolMapper under the given client scope + CreateClientScopeProtocolMapper(ctx context.Context, accessToken, realm, scopeID string, protocolMapper ProtocolMappers) (string, error) // CreateComponent creates a new component CreateComponent(ctx context.Context, accessToken, realm string, component Component) (string, error) // CreateClientScopeMappingsRealmRoles creates realm-level roles to the client’s scope @@ -95,6 +97,8 @@ type GoCloak interface { UpdateClient(ctx context.Context, accessToken, realm string, updatedClient Client) error // UpdateClientScope updates the given clientScope UpdateClientScope(ctx context.Context, accessToken, realm string, scope ClientScope) error + // UpdateClientScopeProtocolMapper updates the given protocol mapper for a client scope + UpdateClientScopeProtocolMapper(ctx context.Context, accessToken, realm, scopeID string, protocolMapper ProtocolMappers) error // UpdateClientRepresentation updates the given client representation UpdateClientRepresentation(ctx context.Context, accessToken, realm string, updatedClient Client) (*Client, error) @@ -106,6 +110,8 @@ type GoCloak interface { DeleteClient(ctx context.Context, accessToken, realm, idOfClient string) error // DeleteClientScope DeleteClientScope(ctx context.Context, accessToken, realm, scopeID string) error + // DeleteClientScopeProtocolMapper deletes the given protocol mapper from the client scope + DeleteClientScopeProtocolMapper(ctx context.Context, accessToken, realm, scopeID, protocolMapperID string) error // DeleteClientScopeMappingsRealmRoles deletes realm-level roles from the client’s scope DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error // DeleteClientScopeMappingsClientRoles deletes client-level roles from the client’s scope @@ -137,6 +143,10 @@ type GoCloak interface { GetClientScope(ctx context.Context, token, realm, scopeID string) (*ClientScope, error) // GetClientScopes returns all client scopes GetClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) + // GetClientScopeProtocolMappers returns all protocol mappers of a client scope + GetClientScopeProtocolMappers(ctx context.Context, token, realm, scopeID string) ([]*ProtocolMappers, error) + // GetClientScopeProtocolMapper returns a protocol mapper of a client scope + GetClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) (*ProtocolMappers, error) // GetClientScopeMappings returns all scope mappings for the client GetClientScopeMappings(ctx context.Context, token, realm, idOfClient string) (*MappingsRepresentation, error) // GetClientScopeMappingsRealmRoles returns realm-level roles associated with the client’s scope From c740220171ec1414a232fafb2543d213d23b8232 Mon Sep 17 00:00:00 2001 From: Mateus Santos de Melo Date: Thu, 5 May 2022 05:46:21 -0300 Subject: [PATCH 18/60] add: full path field (#349) --- models.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models.go b/models.go index a9a140fd..3586b3f3 100644 --- a/models.go +++ b/models.go @@ -398,6 +398,7 @@ type ProtocolMappersConfig struct { Multivalued *string `json:"multivalued,omitempty"` UsermodelClientRoleMappingClientID *string `json:"usermodel.clientRoleMapping.clientId,omitempty"` IncludedClientAudience *string `json:"included.client.audience,omitempty"` + FullPath *string `json:"full.path,omitempty"` } // Client is a ClientRepresentation From 04f3ff43ffe1b5683374a05f8b83fb63ad601589 Mon Sep 17 00:00:00 2001 From: Philipp Nowak Date: Tue, 10 May 2022 10:51:56 +0200 Subject: [PATCH 19/60] Add missing endpoints for client scopes -> scope mappings -> client roles (#348) #348 Add missing endpoints for client scopes -> scope mappings -> client roles --- README.md | 4 ++ client.go | 62 +++++++++++++++++++++++++++ client_test.go | 112 ++++++++++++++++++++++++++++++++++++++++++++++++- gocloak.go | 8 ++++ 4 files changed, 184 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c7b2c6ac..7df6e9ab 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,7 @@ type GoCloak interface { CreateClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfCLientScope string, roles []Role) error + CreateClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error UpdateUser(ctx context.Context, accessToken, realm string, user User) error UpdateGroup(ctx context.Context, accessToken, realm string, updatedGroup Group) error @@ -177,6 +178,7 @@ type GoCloak interface { DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfCLientScope string, roles []Role) error + DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, ifOfClient string, roles []Role) error GetClient(ctx context.Context, accessToken, realm, idOfClient string) (*Client, error) GetClientsDefaultScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) @@ -193,8 +195,10 @@ type GoCloak interface { GetClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) + GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) GetClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) GetClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) + GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) GetClientScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) GetClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) GetClientServiceAccount(ctx context.Context, token, realm, idOfClient string) (*User, error) diff --git a/client.go b/client.go index 98c7c1a4..6447f74f 100644 --- a/client.go +++ b/client.go @@ -3777,3 +3777,65 @@ func (client *gocloak) UpdateRequiredAction(ctx context.Context, token string, r return err } + +// CreateClientScopesScopeMappingsClientRoles attaches a client role to a client scope (not client's scope) +func (client *gocloak) CreateClientScopesScopeMappingsClientRoles( + ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role, +) error { + const errMessage = "could not create client-level roles to the client-scope" + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetBody(roles). + Post(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) + + return checkForError(resp, err, errMessage) +} + +// GetClientScopesScopeMappingsClientRolesAvailable returns available (i.e. not attached via +// CreateClientScopesScopeMappingsClientRoles) client roles for a specific client, for a client scope +// (not client's scope). +func (client *gocloak) GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) { + const errMessage = "could not get available client-level roles with the client-scope" + + var result []*Role + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient, "available")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// GetClientScopesScopeMappingsClientRoles returns attached client roles for a specific client, for a client scope +// (not client's scope). +func (client *gocloak) GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) { + const errMessage = "could not get client-level roles with the client-scope" + + var result []*Role + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// DeleteClientScopesScopeMappingsClientRoles removes attachment of client roles from a client scope +// (not client's scope). +func (client *gocloak) DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error { + const errMessage = "could not delete client-level roles from the client-scope" + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetBody(roles). + Delete(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) + + return checkForError(resp, err, errMessage) +} diff --git a/client_test.go b/client_test.go index 6d94ff0d..6a4209d2 100644 --- a/client_test.go +++ b/client_test.go @@ -1665,7 +1665,7 @@ func Test_ClientScopeMappingsClientRoles(t *testing.T) { token := GetAdminToken(t, client) testClient := gocloak.Client{ ClientID: GetRandomNameP("ClientID"), - BaseURL: gocloak.StringP("http://example.com"), + BaseURL: gocloak.StringP("https://example.com"), FullScopeAllowed: gocloak.BoolP(false), } // Creating client @@ -1811,6 +1811,112 @@ func Test_ClientScopeMappingsRealmRoles(t *testing.T) { ) } +func CreateClientScopesMappingsClientRoles( + t *testing.T, client gocloak.GoCloak, scopeID, idOfClient string, roles []gocloak.Role, +) func() { + token := GetAdminToken(t, client) + cfg := GetConfig(t) + + // Creating client scope mappings + err := client.CreateClientScopesScopeMappingsClientRoles( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + idOfClient, + roles, + ) + require.NoError(t, err, "CreateClientScopesScopeMappingsClientRoles failed") + + tearDown := func() { + err = client.DeleteClientScopesScopeMappingsClientRoles( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + idOfClient, + roles, + ) + require.NoError(t, err, "DeleteClientScopesScopeMappingsClientRoles failed") + } + return tearDown +} + +// Test_ClientScopesMappingsClientRoles tests API calls related to client role attachment for a client scope. +func Test_ClientScopesMappingsClientRoles(t *testing.T) { + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + // Creating client roles (on shared client) + var roles []gocloak.Role + tearDownRole1, assignRoleName := CreateClientRole(t, client) + defer tearDownRole1() + role, err := client.GetClientRole( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloakClientID, + assignRoleName, + ) + require.NoError(t, err, "CreateClientRole failed") + roles = append(roles, *role) + tearDownRole2, noAssignRoleName := CreateClientRole(t, client) + defer tearDownRole2() + role, err = client.GetClientRole( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloakClientID, + noAssignRoleName, + ) + require.NoError(t, err, "GetClientRole after CreateClientRole failed") + roles = append(roles, *role) + + // Creating scope + tearDownScope, scopeID := CreateClientScope(t, client, nil) + defer tearDownScope() + + // Creating client roles for client scope mappings + onlyFirstRole := roles[:1] + tearDownMappings := CreateClientScopesMappingsClientRoles(t, client, scopeID, gocloakClientID, onlyFirstRole) + defer tearDownMappings() + + // Check client roles + mappedRoles, err := client.GetClientScopesScopeMappingsClientRoles( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + gocloakClientID, + ) + require.NoError(t, err, "GetClientScopesScopeMappingsClientRoles failed") + require.Len( + t, mappedRoles, len(onlyFirstRole), + "GetClientScopeMappingsClientRoles should return exact %s roles", len(onlyFirstRole), + ) + + clientRolesAvailable, err := client.GetClientScopesScopeMappingsClientRolesAvailable( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + scopeID, + gocloakClientID, + ) + require.NoError(t, err, "GetClientScopesScopeMappingsClientRolesAvailable failed") + foundUnassignedRole := false + for _, roleAvailable := range clientRolesAvailable { + require.NotEqual( + t, assignRoleName, roleAvailable.Name, + "assigned role %v should not be available", assignRoleName, + ) + if *roleAvailable.Name == noAssignRoleName { + foundUnassignedRole = true + } + } + require.True(t, foundUnassignedRole, "expected role %s to be available", noAssignRoleName) +} + func Test_CreateListGetUpdateDeleteClient(t *testing.T) { // t.Parallel() cfg := GetConfig(t) @@ -5306,7 +5412,9 @@ func Test_CreateGetUpdateDeleteResourcePolicy(t *testing.T) { Name: policyNameP, Description: gocloak.StringP("Role Policy"), Scopes: &scopes, - Roles: &[]string{roleName}, + // "gocloak" is the client name here, apparently it's necessary to scope client roles like that here. + // ref: https://github.com/keycloak/keycloak/blob/main/core/src/main/java/org/keycloak/representations/idm/authorization/UmaPermissionRepresentation.java#L53 + Roles: &[]string{fmt.Sprintf("gocloak/%v", roleName)}, }, { Name: policyNameP, diff --git a/gocloak.go b/gocloak.go index a4788548..91c4af32 100644 --- a/gocloak.go +++ b/gocloak.go @@ -86,6 +86,8 @@ type GoCloak interface { CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error // CreateClientScopesScopeMappingsRealmRoles creates realm-level roles to the client-scope CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string, roles []Role) error + // CreateClientScopesScopeMappingsClientRoles creates client-level roles to the client-scope + CreateClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error // CreateClientRepresentation creates a new client representation CreateClientRepresentation(ctx context.Context, realm string) (*Client, error) @@ -118,6 +120,8 @@ type GoCloak interface { DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error // DeleteClientScopesScopeMappingsRealmRoles deletes realm-level roles from the client-scope DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string, roles []Role) error + // DeleteClientScopesScopeMappingsClientRoles deletes client-level roles from the client-scope + DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, ifOfClient string, roles []Role) error // DeleteClientRepresentation deletes a given client representation DeleteClientRepresentation(ctx context.Context, accessToken, realm, clientID string) error @@ -155,10 +159,14 @@ type GoCloak interface { GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) // GetClientScopesScopeMappingsRealmRolesAvailable returns realm-level roles that are available to attach to this client-scope GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) + // GetClientScopesScopeMappingsClientRolesAvailable returns client-level roles that are available to attach to this client-scope + GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) // GetClientScopeMappingsClientRoles returns roles associated with a client’s scope GetClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) // GetClientScopesScopeMappingsRealmRoles returns roles associated with a client-scope GetClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) + // GetClientScopesScopeMappingsClientRoles returns client roles associated with a client-scope + GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) // GetClientScopeMappingsClientRolesAvailable returns available roles associated with a client’s scope GetClientScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) // GetClientSecret returns a client's secret From 9556250acd6a20d04682540e7a40230daaac9ca7 Mon Sep 17 00:00:00 2001 From: Dominik Dumont <49190107+dmnkdmnt@users.noreply.github.com> Date: Thu, 19 May 2022 13:59:43 +0200 Subject: [PATCH 20/60] resolve protocol mapper types and builtin protocol mappers on server info (#354) --- model_test.go | 47 +++++++++++++++++++++++++++++- models.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 119 insertions(+), 9 deletions(-) diff --git a/model_test.go b/model_test.go index cb9fea0a..fdb3c6df 100644 --- a/model_test.go +++ b/model_test.go @@ -36,10 +36,55 @@ func TestStringOrArray_Marshal(t *testing.T) { dataArray := gocloak.StringOrArray{"1", "2", "3"} jsonArray, err := json.Marshal(&dataArray) - assert.NoError(t, err, "Marshaling failed for array of strings: %s", dataString) + assert.NoError(t, err, "Marshaling failed for array of strings: %s", dataArray) assert.Equal(t, "[\"1\",\"2\",\"3\"]", string(jsonArray)) } +func TestEnforcedString_UnmarshalJSON(t *testing.T) { + t.Parallel() + + type testData struct { + In []byte + Out gocloak.EnforcedString + } + + data := []testData{{ + In: []byte(`"string value"`), + Out: "string value", + }, { + In: []byte(`"\"quoted string value\""`), + Out: `"quoted string value"`, + }, { + In: []byte(`true`), + Out: "true", + }, { + In: []byte(`42`), + Out: "42", + }, { + In: []byte(`{"foo": "bar"}`), + Out: `{"foo": "bar"}`, + }, { + In: []byte(`["foo"]`), + Out: `["foo"]`, + }} + + for _, d := range data { + var val gocloak.EnforcedString + err := json.Unmarshal(d.In, &val) + assert.NoErrorf(t, err, "Unmarshalling failed with data: %v", d.In) + assert.Equal(t, d.Out, val) + } +} + +func TestEnforcedString_MarshalJSON(t *testing.T) { + t.Parallel() + + data := gocloak.EnforcedString("foo") + jsonString, err := json.Marshal(&data) + assert.NoErrorf(t, err, "Unmarshalling failed with data: %v", data) + assert.Equal(t, `"foo"`, string(jsonString)) +} + func TestGetQueryParams(t *testing.T) { t.Parallel() diff --git a/models.go b/models.go index 3586b3f3..d4057924 100644 --- a/models.go +++ b/models.go @@ -1,6 +1,7 @@ package gocloak import ( + "bytes" "encoding/json" "strings" @@ -60,6 +61,32 @@ func (s *StringOrArray) MarshalJSON() ([]byte, error) { return json.Marshal([]string(*s)) } +// EnforcedString can be used when the expected value is string but Keycloak in some cases gives you mixed types +type EnforcedString string + +// UnmarshalJSON modify data as string before json unmarshal +func (s *EnforcedString) UnmarshalJSON(data []byte) error { + if data[0] != '"' { + // Escape unescaped quotes + data = bytes.ReplaceAll(data, []byte(`"`), []byte(`\"`)) + data = bytes.ReplaceAll(data, []byte(`\\"`), []byte(`\"`)) + + // Wrap data in quotes + data = append([]byte(`"`), data...) + data = append(data, []byte(`"`)...) + } + + var val string + err := json.Unmarshal(data, &val) + *s = EnforcedString(val) + return err +} + +// MarshalJSON return json marshal +func (s *EnforcedString) MarshalJSON() ([]byte, error) { + return json.Marshal(*s) +} + // APIErrType is a field containing more specific API error types // that may be checked by the receiver. type APIErrType string @@ -610,11 +637,12 @@ type ScopeRepresentation struct { // ProtocolMapperRepresentation represents.... type ProtocolMapperRepresentation struct { - Config *map[string]string `json:"config,omitempty"` - ID *string `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - Protocol *string `json:"protocol,omitempty"` - ProtocolMapper *string `json:"protocolMapper,omitempty"` + Config *map[string]string `json:"config,omitempty"` + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Protocol *string `json:"protocol,omitempty"` + ProtocolMapper *string `json:"protocolMapper,omitempty"` + ConsentRequired *bool `json:"consentRequired,omitempty"` } // GetClientsParams represents the query parameters @@ -964,11 +992,48 @@ type PasswordPolicy struct { MultipleSupported bool `json:"multipleSupported,omitempty"` } +// ProtocolMapperTypeProperty represents a property of a ProtocolMapperType +type ProtocolMapperTypeProperty struct { + Name string `json:"name,omitempty"` + Label string `json:"label,omitempty"` + HelpText string `json:"helpText,omitempty"` + Type string `json:"type,omitempty"` + Options []string `json:"options,omitempty"` + DefaultValue EnforcedString `json:"defaultValue,omitempty"` + Secret bool `json:"secret,omitempty"` + ReadOnly bool `json:"readOnly,omitempty"` +} + +// ProtocolMapperType represents a type of protocol mapper +type ProtocolMapperType struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Category string `json:"category,omitempty"` + HelpText string `json:"helpText,omitempty"` + Priority int `json:"priority,omitempty"` + Properties []ProtocolMapperTypeProperty `json:"properties,omitempty"` +} + +// ProtocolMapperTypes holds the currently available ProtocolMapperType-s grouped by protocol +type ProtocolMapperTypes struct { + DockerV2 []ProtocolMapperType `json:"docker-v2,omitempty"` + SAML []ProtocolMapperType `json:"saml,omitempty"` + OpenIDConnect []ProtocolMapperType `json:"openid-connect,omitempty"` +} + +// BuiltinProtocolMappers holds the currently available built-in blueprints of ProtocolMapper-s grouped by protocol +type BuiltinProtocolMappers struct { + SAML []ProtocolMapperRepresentation `json:"saml,omitempty"` + OpenIDConnect []ProtocolMapperRepresentation `json:"openid-connect,omitempty"` +} + // ServerInfoRepesentation represents a server info type ServerInfoRepesentation struct { - SystemInfo *SystemInfoRepresentation `json:"systemInfo,omitempty"` - MemoryInfo *MemoryInfoRepresentation `json:"memoryInfo,omitempty"` - PasswordPolicies []*PasswordPolicy `json:"passwordPolicies,omitempty"` + SystemInfo *SystemInfoRepresentation `json:"systemInfo,omitempty"` + MemoryInfo *MemoryInfoRepresentation `json:"memoryInfo,omitempty"` + PasswordPolicies []*PasswordPolicy `json:"passwordPolicies,omitempty"` + ProtocolMapperTypes *ProtocolMapperTypes `json:"protocolMapperTypes,omitempty"` + BuiltinProtocolMappers *BuiltinProtocolMappers `json:"builtinProtocolMappers,omitempty"` } // FederatedIdentityRepresentation represents an user federated identity From 1c89abf61f250a344b37bd27fb79c64363892a3e Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 27 Jun 2022 19:50:24 +0600 Subject: [PATCH 21/60] feat: add supporing ecdsa algorithm (#356) * feat: add supporing es256 algorithm * feat: add supporing es256 algorithm in method DecodeAccessTokenCustomClaims * fix: rename method * fix: fix an algorithm detecting bug * refactor: remove code duplicates * fix: remove useless println * refactor: remove code duplicates * test: add tests * refactor: add comments * refactor: refactor of decodeECDSAPublicKey func Co-authored-by: Vladimir Stepanov --- client.go | 48 ++++++++++++--------------- models.go | 3 ++ pkg/jwx/jwx.go | 79 ++++++++++++++++++++++++++++++++------------- pkg/jwx/jwx_test.go | 66 +++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 49 deletions(-) create mode 100644 pkg/jwx/jwx_test.go diff --git a/client.go b/client.go index 6447f74f..38498f4e 100644 --- a/client.go +++ b/client.go @@ -379,54 +379,48 @@ func (client *gocloak) RetrospectToken(ctx context.Context, accessToken, clientI return &result, nil } -// DecodeAccessToken decodes the accessToken -func (client *gocloak) DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error) { +func (client *gocloak) decodeAccessTokenWithClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) { const errMessage = "could not decode access token" accessToken = strings.Replace(accessToken, "Bearer ", "", 1) decodedHeader, err := jwx.DecodeAccessTokenHeader(accessToken) if err != nil { - return nil, nil, errors.Wrap(err, errMessage) + return nil, errors.Wrap(err, errMessage) } certResult, err := client.GetCerts(ctx, realm) if err != nil { - return nil, nil, errors.Wrap(err, errMessage) + return nil, errors.Wrap(err, errMessage) } if certResult.Keys == nil { - return nil, nil, errors.Wrap(errors.New("there is no keys to decode the token"), errMessage) + return nil, errors.Wrap(errors.New("there is no keys to decode the token"), errMessage) } usedKey := findUsedKey(decodedHeader.Kid, *certResult.Keys) if usedKey == nil { - return nil, nil, errors.Wrap(errors.New("cannot find a key to decode the token"), errMessage) + return nil, errors.Wrap(errors.New("cannot find a key to decode the token"), errMessage) } - return jwx.DecodeAccessToken(accessToken, usedKey.E, usedKey.N) -} - -// DecodeAccessTokenCustomClaims decodes the accessToken and writes claims into the given claims -func (client *gocloak) DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) { - const errMessage = "could not decode access token with custom claims" - accessToken = strings.Replace(accessToken, "Bearer ", "", 1) - - decodedHeader, err := jwx.DecodeAccessTokenHeader(accessToken) - if err != nil { - return nil, errors.Wrap(err, errMessage) + if strings.HasPrefix(decodedHeader.Alg, "ES") { + return jwx.DecodeAccessTokenECDSACustomClaims(accessToken, usedKey.X, usedKey.Y, usedKey.Crv, claims) + } else if strings.HasPrefix(decodedHeader.Alg, "RS") { + return jwx.DecodeAccessTokenRSACustomClaims(accessToken, usedKey.E, usedKey.N, claims) } + return nil, fmt.Errorf("unsupported algorithm") +} - certResult, err := client.GetCerts(ctx, realm) +// DecodeAccessToken decodes the accessToken +func (client *gocloak) DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error) { + claims := jwt.MapClaims{} + token, err := client.decodeAccessTokenWithClaims(ctx, accessToken, realm, claims) if err != nil { - return nil, errors.Wrap(err, errMessage) - } - if certResult.Keys == nil { - return nil, errors.Wrap(errors.New("there is no keys to decode the token"), errMessage) - } - usedKey := findUsedKey(decodedHeader.Kid, *certResult.Keys) - if usedKey == nil { - return nil, errors.Wrap(errors.New("cannot find a key to decode the token"), errMessage) + return nil, nil, err } + return token, &claims, nil +} - return jwx.DecodeAccessTokenCustomClaims(accessToken, usedKey.E, usedKey.N, claims) +// DecodeAccessTokenCustomClaims decodes the accessToken and writes claims into the given claims +func (client *gocloak) DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) { + return client.decodeAccessTokenWithClaims(ctx, accessToken, realm, claims) } func (client *gocloak) GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error) { diff --git a/models.go b/models.go index d4057924..2de1eac8 100644 --- a/models.go +++ b/models.go @@ -137,6 +137,9 @@ type CertResponseKey struct { Use *string `json:"use,omitempty"` N *string `json:"n,omitempty"` E *string `json:"e,omitempty"` + X *string `json:"x,omitempty"` + Y *string `json:"y,omitempty"` + Crv *string `json:"crv,omitempty"` KeyOps *[]string `json:"key_ops,omitempty"` X5u *string `json:"x5u,omitempty"` X5c *[]string `json:"x5c,omitempty"` diff --git a/pkg/jwx/jwx.go b/pkg/jwx/jwx.go index 23b8d5f1..ccf000f5 100644 --- a/pkg/jwx/jwx.go +++ b/pkg/jwx/jwx.go @@ -2,6 +2,8 @@ package jwx import ( "bytes" + "crypto/ecdsa" + "crypto/elliptic" "crypto/rsa" "encoding/base64" "encoding/binary" @@ -39,16 +41,53 @@ func DecodeAccessTokenHeader(token string) (*DecodedAccessTokenHeader, error) { return result, nil } -func decodePublicKey(e, n *string) (*rsa.PublicKey, error) { +func toBigInt(v string) (*big.Int, error) { + decRes, err := base64.RawURLEncoding.DecodeString(v) + if err != nil { + return nil, err + } + + res := big.NewInt(0) + res.SetBytes(decRes) + return res, nil +} + +var ( + curves = map[string]elliptic.Curve{ + "P-224": elliptic.P224(), + "P-256": elliptic.P256(), + "P-384": elliptic.P384(), + "P-521": elliptic.P521(), + } +) + +func decodeECDSAPublicKey(x, y, crv *string) (*ecdsa.PublicKey, error) { const errMessage = "could not decode public key" - decN, err := base64.RawURLEncoding.DecodeString(*n) + xInt, err := toBigInt(*x) if err != nil { return nil, errors.Wrap(err, errMessage) } - nInt := big.NewInt(0) - nInt.SetBytes(decN) + yInt, err := toBigInt(*y) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + var c elliptic.Curve + var ok bool + if c, ok = curves[*crv]; !ok { + return nil, errors.Wrap(fmt.Errorf("unknown curve alg: %s", *crv), errMessage) + } + return &ecdsa.PublicKey{X: xInt, Y: yInt, Curve: c}, nil +} + +func decodeRSAPublicKey(e, n *string) (*rsa.PublicKey, error) { + const errMessage = "could not decode public key" + + nInt, err := toBigInt(*n) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } decE, err := base64.RawURLEncoding.DecodeString(*e) if err != nil { @@ -74,19 +113,17 @@ func decodePublicKey(e, n *string) (*rsa.PublicKey, error) { return &pKey, nil } -// DecodeAccessToken currently only supports RSA - sorry for that -func DecodeAccessToken(accessToken string, e, n *string) (*jwt.Token, *jwt.MapClaims, error) { - const errMessage = "could not decode accessToken" +// DecodeAccessTokenRSACustomClaims decodes string access token into jwt.Token +func DecodeAccessTokenRSACustomClaims(accessToken string, e, n *string, customClaims jwt.Claims) (*jwt.Token, error) { + const errMessage = "could not decode accessToken with custom claims" accessToken = strings.Replace(accessToken, "Bearer ", "", 1) - rsaPublicKey, err := decodePublicKey(e, n) + rsaPublicKey, err := decodeRSAPublicKey(e, n) if err != nil { - return nil, nil, errors.Wrap(err, errMessage) + return nil, errors.Wrap(err, errMessage) } - claims := &jwt.MapClaims{} - - token2, err := jwt.ParseWithClaims(accessToken, claims, func(token *jwt.Token) (interface{}, error) { + token2, err := jwt.ParseWithClaims(accessToken, customClaims, func(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) @@ -95,33 +132,31 @@ func DecodeAccessToken(accessToken string, e, n *string) (*jwt.Token, *jwt.MapCl }) if err != nil { - return nil, nil, errors.Wrap(err, errMessage) + return nil, errors.Wrap(err, errMessage) } - - return token2, claims, nil + return token2, nil } -// DecodeAccessTokenCustomClaims currently only supports RSA - sorry for that -func DecodeAccessTokenCustomClaims(accessToken string, e, n *string, customClaims jwt.Claims) (*jwt.Token, error) { - const errMessage = "could not decode accessToken with custom claims" +// DecodeAccessTokenECDSACustomClaims decodes string access token into jwt.Token +func DecodeAccessTokenECDSACustomClaims(accessToken string, x, y, crv *string, customClaims jwt.Claims) (*jwt.Token, error) { + const errMessage = "could not decode accessToken" accessToken = strings.Replace(accessToken, "Bearer ", "", 1) - rsaPublicKey, err := decodePublicKey(e, n) + publicKey, err := decodeECDSAPublicKey(x, y, crv) if err != nil { return nil, errors.Wrap(err, errMessage) } token2, err := jwt.ParseWithClaims(accessToken, customClaims, func(token *jwt.Token) (interface{}, error) { // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { + if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } - return rsaPublicKey, nil + return publicKey, nil }) if err != nil { return nil, errors.Wrap(err, errMessage) } - return token2, nil } diff --git a/pkg/jwx/jwx_test.go b/pkg/jwx/jwx_test.go new file mode 100644 index 00000000..97a6ba98 --- /dev/null +++ b/pkg/jwx/jwx_test.go @@ -0,0 +1,66 @@ +package jwx + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/base64" + "log" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/golang-jwt/jwt/v4" +) + +var claims = jwt.MapClaims{ + "testKey": "testValue", +} + +func generateJWTToken(privKey *ecdsa.PrivateKey, sMethod *jwt.SigningMethodECDSA) (string, error) { + token := jwt.NewWithClaims(sMethod, claims) + tokenString, err := token.SignedString(privKey) + if err != nil { + log.Fatal(err) + } + return tokenString, nil +} + +func TestDecodeAccessTokenECDSACustomClaims(t *testing.T) { + tests := []struct { + curveAlg elliptic.Curve + curveStr string + jwtSighAlg *jwt.SigningMethodECDSA + }{ + { + jwtSighAlg: jwt.SigningMethodES256, + curveAlg: elliptic.P256(), + curveStr: "P-256", + }, + { + jwtSighAlg: jwt.SigningMethodES384, + curveAlg: elliptic.P384(), + curveStr: "P-384", + }, + { + jwtSighAlg: jwt.SigningMethodES512, + curveAlg: elliptic.P521(), + curveStr: "P-521", + }, + } + + for _, tc := range tests { + t.Run(tc.curveStr, func(t *testing.T) { + pk, _ := ecdsa.GenerateKey(tc.curveAlg, rand.Reader) + token, err := generateJWTToken(pk, tc.jwtSighAlg) + require.NoError(t, err) + + testClaims := jwt.MapClaims{} + x := base64.RawURLEncoding.EncodeToString(pk.X.Bytes()) + y := base64.RawURLEncoding.EncodeToString(pk.Y.Bytes()) + _, err = DecodeAccessTokenECDSACustomClaims(token, &x, &y, &tc.curveStr, testClaims) + require.NoError(t, err) + require.Equal(t, claims, testClaims) + }) + } +} From fe4f627eaf1bff988ee5df2fd0d0b87daac6c074 Mon Sep 17 00:00:00 2001 From: Sven Ziegler Date: Thu, 11 Aug 2022 09:51:44 +0200 Subject: [PATCH 22/60] =?UTF-8?q?feat:=20add=20functionality=20to=20regist?= =?UTF-8?q?er,=20get,=20list=20and=20delete=20required=20ac=E2=80=A6=20(#3?= =?UTF-8?q?60)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add functionality to register, get, list and delete required actions * fix: golangci-lint errors by using go 1.19 binaries * chore: add some more tests * chore: rename misspelled key in test --- client.go | 82 +++++++++++++++++++++++++++++++++++++++++++++----- client_test.go | 69 ++++++++++++++++++++++++++++++++++++++++-- gocloak.go | 8 +++++ 3 files changed, 149 insertions(+), 10 deletions(-) diff --git a/client.go b/client.go index 38498f4e..d4c88c6b 100644 --- a/client.go +++ b/client.go @@ -2196,7 +2196,7 @@ func (client *gocloak) ClearKeysCache(ctx context.Context, token, realm string) return checkForError(resp, err, errMessage) } -//GetAuthenticationFlows get all authentication flows from a realm +// GetAuthenticationFlows get all authentication flows from a realm func (client *gocloak) GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) { const errMessage = "could not retrieve authentication flows" var result []*AuthenticationFlowRepresentation @@ -2210,7 +2210,7 @@ func (client *gocloak) GetAuthenticationFlows(ctx context.Context, token, realm return result, nil } -//Create a new Authentication flow in a realm +// Create a new Authentication flow in a realm func (client *gocloak) CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error { const errMessage = "could not create authentication flows" var result []*AuthenticationFlowRepresentation @@ -2221,7 +2221,7 @@ func (client *gocloak) CreateAuthenticationFlow(ctx context.Context, token, real return checkForError(resp, err, errMessage) } -//DeleteAuthenticationFlow deletes a flow in a realm with the given ID +// DeleteAuthenticationFlow deletes a flow in a realm with the given ID func (client *gocloak) DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error { const errMessage = "could not delete authentication flows" resp, err := client.getRequestWithBearerAuth(ctx, token). @@ -2230,7 +2230,7 @@ func (client *gocloak) DeleteAuthenticationFlow(ctx context.Context, token, real return checkForError(resp, err, errMessage) } -//GetAuthenticationExecutions retrieves all executions of a given flow +// GetAuthenticationExecutions retrieves all executions of a given flow func (client *gocloak) GetAuthenticationExecutions(ctx context.Context, token, realm, flow string) ([]*ModifyAuthenticationExecutionRepresentation, error) { const errMessage = "could not retrieve authentication flows" var result []*ModifyAuthenticationExecutionRepresentation @@ -2244,7 +2244,7 @@ func (client *gocloak) GetAuthenticationExecutions(ctx context.Context, token, r return result, nil } -//CreateAuthenticationExecution creates a new execution for the given flow name in the given realm +// CreateAuthenticationExecution creates a new execution for the given flow name in the given realm func (client *gocloak) CreateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionRepresentation) error { const errMessage = "could not create authentication execution" resp, err := client.getRequestWithBearerAuth(ctx, token).SetBody(execution). @@ -2253,7 +2253,7 @@ func (client *gocloak) CreateAuthenticationExecution(ctx context.Context, token, return checkForError(resp, err, errMessage) } -//UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm +// UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm func (client *gocloak) UpdateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution ModifyAuthenticationExecutionRepresentation) error { const errMessage = "could not update authentication execution" resp, err := client.getRequestWithBearerAuth(ctx, token).SetBody(execution). @@ -2271,7 +2271,7 @@ 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 +// 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). @@ -3758,6 +3758,57 @@ func (client *gocloak) CreateClientScopesScopeMappingsRealmRoles(ctx context.Con return checkForError(resp, err, errMessage) } +// CreateRequiredAction creates a required action for a given realm +func (client *gocloak) RegisterRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error { + const errMessage = "could not create required action" + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetBody(requiredAction). + Post(client.getAdminRealmURL(realm, "authentication", "register-required-action")) + + if err := checkForError(resp, err, errMessage); err != nil { + return err + } + + return err +} + +// GetRequiredActions gets a list of required actions for a given realm +func (client *gocloak) GetRequiredActions(ctx context.Context, token string, realm string) ([]*RequiredActionProviderRepresentation, error) { + const errMessage = "could not get required actions" + var result []*RequiredActionProviderRepresentation + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "authentication", "required-actions")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, err +} + +// GetRequiredAction gets a required action for a given realm +func (client *gocloak) GetRequiredAction(ctx context.Context, token string, realm string, alias string) (*RequiredActionProviderRepresentation, error) { + const errMessage = "could not get required action" + var result RequiredActionProviderRepresentation + + if alias == "" { + return nil, errors.New("alias is required for getting a required action") + } + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "authentication", "required-actions", alias)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, err +} + // 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" @@ -3772,6 +3823,23 @@ func (client *gocloak) UpdateRequiredAction(ctx context.Context, token string, r return err } +// DeleteRequiredAction updates a required action for a given realm +func (client *gocloak) DeleteRequiredAction(ctx context.Context, token string, realm string, alias string) error { + const errMessage = "could not delete required action" + + if alias == "" { + return errors.New("alias is required for deleting a required action") + } + resp, err := client.getRequestWithBearerAuth(ctx, token). + Delete(client.getAdminRealmURL(realm, "authentication", "required-actions", alias)) + + if err := checkForError(resp, err, errMessage); err != nil { + return err + } + + return err +} + // CreateClientScopesScopeMappingsClientRoles attaches a client role to a client scope (not client's scope) func (client *gocloak) CreateClientScopesScopeMappingsClientRoles( ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role, diff --git a/client_test.go b/client_test.go index 6a4209d2..55524ba2 100644 --- a/client_test.go +++ b/client_test.go @@ -528,9 +528,10 @@ func NewClientWithDebug(t testing.TB) gocloak.GoCloak { } // FailRequest fails requests and returns an error -// err - returned error or nil to return the default error -// failN - number of requests to be failed -// skipN = number of requests to be executed and not failed by this function +// +// err - returned error or nil to return the default error +// failN - number of requests to be failed +// skipN = number of requests to be executed and not failed by this function func FailRequest(client gocloak.GoCloak, err error, failN, skipN int) gocloak.GoCloak { client.RestyClient().OnBeforeRequest( func(c *resty.Client, r *resty.Request) error { @@ -6490,6 +6491,68 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecutionAndFlo require.True(t, deleted, "Failed to delete authentication flow, no flow was deleted") } +func TestGocloak_CreateAndGetRequiredAction(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + requiredAction := gocloak.RequiredActionProviderRepresentation{ + Alias: gocloak.StringP("VERIFY_EMAIL_NEW"), + Config: nil, + DefaultAction: gocloak.BoolP(false), + Enabled: gocloak.BoolP(true), + Name: gocloak.StringP("Verify Email new"), + Priority: gocloak.Int32P(50), + ProviderID: gocloak.StringP("VERIFY_EMAIL_NEW"), + } + err := client.RegisterRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, requiredAction) + require.NoError(t, err, "Failed to register required action") + + ra, err := client.GetRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, *requiredAction.Alias) + require.NoError(t, err, "Failed to get required action") + require.NotNil(t, ra, "required action created must not be nil") + require.Equal(t, *ra.Alias, *requiredAction.Alias, "required action alias must be equal with template") + t.Logf("got required action: %+v", ra) + + ras, err := client.GetRequiredActions(context.Background(), token.AccessToken, cfg.GoCloak.Realm) + require.NoError(t, err, "Failed to get required actions") + + for _, r := range ras { + t.Logf("got required action: %+v", r) + if r.Alias != nil && *r.Alias == *ra.Alias { + goto FOUND_RA + } + } + require.Fail(t, "required action not found in list of required actions") + +FOUND_RA: + + err = client.DeleteRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, *requiredAction.Alias) + require.NoError(t, err, "Failed to Delete required action") +} + +func TestGocloak_GetUnknownRequiredAction(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + ra, err := client.GetRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, "unknown_required_action") + require.Error(t, err, "Request should fail if no required action with the given name is there") + require.Nil(t, ra, "required action created must be nil if it could not be found") +} + +func TestGocloak_GetEmptyAliasRequiredAction(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + ra, err := client.GetRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, "") + require.Error(t, err, "Request should fail if no alias is given") + require.Nil(t, ra, "required action created must be nil if it could not be found") +} + func TestGocloak_UpdateRequiredAction(t *testing.T) { t.Parallel() cfg := GetConfig(t) diff --git a/gocloak.go b/gocloak.go index 91c4af32..ac803466 100644 --- a/gocloak.go +++ b/gocloak.go @@ -522,6 +522,14 @@ type GoCloak interface { // RequiredActions API // ------------------- + // UpdateRequiredAction updates a required action for a given realm + RegisterRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error // UpdateRequiredAction updates a required action for a given realm UpdateRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error + // UpdateRequiredAction updates a required action for a given realm + GetRequiredAction(ctx context.Context, token string, realm string, alias string) (*RequiredActionProviderRepresentation, error) + // UpdateRequiredAction updates a required action for a given realm + GetRequiredActions(ctx context.Context, token string, realm string) ([]*RequiredActionProviderRepresentation, error) + // UpdateRequiredAction updates a required action for a given realm + DeleteRequiredAction(ctx context.Context, token string, realm string, alias string) error } From 1137160ec90381be67ca78acafec3f7bbaa8e56d Mon Sep 17 00:00:00 2001 From: Bastian Date: Wed, 12 Oct 2022 18:15:09 +0200 Subject: [PATCH 23/60] fix(realm): add webauthn config (#371) --- models.go | 208 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 114 insertions(+), 94 deletions(-) diff --git a/models.go b/models.go index 2de1eac8..a37e4c8c 100644 --- a/models.go +++ b/models.go @@ -701,100 +701,120 @@ type RolesRepresentation struct { // RealmRepresentation represents a realm type RealmRepresentation struct { - AccessCodeLifespan *int `json:"accessCodeLifespan,omitempty"` - AccessCodeLifespanLogin *int `json:"accessCodeLifespanLogin,omitempty"` - AccessCodeLifespanUserAction *int `json:"accessCodeLifespanUserAction,omitempty"` - AccessTokenLifespan *int `json:"accessTokenLifespan,omitempty"` - AccessTokenLifespanForImplicitFlow *int `json:"accessTokenLifespanForImplicitFlow,omitempty"` - AccountTheme *string `json:"accountTheme,omitempty"` - ActionTokenGeneratedByAdminLifespan *int `json:"actionTokenGeneratedByAdminLifespan,omitempty"` - ActionTokenGeneratedByUserLifespan *int `json:"actionTokenGeneratedByUserLifespan,omitempty"` - AdminEventsDetailsEnabled *bool `json:"adminEventsDetailsEnabled,omitempty"` - AdminEventsEnabled *bool `json:"adminEventsEnabled,omitempty"` - AdminTheme *string `json:"adminTheme,omitempty"` - Attributes *map[string]string `json:"attributes,omitempty"` - AuthenticationFlows *[]interface{} `json:"authenticationFlows,omitempty"` - AuthenticatorConfig *[]interface{} `json:"authenticatorConfig,omitempty"` - BrowserFlow *string `json:"browserFlow,omitempty"` - BrowserSecurityHeaders *map[string]string `json:"browserSecurityHeaders,omitempty"` - BruteForceProtected *bool `json:"bruteForceProtected,omitempty"` - ClientAuthenticationFlow *string `json:"clientAuthenticationFlow,omitempty"` - ClientScopeMappings *map[string]string `json:"clientScopeMappings,omitempty"` - ClientScopes *[]ClientScope `json:"clientScopes,omitempty"` - Clients *[]Client `json:"clients,omitempty"` - Components interface{} `json:"components,omitempty"` - DefaultDefaultClientScopes *[]string `json:"defaultDefaultClientScopes,omitempty"` - DefaultGroups *[]string `json:"defaultGroups,omitempty"` - DefaultLocale *string `json:"defaultLocale,omitempty"` - DefaultOptionalClientScopes *[]string `json:"defaultOptionalClientScopes,omitempty"` - DefaultRole *Role `json:"defaultRole,omitempty"` - DefaultRoles *[]string `json:"defaultRoles,omitempty"` - DefaultSignatureAlgorithm *string `json:"defaultSignatureAlgorithm,omitempty"` - DirectGrantFlow *string `json:"directGrantFlow,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - DisplayNameHTML *string `json:"displayNameHtml,omitempty"` - DockerAuthenticationFlow *string `json:"dockerAuthenticationFlow,omitempty"` - DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"` - EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"` - EmailTheme *string `json:"emailTheme,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - EnabledEventTypes *[]string `json:"enabledEventTypes,omitempty"` - EventsEnabled *bool `json:"eventsEnabled,omitempty"` - EventsExpiration *int64 `json:"eventsExpiration,omitempty"` - EventsListeners *[]string `json:"eventsListeners,omitempty"` - FailureFactor *int `json:"failureFactor,omitempty"` - FederatedUsers *[]interface{} `json:"federatedUsers,omitempty"` - Groups *[]interface{} `json:"groups,omitempty"` - ID *string `json:"id,omitempty"` - IdentityProviderMappers *[]interface{} `json:"identityProviderMappers,omitempty"` - IdentityProviders *[]interface{} `json:"identityProviders,omitempty"` - InternationalizationEnabled *bool `json:"internationalizationEnabled,omitempty"` - KeycloakVersion *string `json:"keycloakVersion,omitempty"` - LoginTheme *string `json:"loginTheme,omitempty"` - LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"` - MaxDeltaTimeSeconds *int `json:"maxDeltaTimeSeconds,omitempty"` - MaxFailureWaitSeconds *int `json:"maxFailureWaitSeconds,omitempty"` - MinimumQuickLoginWaitSeconds *int `json:"minimumQuickLoginWaitSeconds,omitempty"` - NotBefore *int `json:"notBefore,omitempty"` - OfflineSessionIdleTimeout *int `json:"offlineSessionIdleTimeout,omitempty"` - OfflineSessionMaxLifespan *int `json:"offlineSessionMaxLifespan,omitempty"` - OfflineSessionMaxLifespanEnabled *bool `json:"offlineSessionMaxLifespanEnabled,omitempty"` - OtpPolicyAlgorithm *string `json:"otpPolicyAlgorithm,omitempty"` - OtpPolicyDigits *int `json:"otpPolicyDigits,omitempty"` - OtpPolicyInitialCounter *int `json:"otpPolicyInitialCounter,omitempty"` - OtpPolicyLookAheadWindow *int `json:"otpPolicyLookAheadWindow,omitempty"` - OtpPolicyPeriod *int `json:"otpPolicyPeriod,omitempty"` - OtpPolicyType *string `json:"otpPolicyType,omitempty"` - OtpSupportedApplications *[]string `json:"otpSupportedApplications,omitempty"` - PasswordPolicy *string `json:"passwordPolicy,omitempty"` - PermanentLockout *bool `json:"permanentLockout,omitempty"` - ProtocolMappers *[]interface{} `json:"protocolMappers,omitempty"` - QuickLoginCheckMilliSeconds *int64 `json:"quickLoginCheckMilliSeconds,omitempty"` - Realm *string `json:"realm,omitempty"` - RefreshTokenMaxReuse *int `json:"refreshTokenMaxReuse,omitempty"` - RegistrationAllowed *bool `json:"registrationAllowed,omitempty"` - RegistrationEmailAsUsername *bool `json:"registrationEmailAsUsername,omitempty"` - RegistrationFlow *string `json:"registrationFlow,omitempty"` - RememberMe *bool `json:"rememberMe,omitempty"` - RequiredActions *[]interface{} `json:"requiredActions,omitempty"` - ResetCredentialsFlow *string `json:"resetCredentialsFlow,omitempty"` - ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"` - RevokeRefreshToken *bool `json:"revokeRefreshToken,omitempty"` - Roles *RolesRepresentation `json:"roles,omitempty"` - ScopeMappings *[]interface{} `json:"scopeMappings,omitempty"` - SMTPServer *map[string]string `json:"smtpServer,omitempty"` - SslRequired *string `json:"sslRequired,omitempty"` - SsoSessionIdleTimeout *int `json:"ssoSessionIdleTimeout,omitempty"` - SsoSessionIdleTimeoutRememberMe *int `json:"ssoSessionIdleTimeoutRememberMe,omitempty"` - SsoSessionMaxLifespan *int `json:"ssoSessionMaxLifespan,omitempty"` - SsoSessionMaxLifespanRememberMe *int `json:"ssoSessionMaxLifespanRememberMe,omitempty"` - SupportedLocales *[]string `json:"supportedLocales,omitempty"` - UserFederationMappers *[]interface{} `json:"userFederationMappers,omitempty"` - UserFederationProviders *[]interface{} `json:"userFederationProviders,omitempty"` - UserManagedAccessAllowed *bool `json:"userManagedAccessAllowed,omitempty"` - Users *[]User `json:"users,omitempty"` - VerifyEmail *bool `json:"verifyEmail,omitempty"` - WaitIncrementSeconds *int `json:"waitIncrementSeconds,omitempty"` + AccessCodeLifespan *int `json:"accessCodeLifespan,omitempty"` + AccessCodeLifespanLogin *int `json:"accessCodeLifespanLogin,omitempty"` + AccessCodeLifespanUserAction *int `json:"accessCodeLifespanUserAction,omitempty"` + AccessTokenLifespan *int `json:"accessTokenLifespan,omitempty"` + AccessTokenLifespanForImplicitFlow *int `json:"accessTokenLifespanForImplicitFlow,omitempty"` + AccountTheme *string `json:"accountTheme,omitempty"` + ActionTokenGeneratedByAdminLifespan *int `json:"actionTokenGeneratedByAdminLifespan,omitempty"` + ActionTokenGeneratedByUserLifespan *int `json:"actionTokenGeneratedByUserLifespan,omitempty"` + AdminEventsDetailsEnabled *bool `json:"adminEventsDetailsEnabled,omitempty"` + AdminEventsEnabled *bool `json:"adminEventsEnabled,omitempty"` + AdminTheme *string `json:"adminTheme,omitempty"` + Attributes *map[string]string `json:"attributes,omitempty"` + AuthenticationFlows *[]interface{} `json:"authenticationFlows,omitempty"` + AuthenticatorConfig *[]interface{} `json:"authenticatorConfig,omitempty"` + BrowserFlow *string `json:"browserFlow,omitempty"` + BrowserSecurityHeaders *map[string]string `json:"browserSecurityHeaders,omitempty"` + BruteForceProtected *bool `json:"bruteForceProtected,omitempty"` + ClientAuthenticationFlow *string `json:"clientAuthenticationFlow,omitempty"` + ClientScopeMappings *map[string]string `json:"clientScopeMappings,omitempty"` + ClientScopes *[]ClientScope `json:"clientScopes,omitempty"` + Clients *[]Client `json:"clients,omitempty"` + Components interface{} `json:"components,omitempty"` + DefaultDefaultClientScopes *[]string `json:"defaultDefaultClientScopes,omitempty"` + DefaultGroups *[]string `json:"defaultGroups,omitempty"` + DefaultLocale *string `json:"defaultLocale,omitempty"` + DefaultOptionalClientScopes *[]string `json:"defaultOptionalClientScopes,omitempty"` + DefaultRole *Role `json:"defaultRole,omitempty"` + DefaultRoles *[]string `json:"defaultRoles,omitempty"` + DefaultSignatureAlgorithm *string `json:"defaultSignatureAlgorithm,omitempty"` + DirectGrantFlow *string `json:"directGrantFlow,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + DisplayNameHTML *string `json:"displayNameHtml,omitempty"` + DockerAuthenticationFlow *string `json:"dockerAuthenticationFlow,omitempty"` + DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"` + EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"` + EmailTheme *string `json:"emailTheme,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + EnabledEventTypes *[]string `json:"enabledEventTypes,omitempty"` + EventsEnabled *bool `json:"eventsEnabled,omitempty"` + EventsExpiration *int64 `json:"eventsExpiration,omitempty"` + EventsListeners *[]string `json:"eventsListeners,omitempty"` + FailureFactor *int `json:"failureFactor,omitempty"` + FederatedUsers *[]interface{} `json:"federatedUsers,omitempty"` + Groups *[]interface{} `json:"groups,omitempty"` + ID *string `json:"id,omitempty"` + IdentityProviderMappers *[]interface{} `json:"identityProviderMappers,omitempty"` + IdentityProviders *[]interface{} `json:"identityProviders,omitempty"` + InternationalizationEnabled *bool `json:"internationalizationEnabled,omitempty"` + KeycloakVersion *string `json:"keycloakVersion,omitempty"` + LoginTheme *string `json:"loginTheme,omitempty"` + LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"` + MaxDeltaTimeSeconds *int `json:"maxDeltaTimeSeconds,omitempty"` + MaxFailureWaitSeconds *int `json:"maxFailureWaitSeconds,omitempty"` + MinimumQuickLoginWaitSeconds *int `json:"minimumQuickLoginWaitSeconds,omitempty"` + NotBefore *int `json:"notBefore,omitempty"` + OfflineSessionIdleTimeout *int `json:"offlineSessionIdleTimeout,omitempty"` + OfflineSessionMaxLifespan *int `json:"offlineSessionMaxLifespan,omitempty"` + OfflineSessionMaxLifespanEnabled *bool `json:"offlineSessionMaxLifespanEnabled,omitempty"` + OtpPolicyAlgorithm *string `json:"otpPolicyAlgorithm,omitempty"` + OtpPolicyDigits *int `json:"otpPolicyDigits,omitempty"` + OtpPolicyInitialCounter *int `json:"otpPolicyInitialCounter,omitempty"` + OtpPolicyLookAheadWindow *int `json:"otpPolicyLookAheadWindow,omitempty"` + OtpPolicyPeriod *int `json:"otpPolicyPeriod,omitempty"` + OtpPolicyType *string `json:"otpPolicyType,omitempty"` + OtpSupportedApplications *[]string `json:"otpSupportedApplications,omitempty"` + PasswordPolicy *string `json:"passwordPolicy,omitempty"` + PermanentLockout *bool `json:"permanentLockout,omitempty"` + ProtocolMappers *[]interface{} `json:"protocolMappers,omitempty"` + QuickLoginCheckMilliSeconds *int64 `json:"quickLoginCheckMilliSeconds,omitempty"` + Realm *string `json:"realm,omitempty"` + RefreshTokenMaxReuse *int `json:"refreshTokenMaxReuse,omitempty"` + RegistrationAllowed *bool `json:"registrationAllowed,omitempty"` + RegistrationEmailAsUsername *bool `json:"registrationEmailAsUsername,omitempty"` + RegistrationFlow *string `json:"registrationFlow,omitempty"` + RememberMe *bool `json:"rememberMe,omitempty"` + RequiredActions *[]interface{} `json:"requiredActions,omitempty"` + ResetCredentialsFlow *string `json:"resetCredentialsFlow,omitempty"` + ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"` + RevokeRefreshToken *bool `json:"revokeRefreshToken,omitempty"` + Roles *RolesRepresentation `json:"roles,omitempty"` + ScopeMappings *[]interface{} `json:"scopeMappings,omitempty"` + SMTPServer *map[string]string `json:"smtpServer,omitempty"` + SslRequired *string `json:"sslRequired,omitempty"` + SsoSessionIdleTimeout *int `json:"ssoSessionIdleTimeout,omitempty"` + SsoSessionIdleTimeoutRememberMe *int `json:"ssoSessionIdleTimeoutRememberMe,omitempty"` + SsoSessionMaxLifespan *int `json:"ssoSessionMaxLifespan,omitempty"` + SsoSessionMaxLifespanRememberMe *int `json:"ssoSessionMaxLifespanRememberMe,omitempty"` + SupportedLocales *[]string `json:"supportedLocales,omitempty"` + UserFederationMappers *[]interface{} `json:"userFederationMappers,omitempty"` + UserFederationProviders *[]interface{} `json:"userFederationProviders,omitempty"` + UserManagedAccessAllowed *bool `json:"userManagedAccessAllowed,omitempty"` + Users *[]User `json:"users,omitempty"` + VerifyEmail *bool `json:"verifyEmail,omitempty"` + WaitIncrementSeconds *int `json:"waitIncrementSeconds,omitempty"` + WebAuthnPolicyAcceptableAaguids *[]string `json:"webAuthnPolicyAcceptableAaguids,omitempty"` + WebAuthnPolicyAttestationConveyancePreference *string `json:"webAuthnPolicyAttestationConveyancePreference,omitempty"` + WebAuthnPolicyAuthenticatorAttachment *string `json:"webAuthnPolicyAuthenticatorAttachment,omitempty"` + WebAuthnPolicyAvoidSameAuthenticatorRegister *bool `json:"webAuthnPolicyAvoidSameAuthenticatorRegister,omitempty"` + WebAuthnPolicyCreateTimeout *int `json:"webAuthnPolicyCreateTimeout,omitempty"` + WebAuthnPolicyPasswordlessAcceptableAaguids *[]string `json:"webAuthnPolicyPasswordlessAcceptableAaguids,omitempty"` + WebAuthnPolicyPasswordlessAttestationConveyancePreference *string `json:"webAuthnPolicyPasswordlessAttestationConveyancePreference,omitempty"` + WebAuthnPolicyPasswordlessAuthenticatorAttachment *string `json:"webAuthnPolicyPasswordlessAuthenticatorAttachment,omitempty"` + WebAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister *bool `json:"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister,omitempty"` + WebAuthnPolicyPasswordlessCreateTimeout *int `json:"webAuthnPolicyPasswordlessCreateTimeout,omitempty"` + WebAuthnPolicyPasswordlessRequireResidentKey *string `json:"webAuthnPolicyPasswordlessRequireResidentKey,omitempty"` + WebAuthnPolicyPasswordlessRpEntityName *string `json:"webAuthnPolicyPasswordlessRpEntityName,omitempty"` + WebAuthnPolicyPasswordlessRpID *string `json:"webAuthnPolicyPasswordlessRpId,omitempty"` + WebAuthnPolicyPasswordlessSignatureAlgorithms *[]string `json:"webAuthnPolicyPasswordlessSignatureAlgorithms,omitempty"` + WebAuthnPolicyPasswordlessUserVerificationRequirement *string `json:"webAuthnPolicyPasswordlessUserVerificationRequirement,omitempty"` + WebAuthnPolicyRequireResidentKey *string `json:"webAuthnPolicyRequireResidentKey,omitempty"` + WebAuthnPolicyRpEntityName *string `json:"webAuthnPolicyRpEntityName,omitempty"` + WebAuthnPolicyRpID *string `json:"webAuthnPolicyRpId,omitempty"` + WebAuthnPolicySignatureAlgorithms *[]string `json:"webAuthnPolicySignatureAlgorithms,omitempty"` + WebAuthnPolicyUserVerificationRequirement *string `json:"webAuthnPolicyUserVerificationRequirement,omitempty"` } // AuthenticationFlowRepresentation represents an authentication flow of a realm From 2cb779b591064a777c9333313006f6ee680d457b Mon Sep 17 00:00:00 2001 From: Bastian Date: Wed, 12 Oct 2022 18:15:41 +0200 Subject: [PATCH 24/60] feat(Realm): get/alter localizations (#372) Co-authored-by: Dirk Gerretz --- client_test.go | 2 +- gocloak.go | 14 +++++++------- model_test.go | 2 +- models.go | 17 +++++++++++++++++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/client_test.go b/client_test.go index 55524ba2..1143374b 100644 --- a/client_test.go +++ b/client_test.go @@ -6265,7 +6265,7 @@ func Test_ImportIdentityProviderConfig(t *testing.T) { } func Test_ImportIdentityProviderConfigFromFile(t *testing.T) { - //// t.Parallel() + // t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) diff --git a/gocloak.go b/gocloak.go index ac803466..e6b4d019 100644 --- a/gocloak.go +++ b/gocloak.go @@ -319,22 +319,22 @@ type GoCloak interface { ClearUserCache(ctx context.Context, token, realm string) error // ClearKeysCache clears realm cache ClearKeysCache(ctx context.Context, token, realm string) error - //GetAuthenticationFlows get all authentication flows from a realm + // GetAuthenticationFlows get all authentication flows from a realm GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) - //Create a new Authentication flow in a realm + // Create a new Authentication flow in a realm CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error - //DeleteAuthenticationFlow deletes a flow in a realm with the given ID + // DeleteAuthenticationFlow deletes a flow in a realm with the given ID DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error - //GetAuthenticationExecutions retrieves all executions of a given flow + // GetAuthenticationExecutions retrieves all executions of a given flow GetAuthenticationExecutions(ctx context.Context, token, realm, flow string) ([]*ModifyAuthenticationExecutionRepresentation, error) - //CreateAuthenticationExecution creates a new execution for the given flow name in the given realm + // CreateAuthenticationExecution creates a new execution for the given flow name in the given realm CreateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionRepresentation) error - //UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm + // UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm UpdateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution ModifyAuthenticationExecutionRepresentation) error // 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 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 *** diff --git a/model_test.go b/model_test.go index fdb3c6df..55048937 100644 --- a/model_test.go +++ b/model_test.go @@ -167,7 +167,7 @@ func TestParseAPIErrType(t *testing.T) { } func TestStringer(t *testing.T) { - //nested structs + // nested structs actions := []string{"someAction", "anotherAction"} access := gocloak.AccessRepresentation{ Manage: gocloak.BoolP(true), diff --git a/models.go b/models.go index a37e4c8c..450f0e05 100644 --- a/models.go +++ b/models.go @@ -1057,6 +1057,23 @@ type ServerInfoRepesentation struct { PasswordPolicies []*PasswordPolicy `json:"passwordPolicies,omitempty"` ProtocolMapperTypes *ProtocolMapperTypes `json:"protocolMapperTypes,omitempty"` BuiltinProtocolMappers *BuiltinProtocolMappers `json:"builtinProtocolMappers,omitempty"` + Themes *Themes `json:"themes,omitempty"` +} + +// ThemeRepresentation contains the theme name and locales +type ThemeRepresentation struct { + Name string `json:"name,omitempty"` + Locales []string `json:"locales,omitempty"` +} + +// Themes contains the available keycloak themes with locales +type Themes struct { + Accounts []ThemeRepresentation `json:"account,omitempty"` + Admin []ThemeRepresentation `json:"admin,omitempty"` + Common []ThemeRepresentation `json:"common,omitempty"` + Email []ThemeRepresentation `json:"email,omitempty"` + Login []ThemeRepresentation `json:"login,omitempty"` + Welcome []ThemeRepresentation `json:"welcome,omitempty"` } // FederatedIdentityRepresentation represents an user federated identity From 287fa81adca19561577f38fa03d586b3ffa5a34d Mon Sep 17 00:00:00 2001 From: ingoaf <53079496+ingoaf@users.noreply.github.com> Date: Wed, 12 Oct 2022 18:16:47 +0200 Subject: [PATCH 25/60] remove deprecated linter (#369) --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 9e1d67ac..d59a6c32 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -9,7 +9,6 @@ linters: - gofmt - misspell - gosec - - maligned - unconvert - revive - gocognit From f15f3bd541e6a6ba54e5ce1bce8667a68336ee3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20M=C3=BCcke?= Date: Wed, 12 Oct 2022 18:18:17 +0200 Subject: [PATCH 26/60] fix(realm): error handling for update required action (#374) --- client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client.go b/client.go index d4c88c6b..ac924d1e 100644 --- a/client.go +++ b/client.go @@ -3816,11 +3816,11 @@ func (client *gocloak) UpdateRequiredAction(ctx context.Context, token string, r if NilOrEmpty(requiredAction.ProviderID) { return errors.New("providerId is required for updating a required action") } - _, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := client.getRequestWithBearerAuth(ctx, token). SetBody(requiredAction). Put(client.getAdminRealmURL(realm, "authentication", "required-actions", *requiredAction.ProviderID)) - return err + return checkForError(resp, err, errMessage) } // DeleteRequiredAction updates a required action for a given realm From e42788eda8ea7e19c85829ab5d17261f002a4075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20M=C3=BCcke?= Date: Wed, 12 Oct 2022 18:18:43 +0200 Subject: [PATCH 27/60] feat(roles): get groups by client role (#373) * feat(roles): get groups by client role * fix(lint): rename id parameters * test: add unit tests for GroupsByRole and GroupsByClientRole --- client.go | 18 +++++++++++++++++- client_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ gocloak.go | 2 ++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/client.go b/client.go index ac924d1e..04f126e2 100644 --- a/client.go +++ b/client.go @@ -1548,7 +1548,23 @@ func (client *gocloak) GetGroupsByRole(ctx context.Context, token, realm string, var result []*Group resp, err := client.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(fmt.Sprintf("%s/%s/%s", client.getAdminRealmURL(realm, "roles"), roleName, "groups")) + Get(client.getAdminRealmURL(realm, "roles", roleName, "groups")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// GetGroupsByClientRole gets groups with specified roles assigned of given client within a realm +func (client *gocloak) GetGroupsByClientRole(ctx context.Context, token, realm string, roleName string, clientID string) ([]*Group, error) { + const errMessage = "could not get groups" + + var result []*Group + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "clients", clientID, "roles", roleName, "groups")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err diff --git a/client_test.go b/client_test.go index 1143374b..cdbf9608 100644 --- a/client_test.go +++ b/client_test.go @@ -2216,6 +2216,47 @@ func Test_GetGroupsBriefRepresentation(t *testing.T) { require.Fail(t, "GetGroupsBriefRepresentation failed") } +func Test_GetGroupsByRole(t *testing.T) { + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + ctx := context.Background() + + grpTearDown, groupID := CreateGroup(t, client) + defer grpTearDown() + + roleTearDown, roleName := CreateRealmRole(t, client) + defer roleTearDown() + + role, _ := client.GetRealmRole(ctx, token.AccessToken, cfg.GoCloak.Realm, roleName) + _ = client.AddRealmRoleToGroup(ctx, token.AccessToken, cfg.GoCloak.Realm, groupID, []gocloak.Role{*role}) + + groupsByRole, err := client.GetGroupsByRole(ctx, token.AccessToken, cfg.GoCloak.Realm, *role.Name) + require.NoError(t, err, "GetGroupsByRole failed") + require.Len(t, groupsByRole, 1) +} + +func Test_GetGroupsByClientRole(t *testing.T) { + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + ctx := context.Background() + + grpTearDown, groupID := CreateGroup(t, client) + defer grpTearDown() + + clientRoleTeardown, roleName := CreateClientRole(t, client) + defer clientRoleTeardown() + + role, _ := client.GetClientRole(ctx, token.AccessToken, cfg.GoCloak.Realm, gocloakClientID, roleName) + + _ = client.AddClientRoleToGroup(ctx, token.AccessToken, cfg.GoCloak.Realm, gocloakClientID, groupID, []gocloak.Role{*role}) + + groupsByClientRole, err := client.GetGroupsByClientRole(ctx, token.AccessToken, cfg.GoCloak.Realm, roleName, gocloakClientID) + require.NoError(t, err, "GetGroupsByClientRole failed") + require.Len(t, groupsByClientRole, 1) +} + func Test_GetGroupFull(t *testing.T) { // t.Parallel() cfg := GetConfig(t) diff --git a/gocloak.go b/gocloak.go index e6b4d019..84dddd7c 100644 --- a/gocloak.go +++ b/gocloak.go @@ -189,6 +189,8 @@ type GoCloak interface { GetGroups(ctx context.Context, accessToken, realm string, params GetGroupsParams) ([]*Group, error) // GetGroupsByRole gets groups with specified roles assigned of given realm GetGroupsByRole(ctx context.Context, accessToken, realm string, roleName string) ([]*Group, error) + // GetGroupsByClientRole gets groups with specified roles assigned of given client within a realm + GetGroupsByClientRole(ctx context.Context, accessToken, realm string, roleName string, clientID string) ([]*Group, error) // GetGroupsCount gets groups count of the given realm GetGroupsCount(ctx context.Context, token, realm string, params GetGroupsParams) (int, error) // GetGroup gets the given group From 4f04556a7a037f207eb3ae9b4193f426d54f6551 Mon Sep 17 00:00:00 2001 From: Bastian Date: Wed, 12 Oct 2022 18:19:08 +0200 Subject: [PATCH 28/60] feat(gocloak): add GetCompositeRolesByRoleID (#376) --- client.go | 16 ++++++++++++++++ gocloak.go | 2 ++ 2 files changed, 18 insertions(+) diff --git a/client.go b/client.go index 04f126e2..71227ab1 100644 --- a/client.go +++ b/client.go @@ -2031,6 +2031,22 @@ func (client *gocloak) GetCompositeRealmRoles(ctx context.Context, token, realm, return result, nil } +// GetCompositeRolesByRoleID returns all realm composite roles associated with the given client role +func (client *gocloak) GetCompositeRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) { + const errMessage = "could not get composite client roles by role id" + + var result []*Role + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) + + if err = checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + // GetCompositeRealmRolesByRoleID returns all realm composite roles associated with the given client role func (client *gocloak) GetCompositeRealmRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) { const errMessage = "could not get composite client roles by role id" diff --git a/gocloak.go b/gocloak.go index 84dddd7c..dfb8ff91 100644 --- a/gocloak.go +++ b/gocloak.go @@ -252,6 +252,8 @@ type GoCloak interface { DeleteRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error // GetCompositeRealmRoles returns all realm composite roles associated with the given realm role GetCompositeRealmRoles(ctx context.Context, token, realm, roleName string) ([]*Role, error) + // GetCompositeRolesByRoleID returns all realm composite roles associated with the given client role + GetCompositeRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) // GetCompositeRealmRolesByRoleID returns all realm composite roles associated with the given client role GetCompositeRealmRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) // GetCompositeRealmRolesByUserID returns all realm roles and composite roles assigned to the given user From 1cd6e0f75ba0f7b6be619b0f275894c5d2cc8353 Mon Sep 17 00:00:00 2001 From: Timothee Gosselin Date: Wed, 12 Oct 2022 18:19:40 +0200 Subject: [PATCH 29/60] add missing attributes to ProtocolMappersConfig (#363) --- models.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/models.go b/models.go index 450f0e05..d3cd449c 100644 --- a/models.go +++ b/models.go @@ -429,6 +429,9 @@ type ProtocolMappersConfig struct { UsermodelClientRoleMappingClientID *string `json:"usermodel.clientRoleMapping.clientId,omitempty"` IncludedClientAudience *string `json:"included.client.audience,omitempty"` FullPath *string `json:"full.path,omitempty"` + AttributeName *string `json:"attribute.name,omitempty"` + AttributeNameFormat *string `json:"attribute.nameformat,omitempty"` + Single *string `json:"single,omitempty"` } // Client is a ClientRepresentation From 1a6a98e02c843c1866c824aa644113df2a06e865 Mon Sep 17 00:00:00 2001 From: Undefined K Date: Thu, 13 Oct 2022 00:20:04 +0800 Subject: [PATCH 30/60] feat: support getting group by path (#375) --- client.go | 17 +++++++++++++++++ gocloak.go | 2 ++ 2 files changed, 19 insertions(+) diff --git a/client.go b/client.go index 71227ab1..0b1c7cec 100644 --- a/client.go +++ b/client.go @@ -1519,6 +1519,23 @@ func (client *gocloak) GetGroup(ctx context.Context, token, realm, groupID strin return &result, nil } +// GetGroupByPath get group with path in realm +func (client *gocloak) GetGroupByPath(ctx context.Context, token, realm, groupPath string) (*Group, error) { + const errMessage = "could not get group" + + var result Group + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, "group-by-path", groupPath)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, nil +} + // GetGroups get all groups in realm func (client *gocloak) GetGroups(ctx context.Context, token, realm string, params GetGroupsParams) ([]*Group, error) { const errMessage = "could not get groups" diff --git a/gocloak.go b/gocloak.go index dfb8ff91..e0735d52 100644 --- a/gocloak.go +++ b/gocloak.go @@ -195,6 +195,8 @@ type GoCloak interface { GetGroupsCount(ctx context.Context, token, realm string, params GetGroupsParams) (int, error) // GetGroup gets the given group GetGroup(ctx context.Context, accessToken, realm, groupID string) (*Group, error) + // GetGroupByPath get group with path in realm + GetGroupByPath(ctx context.Context, token, realm, groupPath string) (*Group, error) // GetGroupMembers get a list of users of group with id in realm GetGroupMembers(ctx context.Context, accessToken, realm, groupID string, params GetGroupsParams) ([]*User, error) // GetRoleMappingByGroupID gets the rolemapping for the given group id From b4b5d20412546ecd710d3d211f543b201fb0fcd5 Mon Sep 17 00:00:00 2001 From: Tolyar Date: Thu, 13 Oct 2022 11:57:57 +0300 Subject: [PATCH 31/60] GetComponentsWithParams and UpdateComponent added (#359) * GetComponentsWithParams and test for it * Possible fix for GetComponent tests * UpdateComponent and tests for it * Possible fix for UpdateComponent tests * Check component name after UpdateComponent. It should be changed. * Allow to get component by ID * Add GetComponent for fetch component by ID. * GetComponent always return only one component. * Fix GetComponents query params * Fix whitespace Co-authored-by: Vladimir Fidunin --- client.go | 51 ++++++++++++++++++++- client_test.go | 118 ++++++++++++++++++++++++++++++++++++++++++++++--- gocloak.go | 6 +++ model_test.go | 5 +-- models.go | 9 +++- 5 files changed, 178 insertions(+), 11 deletions(-) diff --git a/client.go b/client.go index 0b1c7cec..ae1f8708 100644 --- a/client.go +++ b/client.go @@ -158,7 +158,6 @@ func injectTracingHeaders(ctx context.Context, req *resty.Request) *resty.Reques // inject tracing header into request err := tracer.Inject(span.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header)) - if err != nil { return req } @@ -1440,6 +1439,56 @@ func (client *gocloak) GetComponents(ctx context.Context, token, realm string) ( return result, nil } +// GetComponentsWithParams get all components in realm with query params +func (client *gocloak) GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error) { + const errMessage = "could not get components" + var result []*Component + + queryParams, err := GetQueryParams(params) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + SetQueryParams(queryParams). + Get(client.getAdminRealmURL(realm, "components")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// GetComponent get exactly one component by ID +func (client *gocloak) GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error) { + const errMessage = "could not get components" + var result *Component + + componentURL := fmt.Sprintf("components/%s", componentID) + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(client.getAdminRealmURL(realm, componentURL)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + +// UpdateComponent updates the given component +func (client *gocloak) UpdateComponent(ctx context.Context, token, realm string, component Component) error { + const errMessage = "could not update component" + + resp, err := client.getRequestWithBearerAuth(ctx, token). + SetBody(component). + Put(client.getAdminRealmURL(realm, "components", PString(component.ID))) + + return checkForError(resp, err, errMessage) +} + // GetDefaultGroups returns a list of default groups func (client *gocloak) GetDefaultGroups(ctx context.Context, token, realm string) ([]*Group, error) { const errMessage = "could not get default groups" diff --git a/client_test.go b/client_test.go index cdbf9608..941569b5 100644 --- a/client_test.go +++ b/client_test.go @@ -5321,7 +5321,6 @@ func Test_ErrorsGetAuthorizationPolicyScopes(t *testing.T) { }, }, }) - }) // Create SCOPE @@ -6405,10 +6404,9 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecutionAndFlo cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) - authExec := - gocloak.CreateAuthenticationExecutionRepresentation{ - Provider: gocloak.StringP("idp-auto-link"), - } + authExec := gocloak.CreateAuthenticationExecutionRepresentation{ + Provider: gocloak.StringP("idp-auto-link"), + } authFlow := gocloak.AuthenticationFlowRepresentation{ Alias: gocloak.StringP("testauthflow2"), BuiltIn: gocloak.BoolP(false), @@ -6611,3 +6609,113 @@ func TestGocloak_UpdateRequiredAction(t *testing.T) { err := client.UpdateRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, requiredAction) require.NoError(t, err, "Failed to update required action") } + +func CreateComponent(t *testing.T, client gocloak.GoCloak) (func(), *gocloak.Component) { + newComponent := &gocloak.Component{ + Name: GetRandomNameP("CreateComponent"), + ProviderID: gocloak.StringP("rsa-generated"), + ProviderType: gocloak.StringP("org.keycloak.keys.KeyProvider"), + } + cfg := GetConfig(t) + token := GetAdminToken(t, client) + createdID, err := client.CreateComponent( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *newComponent, + ) + require.NoError(t, err, "CreateComponent failed") + tearDown := func() { + _ = client.DeleteComponent( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + createdID, + ) + } + newComponent.ID = &createdID + return tearDown, newComponent +} + +func Test_GetComponentsWithParams(t *testing.T) { + // t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + tearDownComponent, component := CreateComponent(t, client) + defer tearDownComponent() + + components, err := client.GetComponentsWithParams( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloak.GetComponentsParams{ + Name: component.Name, + ProviderType: component.ProviderType, + ParentID: component.ParentID, + }, + ) + require.NoError(t, err, "GetComponentsWithParams failed") + if len(components) != 1 { + require.NoError(t, fmt.Errorf("Expected 1 component, got %d", len(components)), "GetComponentsWithParams failed") + } +} + +func Test_GetComponent(t *testing.T) { + // t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + tearDownComponent, component := CreateComponent(t, client) + defer tearDownComponent() + + _, err := client.GetComponent( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *component.ID, + ) + require.NoError(t, err, "GetComponent failed") +} + +func Test_UpdateComponent(t *testing.T) { + // t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + tearDownComponent, component := CreateComponent(t, client) + defer tearDownComponent() + + component.Name = GetRandomNameP("UpdateComponent") + + err := client.UpdateComponent( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *component, + ) + require.NoError(t, err, "UpdateComponent failed") + + components, err := client.GetComponentsWithParams( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloak.GetComponentsParams{ + Name: component.Name, + ProviderType: component.ProviderType, + ParentID: component.ParentID, + }, + ) + require.NoError(t, err, "GetComponentWithParams after UpdateComponent failed") + + if len(components) != 1 { + require.NoError(t, fmt.Errorf("Expected 1 component, got %d", len(components)), "UpdateComponent failed") + } + if *components[0].Name != *component.Name { + require.NoError( + t, + fmt.Errorf("Expected name after update '%s', got '%s'", *component.Name, *components[0].Name), + "UpdateComponent failed", + ) + } +} diff --git a/gocloak.go b/gocloak.go index e0735d52..75dccc30 100644 --- a/gocloak.go +++ b/gocloak.go @@ -179,6 +179,12 @@ type GoCloak interface { GetKeyStoreConfig(ctx context.Context, accessToken, realm string) (*KeyStoreConfig, error) // GetComponents gets components of the given realm GetComponents(ctx context.Context, accessToken, realm string) ([]*Component, error) + // GetComponentsWithParams get all components in realm with query params + GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error) + // GetComponent get exactly one component by ID + GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error) + // UpdateComponent updates the given component + UpdateComponent(ctx context.Context, token, realm string, component Component) error // GetDefaultGroups returns a list of default groups GetDefaultGroups(ctx context.Context, accessToken, realm string) ([]*Group, error) // AddDefaultGroup adds group to the list of default groups diff --git a/model_test.go b/model_test.go index 55048937..ebda1396 100644 --- a/model_test.go +++ b/model_test.go @@ -247,7 +247,6 @@ func TestStringer(t *testing.T) { "displayName": "someRealm" }` assert.Equal(t, expectedStr, str) - } type Stringable interface { @@ -255,7 +254,6 @@ type Stringable interface { } func TestStringerOmitEmpty(t *testing.T) { - customs := []Stringable{ &gocloak.CertResponseKey{}, &gocloak.CertResponse{}, @@ -333,14 +331,13 @@ func TestStringerOmitEmpty(t *testing.T) { &gocloak.GetResourcePoliciesParams{}, &gocloak.CredentialRepresentation{}, &gocloak.GetUsersParams{}, + &gocloak.GetComponentsParams{}, &gocloak.GetClientsParams{}, &gocloak.RequestingPartyTokenOptions{}, &gocloak.RequestingPartyPermission{}, } for _, custom := range customs { - assert.Equal(t, "{}", custom.(Stringable).String()) } - } diff --git a/models.go b/models.go index d3cd449c..36c360a5 100644 --- a/models.go +++ b/models.go @@ -301,6 +301,13 @@ type GetUsersParams struct { Username *string `json:"username,omitempty"` } +// GetComponentsParams represents the optional parameters for getting components +type GetComponentsParams struct { + Name *string `json:"name,omitempty"` + ProviderType *string `json:"provider,omitempty"` + ParentID *string `json:"parent,omitempty"` +} + // ExecuteActionsEmail represents parameters for executing action emails type ExecuteActionsEmail struct { UserID *string `json:"-"` @@ -1361,7 +1368,6 @@ type RequiredActionProviderRepresentation struct { // prettyStringStruct returns struct formatted into pretty string func prettyStringStruct(t interface{}) string { - json, err := json.MarshalIndent(t, "", "\t") if err != nil { return "" @@ -1388,6 +1394,7 @@ func (v *Attributes) String() string { return pre func (v *Access) String() string { return prettyStringStruct(v) } func (v *UserGroup) String() string { return prettyStringStruct(v) } func (v *GetUsersParams) String() string { return prettyStringStruct(v) } +func (v *GetComponentsParams) String() string { return prettyStringStruct(v) } func (v *ExecuteActionsEmail) String() string { return prettyStringStruct(v) } func (v *Group) String() string { return prettyStringStruct(v) } func (v *GroupsCount) String() string { return prettyStringStruct(v) } From 18f0f3d14cb8dd31a49d357ca37fab0aa8ca337f Mon Sep 17 00:00:00 2001 From: Nerzal Date: Wed, 19 Oct 2022 14:34:15 +0200 Subject: [PATCH 32/60] WIP: Support for Keycloak 17+ / Version 19 as target (#361) * accept interfaces, return structs * update dependencies * update go version in CI * Fix linter errors * BreakingChange: fix typo in ServerInfoRepresentation * BreakingChange: rename RetrospectTokenResult to IntrospectTokenResult * fix more linter errors * BreakingChange: Bugfix - Issue #358 CreateClientRepresentation does now require a token * upgrade for keycloak 19 * update CI * jub * cleanup * add SendVerifyEmail function * test * Fix #248 * Fix realm import (#367) * Fix realm import * Fix gocloak-realm * Add test permissions, policy * Change JS policies to client, remove test for uploading JS policy * Fix register client tests Co-authored-by: Pavol Ipoth * fix tests (#379) * fix tests * Fix Comment go-linter * update dependencies and add nancy ignore case * Add -d to make file Co-authored-by: Jonas Heinemann * upgrade gocloak version (#380) Co-authored-by: Tobias Theel Co-authored-by: p53 Co-authored-by: Pavol Ipoth Co-authored-by: Jonas <57955592+JonasHeinemann@users.noreply.github.com> Co-authored-by: Jonas Heinemann Co-authored-by: WilliPkv <105049959+WilliPkv@users.noreply.github.com> --- .github/workflows/go.yml | 5 +- .nancy-ignore | 2 +- Dockerfile | 11 + Makefile | 5 +- README.md | 4 +- client.go | 1696 ++++++++++++++++++----------------- client_benchmark_test.go | 2 +- client_test.go | 450 +++++----- docker-compose.yml | 11 +- go.mod | 19 +- go.sum | 28 +- gocloak.go | 547 ----------- model_test.go | 6 +- models.go | 18 +- testdata/gocloak-realm.json | 329 ++++--- utils_test.go | 2 +- 16 files changed, 1396 insertions(+), 1739 deletions(-) create mode 100644 Dockerfile delete mode 100644 gocloak.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 0fbb1b27..9dc4aacc 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -9,7 +9,7 @@ jobs: - name: Setup Go environment uses: actions/setup-go@v3.0.0 with: - go-version: 1.18 + go-version: 1.19 - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint @@ -20,8 +20,7 @@ jobs: uses: sonatype-nexus-community/nancy-github-action@main - name: Run Keycloak run: | - docker pull jboss/keycloak:12.0.3 - docker run -d -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=secret -e KEYCLOAK_IMPORT=/tmp/gocloak-realm.json -v "`pwd`/testdata/gocloak-realm.json:/tmp/gocloak-realm.json" -p 8080:8080 --name keycloak jboss/keycloak:12.0.3 -Dkeycloak.profile.feature.upload_scripts=enabled + make start-keycloak sleep 15 - name: Unit Tests run: | diff --git a/.nancy-ignore b/.nancy-ignore index 6c4168fa..d23fc372 100644 --- a/.nancy-ignore +++ b/.nancy-ignore @@ -1 +1 @@ -CVE-2019-11840 +CVE-2022-32149 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..fe10a523 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM quay.io/keycloak/keycloak:latest +COPY testdata data/import +WORKDIR /opt/keycloak +ENV KC_HOSTNAME=localhost +ENV KEYCLOAK_USER=admin +ENV KEYCLOAK_PASSWORD=secret +ENV KEYCLOAK_ADMIN=admin +ENV KEYCLOAK_ADMIN_PASSWORD=secret +ENV KC_FEATURES=account-api,account2,authorization,client-policies,impersonation,docker,scripts,upload_scripts +RUN /opt/keycloak/bin/kc.sh import --file /data/import/gocloak-realm.json +ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] \ No newline at end of file diff --git a/Makefile b/Makefile index 783ef7d8..1664ecb4 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ test: ./run-tests.sh - \ No newline at end of file + +start-keycloak: + docker-compose down + docker-compose up -d \ No newline at end of file diff --git a/README.md b/README.md index 7df6e9ab..b1d99fb8 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ For release notes please consult the specific releases [here](https://github.com ### Installation ```shell -go get github.com/Nerzal/gocloak/v11 +go get github.com/Nerzal/gocloak/v12 ``` ### Importing ```go - import "github.com/Nerzal/gocloak/v11" + import "github.com/Nerzal/gocloak/v12" ``` ### Create New User diff --git a/client.go b/client.go index ae1f8708..69d24b64 100644 --- a/client.go +++ b/client.go @@ -1,3 +1,4 @@ +// Package gocloak is a golang keycloak adaptor. package gocloak import ( @@ -17,10 +18,11 @@ import ( "github.com/pkg/errors" "github.com/segmentio/ksuid" - "github.com/Nerzal/gocloak/v11/pkg/jwx" + "github.com/Nerzal/gocloak/v12/pkg/jwx" ) -type gocloak struct { +// GoCloak provides functionalities to talk to Keycloak. +type GoCloak struct { basePath string certsCache sync.Map certsLock sync.Mutex @@ -44,36 +46,36 @@ func makeURL(path ...string) string { return strings.Join(path, urlSeparator) } -func (client *gocloak) getRequest(ctx context.Context) *resty.Request { +func (g *GoCloak) getRequest(ctx context.Context) *resty.Request { var err HTTPErrorResponse return injectTracingHeaders( - ctx, client.restyClient.R(). + ctx, g.restyClient.R(). SetContext(ctx). SetError(&err), ) } -func (client *gocloak) getRequestWithBearerAuthNoCache(ctx context.Context, token string) *resty.Request { - return client.getRequest(ctx). +func (g *GoCloak) getRequestWithBearerAuthNoCache(ctx context.Context, token string) *resty.Request { + return g.getRequest(ctx). SetAuthToken(token). SetHeader("Content-Type", "application/json"). SetHeader("Cache-Control", "no-cache") } -func (client *gocloak) getRequestWithBearerAuth(ctx context.Context, token string) *resty.Request { - return client.getRequest(ctx). +func (g *GoCloak) getRequestWithBearerAuth(ctx context.Context, token string) *resty.Request { + return g.getRequest(ctx). SetAuthToken(token). SetHeader("Content-Type", "application/json") } -func (client *gocloak) getRequestWithBearerAuthXMLHeader(ctx context.Context, token string) *resty.Request { - return client.getRequest(ctx). +func (g *GoCloak) getRequestWithBearerAuthXMLHeader(ctx context.Context, token string) *resty.Request { + return g.getRequest(ctx). SetAuthToken(token). SetHeader("Content-Type", "application/xml;charset=UTF-8") } -func (client *gocloak) getRequestWithBasicAuth(ctx context.Context, clientID, clientSecret string) *resty.Request { - req := client.getRequest(ctx). +func (g *GoCloak) getRequestWithBasicAuth(ctx context.Context, clientID, clientSecret string) *resty.Request { + req := g.getRequest(ctx). SetHeader("Content-Type", "application/x-www-form-urlencoded") // Public client doesn't require Basic Auth if len(clientID) > 0 && len(clientSecret) > 0 { @@ -84,12 +86,12 @@ func (client *gocloak) getRequestWithBasicAuth(ctx context.Context, clientID, cl return req } -func (client *gocloak) getRequestingParty(ctx context.Context, token string, realm string, options RequestingPartyTokenOptions, res interface{}) (*resty.Response, error) { - return client.getRequestWithBearerAuth(ctx, token). +func (g *GoCloak) getRequestingParty(ctx context.Context, token string, realm string, options RequestingPartyTokenOptions, res interface{}) (*resty.Response, error) { + return g.getRequestWithBearerAuth(ctx, token). SetFormData(options.FormData()). SetFormDataFromValues(url.Values{"permission": PStringSlice(options.Permissions)}). SetResult(&res). - Post(client.getRealmURL(realm, client.Config.tokenEndpoint)) + Post(g.getRealmURL(realm, g.Config.tokenEndpoint)) } func checkForError(resp *resty.Response, err error, errMessage string) error { @@ -130,6 +132,7 @@ func checkForError(resp *resty.Response, err error, errMessage string) error { func getID(resp *resty.Response) string { header := resp.Header().Get("Location") splittedPath := strings.Split(header, urlSeparator) + return splittedPath[len(splittedPath)-1] } @@ -170,15 +173,15 @@ func injectTracingHeaders(ctx context.Context, req *resty.Request) *resty.Reques // =============== // NewClient creates a new Client -func NewClient(basePath string, options ...func(*gocloak)) GoCloak { - c := gocloak{ +func NewClient(basePath string, options ...func(*GoCloak)) *GoCloak { + c := GoCloak{ basePath: strings.TrimRight(basePath, urlSeparator), restyClient: resty.New(), } c.Config.CertsInvalidateTime = 10 * time.Minute - c.Config.authAdminRealms = makeURL("auth", "admin", "realms") - c.Config.authRealms = makeURL("auth", "realms") + c.Config.authAdminRealms = makeURL("admin", "realms") + c.Config.authRealms = makeURL("realms") c.Config.tokenEndpoint = makeURL("protocol", "openid-connect", "token") c.Config.logoutEndpoint = makeURL("protocol", "openid-connect", "logout") c.Config.openIDConnect = makeURL("protocol", "openid-connect") @@ -190,91 +193,103 @@ func NewClient(basePath string, options ...func(*gocloak)) GoCloak { return &c } -func (client *gocloak) RestyClient() *resty.Client { - return client.restyClient +// RestyClient returns the internal resty g. +// This can be used to configure the g. +func (g *GoCloak) RestyClient() *resty.Client { + return g.restyClient } -func (client *gocloak) SetRestyClient(restyClient *resty.Client) { - client.restyClient = restyClient +// SetRestyClient overwrites the internal resty g. +func (g *GoCloak) SetRestyClient(restyClient *resty.Client) { + g.restyClient = restyClient } -func (client *gocloak) getRealmURL(realm string, path ...string) string { - path = append([]string{client.basePath, client.Config.authRealms, realm}, path...) +func (g *GoCloak) getRealmURL(realm string, path ...string) string { + path = append([]string{g.basePath, g.Config.authRealms, realm}, path...) return makeURL(path...) } -func (client *gocloak) getAdminRealmURL(realm string, path ...string) string { - path = append([]string{client.basePath, client.Config.authAdminRealms, realm}, path...) +func (g *GoCloak) getAdminRealmURL(realm string, path ...string) string { + path = append([]string{g.basePath, g.Config.authAdminRealms, realm}, path...) return makeURL(path...) } // ==== Functional Options === +// SetLegacyWildFlySupport maintain legacy WildFly support. +func SetLegacyWildFlySupport() func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.authAdminRealms = makeURL("auth", "admin", "realms") + g.Config.authRealms = makeURL("auth", "realms") + } +} + // SetAuthRealms sets the auth realm -func SetAuthRealms(url string) func(client *gocloak) { - return func(client *gocloak) { - client.Config.authRealms = url +func SetAuthRealms(url string) func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.authRealms = url } } // SetAuthAdminRealms sets the auth admin realm -func SetAuthAdminRealms(url string) func(client *gocloak) { - return func(client *gocloak) { - client.Config.authAdminRealms = url +func SetAuthAdminRealms(url string) func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.authAdminRealms = url } } // SetTokenEndpoint sets the token endpoint -func SetTokenEndpoint(url string) func(client *gocloak) { - return func(client *gocloak) { - client.Config.tokenEndpoint = url +func SetTokenEndpoint(url string) func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.tokenEndpoint = url } } // SetLogoutEndpoint sets the logout -func SetLogoutEndpoint(url string) func(client *gocloak) { - return func(client *gocloak) { - client.Config.logoutEndpoint = url +func SetLogoutEndpoint(url string) func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.logoutEndpoint = url } } // SetOpenIDConnectEndpoint sets the logout -func SetOpenIDConnectEndpoint(url string) func(client *gocloak) { - return func(client *gocloak) { - client.Config.openIDConnect = url +func SetOpenIDConnectEndpoint(url string) func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.openIDConnect = url } } // SetCertCacheInvalidationTime sets the logout -func SetCertCacheInvalidationTime(duration time.Duration) func(client *gocloak) { - return func(client *gocloak) { - client.Config.CertsInvalidateTime = duration +func SetCertCacheInvalidationTime(duration time.Duration) func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.CertsInvalidateTime = duration } } -func (client *gocloak) GetServerInfo(ctx context.Context, accessToken string) (*ServerInfoRepesentation, error) { +// GetServerInfo fetches the server info. +func (g *GoCloak) GetServerInfo(ctx context.Context, accessToken string) ([]*ServerInfoRepresentation, error) { errMessage := "could not get server info" - var result ServerInfoRepesentation + var result []*ServerInfoRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetResult(&result). - Get(makeURL(client.basePath, "auth", "admin", "serverinfo")) + Get(makeURL(g.basePath, "admin", "realms")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err } - return &result, nil + return result, nil } // GetUserInfo calls the UserInfo endpoint -func (client *gocloak) GetUserInfo(ctx context.Context, accessToken, realm string) (*UserInfo, error) { +func (g *GoCloak) GetUserInfo(ctx context.Context, accessToken, realm string) (*UserInfo, error) { const errMessage = "could not get user info" var result UserInfo - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetResult(&result). - Get(client.getRealmURL(realm, client.Config.openIDConnect, "userinfo")) + Get(g.getRealmURL(realm, g.Config.openIDConnect, "userinfo")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -284,13 +299,13 @@ func (client *gocloak) GetUserInfo(ctx context.Context, accessToken, realm strin } // GetRawUserInfo calls the UserInfo endpoint and returns a raw json object -func (client *gocloak) GetRawUserInfo(ctx context.Context, accessToken, realm string) (map[string]interface{}, error) { +func (g *GoCloak) GetRawUserInfo(ctx context.Context, accessToken, realm string) (map[string]interface{}, error) { const errMessage = "could not get user info" var result map[string]interface{} - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetResult(&result). - Get(client.getRealmURL(realm, client.Config.openIDConnect, "userinfo")) + Get(g.getRealmURL(realm, g.Config.openIDConnect, "userinfo")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -299,13 +314,13 @@ func (client *gocloak) GetRawUserInfo(ctx context.Context, accessToken, realm st return result, nil } -func (client *gocloak) getNewCerts(ctx context.Context, realm string) (*CertResponse, error) { +func (g *GoCloak) getNewCerts(ctx context.Context, realm string) (*CertResponse, error) { const errMessage = "could not get newCerts" var result CertResponse - resp, err := client.getRequest(ctx). + resp, err := g.getRequest(ctx). SetResult(&result). - Get(client.getRealmURL(realm, client.Config.openIDConnect, "certs")) + Get(g.getRealmURL(realm, g.Config.openIDConnect, "certs")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -315,41 +330,41 @@ func (client *gocloak) getNewCerts(ctx context.Context, realm string) (*CertResp } // GetCerts fetches certificates for the given realm from the public /open-id-connect/certs endpoint -func (client *gocloak) GetCerts(ctx context.Context, realm string) (*CertResponse, error) { +func (g *GoCloak) GetCerts(ctx context.Context, realm string) (*CertResponse, error) { const errMessage = "could not get certs" - if cert, ok := client.certsCache.Load(realm); ok { + if cert, ok := g.certsCache.Load(realm); ok { return cert.(*CertResponse), nil } - client.certsLock.Lock() - defer client.certsLock.Unlock() + g.certsLock.Lock() + defer g.certsLock.Unlock() - if cert, ok := client.certsCache.Load(realm); ok { + if cert, ok := g.certsCache.Load(realm); ok { return cert.(*CertResponse), nil } - cert, err := client.getNewCerts(ctx, realm) + cert, err := g.getNewCerts(ctx, realm) if err != nil { return nil, errors.Wrap(err, errMessage) } - client.certsCache.Store(realm, cert) - time.AfterFunc(client.Config.CertsInvalidateTime, func() { - client.certsCache.Delete(realm) + g.certsCache.Store(realm, cert) + time.AfterFunc(g.Config.CertsInvalidateTime, func() { + g.certsCache.Delete(realm) }) return cert, nil } // GetIssuer gets the issuer of the given realm -func (client *gocloak) GetIssuer(ctx context.Context, realm string) (*IssuerResponse, error) { +func (g *GoCloak) GetIssuer(ctx context.Context, realm string) (*IssuerResponse, error) { const errMessage = "could not get issuer" var result IssuerResponse - resp, err := client.getRequest(ctx). + resp, err := g.getRequest(ctx). SetResult(&result). - Get(client.getRealmURL(realm)) + Get(g.getRealmURL(realm)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -359,17 +374,17 @@ func (client *gocloak) GetIssuer(ctx context.Context, realm string) (*IssuerResp } // RetrospectToken calls the openid-connect introspect endpoint -func (client *gocloak) RetrospectToken(ctx context.Context, accessToken, clientID, clientSecret, realm string) (*RetrospecTokenResult, error) { +func (g *GoCloak) RetrospectToken(ctx context.Context, accessToken, clientID, clientSecret, realm string) (*IntroSpectTokenResult, error) { const errMessage = "could not introspect requesting party token" - var result RetrospecTokenResult - resp, err := client.getRequestWithBasicAuth(ctx, clientID, clientSecret). + var result IntroSpectTokenResult + resp, err := g.getRequestWithBasicAuth(ctx, clientID, clientSecret). SetFormData(map[string]string{ "token_type_hint": "requesting_party_token", "token": accessToken, }). SetResult(&result). - Post(client.getRealmURL(realm, client.Config.tokenEndpoint, "introspect")) + Post(g.getRealmURL(realm, g.Config.tokenEndpoint, "introspect")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -378,7 +393,7 @@ func (client *gocloak) RetrospectToken(ctx context.Context, accessToken, clientI return &result, nil } -func (client *gocloak) decodeAccessTokenWithClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) { +func (g *GoCloak) decodeAccessTokenWithClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) { const errMessage = "could not decode access token" accessToken = strings.Replace(accessToken, "Bearer ", "", 1) @@ -387,7 +402,7 @@ func (client *gocloak) decodeAccessTokenWithClaims(ctx context.Context, accessTo return nil, errors.Wrap(err, errMessage) } - certResult, err := client.GetCerts(ctx, realm) + certResult, err := g.GetCerts(ctx, realm) if err != nil { return nil, errors.Wrap(err, errMessage) } @@ -408,9 +423,9 @@ func (client *gocloak) decodeAccessTokenWithClaims(ctx context.Context, accessTo } // DecodeAccessToken decodes the accessToken -func (client *gocloak) DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error) { +func (g *GoCloak) DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error) { claims := jwt.MapClaims{} - token, err := client.decodeAccessTokenWithClaims(ctx, accessToken, realm, claims) + token, err := g.decodeAccessTokenWithClaims(ctx, accessToken, realm, claims) if err != nil { return nil, nil, err } @@ -418,25 +433,26 @@ func (client *gocloak) DecodeAccessToken(ctx context.Context, accessToken, realm } // DecodeAccessTokenCustomClaims decodes the accessToken and writes claims into the given claims -func (client *gocloak) DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) { - return client.decodeAccessTokenWithClaims(ctx, accessToken, realm, claims) +func (g *GoCloak) DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) { + return g.decodeAccessTokenWithClaims(ctx, accessToken, realm, claims) } -func (client *gocloak) GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error) { +// GetToken uses TokenOptions to fetch a token. +func (g *GoCloak) GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error) { const errMessage = "could not get token" var token JWT var req *resty.Request if !NilOrEmpty(options.ClientSecret) { - req = client.getRequestWithBasicAuth(ctx, *options.ClientID, *options.ClientSecret) + req = g.getRequestWithBasicAuth(ctx, *options.ClientID, *options.ClientSecret) } else { - req = client.getRequest(ctx) + req = g.getRequest(ctx) } resp, err := req.SetFormData(options.FormData()). SetResult(&token). - Post(client.getRealmURL(realm, client.Config.tokenEndpoint)) + Post(g.getRealmURL(realm, g.Config.tokenEndpoint)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -446,13 +462,12 @@ func (client *gocloak) GetToken(ctx context.Context, realm string, options Token } // GetRequestingPartyToken returns a requesting party token with permissions granted by the server -func (client *gocloak) GetRequestingPartyToken(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*JWT, error) { +func (g *GoCloak) GetRequestingPartyToken(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*JWT, error) { const errMessage = "could not get requesting party token" var res JWT - resp, err := client.getRequestingParty(ctx, token, realm, options, &res) - + resp, err := g.getRequestingParty(ctx, token, realm, options, &res) if err := checkForError(resp, err, errMessage); err != nil { return nil, err } @@ -461,15 +476,14 @@ func (client *gocloak) GetRequestingPartyToken(ctx context.Context, token, realm } // GetRequestingPartyPermissions returns a requesting party permissions granted by the server -func (client *gocloak) GetRequestingPartyPermissions(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*[]RequestingPartyPermission, error) { +func (g *GoCloak) GetRequestingPartyPermissions(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*[]RequestingPartyPermission, error) { const errMessage = "could not get requesting party token" var res []RequestingPartyPermission options.ResponseMode = StringP("permissions") - resp, err := client.getRequestingParty(ctx, token, realm, options, &res) - + resp, err := g.getRequestingParty(ctx, token, realm, options, &res) if err := checkForError(resp, err, errMessage); err != nil { return nil, err } @@ -478,15 +492,14 @@ func (client *gocloak) GetRequestingPartyPermissions(ctx context.Context, token, } // GetRequestingPartyPermissionDecision returns a requesting party permission decision granted by the server -func (client *gocloak) GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error) { +func (g *GoCloak) GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error) { const errMessage = "could not get requesting party token" var res RequestingPartyPermissionDecision options.ResponseMode = StringP("decision") - resp, err := client.getRequestingParty(ctx, token, realm, options, &res) - + resp, err := g.getRequestingParty(ctx, token, realm, options, &res) if err := checkForError(resp, err, errMessage); err != nil { return nil, err } @@ -496,8 +509,8 @@ func (client *gocloak) GetRequestingPartyPermissionDecision(ctx context.Context, // RefreshToken refreshes the given token. // May return a *APIError with further details about the issue. -func (client *gocloak) RefreshToken(ctx context.Context, refreshToken, clientID, clientSecret, realm string) (*JWT, error) { - return client.GetToken(ctx, realm, TokenOptions{ +func (g *GoCloak) RefreshToken(ctx context.Context, refreshToken, clientID, clientSecret, realm string) (*JWT, error) { + return g.GetToken(ctx, realm, TokenOptions{ ClientID: &clientID, ClientSecret: &clientSecret, GrantType: StringP("refresh_token"), @@ -506,8 +519,8 @@ func (client *gocloak) RefreshToken(ctx context.Context, refreshToken, clientID, } // LoginAdmin performs a login with Admin client -func (client *gocloak) LoginAdmin(ctx context.Context, username, password, realm string) (*JWT, error) { - return client.GetToken(ctx, realm, TokenOptions{ +func (g *GoCloak) LoginAdmin(ctx context.Context, username, password, realm string) (*JWT, error) { + return g.GetToken(ctx, realm, TokenOptions{ ClientID: StringP(adminClientID), GrantType: StringP("password"), Username: &username, @@ -516,8 +529,8 @@ func (client *gocloak) LoginAdmin(ctx context.Context, username, password, realm } // LoginClient performs a login with client credentials -func (client *gocloak) LoginClient(ctx context.Context, clientID, clientSecret, realm string) (*JWT, error) { - return client.GetToken(ctx, realm, TokenOptions{ +func (g *GoCloak) LoginClient(ctx context.Context, clientID, clientSecret, realm string) (*JWT, error) { + return g.GetToken(ctx, realm, TokenOptions{ ClientID: &clientID, ClientSecret: &clientSecret, GrantType: StringP("client_credentials"), @@ -526,7 +539,7 @@ func (client *gocloak) LoginClient(ctx context.Context, clientID, clientSecret, // LoginClientTokenExchange will exchange the presented token for a user's token // Requires Token-Exchange is enabled: https://www.keycloak.org/docs/latest/securing_apps/index.html#_token-exchange -func (client *gocloak) LoginClientTokenExchange(ctx context.Context, clientID, token, clientSecret, realm, targetClient, userID string) (*JWT, error) { +func (g *GoCloak) LoginClientTokenExchange(ctx context.Context, clientID, token, clientSecret, realm, targetClient, userID string) (*JWT, error) { tokenOptions := TokenOptions{ ClientID: &clientID, ClientSecret: &clientSecret, @@ -538,11 +551,11 @@ func (client *gocloak) LoginClientTokenExchange(ctx context.Context, clientID, t if userID != "" { tokenOptions.RequestedSubject = &userID } - return client.GetToken(ctx, realm, tokenOptions) + return g.GetToken(ctx, realm, tokenOptions) } // LoginClientSignedJWT performs a login with client credentials and signed jwt claims -func (client *gocloak) LoginClientSignedJWT( +func (g *GoCloak) LoginClientSignedJWT( ctx context.Context, clientID, realm string, @@ -556,7 +569,7 @@ func (client *gocloak) LoginClientSignedJWT( Subject: clientID, ID: ksuid.New().String(), Audience: jwt.ClaimStrings{ - client.getRealmURL(realm), + g.getRealmURL(realm), }, } assertion, err := jwx.SignClaims(claims, key, signedMethod) @@ -564,7 +577,7 @@ func (client *gocloak) LoginClientSignedJWT( return nil, err } - return client.GetToken(ctx, realm, TokenOptions{ + return g.GetToken(ctx, realm, TokenOptions{ ClientID: &clientID, GrantType: StringP("client_credentials"), ClientAssertionType: StringP("urn:ietf:params:oauth:client-assertion-type:jwt-bearer"), @@ -573,8 +586,8 @@ func (client *gocloak) LoginClientSignedJWT( } // Login performs a login with user credentials and a client -func (client *gocloak) Login(ctx context.Context, clientID, clientSecret, realm, username, password string) (*JWT, error) { - return client.GetToken(ctx, realm, TokenOptions{ +func (g *GoCloak) Login(ctx context.Context, clientID, clientSecret, realm, username, password string) (*JWT, error) { + return g.GetToken(ctx, realm, TokenOptions{ ClientID: &clientID, ClientSecret: &clientSecret, GrantType: StringP("password"), @@ -584,8 +597,8 @@ func (client *gocloak) Login(ctx context.Context, clientID, clientSecret, realm, } // LoginOtp performs a login with user credentials and otp token -func (client *gocloak) LoginOtp(ctx context.Context, clientID, clientSecret, realm, username, password, totp string) (*JWT, error) { - return client.GetToken(ctx, realm, TokenOptions{ +func (g *GoCloak) LoginOtp(ctx context.Context, clientID, clientSecret, realm, username, password, totp string) (*JWT, error) { + return g.GetToken(ctx, realm, TokenOptions{ ClientID: &clientID, ClientSecret: &clientSecret, GrantType: StringP("password"), @@ -596,63 +609,65 @@ func (client *gocloak) LoginOtp(ctx context.Context, clientID, clientSecret, rea } // Logout logs out users with refresh token -func (client *gocloak) Logout(ctx context.Context, clientID, clientSecret, realm, refreshToken string) error { +func (g *GoCloak) Logout(ctx context.Context, clientID, clientSecret, realm, refreshToken string) error { const errMessage = "could not logout" - resp, err := client.getRequestWithBasicAuth(ctx, clientID, clientSecret). + resp, err := g.getRequestWithBasicAuth(ctx, clientID, clientSecret). SetFormData(map[string]string{ "client_id": clientID, "refresh_token": refreshToken, }). - Post(client.getRealmURL(realm, client.Config.logoutEndpoint)) + Post(g.getRealmURL(realm, g.Config.logoutEndpoint)) return checkForError(resp, err, errMessage) } -func (client *gocloak) LogoutPublicClient(ctx context.Context, clientID, realm, accessToken, refreshToken string) error { +// LogoutPublicClient performs a logout using a public client and the accessToken. +func (g *GoCloak) LogoutPublicClient(ctx context.Context, clientID, realm, accessToken, refreshToken string) error { const errMessage = "could not logout public client" - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetFormData(map[string]string{ "client_id": clientID, "refresh_token": refreshToken, }). - Post(client.getRealmURL(realm, client.Config.logoutEndpoint)) + Post(g.getRealmURL(realm, g.Config.logoutEndpoint)) return checkForError(resp, err, errMessage) } -// LogoutAllSessions logs out all sessions of a user given an id -func (client *gocloak) LogoutAllSessions(ctx context.Context, accessToken, realm, userID string) error { +// LogoutAllSessions logs out all sessions of a user given an id. +func (g *GoCloak) LogoutAllSessions(ctx context.Context, accessToken, realm, userID string) error { const errMessage = "could not logout" - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). - Post(client.getAdminRealmURL(realm, "users", userID, "logout")) + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + Post(g.getAdminRealmURL(realm, "users", userID, "logout")) return checkForError(resp, err, errMessage) } -func (client *gocloak) RevokeUserConsents(ctx context.Context, accessToken, realm, userID, clientID string) error { +// RevokeUserConsents revokes the given user consent. +func (g *GoCloak) RevokeUserConsents(ctx context.Context, accessToken, realm, userID, clientID string) error { const errMessage = "could not revoke consents" - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). - Delete(client.getAdminRealmURL(realm, "users", userID, "consents", clientID)) + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + Delete(g.getAdminRealmURL(realm, "users", userID, "consents", clientID)) return checkForError(resp, err, errMessage) } -// LogoutUserSessions logs out a single sessions of a user given a session id -func (client *gocloak) LogoutUserSession(ctx context.Context, accessToken, realm, session string) error { +// LogoutUserSession logs out a single sessions of a user given a session id +func (g *GoCloak) LogoutUserSession(ctx context.Context, accessToken, realm, session string) error { const errMessage = "could not logout" - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). - Delete(client.getAdminRealmURL(realm, "sessions", session)) + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + Delete(g.getAdminRealmURL(realm, "sessions", session)) return checkForError(resp, err, errMessage) } // ExecuteActionsEmail executes an actions email -func (client *gocloak) ExecuteActionsEmail(ctx context.Context, token, realm string, params ExecuteActionsEmail) error { +func (g *GoCloak) ExecuteActionsEmail(ctx context.Context, token, realm string, params ExecuteActionsEmail) error { const errMessage = "could not execute actions email" queryParams, err := GetQueryParams(params) @@ -660,20 +675,43 @@ func (client *gocloak) ExecuteActionsEmail(ctx context.Context, token, realm str return errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(params.Actions). SetQueryParams(queryParams). - Put(client.getAdminRealmURL(realm, "users", *(params.UserID), "execute-actions-email")) + Put(g.getAdminRealmURL(realm, "users", *(params.UserID), "execute-actions-email")) + + return checkForError(resp, err, errMessage) +} + +// SendVerifyEmail sends a verification e-mail to a user. +func (g *GoCloak) SendVerifyEmail(ctx context.Context, token, userID, realm string, params ...SendVerificationMailParams) error { + const errMessage = "could not execute actions email" + + queryParams := map[string]string{} + if params != nil { + if params[0].ClientID != nil { + queryParams["client_id"] = *params[0].ClientID + } + + if params[0].RedirectURI != nil { + queryParams["redirect_uri"] = *params[0].RedirectURI + } + } + + resp, err := g.getRequestWithBearerAuth(ctx, token). + SetQueryParams(queryParams). + Put(g.getAdminRealmURL(realm, "users", userID, "send-verify-email")) return checkForError(resp, err, errMessage) } -func (client *gocloak) CreateGroup(ctx context.Context, token, realm string, group Group) (string, error) { +// CreateGroup creates a new group. +func (g *GoCloak) CreateGroup(ctx context.Context, token, realm string, group Group) (string, error) { const errMessage = "could not create group" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(group). - Post(client.getAdminRealmURL(realm, "groups")) + Post(g.getAdminRealmURL(realm, "groups")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -682,12 +720,12 @@ func (client *gocloak) CreateGroup(ctx context.Context, token, realm string, gro } // CreateChildGroup creates a new child group -func (client *gocloak) CreateChildGroup(ctx context.Context, token, realm, groupID string, group Group) (string, error) { +func (g *GoCloak) CreateChildGroup(ctx context.Context, token, realm, groupID string, group Group) (string, error) { const errMessage = "could not create child group" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(group). - Post(client.getAdminRealmURL(realm, "groups", groupID, "children")) + Post(g.getAdminRealmURL(realm, "groups", groupID, "children")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -696,12 +734,13 @@ func (client *gocloak) CreateChildGroup(ctx context.Context, token, realm, group return getID(resp), nil } -func (client *gocloak) CreateComponent(ctx context.Context, token, realm string, component Component) (string, error) { +// CreateComponent creates the given component. +func (g *GoCloak) CreateComponent(ctx context.Context, token, realm string, component Component) (string, error) { const errMessage = "could not create component" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(component). - Post(client.getAdminRealmURL(realm, "components")) + Post(g.getAdminRealmURL(realm, "components")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -710,12 +749,13 @@ func (client *gocloak) CreateComponent(ctx context.Context, token, realm string, return getID(resp), nil } -func (client *gocloak) CreateClient(ctx context.Context, accessToken, realm string, newClient Client) (string, error) { +// CreateClient creates the given g. +func (g *GoCloak) CreateClient(ctx context.Context, accessToken, realm string, newClient Client) (string, error) { const errMessage = "could not create client" - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetBody(newClient). - Post(client.getAdminRealmURL(realm, "clients")) + Post(g.getAdminRealmURL(realm, "clients")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -725,15 +765,15 @@ func (client *gocloak) CreateClient(ctx context.Context, accessToken, realm stri } // CreateClientRepresentation creates a new client representation -func (client *gocloak) CreateClientRepresentation(ctx context.Context, realm string) (*Client, error) { +func (g *GoCloak) CreateClientRepresentation(ctx context.Context, token, realm string, newClient Client) (*Client, error) { const errMessage = "could not create client representation" var result Client - resp, err := client.getRequest(ctx). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - SetBody(Client{}). - Post(client.getRealmURL(realm, "clients-registrations", "default")) + SetBody(newClient). + Post(g.getRealmURL(realm, "clients-registrations", "default")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -743,12 +783,12 @@ func (client *gocloak) CreateClientRepresentation(ctx context.Context, realm str } // CreateClientRole creates a new role for a client -func (client *gocloak) CreateClientRole(ctx context.Context, token, realm, idOfClient string, role Role) (string, error) { +func (g *GoCloak) CreateClientRole(ctx context.Context, token, realm, idOfClient string, role Role) (string, error) { const errMessage = "could not create client role" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(role). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "roles")) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "roles")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -758,12 +798,12 @@ func (client *gocloak) CreateClientRole(ctx context.Context, token, realm, idOfC } // CreateClientScope creates a new client scope -func (client *gocloak) CreateClientScope(ctx context.Context, token, realm string, scope ClientScope) (string, error) { +func (g *GoCloak) CreateClientScope(ctx context.Context, token, realm string, scope ClientScope) (string, error) { const errMessage = "could not create client scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(scope). - Post(client.getAdminRealmURL(realm, "client-scopes")) + Post(g.getAdminRealmURL(realm, "client-scopes")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -773,12 +813,12 @@ func (client *gocloak) CreateClientScope(ctx context.Context, token, realm strin } // CreateClientScopeProtocolMapper creates a new protocolMapper under the given client scope -func (client *gocloak) CreateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) (string, error) { +func (g *GoCloak) CreateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) (string, error) { const errMessage = "could not create client scope protocol mapper" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(protocolMapper). - Post(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) + Post(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -787,36 +827,37 @@ func (client *gocloak) CreateClientScopeProtocolMapper(ctx context.Context, toke return getID(resp), nil } -func (client *gocloak) UpdateGroup(ctx context.Context, token, realm string, updatedGroup Group) error { +// UpdateGroup updates the given group. +func (g *GoCloak) UpdateGroup(ctx context.Context, token, realm string, updatedGroup Group) error { const errMessage = "could not update group" if NilOrEmpty(updatedGroup.ID) { return errors.Wrap(errors.New("ID of a group required"), errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(updatedGroup). - Put(client.getAdminRealmURL(realm, "groups", PString(updatedGroup.ID))) + Put(g.getAdminRealmURL(realm, "groups", PString(updatedGroup.ID))) return checkForError(resp, err, errMessage) } // UpdateClient updates the given Client -func (client *gocloak) UpdateClient(ctx context.Context, token, realm string, updatedClient Client) error { +func (g *GoCloak) UpdateClient(ctx context.Context, token, realm string, updatedClient Client) error { const errMessage = "could not update client" if NilOrEmpty(updatedClient.ID) { return errors.Wrap(errors.New("ID of a client required"), errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(updatedClient). - Put(client.getAdminRealmURL(realm, "clients", PString(updatedClient.ID))) + Put(g.getAdminRealmURL(realm, "clients", PString(updatedClient.ID))) return checkForError(resp, err, errMessage) } // UpdateClientRepresentation updates the given client representation -func (client *gocloak) UpdateClientRepresentation(ctx context.Context, accessToken, realm string, updatedClient Client) (*Client, error) { +func (g *GoCloak) UpdateClientRepresentation(ctx context.Context, accessToken, realm string, updatedClient Client) (*Client, error) { const errMessage = "could not update client representation" if NilOrEmpty(updatedClient.ID) { @@ -825,10 +866,10 @@ func (client *gocloak) UpdateClientRepresentation(ctx context.Context, accessTok var result Client - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetResult(&result). SetBody(updatedClient). - Put(client.getRealmURL(realm, "clients-registrations", "default", PString(updatedClient.ID))) + Put(g.getRealmURL(realm, "clients-registrations", "default", PString(updatedClient.ClientID))) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -837,113 +878,118 @@ func (client *gocloak) UpdateClientRepresentation(ctx context.Context, accessTok return &result, nil } -func (client *gocloak) UpdateRole(ctx context.Context, token, realm, idOfClient string, role Role) error { +// UpdateRole updates the given role. +func (g *GoCloak) UpdateRole(ctx context.Context, token, realm, idOfClient string, role Role) error { const errMessage = "could not update role" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(role). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "roles", PString(role.Name))) + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", PString(role.Name))) return checkForError(resp, err, errMessage) } -func (client *gocloak) UpdateClientScope(ctx context.Context, token, realm string, scope ClientScope) error { +// UpdateClientScope updates the given client scope. +func (g *GoCloak) UpdateClientScope(ctx context.Context, token, realm string, scope ClientScope) error { const errMessage = "could not update client scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(scope). - Put(client.getAdminRealmURL(realm, "client-scopes", PString(scope.ID))) + Put(g.getAdminRealmURL(realm, "client-scopes", PString(scope.ID))) return checkForError(resp, err, errMessage) } // UpdateClientScopeProtocolMapper updates the given protocol mapper for a client scope -func (client *gocloak) UpdateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) error { +func (g *GoCloak) UpdateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) error { const errMessage = "could not update client scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(protocolMapper). - Put(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", PString(protocolMapper.ID))) + Put(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", PString(protocolMapper.ID))) return checkForError(resp, err, errMessage) } -func (client *gocloak) DeleteGroup(ctx context.Context, token, realm, groupID string) error { +// DeleteGroup deletes the group with the given groupID. +func (g *GoCloak) DeleteGroup(ctx context.Context, token, realm, groupID string) error { const errMessage = "could not delete group" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "groups", groupID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "groups", groupID)) return checkForError(resp, err, errMessage) } // DeleteClient deletes a given client -func (client *gocloak) DeleteClient(ctx context.Context, token, realm, idOfClient string) error { +func (g *GoCloak) DeleteClient(ctx context.Context, token, realm, idOfClient string) error { const errMessage = "could not delete client" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient)) return checkForError(resp, err, errMessage) } -func (client *gocloak) DeleteComponent(ctx context.Context, token, realm, componentID string) error { +// DeleteComponent deletes the component with the given id. +func (g *GoCloak) DeleteComponent(ctx context.Context, token, realm, componentID string) error { const errMessage = "could not delete component" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "components", componentID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "components", componentID)) return checkForError(resp, err, errMessage) } -// DeleteClientRepresentation deletes a given client representation -func (client *gocloak) DeleteClientRepresentation(ctx context.Context, accessToken, realm, clientID string) error { +// DeleteClientRepresentation deletes a given client representation. +func (g *GoCloak) DeleteClientRepresentation(ctx context.Context, accessToken, realm, clientID string) error { const errMessage = "could not delete client representation" - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). - Delete(client.getRealmURL(realm, "clients-registrations", "default", clientID)) + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + Delete(g.getRealmURL(realm, "clients-registrations", "default", clientID)) return checkForError(resp, err, errMessage) } -// DeleteClientRole deletes a given role -func (client *gocloak) DeleteClientRole(ctx context.Context, token, realm, idOfClient, roleName string) error { +// DeleteClientRole deletes a given role. +func (g *GoCloak) DeleteClientRole(ctx context.Context, token, realm, idOfClient, roleName string) error { const errMessage = "could not delete client role" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName)) return checkForError(resp, err, errMessage) } -func (client *gocloak) DeleteClientScope(ctx context.Context, token, realm, scopeID string) error { +// DeleteClientScope deletes the scope with the given id. +func (g *GoCloak) DeleteClientScope(ctx context.Context, token, realm, scopeID string) error { const errMessage = "could not delete client scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "client-scopes", scopeID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "client-scopes", scopeID)) return checkForError(resp, err, errMessage) } // DeleteClientScopeProtocolMapper deletes the given protocol mapper from the client scope -func (client *gocloak) DeleteClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) error { +func (g *GoCloak) DeleteClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) error { const errMessage = "could not delete client scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) return checkForError(resp, err, errMessage) } // GetClient returns a client -func (client *gocloak) GetClient(ctx context.Context, token, realm, idOfClient string) (*Client, error) { +func (g *GoCloak) GetClient(ctx context.Context, token, realm, idOfClient string) (*Client, error) { const errMessage = "could not get client" var result Client - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient)) + Get(g.getAdminRealmURL(realm, "clients", idOfClient)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -953,14 +999,14 @@ func (client *gocloak) GetClient(ctx context.Context, token, realm, idOfClient s } // GetClientRepresentation returns a client representation -func (client *gocloak) GetClientRepresentation(ctx context.Context, accessToken, realm, clientID string) (*Client, error) { +func (g *GoCloak) GetClientRepresentation(ctx context.Context, accessToken, realm, clientID string) (*Client, error) { const errMessage = "could not get client representation" var result Client - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetResult(&result). - Get(client.getRealmURL(realm, "clients-registrations", "default", clientID)) + Get(g.getRealmURL(realm, "clients-registrations", "default", clientID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -970,14 +1016,14 @@ func (client *gocloak) GetClientRepresentation(ctx context.Context, accessToken, } // GetAdapterConfiguration returns a adapter configuration -func (client *gocloak) GetAdapterConfiguration(ctx context.Context, accessToken, realm, clientID string) (*AdapterConfiguration, error) { +func (g *GoCloak) GetAdapterConfiguration(ctx context.Context, accessToken, realm, clientID string) (*AdapterConfiguration, error) { const errMessage = "could not get adapter configuration" var result AdapterConfiguration - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetResult(&result). - Get(client.getRealmURL(realm, "clients-registrations", "install", clientID)) + Get(g.getRealmURL(realm, "clients-registrations", "install", clientID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -987,14 +1033,14 @@ func (client *gocloak) GetAdapterConfiguration(ctx context.Context, accessToken, } // GetClientsDefaultScopes returns a list of the client's default scopes -func (client *gocloak) GetClientsDefaultScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) { +func (g *GoCloak) GetClientsDefaultScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) { const errMessage = "could not get clients default scopes" var result []*ClientScope - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1004,34 +1050,34 @@ func (client *gocloak) GetClientsDefaultScopes(ctx context.Context, token, realm } // AddDefaultScopeToClient adds a client scope to the list of client's default scopes -func (client *gocloak) AddDefaultScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { +func (g *GoCloak) AddDefaultScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not add default scope to client" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes", scopeID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes", scopeID)) return checkForError(resp, err, errMessage) } // RemoveDefaultScopeFromClient removes a client scope from the list of client's default scopes -func (client *gocloak) RemoveDefaultScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { +func (g *GoCloak) RemoveDefaultScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not remove default scope from client" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes", scopeID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes", scopeID)) return checkForError(resp, err, errMessage) } // GetClientsOptionalScopes returns a list of the client's optional scopes -func (client *gocloak) GetClientsOptionalScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) { +func (g *GoCloak) GetClientsOptionalScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) { const errMessage = "could not get clients optional scopes" var result []*ClientScope - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1041,34 +1087,34 @@ func (client *gocloak) GetClientsOptionalScopes(ctx context.Context, token, real } // AddOptionalScopeToClient adds a client scope to the list of client's optional scopes -func (client *gocloak) AddOptionalScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { +func (g *GoCloak) AddOptionalScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not add optional scope to client" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes", scopeID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes", scopeID)) return checkForError(resp, err, errMessage) } // RemoveOptionalScopeFromClient deletes a client scope from the list of client's optional scopes -func (client *gocloak) RemoveOptionalScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { +func (g *GoCloak) RemoveOptionalScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not remove optional scope from client" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes", scopeID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes", scopeID)) return checkForError(resp, err, errMessage) } // GetDefaultOptionalClientScopes returns a list of default realm optional scopes -func (client *gocloak) GetDefaultOptionalClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) { +func (g *GoCloak) GetDefaultOptionalClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) { const errMessage = "could not get default optional client scopes" var result []*ClientScope - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "default-optional-client-scopes")) + Get(g.getAdminRealmURL(realm, "default-optional-client-scopes")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1078,14 +1124,14 @@ func (client *gocloak) GetDefaultOptionalClientScopes(ctx context.Context, token } // GetDefaultDefaultClientScopes returns a list of default realm default scopes -func (client *gocloak) GetDefaultDefaultClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) { +func (g *GoCloak) GetDefaultDefaultClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) { const errMessage = "could not get default client scopes" var result []*ClientScope - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "default-default-client-scopes")) + Get(g.getAdminRealmURL(realm, "default-default-client-scopes")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1095,14 +1141,14 @@ func (client *gocloak) GetDefaultDefaultClientScopes(ctx context.Context, token, } // GetClientScope returns a clientscope -func (client *gocloak) GetClientScope(ctx context.Context, token, realm, scopeID string) (*ClientScope, error) { +func (g *GoCloak) GetClientScope(ctx context.Context, token, realm, scopeID string) (*ClientScope, error) { const errMessage = "could not get client scope" var result ClientScope - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes", scopeID)) + Get(g.getAdminRealmURL(realm, "client-scopes", scopeID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1112,14 +1158,14 @@ func (client *gocloak) GetClientScope(ctx context.Context, token, realm, scopeID } // GetClientScopes returns all client scopes -func (client *gocloak) GetClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) { +func (g *GoCloak) GetClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) { const errMessage = "could not get client scopes" var result []*ClientScope - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes")) + Get(g.getAdminRealmURL(realm, "client-scopes")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1129,14 +1175,14 @@ func (client *gocloak) GetClientScopes(ctx context.Context, token, realm string) } // GetClientScopeProtocolMappers returns all protocol mappers of a client scope -func (client *gocloak) GetClientScopeProtocolMappers(ctx context.Context, token, realm, scopeID string) ([]*ProtocolMappers, error) { +func (g *GoCloak) GetClientScopeProtocolMappers(ctx context.Context, token, realm, scopeID string) ([]*ProtocolMappers, error) { const errMessage = "could not get client scope protocol mappers" var result []*ProtocolMappers - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) + Get(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1146,14 +1192,14 @@ func (client *gocloak) GetClientScopeProtocolMappers(ctx context.Context, token, } // GetClientScopeProtocolMapper returns a protocol mapper of a client scope -func (client *gocloak) GetClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) (*ProtocolMappers, error) { +func (g *GoCloak) GetClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) (*ProtocolMappers, error) { const errMessage = "could not get client scope protocol mappers" var result *ProtocolMappers - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) + Get(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1163,14 +1209,14 @@ func (client *gocloak) GetClientScopeProtocolMapper(ctx context.Context, token, } // GetClientScopeMappings returns all scope mappings for the client -func (client *gocloak) GetClientScopeMappings(ctx context.Context, token, realm, idOfClient string) (*MappingsRepresentation, error) { +func (g *GoCloak) GetClientScopeMappings(ctx context.Context, token, realm, idOfClient string) (*MappingsRepresentation, error) { const errMessage = "could not get all scope mappings for the client" var result *MappingsRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1180,14 +1226,14 @@ func (client *gocloak) GetClientScopeMappings(ctx context.Context, token, realm, } // GetClientScopeMappingsRealmRoles returns realm-level roles associated with the client’s scope -func (client *gocloak) GetClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) { +func (g *GoCloak) GetClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) { const errMessage = "could not get realm-level roles with the client’s scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1197,14 +1243,14 @@ func (client *gocloak) GetClientScopeMappingsRealmRoles(ctx context.Context, tok } // GetClientScopeMappingsRealmRolesAvailable returns realm-level roles that are available to attach to this client’s scope -func (client *gocloak) GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) { +func (g *GoCloak) GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) { const errMessage = "could not get available realm-level roles with the client’s scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm", "available")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm", "available")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1214,36 +1260,36 @@ func (client *gocloak) GetClientScopeMappingsRealmRolesAvailable(ctx context.Con } // CreateClientScopeMappingsRealmRoles create realm-level roles to the client’s scope -func (client *gocloak) CreateClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error { +func (g *GoCloak) CreateClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error { const errMessage = "could not create realm-level roles to the client’s scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) return checkForError(resp, err, errMessage) } // DeleteClientScopeMappingsRealmRoles deletes realm-level roles from the client’s scope -func (client *gocloak) DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error { +func (g *GoCloak) DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error { const errMessage = "could not delete realm-level roles from the client’s scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) return checkForError(resp, err, errMessage) } // GetClientScopeMappingsClientRoles returns roles associated with a client’s scope -func (client *gocloak) GetClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) { +func (g *GoCloak) GetClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) { const errMessage = "could not get roles associated with a client’s scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1253,14 +1299,14 @@ func (client *gocloak) GetClientScopeMappingsClientRoles(ctx context.Context, to } // GetClientScopeMappingsClientRolesAvailable returns available roles associated with a client’s scope -func (client *gocloak) GetClientScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) { +func (g *GoCloak) GetClientScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) { const errMessage = "could not get available roles associated with a client’s scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient, "available")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient, "available")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1270,36 +1316,36 @@ func (client *gocloak) GetClientScopeMappingsClientRolesAvailable(ctx context.Co } // CreateClientScopeMappingsClientRoles creates client-level roles from the client’s scope -func (client *gocloak) CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error { +func (g *GoCloak) CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error { const errMessage = "could not create client-level roles from the client’s scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) return checkForError(resp, err, errMessage) } // DeleteClientScopeMappingsClientRoles deletes client-level roles from the client’s scope -func (client *gocloak) DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error { +func (g *GoCloak) DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error { const errMessage = "could not delete client-level roles from the client’s scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) return checkForError(resp, err, errMessage) } // GetClientSecret returns a client's secret -func (client *gocloak) GetClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) { +func (g *GoCloak) GetClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) { const errMessage = "could not get client secret" var result CredentialRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "client-secret")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "client-secret")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1309,13 +1355,13 @@ func (client *gocloak) GetClientSecret(ctx context.Context, token, realm, idOfCl } // GetClientServiceAccount retrieves the service account "user" for a client if enabled -func (client *gocloak) GetClientServiceAccount(ctx context.Context, token, realm, idOfClient string) (*User, error) { +func (g *GoCloak) GetClientServiceAccount(ctx context.Context, token, realm, idOfClient string) (*User, error) { const errMessage = "could not get client service account" var result User - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "service-account-user")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "service-account-user")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1324,13 +1370,14 @@ func (client *gocloak) GetClientServiceAccount(ctx context.Context, token, realm return &result, nil } -func (client *gocloak) RegenerateClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) { +// RegenerateClientSecret triggers the creation of the new client secret. +func (g *GoCloak) RegenerateClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) { const errMessage = "could not regenerate client secret" var result CredentialRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "client-secret")) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "client-secret")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1340,13 +1387,13 @@ func (client *gocloak) RegenerateClientSecret(ctx context.Context, token, realm, } // GetClientOfflineSessions returns offline sessions associated with the client -func (client *gocloak) GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) { +func (g *GoCloak) GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) { const errMessage = "could not get client offline sessions" var res []*UserSessionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&res). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "offline-sessions")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "offline-sessions")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1356,13 +1403,13 @@ func (client *gocloak) GetClientOfflineSessions(ctx context.Context, token, real } // GetClientUserSessions returns user sessions associated with the client -func (client *gocloak) GetClientUserSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) { +func (g *GoCloak) GetClientUserSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) { const errMessage = "could not get client user sessions" var res []*UserSessionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&res). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "user-sessions")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "user-sessions")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1372,12 +1419,12 @@ func (client *gocloak) GetClientUserSessions(ctx context.Context, token, realm, } // CreateClientProtocolMapper creates a protocol mapper in client scope -func (client *gocloak) CreateClientProtocolMapper(ctx context.Context, token, realm, idOfClient string, mapper ProtocolMapperRepresentation) (string, error) { +func (g *GoCloak) CreateClientProtocolMapper(ctx context.Context, token, realm, idOfClient string, mapper ProtocolMapperRepresentation) (string, error) { const errMessage = "could not create client protocol mapper" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(mapper). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models")) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -1387,34 +1434,34 @@ func (client *gocloak) CreateClientProtocolMapper(ctx context.Context, token, re } // UpdateClientProtocolMapper updates a protocol mapper in client scope -func (client *gocloak) UpdateClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string, mapper ProtocolMapperRepresentation) error { +func (g *GoCloak) UpdateClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string, mapper ProtocolMapperRepresentation) error { const errMessage = "could not update client protocol mapper" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(mapper). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models", mapperID)) + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models", mapperID)) return checkForError(resp, err, errMessage) } // DeleteClientProtocolMapper deletes a protocol mapper in client scope -func (client *gocloak) DeleteClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string) error { +func (g *GoCloak) DeleteClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string) error { const errMessage = "could not delete client protocol mapper" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models", mapperID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models", mapperID)) return checkForError(resp, err, errMessage) } // GetKeyStoreConfig get keystoreconfig of the realm -func (client *gocloak) GetKeyStoreConfig(ctx context.Context, token, realm string) (*KeyStoreConfig, error) { +func (g *GoCloak) GetKeyStoreConfig(ctx context.Context, token, realm string) (*KeyStoreConfig, error) { const errMessage = "could not get key store config" var result KeyStoreConfig - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "keys")) + Get(g.getAdminRealmURL(realm, "keys")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1424,13 +1471,13 @@ func (client *gocloak) GetKeyStoreConfig(ctx context.Context, token, realm strin } // GetComponents get all components in realm -func (client *gocloak) GetComponents(ctx context.Context, token, realm string) ([]*Component, error) { +func (g *GoCloak) GetComponents(ctx context.Context, token, realm string) ([]*Component, error) { const errMessage = "could not get components" var result []*Component - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "components")) + Get(g.getAdminRealmURL(realm, "components")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1440,7 +1487,7 @@ func (client *gocloak) GetComponents(ctx context.Context, token, realm string) ( } // GetComponentsWithParams get all components in realm with query params -func (client *gocloak) GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error) { +func (g *GoCloak) GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error) { const errMessage = "could not get components" var result []*Component @@ -1448,10 +1495,10 @@ func (client *gocloak) GetComponentsWithParams(ctx context.Context, token, realm if err != nil { return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "components")) + Get(g.getAdminRealmURL(realm, "components")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1461,15 +1508,15 @@ func (client *gocloak) GetComponentsWithParams(ctx context.Context, token, realm } // GetComponent get exactly one component by ID -func (client *gocloak) GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error) { +func (g *GoCloak) GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error) { const errMessage = "could not get components" var result *Component componentURL := fmt.Sprintf("components/%s", componentID) - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, componentURL)) + Get(g.getAdminRealmURL(realm, componentURL)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1479,25 +1526,25 @@ func (client *gocloak) GetComponent(ctx context.Context, token, realm string, co } // UpdateComponent updates the given component -func (client *gocloak) UpdateComponent(ctx context.Context, token, realm string, component Component) error { +func (g *GoCloak) UpdateComponent(ctx context.Context, token, realm string, component Component) error { const errMessage = "could not update component" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(component). - Put(client.getAdminRealmURL(realm, "components", PString(component.ID))) + Put(g.getAdminRealmURL(realm, "components", PString(component.ID))) return checkForError(resp, err, errMessage) } // GetDefaultGroups returns a list of default groups -func (client *gocloak) GetDefaultGroups(ctx context.Context, token, realm string) ([]*Group, error) { +func (g *GoCloak) GetDefaultGroups(ctx context.Context, token, realm string) ([]*Group, error) { const errMessage = "could not get default groups" var result []*Group - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "default-groups")) + Get(g.getAdminRealmURL(realm, "default-groups")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1507,32 +1554,32 @@ func (client *gocloak) GetDefaultGroups(ctx context.Context, token, realm string } // AddDefaultGroup adds group to the list of default groups -func (client *gocloak) AddDefaultGroup(ctx context.Context, token, realm, groupID string) error { +func (g *GoCloak) AddDefaultGroup(ctx context.Context, token, realm, groupID string) error { const errMessage = "could not add default group" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Put(client.getAdminRealmURL(realm, "default-groups", groupID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Put(g.getAdminRealmURL(realm, "default-groups", groupID)) return checkForError(resp, err, errMessage) } // RemoveDefaultGroup removes group from the list of default groups -func (client *gocloak) RemoveDefaultGroup(ctx context.Context, token, realm, groupID string) error { +func (g *GoCloak) RemoveDefaultGroup(ctx context.Context, token, realm, groupID string) error { const errMessage = "could not remove default group" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "default-groups", groupID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "default-groups", groupID)) return checkForError(resp, err, errMessage) } -func (client *gocloak) getRoleMappings(ctx context.Context, token, realm, path, objectID string) (*MappingsRepresentation, error) { +func (g *GoCloak) getRoleMappings(ctx context.Context, token, realm, path, objectID string) (*MappingsRepresentation, error) { const errMessage = "could not get role mappings" var result MappingsRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, path, objectID, "role-mappings")) + Get(g.getAdminRealmURL(realm, path, objectID, "role-mappings")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1542,24 +1589,24 @@ func (client *gocloak) getRoleMappings(ctx context.Context, token, realm, path, } // GetRoleMappingByGroupID gets the role mappings by group -func (client *gocloak) GetRoleMappingByGroupID(ctx context.Context, token, realm, groupID string) (*MappingsRepresentation, error) { - return client.getRoleMappings(ctx, token, realm, "groups", groupID) +func (g *GoCloak) GetRoleMappingByGroupID(ctx context.Context, token, realm, groupID string) (*MappingsRepresentation, error) { + return g.getRoleMappings(ctx, token, realm, "groups", groupID) } // GetRoleMappingByUserID gets the role mappings by user -func (client *gocloak) GetRoleMappingByUserID(ctx context.Context, token, realm, userID string) (*MappingsRepresentation, error) { - return client.getRoleMappings(ctx, token, realm, "users", userID) +func (g *GoCloak) GetRoleMappingByUserID(ctx context.Context, token, realm, userID string) (*MappingsRepresentation, error) { + return g.getRoleMappings(ctx, token, realm, "users", userID) } // GetGroup get group with id in realm -func (client *gocloak) GetGroup(ctx context.Context, token, realm, groupID string) (*Group, error) { +func (g *GoCloak) GetGroup(ctx context.Context, token, realm, groupID string) (*Group, error) { const errMessage = "could not get group" var result Group - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "groups", groupID)) + Get(g.getAdminRealmURL(realm, "groups", groupID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1569,14 +1616,14 @@ func (client *gocloak) GetGroup(ctx context.Context, token, realm, groupID strin } // GetGroupByPath get group with path in realm -func (client *gocloak) GetGroupByPath(ctx context.Context, token, realm, groupPath string) (*Group, error) { +func (g *GoCloak) GetGroupByPath(ctx context.Context, token, realm, groupPath string) (*Group, error) { const errMessage = "could not get group" var result Group - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "group-by-path", groupPath)) + Get(g.getAdminRealmURL(realm, "group-by-path", groupPath)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1586,7 +1633,7 @@ func (client *gocloak) GetGroupByPath(ctx context.Context, token, realm, groupPa } // GetGroups get all groups in realm -func (client *gocloak) GetGroups(ctx context.Context, token, realm string, params GetGroupsParams) ([]*Group, error) { +func (g *GoCloak) GetGroups(ctx context.Context, token, realm string, params GetGroupsParams) ([]*Group, error) { const errMessage = "could not get groups" var result []*Group @@ -1595,10 +1642,10 @@ func (client *gocloak) GetGroups(ctx context.Context, token, realm string, param return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "groups")) + Get(g.getAdminRealmURL(realm, "groups")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1608,13 +1655,13 @@ func (client *gocloak) GetGroups(ctx context.Context, token, realm string, param } // GetGroupsByRole gets groups assigned with a specific role of a realm -func (client *gocloak) GetGroupsByRole(ctx context.Context, token, realm string, roleName string) ([]*Group, error) { +func (g *GoCloak) GetGroupsByRole(ctx context.Context, token, realm string, roleName string) ([]*Group, error) { const errMessage = "could not get groups" var result []*Group - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles", roleName, "groups")) + Get(g.getAdminRealmURL(realm, "roles", roleName, "groups")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1624,13 +1671,13 @@ func (client *gocloak) GetGroupsByRole(ctx context.Context, token, realm string, } // GetGroupsByClientRole gets groups with specified roles assigned of given client within a realm -func (client *gocloak) GetGroupsByClientRole(ctx context.Context, token, realm string, roleName string, clientID string) ([]*Group, error) { +func (g *GoCloak) GetGroupsByClientRole(ctx context.Context, token, realm string, roleName string, clientID string) ([]*Group, error) { const errMessage = "could not get groups" var result []*Group - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", clientID, "roles", roleName, "groups")) + Get(g.getAdminRealmURL(realm, "clients", clientID, "roles", roleName, "groups")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1640,7 +1687,7 @@ func (client *gocloak) GetGroupsByClientRole(ctx context.Context, token, realm s } // GetGroupsCount gets the groups count in the realm -func (client *gocloak) GetGroupsCount(ctx context.Context, token, realm string, params GetGroupsParams) (int, error) { +func (g *GoCloak) GetGroupsCount(ctx context.Context, token, realm string, params GetGroupsParams) (int, error) { const errMessage = "could not get groups count" var result GroupsCount @@ -1648,10 +1695,10 @@ func (client *gocloak) GetGroupsCount(ctx context.Context, token, realm string, if err != nil { return 0, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "groups", "count")) + Get(g.getAdminRealmURL(realm, "groups", "count")) if err := checkForError(resp, err, errMessage); err != nil { return -1, errors.Wrap(err, errMessage) @@ -1661,7 +1708,7 @@ func (client *gocloak) GetGroupsCount(ctx context.Context, token, realm string, } // GetGroupMembers get a list of users of group with id in realm -func (client *gocloak) GetGroupMembers(ctx context.Context, token, realm, groupID string, params GetGroupsParams) ([]*User, error) { +func (g *GoCloak) GetGroupMembers(ctx context.Context, token, realm, groupID string, params GetGroupsParams) ([]*User, error) { const errMessage = "could not get group members" var result []*User @@ -1670,10 +1717,10 @@ func (client *gocloak) GetGroupMembers(ctx context.Context, token, realm, groupI return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "groups", groupID, "members")) + Get(g.getAdminRealmURL(realm, "groups", groupID, "members")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1683,7 +1730,7 @@ func (client *gocloak) GetGroupMembers(ctx context.Context, token, realm, groupI } // GetClientRoles get all roles for the given client in realm -func (client *gocloak) GetClientRoles(ctx context.Context, token, realm, idOfClient string, params GetRoleParams) ([]*Role, error) { +func (g *GoCloak) GetClientRoles(ctx context.Context, token, realm, idOfClient string, params GetRoleParams) ([]*Role, error) { const errMessage = "could not get client roles" var result []*Role @@ -1692,10 +1739,10 @@ func (client *gocloak) GetClientRoles(ctx context.Context, token, realm, idOfCli return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "roles")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "roles")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1704,14 +1751,14 @@ func (client *gocloak) GetClientRoles(ctx context.Context, token, realm, idOfCli return result, nil } -// GetClientRoleById gets role for the given client in realm using role ID -func (client *gocloak) GetClientRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) { +// GetClientRoleByID gets role for the given client in realm using role ID +func (g *GoCloak) GetClientRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) { const errMessage = "could not get client role" var result Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles-by-id", roleID)) + Get(g.getAdminRealmURL(realm, "roles-by-id", roleID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1720,14 +1767,14 @@ func (client *gocloak) GetClientRoleByID(ctx context.Context, token, realm, role return &result, nil } -// GetRealmRolesByUserID returns all client roles assigned to the given user -func (client *gocloak) GetClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) { +// GetClientRolesByUserID returns all client roles assigned to the given user +func (g *GoCloak) GetClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) { const errMessage = "could not client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) + Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1737,13 +1784,13 @@ func (client *gocloak) GetClientRolesByUserID(ctx context.Context, token, realm, } // GetClientRolesByGroupID returns all client roles assigned to the given group -func (client *gocloak) GetClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) { +func (g *GoCloak) GetClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) { const errMessage = "could not get client roles by group id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) + Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1753,13 +1800,13 @@ func (client *gocloak) GetClientRolesByGroupID(ctx context.Context, token, realm } // GetCompositeClientRolesByRoleID returns all client composite roles associated with the given client role -func (client *gocloak) GetCompositeClientRolesByRoleID(ctx context.Context, token, realm, idOfClient, roleID string) ([]*Role, error) { +func (g *GoCloak) GetCompositeClientRolesByRoleID(ctx context.Context, token, realm, idOfClient, roleID string) ([]*Role, error) { const errMessage = "could not get composite client roles by role id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles-by-id", roleID, "composites", "clients", idOfClient)) + Get(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites", "clients", idOfClient)) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1769,13 +1816,13 @@ func (client *gocloak) GetCompositeClientRolesByRoleID(ctx context.Context, toke } // GetCompositeClientRolesByUserID returns all client roles and composite roles assigned to the given user -func (client *gocloak) GetCompositeClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) { +func (g *GoCloak) GetCompositeClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) { const errMessage = "could not get composite client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient, "composite")) + Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient, "composite")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1785,13 +1832,13 @@ func (client *gocloak) GetCompositeClientRolesByUserID(ctx context.Context, toke } // GetAvailableClientRolesByUserID returns all available client roles to the given user -func (client *gocloak) GetAvailableClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) { +func (g *GoCloak) GetAvailableClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) { const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient, "available")) + Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient, "available")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1801,13 +1848,13 @@ func (client *gocloak) GetAvailableClientRolesByUserID(ctx context.Context, toke } // GetAvailableClientRolesByGroupID returns all available roles to the given group -func (client *gocloak) GetAvailableClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) { +func (g *GoCloak) GetAvailableClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) { const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient, "available")) + Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient, "available")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1817,13 +1864,13 @@ func (client *gocloak) GetAvailableClientRolesByGroupID(ctx context.Context, tok } // GetCompositeClientRolesByGroupID returns all client roles and composite roles assigned to the given group -func (client *gocloak) GetCompositeClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) { +func (g *GoCloak) GetCompositeClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) { const errMessage = "could not get composite client roles by group id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient, "composite")) + Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient, "composite")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1833,13 +1880,13 @@ func (client *gocloak) GetCompositeClientRolesByGroupID(ctx context.Context, tok } // GetClientRole get a role for the given client in a realm by role name -func (client *gocloak) GetClientRole(ctx context.Context, token, realm, idOfClient, roleName string) (*Role, error) { +func (g *GoCloak) GetClientRole(ctx context.Context, token, realm, idOfClient, roleName string) (*Role, error) { const errMessage = "could not get client role" var result Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName)) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1849,7 +1896,7 @@ func (client *gocloak) GetClientRole(ctx context.Context, token, realm, idOfClie } // GetClients gets all clients in realm -func (client *gocloak) GetClients(ctx context.Context, token, realm string, params GetClientsParams) ([]*Client, error) { +func (g *GoCloak) GetClients(ctx context.Context, token, realm string, params GetClientsParams) ([]*Client, error) { const errMessage = "could not get clients" var result []*Client @@ -1857,10 +1904,10 @@ func (client *gocloak) GetClients(ctx context.Context, token, realm string, para if err != nil { return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "clients")) + Get(g.getAdminRealmURL(realm, "clients")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1884,12 +1931,12 @@ func UserAttributeContains(attributes map[string][]string, attribute, value stri // ----------- // CreateRealmRole creates a role in a realm -func (client *gocloak) CreateRealmRole(ctx context.Context, token string, realm string, role Role) (string, error) { +func (g *GoCloak) CreateRealmRole(ctx context.Context, token string, realm string, role Role) (string, error) { const errMessage = "could not create realm role" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(role). - Post(client.getAdminRealmURL(realm, "roles")) + Post(g.getAdminRealmURL(realm, "roles")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -1899,14 +1946,14 @@ func (client *gocloak) CreateRealmRole(ctx context.Context, token string, realm } // GetRealmRole returns a role from a realm by role's name -func (client *gocloak) GetRealmRole(ctx context.Context, token, realm, roleName string) (*Role, error) { +func (g *GoCloak) GetRealmRole(ctx context.Context, token, realm, roleName string) (*Role, error) { const errMessage = "could not get realm role" var result Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles", roleName)) + Get(g.getAdminRealmURL(realm, "roles", roleName)) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1916,13 +1963,13 @@ func (client *gocloak) GetRealmRole(ctx context.Context, token, realm, roleName } // GetRealmRoleByID returns a role from a realm by role's ID -func (client *gocloak) GetRealmRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) { +func (g *GoCloak) GetRealmRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) { const errMessage = "could not get realm role" var result Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles-by-id", roleID)) + Get(g.getAdminRealmURL(realm, "roles-by-id", roleID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1932,7 +1979,7 @@ func (client *gocloak) GetRealmRoleByID(ctx context.Context, token, realm, roleI } // GetRealmRoles get all roles of the given realm. -func (client *gocloak) GetRealmRoles(ctx context.Context, token, realm string, params GetRoleParams) ([]*Role, error) { +func (g *GoCloak) GetRealmRoles(ctx context.Context, token, realm string, params GetRoleParams) ([]*Role, error) { const errMessage = "could not get realm roles" var result []*Role @@ -1941,10 +1988,10 @@ func (client *gocloak) GetRealmRoles(ctx context.Context, token, realm string, p return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "roles")) + Get(g.getAdminRealmURL(realm, "roles")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1954,13 +2001,13 @@ func (client *gocloak) GetRealmRoles(ctx context.Context, token, realm string, p } // GetRealmRolesByUserID returns all roles assigned to the given user -func (client *gocloak) GetRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) { +func (g *GoCloak) GetRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) { const errMessage = "could not get realm roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) + Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1970,13 +2017,13 @@ func (client *gocloak) GetRealmRolesByUserID(ctx context.Context, token, realm, } // GetRealmRolesByGroupID returns all roles assigned to the given group -func (client *gocloak) GetRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) { +func (g *GoCloak) GetRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) { const errMessage = "could not get realm roles by group id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) + Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -1986,109 +2033,111 @@ func (client *gocloak) GetRealmRolesByGroupID(ctx context.Context, token, realm, } // UpdateRealmRole updates a role in a realm -func (client *gocloak) UpdateRealmRole(ctx context.Context, token, realm, roleName string, role Role) error { +func (g *GoCloak) UpdateRealmRole(ctx context.Context, token, realm, roleName string, role Role) error { const errMessage = "could not update realm role" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(role). - Put(client.getAdminRealmURL(realm, "roles", roleName)) + Put(g.getAdminRealmURL(realm, "roles", roleName)) return checkForError(resp, err, errMessage) } // UpdateRealmRoleByID updates a role in a realm by role's ID -func (client *gocloak) UpdateRealmRoleByID(ctx context.Context, token, realm, roleID string, role Role) error { +func (g *GoCloak) UpdateRealmRoleByID(ctx context.Context, token, realm, roleID string, role Role) error { const errMessage = "could not update realm role" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(role). - Put(client.getAdminRealmURL(realm, "roles-by-id", roleID)) + Put(g.getAdminRealmURL(realm, "roles-by-id", roleID)) return checkForError(resp, err, errMessage) } // DeleteRealmRole deletes a role in a realm by role's name -func (client *gocloak) DeleteRealmRole(ctx context.Context, token, realm, roleName string) error { +func (g *GoCloak) DeleteRealmRole(ctx context.Context, token, realm, roleName string) error { const errMessage = "could not delete realm role" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "roles", roleName)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "roles", roleName)) return checkForError(resp, err, errMessage) } // AddRealmRoleToUser adds realm-level role mappings -func (client *gocloak) AddRealmRoleToUser(ctx context.Context, token, realm, userID string, roles []Role) error { +func (g *GoCloak) AddRealmRoleToUser(ctx context.Context, token, realm, userID string, roles []Role) error { const errMessage = "could not add realm role to user" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) + Post(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) return checkForError(resp, err, errMessage) } // DeleteRealmRoleFromUser deletes realm-level role mappings -func (client *gocloak) DeleteRealmRoleFromUser(ctx context.Context, token, realm, userID string, roles []Role) error { +func (g *GoCloak) DeleteRealmRoleFromUser(ctx context.Context, token, realm, userID string, roles []Role) error { const errMessage = "could not delete realm role from user" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) + Delete(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) return checkForError(resp, err, errMessage) } // AddRealmRoleToGroup adds realm-level role mappings -func (client *gocloak) AddRealmRoleToGroup(ctx context.Context, token, realm, groupID string, roles []Role) error { +func (g *GoCloak) AddRealmRoleToGroup(ctx context.Context, token, realm, groupID string, roles []Role) error { const errMessage = "could not add realm role to group" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) + Post(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) return checkForError(resp, err, errMessage) } // DeleteRealmRoleFromGroup deletes realm-level role mappings -func (client *gocloak) DeleteRealmRoleFromGroup(ctx context.Context, token, realm, groupID string, roles []Role) error { +func (g *GoCloak) DeleteRealmRoleFromGroup(ctx context.Context, token, realm, groupID string, roles []Role) error { const errMessage = "could not delete realm role from group" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) + Delete(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) return checkForError(resp, err, errMessage) } -func (client *gocloak) AddRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error { +// AddRealmRoleComposite adds a role to the composite. +func (g *GoCloak) AddRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error { const errMessage = "could not add realm role composite" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "roles", roleName, "composites")) + Post(g.getAdminRealmURL(realm, "roles", roleName, "composites")) return checkForError(resp, err, errMessage) } -func (client *gocloak) DeleteRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error { +// DeleteRealmRoleComposite deletes a role from the composite. +func (g *GoCloak) DeleteRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error { const errMessage = "could not delete realm role composite" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "roles", roleName, "composites")) + Delete(g.getAdminRealmURL(realm, "roles", roleName, "composites")) return checkForError(resp, err, errMessage) } // GetCompositeRealmRoles returns all realm composite roles associated with the given realm role -func (client *gocloak) GetCompositeRealmRoles(ctx context.Context, token, realm, roleName string) ([]*Role, error) { +func (g *GoCloak) GetCompositeRealmRoles(ctx context.Context, token, realm, roleName string) ([]*Role, error) { const errMessage = "could not get composite realm roles by role" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles", roleName, "composites")) + Get(g.getAdminRealmURL(realm, "roles", roleName, "composites")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2098,13 +2147,13 @@ func (client *gocloak) GetCompositeRealmRoles(ctx context.Context, token, realm, } // GetCompositeRolesByRoleID returns all realm composite roles associated with the given client role -func (client *gocloak) GetCompositeRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) { +func (g *GoCloak) GetCompositeRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) { const errMessage = "could not get composite client roles by role id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) + Get(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2114,13 +2163,13 @@ func (client *gocloak) GetCompositeRolesByRoleID(ctx context.Context, token, rea } // GetCompositeRealmRolesByRoleID returns all realm composite roles associated with the given client role -func (client *gocloak) GetCompositeRealmRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) { +func (g *GoCloak) GetCompositeRealmRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) { const errMessage = "could not get composite client roles by role id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles-by-id", roleID, "composites", "realm")) + Get(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites", "realm")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2130,13 +2179,13 @@ func (client *gocloak) GetCompositeRealmRolesByRoleID(ctx context.Context, token } // GetCompositeRealmRolesByUserID returns all realm roles and composite roles assigned to the given user -func (client *gocloak) GetCompositeRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) { +func (g *GoCloak) GetCompositeRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) { const errMessage = "could not get composite client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm", "composite")) + Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm", "composite")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2146,13 +2195,13 @@ func (client *gocloak) GetCompositeRealmRolesByUserID(ctx context.Context, token } // GetCompositeRealmRolesByGroupID returns all realm roles and composite roles assigned to the given group -func (client *gocloak) GetCompositeRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) { +func (g *GoCloak) GetCompositeRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) { const errMessage = "could not get composite client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm", "composite")) + Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm", "composite")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2162,13 +2211,13 @@ func (client *gocloak) GetCompositeRealmRolesByGroupID(ctx context.Context, toke } // GetAvailableRealmRolesByUserID returns all available realm roles to the given user -func (client *gocloak) GetAvailableRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) { +func (g *GoCloak) GetAvailableRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) { const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm", "available")) + Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm", "available")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2178,13 +2227,13 @@ func (client *gocloak) GetAvailableRealmRolesByUserID(ctx context.Context, token } // GetAvailableRealmRolesByGroupID returns all available realm roles to the given group -func (client *gocloak) GetAvailableRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) { +func (g *GoCloak) GetAvailableRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) { const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm", "available")) + Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm", "available")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2198,13 +2247,13 @@ func (client *gocloak) GetAvailableRealmRolesByGroupID(ctx context.Context, toke // ----- // GetRealm returns top-level representation of the realm -func (client *gocloak) GetRealm(ctx context.Context, token, realm string) (*RealmRepresentation, error) { +func (g *GoCloak) GetRealm(ctx context.Context, token, realm string) (*RealmRepresentation, error) { const errMessage = "could not get realm" var result RealmRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm)) + Get(g.getAdminRealmURL(realm)) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2214,13 +2263,13 @@ func (client *gocloak) GetRealm(ctx context.Context, token, realm string) (*Real } // GetRealms returns top-level representation of all realms -func (client *gocloak) GetRealms(ctx context.Context, token string) ([]*RealmRepresentation, error) { +func (g *GoCloak) GetRealms(ctx context.Context, token string) ([]*RealmRepresentation, error) { const errMessage = "could not get realms" var result []*RealmRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL("")) + Get(g.getAdminRealmURL("")) if err = checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2230,12 +2279,12 @@ func (client *gocloak) GetRealms(ctx context.Context, token string) ([]*RealmRep } // CreateRealm creates a realm -func (client *gocloak) CreateRealm(ctx context.Context, token string, realm RealmRepresentation) (string, error) { +func (g *GoCloak) CreateRealm(ctx context.Context, token string, realm RealmRepresentation) (string, error) { const errMessage = "could not create realm" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(&realm). - Post(client.getAdminRealmURL("")) + Post(g.getAdminRealmURL("")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -2244,63 +2293,63 @@ func (client *gocloak) CreateRealm(ctx context.Context, token string, realm Real } // UpdateRealm updates a given realm -func (client *gocloak) UpdateRealm(ctx context.Context, token string, realm RealmRepresentation) error { +func (g *GoCloak) UpdateRealm(ctx context.Context, token string, realm RealmRepresentation) error { const errMessage = "could not update realm" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(realm). - Put(client.getAdminRealmURL(PString(realm.Realm))) + Put(g.getAdminRealmURL(PString(realm.Realm))) return checkForError(resp, err, errMessage) } // DeleteRealm removes a realm -func (client *gocloak) DeleteRealm(ctx context.Context, token, realm string) error { +func (g *GoCloak) DeleteRealm(ctx context.Context, token, realm string) error { const errMessage = "could not delete realm" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm)) return checkForError(resp, err, errMessage) } // ClearRealmCache clears realm cache -func (client *gocloak) ClearRealmCache(ctx context.Context, token, realm string) error { +func (g *GoCloak) ClearRealmCache(ctx context.Context, token, realm string) error { const errMessage = "could not clear realm cache" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Post(client.getAdminRealmURL(realm, "clear-realm-cache")) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Post(g.getAdminRealmURL(realm, "clear-realm-cache")) return checkForError(resp, err, errMessage) } // ClearUserCache clears realm cache -func (client *gocloak) ClearUserCache(ctx context.Context, token, realm string) error { +func (g *GoCloak) ClearUserCache(ctx context.Context, token, realm string) error { const errMessage = "could not clear user cache" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Post(client.getAdminRealmURL(realm, "clear-user-cache")) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Post(g.getAdminRealmURL(realm, "clear-user-cache")) return checkForError(resp, err, errMessage) } // ClearKeysCache clears realm cache -func (client *gocloak) ClearKeysCache(ctx context.Context, token, realm string) error { +func (g *GoCloak) ClearKeysCache(ctx context.Context, token, realm string) error { const errMessage = "could not clear keys cache" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Post(client.getAdminRealmURL(realm, "clear-keys-cache")) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Post(g.getAdminRealmURL(realm, "clear-keys-cache")) return checkForError(resp, err, errMessage) } // GetAuthenticationFlows get all authentication flows from a realm -func (client *gocloak) GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) { +func (g *GoCloak) GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) { const errMessage = "could not retrieve authentication flows" var result []*AuthenticationFlowRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "authentication", "flows")) + Get(g.getAdminRealmURL(realm, "authentication", "flows")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2308,33 +2357,33 @@ func (client *gocloak) GetAuthenticationFlows(ctx context.Context, token, realm return result, nil } -// Create a new Authentication flow in a realm -func (client *gocloak) CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error { +// CreateAuthenticationFlow creates a new Authentication flow in a realm +func (g *GoCloak) CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error { const errMessage = "could not create authentication flows" var result []*AuthenticationFlowRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result).SetBody(flow). - Post(client.getAdminRealmURL(realm, "authentication", "flows")) + Post(g.getAdminRealmURL(realm, "authentication", "flows")) return checkForError(resp, err, errMessage) } // DeleteAuthenticationFlow deletes a flow in a realm with the given ID -func (client *gocloak) DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error { +func (g *GoCloak) DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error { const errMessage = "could not delete authentication flows" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "authentication", "flows", flowID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "authentication", "flows", flowID)) return checkForError(resp, err, errMessage) } // GetAuthenticationExecutions retrieves all executions of a given flow -func (client *gocloak) GetAuthenticationExecutions(ctx context.Context, token, realm, flow string) ([]*ModifyAuthenticationExecutionRepresentation, error) { +func (g *GoCloak) GetAuthenticationExecutions(ctx context.Context, token, realm, flow string) ([]*ModifyAuthenticationExecutionRepresentation, error) { const errMessage = "could not retrieve authentication flows" var result []*ModifyAuthenticationExecutionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "authentication", "flows", flow, "executions")) + Get(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2343,37 +2392,37 @@ func (client *gocloak) GetAuthenticationExecutions(ctx context.Context, token, r } // CreateAuthenticationExecution creates a new execution for the given flow name in the given realm -func (client *gocloak) CreateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionRepresentation) error { +func (g *GoCloak) CreateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionRepresentation) error { const errMessage = "could not create authentication execution" - resp, err := client.getRequestWithBearerAuth(ctx, token).SetBody(execution). - Post(client.getAdminRealmURL(realm, "authentication", "flows", flow, "executions", "execution")) + resp, err := g.getRequestWithBearerAuth(ctx, token).SetBody(execution). + Post(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions", "execution")) return checkForError(resp, err, errMessage) } // UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm -func (client *gocloak) UpdateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution ModifyAuthenticationExecutionRepresentation) error { +func (g *GoCloak) UpdateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution ModifyAuthenticationExecutionRepresentation) error { const errMessage = "could not update authentication execution" - resp, err := client.getRequestWithBearerAuth(ctx, token).SetBody(execution). - Put(client.getAdminRealmURL(realm, "authentication", "flows", flow, "executions")) + resp, err := g.getRequestWithBearerAuth(ctx, token).SetBody(execution). + Put(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions")) return checkForError(resp, err, errMessage) } // DeleteAuthenticationExecution delete a single execution with the given ID -func (client *gocloak) DeleteAuthenticationExecution(ctx context.Context, token, realm, executionID string) error { +func (g *GoCloak) DeleteAuthenticationExecution(ctx context.Context, token, realm, executionID string) error { const errMessage = "could not delete authentication execution" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "authentication", "executions", executionID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "authentication", "executions", executionID)) 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 { +func (g *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")) + resp, err := g.getRequestWithBearerAuth(ctx, token).SetBody(executionFlow). + Post(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions", "flow")) return checkForError(resp, err, errMessage) } @@ -2383,12 +2432,14 @@ func (client *gocloak) CreateAuthenticationExecutionFlow(ctx context.Context, to // ----- // CreateUser creates the given user in the given realm and returns it's userID -func (client *gocloak) CreateUser(ctx context.Context, token, realm string, user User) (string, error) { +// Note: Keycloak has not documented what members of the User object are actually being accepted, when creating a user. +// Things like RealmRoles must be attached using followup calls to the respective functions. +func (g *GoCloak) CreateUser(ctx context.Context, token, realm string, user User) (string, error) { const errMessage = "could not create user" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(user). - Post(client.getAdminRealmURL(realm, "users")) + Post(g.getAdminRealmURL(realm, "users")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -2398,17 +2449,17 @@ func (client *gocloak) CreateUser(ctx context.Context, token, realm string, user } // DeleteUser delete a given user -func (client *gocloak) DeleteUser(ctx context.Context, token, realm, userID string) error { +func (g *GoCloak) DeleteUser(ctx context.Context, token, realm, userID string) error { const errMessage = "could not delete user" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "users", userID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "users", userID)) return checkForError(resp, err, errMessage) } // GetUserByID fetches a user from the given realm with the given userID -func (client *gocloak) GetUserByID(ctx context.Context, accessToken, realm, userID string) (*User, error) { +func (g *GoCloak) GetUserByID(ctx context.Context, accessToken, realm, userID string) (*User, error) { const errMessage = "could not get user by id" if userID == "" { @@ -2416,9 +2467,9 @@ func (client *gocloak) GetUserByID(ctx context.Context, accessToken, realm, user } var result User - resp, err := client.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID)) + Get(g.getAdminRealmURL(realm, "users", userID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2428,7 +2479,7 @@ func (client *gocloak) GetUserByID(ctx context.Context, accessToken, realm, user } // GetUserCount gets the user count in the realm -func (client *gocloak) GetUserCount(ctx context.Context, token string, realm string, params GetUsersParams) (int, error) { +func (g *GoCloak) GetUserCount(ctx context.Context, token string, realm string, params GetUsersParams) (int, error) { const errMessage = "could not get user count" var result int @@ -2437,10 +2488,10 @@ func (client *gocloak) GetUserCount(ctx context.Context, token string, realm str return 0, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "users", "count")) + Get(g.getAdminRealmURL(realm, "users", "count")) if err := checkForError(resp, err, errMessage); err != nil { return -1, errors.Wrap(err, errMessage) @@ -2450,7 +2501,7 @@ func (client *gocloak) GetUserCount(ctx context.Context, token string, realm str } // GetUserGroups get all groups for user -func (client *gocloak) GetUserGroups(ctx context.Context, token, realm, userID string, params GetGroupsParams) ([]*Group, error) { +func (g *GoCloak) GetUserGroups(ctx context.Context, token, realm, userID string, params GetGroupsParams) ([]*Group, error) { const errMessage = "could not get user groups" var result []*Group @@ -2459,10 +2510,10 @@ func (client *gocloak) GetUserGroups(ctx context.Context, token, realm, userID s return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "users", userID, "groups")) + Get(g.getAdminRealmURL(realm, "users", userID, "groups")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2472,7 +2523,7 @@ func (client *gocloak) GetUserGroups(ctx context.Context, token, realm, userID s } // GetUsers get all users in realm -func (client *gocloak) GetUsers(ctx context.Context, token, realm string, params GetUsersParams) ([]*User, error) { +func (g *GoCloak) GetUsers(ctx context.Context, token, realm string, params GetUsersParams) ([]*User, error) { const errMessage = "could not get users" var result []*User @@ -2481,10 +2532,10 @@ func (client *gocloak) GetUsers(ctx context.Context, token, realm string, params return nil, errors.Wrap(err, errMessage) } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "users")) + Get(g.getAdminRealmURL(realm, "users")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2494,13 +2545,13 @@ func (client *gocloak) GetUsers(ctx context.Context, token, realm string, params } // GetUsersByRoleName returns all users have a given role -func (client *gocloak) GetUsersByRoleName(ctx context.Context, token, realm, roleName string) ([]*User, error) { +func (g *GoCloak) GetUsersByRoleName(ctx context.Context, token, realm, roleName string) ([]*User, error) { const errMessage = "could not get users by role name" var result []*User - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "roles", roleName, "users")) + Get(g.getAdminRealmURL(realm, "roles", roleName, "users")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2510,7 +2561,7 @@ func (client *gocloak) GetUsersByRoleName(ctx context.Context, token, realm, rol } // GetUsersByClientRoleName returns all users have a given client role -func (client *gocloak) GetUsersByClientRoleName(ctx context.Context, token, realm, idOfClient, roleName string, params GetUsersByRoleParams) ([]*User, error) { +func (g *GoCloak) GetUsersByClientRoleName(ctx context.Context, token, realm, idOfClient, roleName string, params GetUsersByRoleParams) ([]*User, error) { const errMessage = "could not get users by client role name" var result []*User @@ -2519,10 +2570,10 @@ func (client *gocloak) GetUsersByClientRoleName(ctx context.Context, token, real return nil, err } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName, "users")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName, "users")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2532,56 +2583,56 @@ func (client *gocloak) GetUsersByClientRoleName(ctx context.Context, token, real } // SetPassword sets a new password for the user with the given id. Needs elevated privileges -func (client *gocloak) SetPassword(ctx context.Context, token, userID, realm, password string, temporary bool) error { +func (g *GoCloak) SetPassword(ctx context.Context, token, userID, realm, password string, temporary bool) error { const errMessage = "could not set password" requestBody := SetPasswordRequest{Password: &password, Temporary: &temporary, Type: StringP("password")} - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(requestBody). - Put(client.getAdminRealmURL(realm, "users", userID, "reset-password")) + Put(g.getAdminRealmURL(realm, "users", userID, "reset-password")) return checkForError(resp, err, errMessage) } // UpdateUser updates a given user -func (client *gocloak) UpdateUser(ctx context.Context, token, realm string, user User) error { +func (g *GoCloak) UpdateUser(ctx context.Context, token, realm string, user User) error { const errMessage = "could not update user" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(user). - Put(client.getAdminRealmURL(realm, "users", PString(user.ID))) + Put(g.getAdminRealmURL(realm, "users", PString(user.ID))) return checkForError(resp, err, errMessage) } // AddUserToGroup puts given user to given group -func (client *gocloak) AddUserToGroup(ctx context.Context, token, realm, userID, groupID string) error { +func (g *GoCloak) AddUserToGroup(ctx context.Context, token, realm, userID, groupID string) error { const errMessage = "could not add user to group" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Put(client.getAdminRealmURL(realm, "users", userID, "groups", groupID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Put(g.getAdminRealmURL(realm, "users", userID, "groups", groupID)) return checkForError(resp, err, errMessage) } // DeleteUserFromGroup deletes given user from given group -func (client *gocloak) DeleteUserFromGroup(ctx context.Context, token, realm, userID, groupID string) error { +func (g *GoCloak) DeleteUserFromGroup(ctx context.Context, token, realm, userID, groupID string) error { const errMessage = "could not delete user from group" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "users", userID, "groups", groupID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "users", userID, "groups", groupID)) return checkForError(resp, err, errMessage) } // GetUserSessions returns user sessions associated with the user -func (client *gocloak) GetUserSessions(ctx context.Context, token, realm, userID string) ([]*UserSessionRepresentation, error) { +func (g *GoCloak) GetUserSessions(ctx context.Context, token, realm, userID string) ([]*UserSessionRepresentation, error) { const errMessage = "could not get user sessions" var res []*UserSessionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&res). - Get(client.getAdminRealmURL(realm, "users", userID, "sessions")) + Get(g.getAdminRealmURL(realm, "users", userID, "sessions")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2591,13 +2642,13 @@ func (client *gocloak) GetUserSessions(ctx context.Context, token, realm, userID } // GetUserOfflineSessionsForClient returns offline sessions associated with the user and client -func (client *gocloak) GetUserOfflineSessionsForClient(ctx context.Context, token, realm, userID, idOfClient string) ([]*UserSessionRepresentation, error) { +func (g *GoCloak) GetUserOfflineSessionsForClient(ctx context.Context, token, realm, userID, idOfClient string) ([]*UserSessionRepresentation, error) { const errMessage = "could not get user offline sessions for client" var res []*UserSessionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&res). - Get(client.getAdminRealmURL(realm, "users", userID, "offline-sessions", idOfClient)) + Get(g.getAdminRealmURL(realm, "users", userID, "offline-sessions", idOfClient)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2606,80 +2657,101 @@ func (client *gocloak) GetUserOfflineSessionsForClient(ctx context.Context, toke return res, nil } -// AddClientRoleToUser adds client-level role mappings -func (client *gocloak) AddClientRoleToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { +// AddClientRolesToUser adds client-level role mappings +func (g *GoCloak) AddClientRolesToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { const errMessage = "could not add client role to user" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) + Post(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) return checkForError(resp, err, errMessage) } -// AddClientRoleToGroup adds a client role to the group -func (client *gocloak) AddClientRoleToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error { +// AddClientRoleToUser adds client-level role mappings +// +// Deprecated: replaced by AddClientRolesToUser +func (g *GoCloak) AddClientRoleToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { + return g.AddClientRolesToUser(ctx, token, realm, idOfClient, userID, roles) +} + +// AddClientRolesToGroup adds a client role to the group +func (g *GoCloak) AddClientRolesToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error { const errMessage = "could not add client role to group" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) + Post(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) return checkForError(resp, err, errMessage) } -// DeleteClientRoleFromUser adds client-level role mappings -func (client *gocloak) DeleteClientRoleFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { +// AddClientRoleToGroup adds a client role to the group +// +// Deprecated: replaced by AddClientRolesToGroup +func (g *GoCloak) AddClientRoleToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error { + return g.AddClientRolesToGroup(ctx, token, realm, idOfClient, groupID, roles) +} + +// DeleteClientRolesFromUser adds client-level role mappings +func (g *GoCloak) DeleteClientRolesFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { const errMessage = "could not delete client role from user" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) + Delete(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) return checkForError(resp, err, errMessage) } +// DeleteClientRoleFromUser adds client-level role mappings +// +// Deprecated: replaced by DeleteClientRolesFrom +func (g *GoCloak) DeleteClientRoleFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { + return g.DeleteClientRolesFromUser(ctx, token, realm, idOfClient, userID, roles) +} + // DeleteClientRoleFromGroup removes a client role from from the group -func (client *gocloak) DeleteClientRoleFromGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error { +func (g *GoCloak) DeleteClientRoleFromGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error { const errMessage = "could not client role from group" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) + Delete(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) return checkForError(resp, err, errMessage) } // AddClientRoleComposite adds roles as composite -func (client *gocloak) AddClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error { +func (g *GoCloak) AddClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error { const errMessage = "could not add client role composite" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) + Post(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) return checkForError(resp, err, errMessage) } // DeleteClientRoleComposite deletes composites from a role -func (client *gocloak) DeleteClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error { +func (g *GoCloak) DeleteClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error { const errMessage = "could not delete client role composite" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) + Delete(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) return checkForError(resp, err, errMessage) } // GetUserFederatedIdentities gets all user federated identities -func (client *gocloak) GetUserFederatedIdentities(ctx context.Context, token, realm, userID string) ([]*FederatedIdentityRepresentation, error) { - const errMessage = "could not get user federeated identities" +func (g *GoCloak) GetUserFederatedIdentities(ctx context.Context, token, realm, userID string) ([]*FederatedIdentityRepresentation, error) { + const errMessage = "could not get user federated identities" var res []*FederatedIdentityRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&res). - Get(client.getAdminRealmURL(realm, "users", userID, "federated-identity")) + Get(g.getAdminRealmURL(realm, "users", userID, "federated-identity")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2689,22 +2761,22 @@ func (client *gocloak) GetUserFederatedIdentities(ctx context.Context, token, re } // CreateUserFederatedIdentity creates an user federated identity -func (client *gocloak) CreateUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string, federatedIdentityRep FederatedIdentityRepresentation) error { +func (g *GoCloak) CreateUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string, federatedIdentityRep FederatedIdentityRepresentation) error { const errMessage = "could not create user federeated identity" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(federatedIdentityRep). - Post(client.getAdminRealmURL(realm, "users", userID, "federated-identity", providerID)) + Post(g.getAdminRealmURL(realm, "users", userID, "federated-identity", providerID)) return checkForError(resp, err, errMessage) } // DeleteUserFederatedIdentity deletes an user federated identity -func (client *gocloak) DeleteUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string) error { +func (g *GoCloak) DeleteUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string) error { const errMessage = "could not delete user federeated identity" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "users", userID, "federated-identity", providerID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "users", userID, "federated-identity", providerID)) return checkForError(resp, err, errMessage) } @@ -2714,12 +2786,12 @@ func (client *gocloak) DeleteUserFederatedIdentity(ctx context.Context, token, r // ------------------ // CreateIdentityProvider creates an identity provider in a realm -func (client *gocloak) CreateIdentityProvider(ctx context.Context, token string, realm string, providerRep IdentityProviderRepresentation) (string, error) { +func (g *GoCloak) CreateIdentityProvider(ctx context.Context, token string, realm string, providerRep IdentityProviderRepresentation) (string, error) { const errMessage = "could not create identity provider" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(providerRep). - Post(client.getAdminRealmURL(realm, "identity-provider", "instances")) + Post(g.getAdminRealmURL(realm, "identity-provider", "instances")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -2729,13 +2801,13 @@ func (client *gocloak) CreateIdentityProvider(ctx context.Context, token string, } // GetIdentityProviders returns list of identity providers in a realm -func (client *gocloak) GetIdentityProviders(ctx context.Context, token, realm string) ([]*IdentityProviderRepresentation, error) { +func (g *GoCloak) GetIdentityProviders(ctx context.Context, token, realm string) ([]*IdentityProviderRepresentation, error) { const errMessage = "could not get identity providers" var result []*IdentityProviderRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "identity-provider", "instances")) + Get(g.getAdminRealmURL(realm, "identity-provider", "instances")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2745,13 +2817,13 @@ func (client *gocloak) GetIdentityProviders(ctx context.Context, token, realm st } // GetIdentityProvider gets the identity provider in a realm -func (client *gocloak) GetIdentityProvider(ctx context.Context, token, realm, alias string) (*IdentityProviderRepresentation, error) { +func (g *GoCloak) GetIdentityProvider(ctx context.Context, token, realm, alias string) (*IdentityProviderRepresentation, error) { const errMessage = "could not get identity provider" var result IdentityProviderRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "identity-provider", "instances", alias)) + Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2761,32 +2833,32 @@ func (client *gocloak) GetIdentityProvider(ctx context.Context, token, realm, al } // UpdateIdentityProvider updates the identity provider in a realm -func (client *gocloak) UpdateIdentityProvider(ctx context.Context, token, realm, alias string, providerRep IdentityProviderRepresentation) error { +func (g *GoCloak) UpdateIdentityProvider(ctx context.Context, token, realm, alias string, providerRep IdentityProviderRepresentation) error { const errMessage = "could not update identity provider" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(providerRep). - Put(client.getAdminRealmURL(realm, "identity-provider", "instances", alias)) + Put(g.getAdminRealmURL(realm, "identity-provider", "instances", alias)) return checkForError(resp, err, errMessage) } // DeleteIdentityProvider deletes the identity provider in a realm -func (client *gocloak) DeleteIdentityProvider(ctx context.Context, token, realm, alias string) error { +func (g *GoCloak) DeleteIdentityProvider(ctx context.Context, token, realm, alias string) error { const errMessage = "could not delete identity provider" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "identity-provider", "instances", alias)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "identity-provider", "instances", alias)) return checkForError(resp, err, errMessage) } // ExportIDPPublicBrokerConfig exports the broker config for a given alias -func (client *gocloak) ExportIDPPublicBrokerConfig(ctx context.Context, token, realm, alias string) (*string, error) { +func (g *GoCloak) ExportIDPPublicBrokerConfig(ctx context.Context, token, realm, alias string) (*string, error) { const errMessage = "could not get public identity provider configuration" - resp, err := client.getRequestWithBearerAuthXMLHeader(ctx, token). - Get(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "export")) + resp, err := g.getRequestWithBearerAuthXMLHeader(ctx, token). + Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "export")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2797,17 +2869,17 @@ func (client *gocloak) ExportIDPPublicBrokerConfig(ctx context.Context, token, r } // ImportIdentityProviderConfig parses and returns the identity provider config at a given URL -func (client *gocloak) ImportIdentityProviderConfig(ctx context.Context, token, realm, fromURL, providerID string) (map[string]string, error) { +func (g *GoCloak) ImportIdentityProviderConfig(ctx context.Context, token, realm, fromURL, providerID string) (map[string]string, error) { const errMessage = "could not import config" result := make(map[string]string) - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(map[string]string{ "fromUrl": fromURL, "providerId": providerID, }). - Post(client.getAdminRealmURL(realm, "identity-provider", "import-config")) + Post(g.getAdminRealmURL(realm, "identity-provider", "import-config")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2817,17 +2889,17 @@ func (client *gocloak) ImportIdentityProviderConfig(ctx context.Context, token, } // ImportIdentityProviderConfigFromFile parses and returns the identity provider config from a given file -func (client *gocloak) ImportIdentityProviderConfigFromFile(ctx context.Context, token, realm, providerID, fileName string, fileBody io.Reader) (map[string]string, error) { +func (g *GoCloak) ImportIdentityProviderConfigFromFile(ctx context.Context, token, realm, providerID, fileName string, fileBody io.Reader) (map[string]string, error) { const errMessage = "could not import config" result := make(map[string]string) - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetFileReader("file", fileName, fileBody). SetFormData(map[string]string{ "providerId": providerID, }). - Post(client.getAdminRealmURL(realm, "identity-provider", "import-config")) + Post(g.getAdminRealmURL(realm, "identity-provider", "import-config")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2837,12 +2909,12 @@ func (client *gocloak) ImportIdentityProviderConfigFromFile(ctx context.Context, } // CreateIdentityProviderMapper creates an instance of an identity provider mapper associated with the given alias -func (client *gocloak) CreateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) (string, error) { +func (g *GoCloak) CreateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) (string, error) { const errMessage = "could not create mapper for identity provider" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(mapper). - Post(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers")) + Post(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers")) if err := checkForError(resp, err, errMessage); err != nil { return "", err @@ -2852,13 +2924,13 @@ func (client *gocloak) CreateIdentityProviderMapper(ctx context.Context, token, } // GetIdentityProviderMapper gets the mapper by id for the given identity provider alias in a realm -func (client *gocloak) GetIdentityProviderMapper(ctx context.Context, token string, realm string, alias string, mapperID string) (*IdentityProviderMapper, error) { +func (g *GoCloak) GetIdentityProviderMapper(ctx context.Context, token string, realm string, alias string, mapperID string) (*IdentityProviderMapper, error) { const errMessage = "could not get identity provider mapper" result := IdentityProviderMapper{} - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) + Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2868,23 +2940,23 @@ func (client *gocloak) GetIdentityProviderMapper(ctx context.Context, token stri } // DeleteIdentityProviderMapper deletes an instance of an identity provider mapper associated with the given alias and mapper ID -func (client *gocloak) DeleteIdentityProviderMapper(ctx context.Context, token, realm, alias, mapperID string) error { +func (g *GoCloak) DeleteIdentityProviderMapper(ctx context.Context, token, realm, alias, mapperID string) error { const errMessage = "could not delete mapper for identity provider" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) return checkForError(resp, err, errMessage) } // GetIdentityProviderMappers returns list of mappers associated with an identity provider -func (client *gocloak) GetIdentityProviderMappers(ctx context.Context, token, realm, alias string) ([]*IdentityProviderMapper, error) { +func (g *GoCloak) GetIdentityProviderMappers(ctx context.Context, token, realm, alias string) ([]*IdentityProviderMapper, error) { const errMessage = "could not get identity provider mappers" var result []*IdentityProviderMapper - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers")) + Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2894,13 +2966,13 @@ func (client *gocloak) GetIdentityProviderMappers(ctx context.Context, token, re } // GetIdentityProviderMapperByID gets the mapper of an identity provider -func (client *gocloak) GetIdentityProviderMapperByID(ctx context.Context, token, realm, alias, mapperID string) (*IdentityProviderMapper, error) { +func (g *GoCloak) GetIdentityProviderMapperByID(ctx context.Context, token, realm, alias, mapperID string) (*IdentityProviderMapper, error) { const errMessage = "could not get identity provider mappers" var result IdentityProviderMapper - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) + Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2910,12 +2982,12 @@ func (client *gocloak) GetIdentityProviderMapperByID(ctx context.Context, token, } // UpdateIdentityProviderMapper updates mapper of an identity provider -func (client *gocloak) UpdateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error { +func (g *GoCloak) UpdateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error { const errMessage = "could not update identity provider mapper" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(mapper). - Put(client.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", PString(mapper.ID))) + Put(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", PString(mapper.ID))) return checkForError(resp, err, errMessage) } @@ -2925,13 +2997,13 @@ func (client *gocloak) UpdateIdentityProviderMapper(ctx context.Context, token, // ------------------ // GetResource returns a client's resource with the given id, using access token from admin -func (client *gocloak) GetResource(ctx context.Context, token, realm, idOfClient, resourceID string) (*ResourceRepresentation, error) { +func (g *GoCloak) GetResource(ctx context.Context, token, realm, idOfClient, resourceID string) (*ResourceRepresentation, error) { const errMessage = "could not get resource" var result ResourceRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", resourceID)) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", resourceID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2940,14 +3012,14 @@ func (client *gocloak) GetResource(ctx context.Context, token, realm, idOfClient return &result, nil } -// GetResource returns a client's resource with the given id, using access token from client -func (client *gocloak) GetResourceClient(ctx context.Context, token, realm, resourceID string) (*ResourceRepresentation, error) { +// GetResourceClient returns a client's resource with the given id, using access token from client +func (g *GoCloak) GetResourceClient(ctx context.Context, token, realm, resourceID string) (*ResourceRepresentation, error) { const errMessage = "could not get resource" var result ResourceRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getRealmURL(realm, "authz", "protection", "resource_set", resourceID)) + Get(g.getRealmURL(realm, "authz", "protection", "resource_set", resourceID)) // http://${host}:${port}/auth/realms/${realm_name}/authz/protection/resource_set/{resource_id} @@ -2959,7 +3031,7 @@ func (client *gocloak) GetResourceClient(ctx context.Context, token, realm, reso } // GetResources returns resources associated with the client, using access token from admin -func (client *gocloak) GetResources(ctx context.Context, token, realm, idOfClient string, params GetResourceParams) ([]*ResourceRepresentation, error) { +func (g *GoCloak) GetResources(ctx context.Context, token, realm, idOfClient string, params GetResourceParams) ([]*ResourceRepresentation, error) { const errMessage = "could not get resources" queryParams, err := GetQueryParams(params) @@ -2968,10 +3040,10 @@ func (client *gocloak) GetResources(ctx context.Context, token, realm, idOfClien } var result []*ResourceRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -2980,8 +3052,8 @@ func (client *gocloak) GetResources(ctx context.Context, token, realm, idOfClien return result, nil } -// GetResources returns resources associated with the client, using access token from client -func (client *gocloak) GetResourcesClient(ctx context.Context, token, realm string, params GetResourceParams) ([]*ResourceRepresentation, error) { +// GetResourcesClient returns resources associated with the client, using access token from client +func (g *GoCloak) GetResourcesClient(ctx context.Context, token, realm string, params GetResourceParams) ([]*ResourceRepresentation, error) { const errMessage = "could not get resources" queryParams, err := GetQueryParams(params) @@ -2991,17 +3063,17 @@ func (client *gocloak) GetResourcesClient(ctx context.Context, token, realm stri var result []*ResourceRepresentation var resourceIDs []string - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&resourceIDs). SetQueryParams(queryParams). - Get(client.getRealmURL(realm, "authz", "protection", "resource_set")) + Get(g.getRealmURL(realm, "authz", "protection", "resource_set")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err } for _, resourceID := range resourceIDs { - resource, err := client.GetResourceClient(ctx, token, realm, resourceID) + resource, err := g.GetResourceClient(ctx, token, realm, resourceID) if err == nil { result = append(result, resource) } @@ -3011,44 +3083,44 @@ func (client *gocloak) GetResourcesClient(ctx context.Context, token, realm stri } // UpdateResource updates a resource associated with the client, using access token from admin -func (client *gocloak) UpdateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) error { +func (g *GoCloak) UpdateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) error { const errMessage = "could not update resource" if NilOrEmpty(resource.ID) { return errors.New("ID of a resource required") } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(resource). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", *(resource.ID))) + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", *(resource.ID))) return checkForError(resp, err, errMessage) } -// UpdateResource updates a resource associated with the client, using access token from client -func (client *gocloak) UpdateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) error { +// UpdateResourceClient updates a resource associated with the client, using access token from client +func (g *GoCloak) UpdateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) error { const errMessage = "could not update resource" if NilOrEmpty(resource.ID) { return errors.New("ID of a resource required") } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(resource). - Put(client.getRealmURL(realm, "authz", "protection", "resource_set", *(resource.ID))) + Put(g.getRealmURL(realm, "authz", "protection", "resource_set", *(resource.ID))) return checkForError(resp, err, errMessage) } // CreateResource creates a resource associated with the client, using access token from admin -func (client *gocloak) CreateResource(ctx context.Context, token, realm string, idOfClient string, resource ResourceRepresentation) (*ResourceRepresentation, error) { +func (g *GoCloak) CreateResource(ctx context.Context, token, realm string, idOfClient string, resource ResourceRepresentation) (*ResourceRepresentation, error) { const errMessage = "could not create resource" var result ResourceRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(resource). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource")) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3057,15 +3129,15 @@ func (client *gocloak) CreateResource(ctx context.Context, token, realm string, return &result, nil } -// CreateResource creates a resource associated with the client, using access token from client -func (client *gocloak) CreateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) (*ResourceRepresentation, error) { +// CreateResourceClient creates a resource associated with the client, using access token from client +func (g *GoCloak) CreateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) (*ResourceRepresentation, error) { const errMessage = "could not create resource" var result ResourceRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(resource). - Post(client.getRealmURL(realm, "authz", "protection", "resource_set")) + Post(g.getRealmURL(realm, "authz", "protection", "resource_set")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3075,33 +3147,33 @@ func (client *gocloak) CreateResourceClient(ctx context.Context, token, realm st } // DeleteResource deletes a resource associated with the client (using an admin token) -func (client *gocloak) DeleteResource(ctx context.Context, token, realm, idOfClient, resourceID string) error { +func (g *GoCloak) DeleteResource(ctx context.Context, token, realm, idOfClient, resourceID string) error { const errMessage = "could not delete resource" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", resourceID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", resourceID)) return checkForError(resp, err, errMessage) } -// DeleteResource deletes a resource associated with the client (using a client token) -func (client *gocloak) DeleteResourceClient(ctx context.Context, token, realm, resourceID string) error { +// DeleteResourceClient deletes a resource associated with the client (using a client token) +func (g *GoCloak) DeleteResourceClient(ctx context.Context, token, realm, resourceID string) error { const errMessage = "could not delete resource" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getRealmURL(realm, "authz", "protection", "resource_set", resourceID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getRealmURL(realm, "authz", "protection", "resource_set", resourceID)) return checkForError(resp, err, errMessage) } // GetScope returns a client's scope with the given id -func (client *gocloak) GetScope(ctx context.Context, token, realm, idOfClient, scopeID string) (*ScopeRepresentation, error) { +func (g *GoCloak) GetScope(ctx context.Context, token, realm, idOfClient, scopeID string) (*ScopeRepresentation, error) { const errMessage = "could not get scope" var result ScopeRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", scopeID)) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", scopeID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3111,7 +3183,7 @@ func (client *gocloak) GetScope(ctx context.Context, token, realm, idOfClient, s } // GetScopes returns scopes associated with the client -func (client *gocloak) GetScopes(ctx context.Context, token, realm, idOfClient string, params GetScopeParams) ([]*ScopeRepresentation, error) { +func (g *GoCloak) GetScopes(ctx context.Context, token, realm, idOfClient string, params GetScopeParams) ([]*ScopeRepresentation, error) { const errMessage = "could not get scopes" queryParams, err := GetQueryParams(params) @@ -3119,10 +3191,10 @@ func (client *gocloak) GetScopes(ctx context.Context, token, realm, idOfClient s return nil, err } var result []*ScopeRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3132,14 +3204,14 @@ func (client *gocloak) GetScopes(ctx context.Context, token, realm, idOfClient s } // CreateScope creates a scope associated with the client -func (client *gocloak) CreateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) (*ScopeRepresentation, error) { +func (g *GoCloak) CreateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) (*ScopeRepresentation, error) { const errMessage = "could not create scope" var result ScopeRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(scope). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope")) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3149,38 +3221,38 @@ func (client *gocloak) CreateScope(ctx context.Context, token, realm, idOfClient } // UpdateScope updates a scope associated with the client -func (client *gocloak) UpdateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) error { +func (g *GoCloak) UpdateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) error { const errMessage = "could not update scope" if NilOrEmpty(scope.ID) { return errors.New("ID of a scope required") } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(scope). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", *(scope.ID))) + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", *(scope.ID))) return checkForError(resp, err, errMessage) } // DeleteScope deletes a scope associated with the client -func (client *gocloak) DeleteScope(ctx context.Context, token, realm, idOfClient, scopeID string) error { +func (g *GoCloak) DeleteScope(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not delete scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", scopeID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", scopeID)) return checkForError(resp, err, errMessage) } // GetPolicy returns a client's policy with the given id -func (client *gocloak) GetPolicy(ctx context.Context, token, realm, idOfClient, policyID string) (*PolicyRepresentation, error) { +func (g *GoCloak) GetPolicy(ctx context.Context, token, realm, idOfClient, policyID string) (*PolicyRepresentation, error) { const errMessage = "could not get policy" var result PolicyRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID)) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3190,7 +3262,7 @@ func (client *gocloak) GetPolicy(ctx context.Context, token, realm, idOfClient, } // GetPolicies returns policies associated with the client -func (client *gocloak) GetPolicies(ctx context.Context, token, realm, idOfClient string, params GetPolicyParams) ([]*PolicyRepresentation, error) { +func (g *GoCloak) GetPolicies(ctx context.Context, token, realm, idOfClient string, params GetPolicyParams) ([]*PolicyRepresentation, error) { const errMessage = "could not get policies" queryParams, err := GetQueryParams(params) @@ -3204,10 +3276,10 @@ func (client *gocloak) GetPolicies(ctx context.Context, token, realm, idOfClient } var result []*PolicyRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, path...)) + Get(g.getAdminRealmURL(realm, path...)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3217,7 +3289,7 @@ func (client *gocloak) GetPolicies(ctx context.Context, token, realm, idOfClient } // CreatePolicy creates a policy associated with the client -func (client *gocloak) CreatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) (*PolicyRepresentation, error) { +func (g *GoCloak) CreatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) (*PolicyRepresentation, error) { const errMessage = "could not create policy" if NilOrEmpty(policy.Type) { @@ -3225,10 +3297,10 @@ func (client *gocloak) CreatePolicy(ctx context.Context, token, realm, idOfClien } var result PolicyRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(policy). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", *(policy.Type))) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", *(policy.Type))) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3238,38 +3310,38 @@ func (client *gocloak) CreatePolicy(ctx context.Context, token, realm, idOfClien } // UpdatePolicy updates a policy associated with the client -func (client *gocloak) UpdatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) error { +func (g *GoCloak) UpdatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) error { const errMessage = "could not update policy" if NilOrEmpty(policy.ID) { return errors.New("ID of a policy required") } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(policy). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", *(policy.Type), *(policy.ID))) + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", *(policy.Type), *(policy.ID))) return checkForError(resp, err, errMessage) } // DeletePolicy deletes a policy associated with the client -func (client *gocloak) DeletePolicy(ctx context.Context, token, realm, idOfClient, policyID string) error { +func (g *GoCloak) DeletePolicy(ctx context.Context, token, realm, idOfClient, policyID string) error { const errMessage = "could not delete policy" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID)) return checkForError(resp, err, errMessage) } // GetAuthorizationPolicyAssociatedPolicies returns a client's associated policies of specific policy with the given policy id, using access token from admin -func (client *gocloak) GetAuthorizationPolicyAssociatedPolicies(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyRepresentation, error) { +func (g *GoCloak) GetAuthorizationPolicyAssociatedPolicies(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyRepresentation, error) { const errMessage = "could not get policy associated policies" var result []*PolicyRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "associatedPolicies")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "associatedPolicies")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3279,13 +3351,13 @@ func (client *gocloak) GetAuthorizationPolicyAssociatedPolicies(ctx context.Cont } // GetAuthorizationPolicyResources returns a client's resources of specific policy with the given policy id, using access token from admin -func (client *gocloak) GetAuthorizationPolicyResources(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyResourceRepresentation, error) { +func (g *GoCloak) GetAuthorizationPolicyResources(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyResourceRepresentation, error) { const errMessage = "could not get policy resources" var result []*PolicyResourceRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "resources")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "resources")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3295,13 +3367,13 @@ func (client *gocloak) GetAuthorizationPolicyResources(ctx context.Context, toke } // GetAuthorizationPolicyScopes returns a client's scopes of specific policy with the given policy id, using access token from admin -func (client *gocloak) GetAuthorizationPolicyScopes(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyScopeRepresentation, error) { +func (g *GoCloak) GetAuthorizationPolicyScopes(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyScopeRepresentation, error) { const errMessage = "could not get policy scopes" var result []*PolicyScopeRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "scopes")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "scopes")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3310,14 +3382,14 @@ func (client *gocloak) GetAuthorizationPolicyScopes(ctx context.Context, token, return result, nil } -// GetResourcePolicy updates a permission for a specifc resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange -func (client *gocloak) GetResourcePolicy(ctx context.Context, token, realm, permissionID string) (*ResourcePolicyRepresentation, error) { +// GetResourcePolicy updates a permission for a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange +func (g *GoCloak) GetResourcePolicy(ctx context.Context, token, realm, permissionID string) (*ResourcePolicyRepresentation, error) { const errMessage = "could not get resource policy" var result ResourcePolicyRepresentation - resp, err := client.getRequestWithBearerAuthNoCache(ctx, token). + resp, err := g.getRequestWithBearerAuthNoCache(ctx, token). SetResult(&result). - Get(client.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) + Get(g.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3327,7 +3399,7 @@ func (client *gocloak) GetResourcePolicy(ctx context.Context, token, realm, perm } // GetResourcePolicies returns resources associated with the client, using token obtained by Resource Owner Password Credentials Grant or Token exchange -func (client *gocloak) GetResourcePolicies(ctx context.Context, token, realm string, params GetResourcePoliciesParams) ([]*ResourcePolicyRepresentation, error) { +func (g *GoCloak) GetResourcePolicies(ctx context.Context, token, realm string, params GetResourcePoliciesParams) ([]*ResourcePolicyRepresentation, error) { const errMessage = "could not get resource policies" queryParams, err := GetQueryParams(params) @@ -3336,10 +3408,10 @@ func (client *gocloak) GetResourcePolicies(ctx context.Context, token, realm str } var result []*ResourcePolicyRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getRealmURL(realm, "authz", "protection", "uma-policy")) + Get(g.getRealmURL(realm, "authz", "protection", "uma-policy")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3348,15 +3420,15 @@ func (client *gocloak) GetResourcePolicies(ctx context.Context, token, realm str return result, nil } -// CreateResourcePolicy associates a permission with a specifc resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange -func (client *gocloak) CreateResourcePolicy(ctx context.Context, token, realm, resourceID string, policy ResourcePolicyRepresentation) (*ResourcePolicyRepresentation, error) { +// CreateResourcePolicy associates a permission with a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange +func (g *GoCloak) CreateResourcePolicy(ctx context.Context, token, realm, resourceID string, policy ResourcePolicyRepresentation) (*ResourcePolicyRepresentation, error) { const errMessage = "could not create resource policy" var result ResourcePolicyRepresentation - resp, err := client.getRequestWithBearerAuthNoCache(ctx, token). + resp, err := g.getRequestWithBearerAuthNoCache(ctx, token). SetResult(&result). SetBody(policy). - Post(client.getRealmURL(realm, "authz", "protection", "uma-policy", resourceID)) + Post(g.getRealmURL(realm, "authz", "protection", "uma-policy", resourceID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3365,35 +3437,35 @@ func (client *gocloak) CreateResourcePolicy(ctx context.Context, token, realm, r return &result, nil } -// UpdateResourcePolicy updates a permission for a specifc resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange -func (client *gocloak) UpdateResourcePolicy(ctx context.Context, token, realm, permissionID string, policy ResourcePolicyRepresentation) error { +// UpdateResourcePolicy updates a permission for a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange +func (g *GoCloak) UpdateResourcePolicy(ctx context.Context, token, realm, permissionID string, policy ResourcePolicyRepresentation) error { const errMessage = "could not update resource policy" - resp, err := client.getRequestWithBearerAuthNoCache(ctx, token). + resp, err := g.getRequestWithBearerAuthNoCache(ctx, token). SetBody(policy). - Put(client.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) + Put(g.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) return checkForError(resp, err, errMessage) } -// DeleteResourcePolicy deletes a permission for a specifc resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange -func (client *gocloak) DeleteResourcePolicy(ctx context.Context, token, realm, permissionID string) error { +// DeleteResourcePolicy deletes a permission for a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange +func (g *GoCloak) DeleteResourcePolicy(ctx context.Context, token, realm, permissionID string) error { const errMessage = "could not delete resource policy" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) return checkForError(resp, err, errMessage) } // GetPermission returns a client's permission with the given id -func (client *gocloak) GetPermission(ctx context.Context, token, realm, idOfClient, permissionID string) (*PermissionRepresentation, error) { +func (g *GoCloak) GetPermission(ctx context.Context, token, realm, idOfClient, permissionID string) (*PermissionRepresentation, error) { const errMessage = "could not get permission" var result PermissionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID)) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3403,13 +3475,13 @@ func (client *gocloak) GetPermission(ctx context.Context, token, realm, idOfClie } // GetDependentPermissions returns a client's permission with the given policy id -func (client *gocloak) GetDependentPermissions(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PermissionRepresentation, error) { +func (g *GoCloak) GetDependentPermissions(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PermissionRepresentation, error) { const errMessage = "could not get permission" var result []*PermissionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "dependentPolicies")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "dependentPolicies")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3418,14 +3490,14 @@ func (client *gocloak) GetDependentPermissions(ctx context.Context, token, realm return result, nil } -// GetPermissionResource returns a client's resource attached for the given permission id -func (client *gocloak) GetPermissionResources(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionResource, error) { +// GetPermissionResources returns a client's resource attached for the given permission id +func (g *GoCloak) GetPermissionResources(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionResource, error) { const errMessage = "could not get permission resource" var result []*PermissionResource - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID, "resources")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID, "resources")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3435,13 +3507,13 @@ func (client *gocloak) GetPermissionResources(ctx context.Context, token, realm, } // GetPermissionScopes returns a client's scopes configured for the given permission id -func (client *gocloak) GetPermissionScopes(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionScope, error) { +func (g *GoCloak) GetPermissionScopes(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionScope, error) { const errMessage = "could not get permission scopes" var result []*PermissionScope - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID, "scopes")) + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID, "scopes")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3451,7 +3523,7 @@ func (client *gocloak) GetPermissionScopes(ctx context.Context, token, realm, id } // GetPermissions returns permissions associated with the client -func (client *gocloak) GetPermissions(ctx context.Context, token, realm, idOfClient string, params GetPermissionParams) ([]*PermissionRepresentation, error) { +func (g *GoCloak) GetPermissions(ctx context.Context, token, realm, idOfClient string, params GetPermissionParams) ([]*PermissionRepresentation, error) { const errMessage = "could not get permissions" queryParams, err := GetQueryParams(params) @@ -3465,10 +3537,10 @@ func (client *gocloak) GetPermissions(ctx context.Context, token, realm, idOfCli } var result []*PermissionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, path...)) + Get(g.getAdminRealmURL(realm, path...)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3497,7 +3569,7 @@ func checkPermissionTicketParams(permissions []CreatePermissionTicketParams) err } // CreatePermissionTicket creates a permission ticket, using access token from client -func (client *gocloak) CreatePermissionTicket(ctx context.Context, token, realm string, permissions []CreatePermissionTicketParams) (*PermissionTicketResponseRepresentation, error) { +func (g *GoCloak) CreatePermissionTicket(ctx context.Context, token, realm string, permissions []CreatePermissionTicketParams) (*PermissionTicketResponseRepresentation, error) { const errMessage = "could not create permission ticket" err := checkPermissionTicketParams(permissions) @@ -3506,10 +3578,10 @@ func (client *gocloak) CreatePermissionTicket(ctx context.Context, token, realm } var result PermissionTicketResponseRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permissions). - Post(client.getRealmURL(realm, "authz", "protection", "permission")) + Post(g.getRealmURL(realm, "authz", "protection", "permission")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3533,8 +3605,8 @@ func checkPermissionGrantParams(permission PermissionGrantParams) error { return nil } -// GrantPermission lets resource owner grant permission for specific resource ID to specific user ID -func (client *gocloak) GrantUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) { +// GrantUserPermission lets resource owner grant permission for specific resource ID to specific user ID +func (g *GoCloak) GrantUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) { const errMessage = "could not grant user permission" err := checkPermissionGrantParams(permission) @@ -3546,10 +3618,10 @@ func (client *gocloak) GrantUserPermission(ctx context.Context, token, realm str var result PermissionGrantResponseRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permission). - Post(client.getRealmURL(realm, "authz", "protection", "permission", "ticket")) + Post(g.getRealmURL(realm, "authz", "protection", "permission", "ticket")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3571,7 +3643,8 @@ func checkPermissionUpdateParams(permission PermissionGrantParams) error { return nil } -func (client *gocloak) UpdateUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) { +// UpdateUserPermission updates user permissions. +func (g *GoCloak) UpdateUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) { const errMessage = "could not update user permission" err := checkPermissionUpdateParams(permission) @@ -3581,10 +3654,10 @@ func (client *gocloak) UpdateUserPermission(ctx context.Context, token, realm st var result PermissionGrantResponseRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permission). - Put(client.getRealmURL(realm, "authz", "protection", "permission", "ticket")) + Put(g.getRealmURL(realm, "authz", "protection", "permission", "ticket")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3597,8 +3670,8 @@ func (client *gocloak) UpdateUserPermission(ctx context.Context, token, realm st return &result, nil } -// GetUserPermission gets granted permissions according query parameters -func (client *gocloak) GetUserPermissions(ctx context.Context, token, realm string, params GetUserPermissionParams) ([]*PermissionGrantResponseRepresentation, error) { +// GetUserPermissions gets granted permissions according query parameters +func (g *GoCloak) GetUserPermissions(ctx context.Context, token, realm string, params GetUserPermissionParams) ([]*PermissionGrantResponseRepresentation, error) { const errMessage = "could not get user permissions" queryParams, err := GetQueryParams(params) @@ -3607,10 +3680,10 @@ func (client *gocloak) GetUserPermissions(ctx context.Context, token, realm stri } var result []*PermissionGrantResponseRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getRealmURL(realm, "authz", "protection", "permission", "ticket")) + Get(g.getRealmURL(realm, "authz", "protection", "permission", "ticket")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3619,17 +3692,18 @@ func (client *gocloak) GetUserPermissions(ctx context.Context, token, realm stri return result, nil } -func (client *gocloak) DeleteUserPermission(ctx context.Context, token, realm, ticketID string) error { +// DeleteUserPermission revokes permissions according query parameters +func (g *GoCloak) DeleteUserPermission(ctx context.Context, token, realm, ticketID string) error { const errMessage = "could not delete user permission" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getRealmURL(realm, "authz", "protection", "permission", "ticket", ticketID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getRealmURL(realm, "authz", "protection", "permission", "ticket", ticketID)) return checkForError(resp, err, errMessage) } // CreatePermission creates a permission associated with the client -func (client *gocloak) CreatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) (*PermissionRepresentation, error) { +func (g *GoCloak) CreatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) (*PermissionRepresentation, error) { const errMessage = "could not create permission" if NilOrEmpty(permission.Type) { @@ -3637,10 +3711,10 @@ func (client *gocloak) CreatePermission(ctx context.Context, token, realm, idOfC } var result PermissionRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permission). - Post(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", *(permission.Type))) + Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", *(permission.Type))) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3650,25 +3724,25 @@ func (client *gocloak) CreatePermission(ctx context.Context, token, realm, idOfC } // UpdatePermission updates a permission associated with the client -func (client *gocloak) UpdatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) error { +func (g *GoCloak) UpdatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) error { const errMessage = "could not update permission" if NilOrEmpty(permission.ID) { return errors.New("ID of a permission required") } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(permission). - Put(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", *permission.Type, *permission.ID)) + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", *permission.Type, *permission.ID)) return checkForError(resp, err, errMessage) } // DeletePermission deletes a policy associated with the client -func (client *gocloak) DeletePermission(ctx context.Context, token, realm, idOfClient, permissionID string) error { +func (g *GoCloak) DeletePermission(ctx context.Context, token, realm, idOfClient, permissionID string) error { const errMessage = "could not delete permission" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID)) return checkForError(resp, err, errMessage) } @@ -3678,13 +3752,13 @@ func (client *gocloak) DeletePermission(ctx context.Context, token, realm, idOfC // --------------- // GetCredentialRegistrators returns credentials registrators -func (client *gocloak) GetCredentialRegistrators(ctx context.Context, token, realm string) ([]string, error) { +func (g *GoCloak) GetCredentialRegistrators(ctx context.Context, token, realm string) ([]string, error) { const errMessage = "could not get user credential registrators" var result []string - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "credential-registrators")) + Get(g.getAdminRealmURL(realm, "credential-registrators")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3694,13 +3768,13 @@ func (client *gocloak) GetCredentialRegistrators(ctx context.Context, token, rea } // GetConfiguredUserStorageCredentialTypes returns credential types, which are provided by the user storage where user is stored -func (client *gocloak) GetConfiguredUserStorageCredentialTypes(ctx context.Context, token, realm, userID string) ([]string, error) { +func (g *GoCloak) GetConfiguredUserStorageCredentialTypes(ctx context.Context, token, realm, userID string) ([]string, error) { const errMessage = "could not get user credential registrators" var result []string - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "configured-user-storage-credential-types")) + Get(g.getAdminRealmURL(realm, "users", userID, "configured-user-storage-credential-types")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3710,13 +3784,13 @@ func (client *gocloak) GetConfiguredUserStorageCredentialTypes(ctx context.Conte } // GetCredentials returns credentials available for a given user -func (client *gocloak) GetCredentials(ctx context.Context, token, realm, userID string) ([]*CredentialRepresentation, error) { +func (g *GoCloak) GetCredentials(ctx context.Context, token, realm, userID string) ([]*CredentialRepresentation, error) { const errMessage = "could not get user credentials" var result []*CredentialRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "users", userID, "credentials")) + Get(g.getAdminRealmURL(realm, "users", userID, "credentials")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3726,60 +3800,60 @@ func (client *gocloak) GetCredentials(ctx context.Context, token, realm, userID } // DeleteCredentials deletes the given credential for a given user -func (client *gocloak) DeleteCredentials(ctx context.Context, token, realm, userID, credentialID string) error { +func (g *GoCloak) DeleteCredentials(ctx context.Context, token, realm, userID, credentialID string) error { const errMessage = "could not delete user credentials" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "users", userID, "credentials", credentialID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID)) return checkForError(resp, err, errMessage) } // UpdateCredentialUserLabel updates label for the given credential for the given user -func (client *gocloak) UpdateCredentialUserLabel(ctx context.Context, token, realm, userID, credentialID, userLabel string) error { +func (g *GoCloak) UpdateCredentialUserLabel(ctx context.Context, token, realm, userID, credentialID, userLabel string) error { const errMessage = "could not update credential label for a user" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetHeader("Content-Type", "text/plain"). SetBody(userLabel). - Put(client.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "userLabel")) + Put(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "userLabel")) return checkForError(resp, err, errMessage) } // DisableAllCredentialsByType disables all credentials for a user of a specific type -func (client *gocloak) DisableAllCredentialsByType(ctx context.Context, token, realm, userID string, types []string) error { +func (g *GoCloak) DisableAllCredentialsByType(ctx context.Context, token, realm, userID string, types []string) error { const errMessage = "could not update disable credentials" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(types). - Put(client.getAdminRealmURL(realm, "users", userID, "disable-credential-types")) + Put(g.getAdminRealmURL(realm, "users", userID, "disable-credential-types")) return checkForError(resp, err, errMessage) } // MoveCredentialBehind move a credential to a position behind another credential -func (client *gocloak) MoveCredentialBehind(ctx context.Context, token, realm, userID, credentialID, newPreviousCredentialID string) error { +func (g *GoCloak) MoveCredentialBehind(ctx context.Context, token, realm, userID, credentialID, newPreviousCredentialID string) error { const errMessage = "could not move credential" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Post(client.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "moveAfter", newPreviousCredentialID)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Post(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "moveAfter", newPreviousCredentialID)) return checkForError(resp, err, errMessage) } // MoveCredentialToFirst move a credential to a first position in the credentials list of the user -func (client *gocloak) MoveCredentialToFirst(ctx context.Context, token, realm, userID, credentialID string) error { +func (g *GoCloak) MoveCredentialToFirst(ctx context.Context, token, realm, userID, credentialID string) error { const errMessage = "could not move credential" - resp, err := client.getRequestWithBearerAuth(ctx, token). - Post(client.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "moveToFirst")) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Post(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "moveToFirst")) return checkForError(resp, err, errMessage) } // GetEvents returns events -func (client *gocloak) GetEvents(ctx context.Context, token string, realm string, params GetEventsParams) ([]*EventRepresentation, error) { +func (g *GoCloak) GetEvents(ctx context.Context, token string, realm string, params GetEventsParams) ([]*EventRepresentation, error) { const errMessage = "could not get events" queryParams, err := GetQueryParams(params) @@ -3788,10 +3862,10 @@ func (client *gocloak) GetEvents(ctx context.Context, token string, realm string } var result []*EventRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). - Get(client.getAdminRealmURL(realm, "events")) + Get(g.getAdminRealmURL(realm, "events")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3801,14 +3875,14 @@ func (client *gocloak) GetEvents(ctx context.Context, token string, realm string } // GetClientScopesScopeMappingsRealmRolesAvailable returns realm-level roles that are available to attach to this client scope -func (client *gocloak) GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, clientScopeID string) ([]*Role, error) { +func (g *GoCloak) GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, clientScopeID string) ([]*Role, error) { const errMessage = "could not get available realm-level roles with the client-scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm", "available")) + Get(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm", "available")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3818,14 +3892,14 @@ func (client *gocloak) GetClientScopesScopeMappingsRealmRolesAvailable(ctx conte } // GetClientScopesScopeMappingsRealmRoles returns roles associated with a client-scope -func (client *gocloak) GetClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string) ([]*Role, error) { +func (g *GoCloak) GetClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string) ([]*Role, error) { const errMessage = "could not get realm-level roles with the client-scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) + Get(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3835,34 +3909,34 @@ func (client *gocloak) GetClientScopesScopeMappingsRealmRoles(ctx context.Contex } // DeleteClientScopesScopeMappingsRealmRoles deletes realm-level roles from the client-scope -func (client *gocloak) DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error { +func (g *GoCloak) DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error { const errMessage = "could not delete realm-level roles from the client-scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) + Delete(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) return checkForError(resp, err, errMessage) } // CreateClientScopesScopeMappingsRealmRoles creates realm-level roles to the client scope -func (client *gocloak) CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error { +func (g *GoCloak) CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error { const errMessage = "could not create realm-level roles to the client-scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) + Post(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) return checkForError(resp, err, errMessage) } -// CreateRequiredAction creates a required action for a given realm -func (client *gocloak) RegisterRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error { +// RegisterRequiredAction creates a required action for a given realm +func (g *GoCloak) RegisterRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error { const errMessage = "could not create required action" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(requiredAction). - Post(client.getAdminRealmURL(realm, "authentication", "register-required-action")) + Post(g.getAdminRealmURL(realm, "authentication", "register-required-action")) if err := checkForError(resp, err, errMessage); err != nil { return err @@ -3872,13 +3946,13 @@ func (client *gocloak) RegisterRequiredAction(ctx context.Context, token string, } // GetRequiredActions gets a list of required actions for a given realm -func (client *gocloak) GetRequiredActions(ctx context.Context, token string, realm string) ([]*RequiredActionProviderRepresentation, error) { +func (g *GoCloak) GetRequiredActions(ctx context.Context, token string, realm string) ([]*RequiredActionProviderRepresentation, error) { const errMessage = "could not get required actions" var result []*RequiredActionProviderRepresentation - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "authentication", "required-actions")) + Get(g.getAdminRealmURL(realm, "authentication", "required-actions")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3888,7 +3962,7 @@ func (client *gocloak) GetRequiredActions(ctx context.Context, token string, rea } // GetRequiredAction gets a required action for a given realm -func (client *gocloak) GetRequiredAction(ctx context.Context, token string, realm string, alias string) (*RequiredActionProviderRepresentation, error) { +func (g *GoCloak) GetRequiredAction(ctx context.Context, token string, realm string, alias string) (*RequiredActionProviderRepresentation, error) { const errMessage = "could not get required action" var result RequiredActionProviderRepresentation @@ -3896,9 +3970,9 @@ func (client *gocloak) GetRequiredAction(ctx context.Context, token string, real return nil, errors.New("alias is required for getting a required action") } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "authentication", "required-actions", alias)) + Get(g.getAdminRealmURL(realm, "authentication", "required-actions", alias)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3908,28 +3982,28 @@ func (client *gocloak) GetRequiredAction(ctx context.Context, token string, real } // UpdateRequiredAction updates a required action for a given realm -func (client *gocloak) UpdateRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error { +func (g *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") } - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(requiredAction). - Put(client.getAdminRealmURL(realm, "authentication", "required-actions", *requiredAction.ProviderID)) + Put(g.getAdminRealmURL(realm, "authentication", "required-actions", *requiredAction.ProviderID)) return checkForError(resp, err, errMessage) } // DeleteRequiredAction updates a required action for a given realm -func (client *gocloak) DeleteRequiredAction(ctx context.Context, token string, realm string, alias string) error { +func (g *GoCloak) DeleteRequiredAction(ctx context.Context, token string, realm string, alias string) error { const errMessage = "could not delete required action" if alias == "" { return errors.New("alias is required for deleting a required action") } - resp, err := client.getRequestWithBearerAuth(ctx, token). - Delete(client.getAdminRealmURL(realm, "authentication", "required-actions", alias)) + resp, err := g.getRequestWithBearerAuth(ctx, token). + Delete(g.getAdminRealmURL(realm, "authentication", "required-actions", alias)) if err := checkForError(resp, err, errMessage); err != nil { return err @@ -3939,14 +4013,14 @@ func (client *gocloak) DeleteRequiredAction(ctx context.Context, token string, r } // CreateClientScopesScopeMappingsClientRoles attaches a client role to a client scope (not client's scope) -func (client *gocloak) CreateClientScopesScopeMappingsClientRoles( +func (g *GoCloak) CreateClientScopesScopeMappingsClientRoles( ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role, ) error { const errMessage = "could not create client-level roles to the client-scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Post(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) + Post(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) return checkForError(resp, err, errMessage) } @@ -3954,14 +4028,14 @@ func (client *gocloak) CreateClientScopesScopeMappingsClientRoles( // GetClientScopesScopeMappingsClientRolesAvailable returns available (i.e. not attached via // CreateClientScopesScopeMappingsClientRoles) client roles for a specific client, for a client scope // (not client's scope). -func (client *gocloak) GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) { +func (g *GoCloak) GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) { const errMessage = "could not get available client-level roles with the client-scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient, "available")) + Get(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient, "available")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3972,14 +4046,14 @@ func (client *gocloak) GetClientScopesScopeMappingsClientRolesAvailable(ctx cont // GetClientScopesScopeMappingsClientRoles returns attached client roles for a specific client, for a client scope // (not client's scope). -func (client *gocloak) GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) { +func (g *GoCloak) GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) { const errMessage = "could not get client-level roles with the client-scope" var result []*Role - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). - Get(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) + Get(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) if err := checkForError(resp, err, errMessage); err != nil { return nil, err @@ -3990,12 +4064,12 @@ func (client *gocloak) GetClientScopesScopeMappingsClientRoles(ctx context.Conte // DeleteClientScopesScopeMappingsClientRoles removes attachment of client roles from a client scope // (not client's scope). -func (client *gocloak) DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error { +func (g *GoCloak) DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error { const errMessage = "could not delete client-level roles from the client-scope" - resp, err := client.getRequestWithBearerAuth(ctx, token). + resp, err := g.getRequestWithBearerAuth(ctx, token). SetBody(roles). - Delete(client.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) + Delete(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) return checkForError(resp, err, errMessage) } diff --git a/client_benchmark_test.go b/client_benchmark_test.go index e097fbd8..cbd3ebab 100644 --- a/client_benchmark_test.go +++ b/client_benchmark_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/Nerzal/gocloak/v11" + "github.com/Nerzal/gocloak/v12" "github.com/stretchr/testify/assert" ) diff --git a/client_test.go b/client_test.go index 941569b5..1312cd86 100644 --- a/client_test.go +++ b/client_test.go @@ -26,7 +26,7 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/pkcs12" - "github.com/Nerzal/gocloak/v11" + "github.com/Nerzal/gocloak/v12" ) type configAdmin struct { @@ -92,7 +92,7 @@ func GetConfig(t testing.TB) *Config { return config } -func GetClientToken(t *testing.T, client gocloak.GoCloak) *gocloak.JWT { +func GetClientToken(t *testing.T, client *gocloak.GoCloak) *gocloak.JWT { cfg := GetConfig(t) token, err := client.LoginClient( context.Background(), @@ -103,7 +103,7 @@ func GetClientToken(t *testing.T, client gocloak.GoCloak) *gocloak.JWT { return token } -func GetUserToken(t *testing.T, client gocloak.GoCloak) *gocloak.JWT { +func GetUserToken(t *testing.T, client *gocloak.GoCloak) *gocloak.JWT { SetUpTestUser(t, client) cfg := GetConfig(t) token, err := client.Login( @@ -117,7 +117,7 @@ func GetUserToken(t *testing.T, client gocloak.GoCloak) *gocloak.JWT { return token } -func GetAdminToken(t testing.TB, client gocloak.GoCloak) *gocloak.JWT { +func GetAdminToken(t testing.TB, client *gocloak.GoCloak) *gocloak.JWT { cfg := GetConfig(t) token, err := client.LoginAdmin( context.Background(), @@ -140,7 +140,7 @@ func GetRandomNameP(name string) *string { return &r } -func GetClientByClientID(t *testing.T, client gocloak.GoCloak, clientID string) *gocloak.Client { +func GetClientByClientID(t *testing.T, client *gocloak.GoCloak, clientID string) *gocloak.Client { cfg := GetConfig(t) token := GetAdminToken(t, client) clients, err := client.GetClients( @@ -163,7 +163,7 @@ func GetClientByClientID(t *testing.T, client gocloak.GoCloak, clientID string) return nil } -func CreateGroup(t *testing.T, client gocloak.GoCloak) (func(), string) { +func CreateGroup(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) group := gocloak.Group{ @@ -192,7 +192,7 @@ func CreateGroup(t *testing.T, client gocloak.GoCloak) (func(), string) { return tearDown, groupID } -func CreateResource(t *testing.T, client gocloak.GoCloak, idOfClient string) (func(), string) { +func CreateResource(t *testing.T, client *gocloak.GoCloak, idOfClient string) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) resource := gocloak.ResourceRepresentation{ @@ -231,7 +231,7 @@ func CreateResource(t *testing.T, client gocloak.GoCloak, idOfClient string) (fu return tearDown, *createdResource.ID } -func CreateResourceClientWithScopes(t *testing.T, client gocloak.GoCloak) (func(), string) { +func CreateResourceClientWithScopes(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetClientToken(t, client) resource := gocloak.ResourceRepresentation{ @@ -275,7 +275,7 @@ func CreateResourceClientWithScopes(t *testing.T, client gocloak.GoCloak) (func( return tearDown, *createdResource.ID } -func CreateResourceClient(t *testing.T, client gocloak.GoCloak) (func(), string) { +func CreateResourceClient(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetClientToken(t, client) resource := gocloak.ResourceRepresentation{ @@ -312,7 +312,7 @@ func CreateResourceClient(t *testing.T, client gocloak.GoCloak) (func(), string) return tearDown, *createdResource.ID } -func CreateScope(t *testing.T, client gocloak.GoCloak, idOfClient string) (func(), string) { +func CreateScope(t *testing.T, client *gocloak.GoCloak, idOfClient string) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) scope := gocloak.ScopeRepresentation{ @@ -341,7 +341,7 @@ func CreateScope(t *testing.T, client gocloak.GoCloak, idOfClient string) (func( return tearDown, *createdScope.ID } -func CreatePolicy(t *testing.T, client gocloak.GoCloak, idOfClient string, policy gocloak.PolicyRepresentation) (func(), string) { +func CreatePolicy(t *testing.T, client *gocloak.GoCloak, idOfClient string, policy gocloak.PolicyRepresentation) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) createdPolicy, err := client.CreatePolicy( @@ -366,7 +366,7 @@ func CreatePolicy(t *testing.T, client gocloak.GoCloak, idOfClient string, polic return tearDown, *createdPolicy.ID } -func CreatePermission(t *testing.T, client gocloak.GoCloak, idOfClient string, permission gocloak.PermissionRepresentation) (func(), string) { +func CreatePermission(t *testing.T, client *gocloak.GoCloak, idOfClient string, permission gocloak.PermissionRepresentation) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) createdPermission, err := client.CreatePermission( @@ -390,10 +390,10 @@ func CreatePermission(t *testing.T, client gocloak.GoCloak, idOfClient string, p return tearDown, *createdPermission.ID } -func CreateClient(t *testing.T, client gocloak.GoCloak, newClient *gocloak.Client) (func(), string) { +func CreateClient(t *testing.T, client *gocloak.GoCloak, newClient *gocloak.Client) (func(), string) { if newClient == nil { newClient = &gocloak.Client{ - ClientID: GetRandomNameP("CliendID"), + ClientID: GetRandomNameP("ClientID"), Name: GetRandomNameP("Name"), BaseURL: gocloak.StringP("http://example.com"), } @@ -418,7 +418,7 @@ func CreateClient(t *testing.T, client gocloak.GoCloak, newClient *gocloak.Clien return tearDown, createdID } -func SetUpTestUser(t testing.TB, client gocloak.GoCloak) { +func SetUpTestUser(t testing.TB, client *gocloak.GoCloak) { setupOnce.Do(func() { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -490,7 +490,7 @@ func (w *RestyLogWriter) write(format string, v ...interface{}) { w.t.Logf(format, v...) } -func NewClientWithDebug(t testing.TB) gocloak.GoCloak { +func NewClientWithDebug(t testing.TB) *gocloak.GoCloak { cfg := GetConfig(t) client := gocloak.NewClient(cfg.HostName) cond := func(resp *resty.Response, err error) bool { @@ -532,7 +532,7 @@ func NewClientWithDebug(t testing.TB) gocloak.GoCloak { // err - returned error or nil to return the default error // failN - number of requests to be failed // skipN = number of requests to be executed and not failed by this function -func FailRequest(client gocloak.GoCloak, err error, failN, skipN int) gocloak.GoCloak { +func FailRequest(client *gocloak.GoCloak, err error, failN, skipN int) *gocloak.GoCloak { client.RestyClient().OnBeforeRequest( func(c *resty.Client, r *resty.Request) error { if skipN > 0 { @@ -552,7 +552,7 @@ func FailRequest(client gocloak.GoCloak, err error, failN, skipN int) gocloak.Go return client } -func ClearRealmCache(t testing.TB, client gocloak.GoCloak, realm ...string) { +func ClearRealmCache(t testing.TB, client *gocloak.GoCloak, realm ...string) { cfg := GetConfig(t) token := GetAdminToken(t, client) if len(realm) == 0 { @@ -574,14 +574,14 @@ func ClearRealmCache(t testing.TB, client gocloak.GoCloak, realm ...string) { // ----- func Test_RestyClient(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) restyClient := client.RestyClient() require.NotEqual(t, restyClient, resty.New()) } func Test_SetRestyClient(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) newRestyClient := resty.New() client.SetRestyClient(newRestyClient) @@ -590,7 +590,7 @@ func Test_SetRestyClient(t *testing.T) { } func Test_checkForError(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) FailRequest(client, nil, 1, 0) _, err := client.Login(context.Background(), "", "", "", "", "") @@ -603,7 +603,7 @@ func Test_checkForError(t *testing.T) { // --------- func Test_GetServerInfo(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) // client.RestyClient().SetDebug(true) token := GetAdminToken(t, client) @@ -623,7 +623,7 @@ func Test_GetServerInfo(t *testing.T) { } func Test_GetUserInfo(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -644,7 +644,7 @@ func Test_GetUserInfo(t *testing.T) { } func Test_GetRawUserInfo(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -660,7 +660,7 @@ func Test_GetRawUserInfo(t *testing.T) { } func Test_RetrospectRequestingPartyToken(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -683,7 +683,7 @@ func Test_RetrospectRequestingPartyToken(t *testing.T) { "Fake Resource", }, }) - require.Error(t, err, "GetRequestingPartyToken failed") + require.Error(t, err, "GetRequestingPartyToken must fail with Fake resource") require.Nil(t, rpt) rpt, err = client.GetRequestingPartyToken( @@ -716,7 +716,7 @@ func Test_RetrospectRequestingPartyToken(t *testing.T) { } func Test_GetRequestingPartyPermissions(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -762,7 +762,7 @@ func Test_GetRequestingPartyPermissions(t *testing.T) { } func Test_GetRequestingPartyPermissionDecision(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -800,7 +800,7 @@ func Test_GetRequestingPartyPermissionDecision(t *testing.T) { } func Test_GetCerts(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) certs, err := client.GetCerts(context.Background(), cfg.GoCloak.Realm) @@ -809,7 +809,7 @@ func Test_GetCerts(t *testing.T) { } func Test_LoginClient_UnknownRealm(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) _, err := client.LoginClient( @@ -822,7 +822,7 @@ func Test_LoginClient_UnknownRealm(t *testing.T) { } func Test_GetIssuer(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) issuer, err := client.GetIssuer(context.Background(), cfg.GoCloak.Realm) @@ -831,7 +831,7 @@ func Test_GetIssuer(t *testing.T) { } func Test_RetrospectToken_InactiveToken(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) @@ -847,7 +847,7 @@ func Test_RetrospectToken_InactiveToken(t *testing.T) { } func Test_RetrospectToken(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -864,7 +864,7 @@ func Test_RetrospectToken(t *testing.T) { } func Test_DecodeAccessToken(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -897,7 +897,7 @@ func Test_DecodeAccessTokenCustomClaims(t *testing.T) { } func Test_RefreshToken(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -914,7 +914,7 @@ func Test_RefreshToken(t *testing.T) { } func Test_UserAttributeContains(t *testing.T) { - // t.Parallel() + t.Parallel() attributes := map[string][]string{} attributes["foo"] = []string{"bar", "alice", "bob", "roflcopter"} @@ -925,7 +925,7 @@ func Test_UserAttributeContains(t *testing.T) { } func Test_GetKeyStoreConfig(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -939,7 +939,7 @@ func Test_GetKeyStoreConfig(t *testing.T) { } func Test_Login(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -954,7 +954,7 @@ func Test_Login(t *testing.T) { } func Test_LoginSignedJWT(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) keystore := filepath.Join("testdata", "keystore.p12") f, err := os.Open(keystore) @@ -1001,7 +1001,7 @@ func Test_LoginSignedJWT(t *testing.T) { func Test_LoginOtp(t *testing.T) { totp := "123456" - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -1018,7 +1018,7 @@ func Test_LoginOtp(t *testing.T) { } func Test_GetToken(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -1084,7 +1084,7 @@ func Test_GetRequestingPartyToken(t *testing.T) { } func Test_LoginClient(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) _, err := client.LoginClient( @@ -1096,7 +1096,7 @@ func Test_LoginClient(t *testing.T) { } func Test_LoginAdmin(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) _, err := client.LoginAdmin( @@ -1108,7 +1108,7 @@ func Test_LoginAdmin(t *testing.T) { } func Test_SetPassword(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1127,7 +1127,7 @@ func Test_SetPassword(t *testing.T) { } func Test_CreateListGetUpdateDeleteGetChildGroup(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1194,7 +1194,7 @@ func Test_CreateListGetUpdateDeleteGetChildGroup(t *testing.T) { require.NoError(t, err, "GetGroup failed") } -func CreateClientRole(t *testing.T, client gocloak.GoCloak) (func(), string) { +func CreateClientRole(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -1225,14 +1225,14 @@ func CreateClientRole(t *testing.T, client gocloak.GoCloak) (func(), string) { } func Test_CreateClientRole(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDown, _ := CreateClientRole(t, client) tearDown() } func Test_GetClientRole(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDown, roleName := CreateClientRole(t, client) defer tearDown() @@ -1269,7 +1269,7 @@ func Test_GetClientRole(t *testing.T) { require.Nil(t, role) } -func CreateClientScope(t *testing.T, client gocloak.GoCloak, scope *gocloak.ClientScope) (func(), string) { +func CreateClientScope(t *testing.T, client *gocloak.GoCloak, scope *gocloak.ClientScope) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -1304,13 +1304,13 @@ func CreateClientScope(t *testing.T, client gocloak.GoCloak, scope *gocloak.Clie } func Test_CreateClientScope_DeleteClientScope(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDown, _ := CreateClientScope(t, client, nil) tearDown() } -func CreateUpdateClientScopeProtocolMapper(t *testing.T, client gocloak.GoCloak, scopeID string, protocolMapper *gocloak.ProtocolMappers) (func(), string) { +func CreateUpdateClientScopeProtocolMapper(t *testing.T, client *gocloak.GoCloak, scopeID string, protocolMapper *gocloak.ProtocolMappers) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -1370,7 +1370,7 @@ func CreateUpdateClientScopeProtocolMapper(t *testing.T, client gocloak.GoCloak, } func Test_CreateClientScopeProtocolMapper_DeleteClientScopeProtocolMapper(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1392,7 +1392,7 @@ func Test_CreateClientScopeProtocolMapper_DeleteClientScopeProtocolMapper(t *tes } func Test_ListAddRemoveDefaultClientScopes(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1457,7 +1457,7 @@ func Test_ListAddRemoveDefaultClientScopes(t *testing.T) { } func Test_ListAddRemoveOptionalClientScopes(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1516,7 +1516,7 @@ func Test_ListAddRemoveOptionalClientScopes(t *testing.T) { } func Test_GetDefaultOptionalClientScopes(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1532,7 +1532,7 @@ func Test_GetDefaultOptionalClientScopes(t *testing.T) { } func Test_GetDefaultDefaultClientScopes(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1547,7 +1547,7 @@ func Test_GetDefaultDefaultClientScopes(t *testing.T) { } func Test_GetClientScope(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1568,7 +1568,7 @@ func Test_GetClientScope(t *testing.T) { } func Test_GetClientScopes(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1584,7 +1584,7 @@ func Test_GetClientScopes(t *testing.T) { } func Test_GetClientScopeProtocolMappers(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1603,7 +1603,7 @@ func Test_GetClientScopeProtocolMappers(t *testing.T) { require.NotNil(t, protocolMappers) } -func CreateClientScopeMappingsRealmRoles(t *testing.T, client gocloak.GoCloak, idOfClient string, roles []gocloak.Role) func() { +func CreateClientScopeMappingsRealmRoles(t *testing.T, client *gocloak.GoCloak, idOfClient string, roles []gocloak.Role) func() { token := GetAdminToken(t, client) cfg := GetConfig(t) @@ -1630,7 +1630,7 @@ func CreateClientScopeMappingsRealmRoles(t *testing.T, client gocloak.GoCloak, i return tearDown } -func CreateClientScopeMappingsClientRoles(t *testing.T, client gocloak.GoCloak, idOfClient, clients string, roles []gocloak.Role) func() { +func CreateClientScopeMappingsClientRoles(t *testing.T, client *gocloak.GoCloak, idOfClient, clients string, roles []gocloak.Role) func() { token := GetAdminToken(t, client) cfg := GetConfig(t) @@ -1660,7 +1660,7 @@ func CreateClientScopeMappingsClientRoles(t *testing.T, client gocloak.GoCloak, } func Test_ClientScopeMappingsClientRoles(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1738,7 +1738,7 @@ func Test_ClientScopeMappingsClientRoles(t *testing.T) { } func Test_ClientScopeMappingsRealmRoles(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -1813,7 +1813,7 @@ func Test_ClientScopeMappingsRealmRoles(t *testing.T) { } func CreateClientScopesMappingsClientRoles( - t *testing.T, client gocloak.GoCloak, scopeID, idOfClient string, roles []gocloak.Role, + t *testing.T, client *gocloak.GoCloak, scopeID, idOfClient string, roles []gocloak.Role, ) func() { token := GetAdminToken(t, client) cfg := GetConfig(t) @@ -1919,7 +1919,7 @@ func Test_ClientScopesMappingsClientRoles(t *testing.T) { } func Test_CreateListGetUpdateDeleteClient(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2015,25 +2015,34 @@ func Test_CreateListGetUpdateDeleteClient(t *testing.T) { } func Test_CreateListGetUpdateDeleteClientRepresentation(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) + token := GetClientToken(t, client) + testClient := gocloak.Client{ + ClientID: GetRandomNameP("gocloak-client-secret-client-id-"), + } + ctx := context.Background() // Creating a client representation - createdClient, err := client.CreateClientRepresentation(context.Background(), cfg.GoCloak.Realm) + createdClient, err := client.CreateClientRepresentation(ctx, token.AccessToken, cfg.GoCloak.Realm, testClient) require.NoError(t, err, "CreateClientRepresentation failed") - t.Logf("Client ID: %s", gocloak.PString(createdClient.ID)) + t.Logf( + "Client ID: %s, ID: %s", + gocloak.PString(createdClient.ClientID), + gocloak.PString(createdClient.ID), + ) // Get the created client representation gotClient, err := client.GetClientRepresentation( context.Background(), gocloak.PString(createdClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.NoError(t, err, "GetClientRepresentation failed") - require.Equal(t, gocloak.PString(createdClient.ID), gocloak.PString(gotClient.ID)) + require.Equal(t, gocloak.PString(createdClient.ClientID), gocloak.PString(gotClient.ClientID)) // Updating the client representation @@ -2062,7 +2071,7 @@ func Test_CreateListGetUpdateDeleteClientRepresentation(t *testing.T) { context.Background(), gocloak.PString(updatedClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.NoError(t, err, "GetClientRepresentation failed") require.Equal(t, gocloak.PString(createdClient.Name), gocloak.PString(gotClient.Name)) @@ -2072,7 +2081,7 @@ func Test_CreateListGetUpdateDeleteClientRepresentation(t *testing.T) { context.Background(), gocloak.PString(gotClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.NoError(t, err, "DeleteClientRepresentation failed") @@ -2081,28 +2090,32 @@ func Test_CreateListGetUpdateDeleteClientRepresentation(t *testing.T) { context.Background(), gocloak.PString(gotClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.Error(t, err, "Should fail because the deleted client doesn't exist anymore") } func Test_GetAdapterConfigurationForClientRepresentation(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) + token := GetClientToken(t, client) + testClient := gocloak.Client{ + ClientID: GetRandomNameP("gocloak-client-secret-client-id-"), + } // Creating a client representation - createdClient, err := client.CreateClientRepresentation(context.Background(), cfg.GoCloak.Realm) + createdClient, err := client.CreateClientRepresentation(context.Background(), token.AccessToken, cfg.GoCloak.Realm, testClient) require.NoError(t, err, "CreateClientRepresentation failed") - t.Logf("Client ID: %s", gocloak.PString(createdClient.ID)) + t.Logf("Client ID: %s", gocloak.PString(createdClient.ClientID)) // Get the created client representation gotClient, err := client.GetClientRepresentation( context.Background(), gocloak.PString(createdClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.NoError(t, err, "GetClientRepresentation failed") require.Equal(t, gocloak.PString(createdClient.ID), gocloak.PString(gotClient.ID)) @@ -2112,17 +2125,17 @@ func Test_GetAdapterConfigurationForClientRepresentation(t *testing.T) { context.Background(), gocloak.PString(gotClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.NoError(t, err, "GetAdapterConfiguration failed") - require.Equal(t, gocloak.PString(gotClient.ID), gocloak.PString(adapterConfig.Resource)) + require.Equal(t, gocloak.PString(gotClient.ClientID), gocloak.PString(adapterConfig.Resource)) // Deleting the client representation err = client.DeleteClientRepresentation( context.Background(), gocloak.PString(gotClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.NoError(t, err, "DeleteClientRepresentation failed") @@ -2131,13 +2144,13 @@ func Test_GetAdapterConfigurationForClientRepresentation(t *testing.T) { context.Background(), gocloak.PString(gotClient.RegistrationAccessToken), cfg.GoCloak.Realm, - gocloak.PString(createdClient.ID), + gocloak.PString(createdClient.ClientID), ) require.Error(t, err, "Should fail because the deleted client doesn't exist anymore") } func Test_GetGroups(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2151,7 +2164,7 @@ func Test_GetGroups(t *testing.T) { } func Test_GetGroupsFull(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2184,7 +2197,7 @@ func Test_GetGroupsFull(t *testing.T) { } func Test_GetGroupsBriefRepresentation(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2258,7 +2271,7 @@ func Test_GetGroupsByClientRole(t *testing.T) { } func Test_GetGroupFull(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2280,7 +2293,7 @@ func Test_GetGroupFull(t *testing.T) { } func Test_GetGroupMembers(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2311,7 +2324,7 @@ func Test_GetGroupMembers(t *testing.T) { } func Test_ListAddRemoveDefaultGroups(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2360,7 +2373,7 @@ func Test_ListAddRemoveDefaultGroups(t *testing.T) { } func Test_GetClientRoles(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2377,7 +2390,7 @@ func Test_GetClientRoles(t *testing.T) { } func Test_GetRoleMappingByGroupID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2394,7 +2407,7 @@ func Test_GetRoleMappingByGroupID(t *testing.T) { } func Test_GetRoleMappingByUserID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2437,8 +2450,34 @@ func Test_ExecuteActionsEmail_UpdatePassword(t *testing.T) { } } +func Test_SendVerifyEmail(t *testing.T) { + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + tearDown, userID := CreateUser(t, client) + defer tearDown() + + params := gocloak.SendVerificationMailParams{ + ClientID: &(cfg.GoCloak.ClientID), + } + + err := client.SendVerifyEmail( + context.Background(), + token.AccessToken, + userID, + cfg.GoCloak.Realm, + params) + if err != nil { + if err.Error() == "500 Internal Server Error: Failed to send execute actions email" { + return + } + require.NoError(t, err, "ExecuteActionsEmail failed") + } +} + func Test_Logout(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetUserToken(t, client) @@ -2453,7 +2492,7 @@ func Test_Logout(t *testing.T) { } func Test_LogoutAllSessions(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2471,7 +2510,7 @@ func Test_LogoutAllSessions(t *testing.T) { } func Test_RevokeUserConsents(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -2503,7 +2542,7 @@ func Test_RevokeUserConsents(t *testing.T) { } func Test_LogoutUserSession(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) uToken := GetUserToken(t, client) @@ -2519,7 +2558,7 @@ func Test_LogoutUserSession(t *testing.T) { } func Test_GetRealm(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2533,7 +2572,7 @@ func Test_GetRealm(t *testing.T) { } func Test_GetRealms(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2549,7 +2588,7 @@ func Test_GetRealms(t *testing.T) { // Realm // ----------- -func CreateRealm(t *testing.T, client gocloak.GoCloak) (func(), string) { +func CreateRealm(t *testing.T, client *gocloak.GoCloak) (func(), string) { token := GetAdminToken(t, client) realmName := GetRandomName("Realm") @@ -2588,14 +2627,14 @@ func CreateRealm(t *testing.T, client gocloak.GoCloak) (func(), string) { } func Test_CreateRealm(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDown, _ := CreateRealm(t, client) defer tearDown() } func Test_UpdateRealm(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2617,7 +2656,7 @@ func Test_UpdateRealm(t *testing.T) { } func Test_ClearRealmCache(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) ClearRealmCache(t, client) } @@ -2626,7 +2665,7 @@ func Test_ClearRealmCache(t *testing.T) { // Realm Roles // ----------- -func CreateRealmRole(t *testing.T, client gocloak.GoCloak) (func(), string) { +func CreateRealmRole(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -2654,14 +2693,14 @@ func CreateRealmRole(t *testing.T, client gocloak.GoCloak) (func(), string) { } func Test_CreateRealmRole(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDown, _ := CreateRealmRole(t, client) defer tearDown() } func Test_GetRealmRole(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2684,7 +2723,7 @@ func Test_GetRealmRole(t *testing.T) { } func Test_GetRealmRoles(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2702,7 +2741,7 @@ func Test_GetRealmRoles(t *testing.T) { } func Test_UpdateRealmRole(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2738,7 +2777,7 @@ func Test_UpdateRealmRole(t *testing.T) { } func Test_DeleteRealmRole(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2754,7 +2793,7 @@ func Test_DeleteRealmRole(t *testing.T) { } func Test_AddRealmRoleToUser_DeleteRealmRoleFromUser(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2790,7 +2829,7 @@ func Test_AddRealmRoleToUser_DeleteRealmRoleFromUser(t *testing.T) { } func Test_AddRealmRoleToGroup_DeleteRealmRoleFromGroup(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2826,7 +2865,7 @@ func Test_AddRealmRoleToGroup_DeleteRealmRoleFromGroup(t *testing.T) { } func Test_GetRealmRolesByUserID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2890,7 +2929,7 @@ func Test_GetRealmRolesByUserID(t *testing.T) { } func Test_GetRealmRolesByGroupID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2930,7 +2969,7 @@ func Test_GetRealmRolesByGroupID(t *testing.T) { } func Test_AddRealmRoleComposite_DeleteRealmRoleComposite(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -2972,7 +3011,7 @@ func Test_AddRealmRoleComposite_DeleteRealmRoleComposite(t *testing.T) { // Users // ----- -func CreateUser(t *testing.T, client gocloak.GoCloak) (func(), string) { +func CreateUser(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -3009,7 +3048,7 @@ func CreateUser(t *testing.T, client gocloak.GoCloak) (func(), string) { } func Test_CreateUser(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDown, _ := CreateUser(t, client) @@ -3017,7 +3056,7 @@ func Test_CreateUser(t *testing.T) { } func Test_CreateUserCustomAttributes(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3040,7 +3079,7 @@ func Test_CreateUserCustomAttributes(t *testing.T) { } func Test_GetUserByID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3058,7 +3097,7 @@ func Test_GetUserByID(t *testing.T) { } func Test_GetUsers(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3075,7 +3114,7 @@ func Test_GetUsers(t *testing.T) { } func Test_GetUserCount(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3091,7 +3130,7 @@ func Test_GetUserCount(t *testing.T) { } func Test_GetGroupsCount(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3106,7 +3145,7 @@ func Test_GetGroupsCount(t *testing.T) { } func Test_AddUserToGroup(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3127,7 +3166,7 @@ func Test_AddUserToGroup(t *testing.T) { } func Test_DeleteUserFromGroup(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3155,7 +3194,7 @@ func Test_DeleteUserFromGroup(t *testing.T) { } func Test_GetUserGroups(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3186,7 +3225,7 @@ func Test_GetUserGroups(t *testing.T) { } func Test_DeleteUser(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDown, _ := CreateUser(t, client) @@ -3194,7 +3233,7 @@ func Test_DeleteUser(t *testing.T) { } func Test_UpdateUser(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3217,7 +3256,7 @@ func Test_UpdateUser(t *testing.T) { } func Test_UpdateUserSetEmptyRequiredActions(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3267,7 +3306,7 @@ func Test_UpdateUserSetEmptyRequiredActions(t *testing.T) { } func Test_UpdateUserSetEmptyEmail(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3299,7 +3338,7 @@ func Test_UpdateUserSetEmptyEmail(t *testing.T) { } func Test_GetUsersByRoleName(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3337,7 +3376,7 @@ func Test_GetUsersByRoleName(t *testing.T) { } func Test_GetUsersByClientRoleName(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3355,7 +3394,7 @@ func Test_GetUsersByClientRoleName(t *testing.T) { gocloakClientID, roleName) require.NoError(t, err) - err = client.AddClientRoleToUser( + err = client.AddClientRolesToUser( context.Background(), token.AccessToken, cfg.GoCloak.Realm, @@ -3378,7 +3417,7 @@ func Test_GetUsersByClientRoleName(t *testing.T) { } func Test_GetUserSessions(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -3406,7 +3445,7 @@ func Test_GetUserSessions(t *testing.T) { } func Test_GetUserOfflineSessionsForClient(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -3437,7 +3476,7 @@ func Test_GetUserOfflineSessionsForClient(t *testing.T) { } func Test_GetClientUserSessions(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -3478,7 +3517,7 @@ func findProtocolMapperByID(t *testing.T, client *gocloak.Client, id string) *go } func Test_CreateUpdateDeleteClientProtocolMapper(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) id := GetRandomName("protocol-mapper-id-") @@ -3576,7 +3615,7 @@ func Test_CreateUpdateDeleteClientProtocolMapper(t *testing.T) { } func Test_GetClientOfflineSessions(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -3606,7 +3645,7 @@ func Test_GetClientOfflineSessions(t *testing.T) { } func Test_ClientSecret(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3657,7 +3696,7 @@ func Test_ClientSecret(t *testing.T) { } func Test_ClientServiceAccount(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3677,7 +3716,7 @@ func Test_ClientServiceAccount(t *testing.T) { } func Test_AddClientRoleToUser_DeleteClientRoleFromUser(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -3703,7 +3742,7 @@ func Test_AddClientRoleToUser_DeleteClientRoleFromUser(t *testing.T) { ) require.NoError(t, err, "GetClientRole failed") roles := []gocloak.Role{*role1, *role2} - err = client.AddClientRoleToUser( + err = client.AddClientRolesToUser( context.Background(), token.AccessToken, cfg.GoCloak.Realm, @@ -3713,7 +3752,7 @@ func Test_AddClientRoleToUser_DeleteClientRoleFromUser(t *testing.T) { ) require.NoError(t, err, "AddClientRoleToUser failed") - err = client.DeleteClientRoleFromUser( + err = client.DeleteClientRolesFromUser( context.Background(), token.AccessToken, cfg.GoCloak.Realm, @@ -3725,7 +3764,7 @@ func Test_AddClientRoleToUser_DeleteClientRoleFromUser(t *testing.T) { } func Test_GetClientRolesByUserID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3742,7 +3781,7 @@ func Test_GetClientRolesByUserID(t *testing.T) { roleName) require.NoError(t, err) - err = client.AddClientRoleToUser( + err = client.AddClientRolesToUser( context.Background(), token.AccessToken, cfg.GoCloak.Realm, @@ -3792,7 +3831,7 @@ func Test_GetClientRolesByUserID(t *testing.T) { } func Test_GetAvailableClientRolesByUserID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3820,7 +3859,7 @@ func Test_GetAvailableClientRolesByUserID(t *testing.T) { roleName2) require.NoError(t, err) - err = client.AddClientRoleToUser( + err = client.AddClientRolesToUser( context.Background(), token.AccessToken, cfg.GoCloak.Realm, @@ -3870,7 +3909,7 @@ func Test_GetAvailableClientRolesByUserID(t *testing.T) { } func Test_GetAvailableRealmRolesByUserID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3943,7 +3982,7 @@ func Test_GetAvailableRealmRolesByUserID(t *testing.T) { } func Test_GetAvailableClientRolesByGroupID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -3971,7 +4010,7 @@ func Test_GetAvailableClientRolesByGroupID(t *testing.T) { roleName2) require.NoError(t, err) - err = client.AddClientRoleToGroup( + err = client.AddClientRolesToGroup( context.Background(), token.AccessToken, cfg.GoCloak.Realm, @@ -4021,7 +4060,7 @@ func Test_GetAvailableClientRolesByGroupID(t *testing.T) { } func Test_GetAvailableRealmRolesByGroupID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -4095,7 +4134,7 @@ func Test_GetAvailableRealmRolesByGroupID(t *testing.T) { } func Test_GetClientRolesByGroupID(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -4121,7 +4160,7 @@ func Test_GetClientRolesByGroupID(t *testing.T) { } func Test_AddClientRoleToGroup_DeleteClientRoleFromGroup(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) SetUpTestUser(t, client) @@ -4151,7 +4190,7 @@ func Test_AddClientRoleToGroup_DeleteClientRoleFromGroup(t *testing.T) { defer tearDownGroup() roles := []gocloak.Role{*role1, *role2} - err = client.AddClientRoleToGroup( + err = client.AddClientRolesToGroup( context.Background(), token.AccessToken, cfg.GoCloak.Realm, @@ -4173,7 +4212,7 @@ func Test_AddClientRoleToGroup_DeleteClientRoleFromGroup(t *testing.T) { } func Test_AddDeleteClientRoleComposite(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -4233,7 +4272,7 @@ func Test_AddDeleteClientRoleComposite(t *testing.T) { } func Test_AddDeleteRealmRoleComposite(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -4434,7 +4473,7 @@ func Test_CreateGetDeleteUserFederatedIdentity(t *testing.T) { } func Test_CreateDeleteClientScopeWithMappers(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -4740,7 +4779,7 @@ func Test_CreateProvider(t *testing.T) { // ----------------- func Test_ErrorsCreateListGetUpdateDeleteResourceClient(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -4790,7 +4829,7 @@ func Test_ErrorsCreateListGetUpdateDeleteResourceClient(t *testing.T) { } func Test_CreateListGetUpdateDeleteResourceClient(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -4855,7 +4894,7 @@ func Test_CreateListGetUpdateDeleteResourceClient(t *testing.T) { } func Test_CreateListGetUpdateDeleteResource(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -4924,7 +4963,7 @@ func Test_CreateListGetUpdateDeleteResource(t *testing.T) { } func Test_CreateListGetUpdateDeleteScope(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -4992,7 +5031,7 @@ func Test_CreateListGetUpdateDeleteScope(t *testing.T) { } func Test_CreateListGetUpdateDeletePolicy(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -5001,10 +5040,12 @@ func Test_CreateListGetUpdateDeletePolicy(t *testing.T) { tearDown, policyID := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ Name: GetRandomNameP("PolicyName"), Description: gocloak.StringP("Policy Description"), - Type: gocloak.StringP("js"), + Type: gocloak.StringP("client"), Logic: gocloak.NEGATIVE, - JSPolicyRepresentation: gocloak.JSPolicyRepresentation{ - Code: gocloak.StringP("$evaluation.grant();"), + ClientPolicyRepresentation: gocloak.ClientPolicyRepresentation{ + Clients: &[]string{ + gocloakClientID, + }, }, }) // Delete @@ -5045,7 +5086,7 @@ func Test_CreateListGetUpdateDeletePolicy(t *testing.T) { gocloakClientID, gocloak.GetPolicyParams{ Name: createdPolicy.Name, - Type: gocloak.StringP("js"), + Type: gocloak.StringP("client"), }, ) require.NoError(t, err, "GetPolicies failed") @@ -5074,8 +5115,10 @@ func Test_CreateListGetUpdateDeletePolicy(t *testing.T) { Description: createdPolicy.Description, Type: createdPolicy.Type, Logic: createdPolicy.Logic, - JSPolicyRepresentation: gocloak.JSPolicyRepresentation{ - Code: gocloak.StringP("$evaluation.grant();"), + ClientPolicyRepresentation: gocloak.ClientPolicyRepresentation{ + Clients: &[]string{ + gocloakClientID, + }, }, }, ) @@ -5521,7 +5564,7 @@ func Test_CreateGetUpdateDeleteResourcePolicy(t *testing.T) { } func Test_RolePolicy(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -5553,26 +5596,8 @@ func Test_RolePolicy(t *testing.T) { defer tearDown() } -func Test_JSPolicy(t *testing.T) { - // t.Parallel() - client := NewClientWithDebug(t) - - // Create - tearDown, _ := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ - Name: GetRandomNameP("PolicyName"), - Description: gocloak.StringP("JS Policy"), - Type: gocloak.StringP("js"), - Logic: gocloak.POSITIVE, - JSPolicyRepresentation: gocloak.JSPolicyRepresentation{ - Code: gocloak.StringP("$evaluation.grant();"), - }, - }) - // Delete - defer tearDown() -} - func Test_ClientPolicy(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) // Create @@ -5591,7 +5616,7 @@ func Test_ClientPolicy(t *testing.T) { } func Test_TimePolicy(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) // Create @@ -5619,7 +5644,7 @@ func Test_TimePolicy(t *testing.T) { } func Test_UserPolicy(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDownUser, userID := CreateUser(t, client) @@ -5641,7 +5666,7 @@ func Test_UserPolicy(t *testing.T) { } func Test_AggregatedPolicy(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDownClient, clientPolicyID := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ @@ -5656,17 +5681,19 @@ func Test_AggregatedPolicy(t *testing.T) { }) defer tearDownClient() - tearDownJS, jsPolicyID := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ + tearDownClient1, clientPolicyID1 := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ Name: GetRandomNameP("PolicyName"), Description: gocloak.StringP("JS Policy"), - Type: gocloak.StringP("js"), + Type: gocloak.StringP("client"), Logic: gocloak.POSITIVE, - JSPolicyRepresentation: gocloak.JSPolicyRepresentation{ - Code: gocloak.StringP("$evaluation.grant();"), + ClientPolicyRepresentation: gocloak.ClientPolicyRepresentation{ + Clients: &[]string{ + gocloakClientID, + }, }, }) // Delete - defer tearDownJS() + defer tearDownClient1() // Create tearDown, _ := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ @@ -5676,7 +5703,7 @@ func Test_AggregatedPolicy(t *testing.T) { AggregatedPolicyRepresentation: gocloak.AggregatedPolicyRepresentation{ Policies: &[]string{ clientPolicyID, - jsPolicyID, + clientPolicyID1, }, }, }) @@ -5685,7 +5712,7 @@ func Test_AggregatedPolicy(t *testing.T) { } func Test_GroupPolicy(t *testing.T) { - // t.Parallel() + t.Parallel() client := NewClientWithDebug(t) tearDownGroup, groupID := CreateGroup(t, client) @@ -5709,7 +5736,7 @@ func Test_GroupPolicy(t *testing.T) { } func Test_ErrorsGrantGetUpdateDeleteUserPermission(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -5774,7 +5801,7 @@ func Test_ErrorsGrantGetUpdateDeleteUserPermission(t *testing.T) { } func Test_GrantGetUpdateDeleteUserPermission(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -5871,7 +5898,7 @@ func Test_GrantGetUpdateDeleteUserPermission(t *testing.T) { } func Test_BadCreatePermissionTicket(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -5907,7 +5934,7 @@ func Test_BadCreatePermissionTicket(t *testing.T) { } func Test_CreatePermissionTicket(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetClientToken(t, client) @@ -5951,7 +5978,7 @@ func Test_CreatePermissionTicket(t *testing.T) { } func Test_CreateListGetUpdateDeletePermission(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -5963,11 +5990,13 @@ func Test_CreateListGetUpdateDeletePermission(t *testing.T) { tearDownPolicy, policyID := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ Name: GetRandomNameP("PolicyName"), - Description: gocloak.StringP("JS Policy"), - Type: gocloak.StringP("js"), + Description: gocloak.StringP("Client Policy"), + Type: gocloak.StringP("client"), Logic: gocloak.POSITIVE, - JSPolicyRepresentation: gocloak.JSPolicyRepresentation{ - Code: gocloak.StringP("$evaluation.grant();"), + ClientPolicyRepresentation: gocloak.ClientPolicyRepresentation{ + Clients: &[]string{ + gocloakClientID, + }, }, }) // Delete @@ -6081,7 +6110,7 @@ func Test_CreateListGetUpdateDeletePermission(t *testing.T) { } func Test_CheckError(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -6111,7 +6140,7 @@ func Test_CheckError(t *testing.T) { // --------------- func Test_GetCredentialRegistrators(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -6126,7 +6155,7 @@ func Test_GetCredentialRegistrators(t *testing.T) { } func Test_GetConfiguredUserStorageCredentialTypes(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -6143,7 +6172,7 @@ func Test_GetConfiguredUserStorageCredentialTypes(t *testing.T) { } func Test_GetUpdateLableDeleteCredentials(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -6212,7 +6241,7 @@ func Test_GetUpdateLableDeleteCredentials(t *testing.T) { func Test_DisableAllCredentialsByType(t *testing.T) { // NOTE(svilgelm): I didn't find a way how to properly test this function, // so the test validates that the API call doesn't return an error. - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -6229,7 +6258,7 @@ func Test_DisableAllCredentialsByType(t *testing.T) { } func Test_TestSetFunctionalOptions(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) gocloak.NewClient(cfg.HostName, gocloak.SetAuthRealms("foo"), gocloak.SetAuthAdminRealms("bar")) @@ -6268,7 +6297,7 @@ func Test_GetClientsWithPagination(t *testing.T) { } func Test_ImportIdentityProviderConfig(t *testing.T) { - // t.Parallel() + t.Parallel() cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) @@ -6363,6 +6392,7 @@ E8go1LcvbfHNyknHu2sptnRq55fHZSHr18vVsQRfDYMG "addExtensionsElementWithKeyInfo": "false", "loginHint": "false", "enabledFromMetadata": "true", + "idpEntityId": "https://accounts.google.com/o/saml2?idpid=C01unc9st", } require.Len( @@ -6610,7 +6640,7 @@ func TestGocloak_UpdateRequiredAction(t *testing.T) { require.NoError(t, err, "Failed to update required action") } -func CreateComponent(t *testing.T, client gocloak.GoCloak) (func(), *gocloak.Component) { +func CreateComponent(t *testing.T, client *gocloak.GoCloak) (func(), *gocloak.Component) { newComponent := &gocloak.Component{ Name: GetRandomNameP("CreateComponent"), ProviderID: gocloak.StringP("rsa-generated"), diff --git a/docker-compose.yml b/docker-compose.yml index d0b25ac5..4f02c3e4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,13 +2,16 @@ version: '3' services: keycloak: - image: jboss/keycloak:latest - command: -Dkeycloak.profile.feature.upload_scripts=enabled + build: . + command: -Dauto-build -Dfeatures=preview environment: - KEYCLOAK_IMPORT: /tmp/gocloak-realm.json KEYCLOAK_USER: admin KEYCLOAK_PASSWORD: secret + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: secret ports: - "8080:8080" volumes: - - ./testdata/gocloak-realm.json:/tmp/gocloak-realm.json \ No newline at end of file + - ./testdata/gocloak-realm.json:/opt/keycloak/data/import/gocloak-realm.json + entrypoint: ["/opt/keycloak/bin/kc.sh", "start-dev --features=preview --import-realm"] + \ No newline at end of file diff --git a/go.mod b/go.mod index d3a67f2f..3359f49d 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,20 @@ -module github.com/Nerzal/gocloak/v11 +module github.com/Nerzal/gocloak/v12 -go 1.15 +go 1.18 require ( github.com/go-resty/resty/v2 v2.7.0 - github.com/golang-jwt/jwt/v4 v4.4.1 + github.com/golang-jwt/jwt/v4 v4.4.2 github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 github.com/segmentio/ksuid v1.0.4 - github.com/stretchr/testify v1.7.1 - golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f - golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + github.com/stretchr/testify v1.8.0 + golang.org/x/crypto v0.0.0-20221012134737-56aed061732a +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/net v0.0.0-20221019024206-cb67ada4b0ad // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 7f4ec501..01590474 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,10 @@ -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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ= -github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -13,26 +14,23 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc= -golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= +golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20221019024206-cb67ada4b0ad h1:Zx6wVVDwwNJFWXNIvDi7o952w3/1ckSwYk/7eykRmjM= +golang.org/x/net v0.0.0-20221019024206-cb67ada4b0ad/go.mod h1:RpDiru2p0u2F0lLpEoqnP2+7xs0ifAuOcJ442g6GU2s= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gocloak.go b/gocloak.go deleted file mode 100644 index 75dccc30..00000000 --- a/gocloak.go +++ /dev/null @@ -1,547 +0,0 @@ -package gocloak - -import ( - "context" - "io" - - "github.com/go-resty/resty/v2" - "github.com/golang-jwt/jwt/v4" -) - -// GoCloak holds all methods a client should fulfill -type GoCloak interface { - // RestyClient returns a resty client that gocloak uses - RestyClient() *resty.Client - // Sets the resty Client that gocloak uses - SetRestyClient(restyClient *resty.Client) - - // GetToken returns a token - GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error) - // GetRequestingPartyToken returns a requesting party token with permissions granted by the server - GetRequestingPartyToken(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*JWT, error) - // GetRequestingPartyPermissions returns a permissions granted by the server to requesting party - GetRequestingPartyPermissions(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*[]RequestingPartyPermission, error) - // GetRequestingPartyPermissionDecision returns a permission decision granted by the server to requesting party - GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error) - // Login sends a request to the token endpoint using user and client credentials - Login(ctx context.Context, clientID, clientSecret, realm, username, password string) (*JWT, error) - // LoginOtp performs a login with user credentials and otp token - LoginOtp(ctx context.Context, clientID, clientSecret, realm, username, password, totp string) (*JWT, error) - // Logout sends a request to the logout endpoint using refresh token - Logout(ctx context.Context, clientID, clientSecret, realm, refreshToken string) error - // LogoutPublicClient sends a request to the logout endpoint using refresh token - LogoutPublicClient(ctx context.Context, idOfClient, realm, accessToken, refreshToken string) error - // LogoutAllSessions logs out all sessions of a user given an id - LogoutAllSessions(ctx context.Context, accessToken, realm, userID string) error - // RevokeConsents revoke consent and offline tokens for particular client from user - RevokeUserConsents(ctx context.Context, accessToken, realm, userID, clientID string) error - // LogoutUserSessions logs out a single sessions of a user given a session id. - // NOTE: this uses bearer token, but this token must belong to a user with proper privileges - LogoutUserSession(ctx context.Context, accessToken, realm, session string) error - // LoginClient sends a request to the token endpoint using client credentials - LoginClient(ctx context.Context, clientID, clientSecret, realm string) (*JWT, error) - // LoginClientTokenExchange requests a login on a specified users behalf. Returning a user's tokens. - LoginClientTokenExchange(ctx context.Context, clientID, token, clientSecret, realm, targetClient, userID string) (*JWT, error) - // LoginClientSignedJWT performs a login with client credentials and signed jwt claims - LoginClientSignedJWT(ctx context.Context, idOfClient, realm string, key interface{}, signedMethod jwt.SigningMethod, expiresAt *jwt.NumericDate) (*JWT, error) - // LoginAdmin login as admin - LoginAdmin(ctx context.Context, username, password, realm string) (*JWT, error) - // RefreshToken used to refresh the token - RefreshToken(ctx context.Context, refreshToken, clientID, clientSecret, realm string) (*JWT, error) - // DecodeAccessToken decodes the accessToken - DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error) - // DecodeAccessTokenCustomClaims decodes the accessToken and fills the given claims - DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) - // RetrospectToken calls the openid-connect introspect endpoint - RetrospectToken(ctx context.Context, accessToken, clientID, clientSecret, realm string) (*RetrospecTokenResult, error) - // GetIssuer calls the issuer endpoint for the given realm - GetIssuer(ctx context.Context, realm string) (*IssuerResponse, error) - // GetCerts gets the public keys for the given realm - GetCerts(ctx context.Context, realm string) (*CertResponse, error) - // GetServerInfo returns the server info - GetServerInfo(ctx context.Context, accessToken string) (*ServerInfoRepesentation, error) - // GetUserInfo gets the user info for the given realm - GetUserInfo(ctx context.Context, accessToken, realm string) (*UserInfo, error) - // GetRawUserInfo calls the UserInfo endpoint and returns a raw json object - GetRawUserInfo(ctx context.Context, accessToken, realm string) (map[string]interface{}, error) - - // ExecuteActionsEmail executes an actions email - ExecuteActionsEmail(ctx context.Context, token, realm string, params ExecuteActionsEmail) error - - // CreateGroup creates a new group - CreateGroup(ctx context.Context, accessToken, realm string, group Group) (string, error) - // CreateChildGroup creates a new child group - CreateChildGroup(ctx context.Context, token, realm, groupID string, group Group) (string, error) - // CreateClient creates a new client - CreateClient(ctx context.Context, accessToken, realm string, newClient Client) (string, error) - // CreateClientScope creates a new clientScope - CreateClientScope(ctx context.Context, accessToken, realm string, scope ClientScope) (string, error) - // CreateClientScopeProtocolMapper creates a new protocolMapper under the given client scope - CreateClientScopeProtocolMapper(ctx context.Context, accessToken, realm, scopeID string, protocolMapper ProtocolMappers) (string, error) - // CreateComponent creates a new component - CreateComponent(ctx context.Context, accessToken, realm string, component Component) (string, error) - // CreateClientScopeMappingsRealmRoles creates realm-level roles to the client’s scope - CreateClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error - // CreateClientScopeMappingsClientRoles creates client-level roles from the client’s scope - CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error - // CreateClientScopesScopeMappingsRealmRoles creates realm-level roles to the client-scope - CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string, roles []Role) error - // CreateClientScopesScopeMappingsClientRoles creates client-level roles to the client-scope - CreateClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error - // CreateClientRepresentation creates a new client representation - CreateClientRepresentation(ctx context.Context, realm string) (*Client, error) - - // UpdateGroup updates the given group - UpdateGroup(ctx context.Context, accessToken, realm string, updatedGroup Group) error - // UpdateRole updates the given role - UpdateRole(ctx context.Context, accessToken, realm, idOfClient string, role Role) error - // UpdateClient updates the given client - UpdateClient(ctx context.Context, accessToken, realm string, updatedClient Client) error - // UpdateClientScope updates the given clientScope - UpdateClientScope(ctx context.Context, accessToken, realm string, scope ClientScope) error - // UpdateClientScopeProtocolMapper updates the given protocol mapper for a client scope - UpdateClientScopeProtocolMapper(ctx context.Context, accessToken, realm, scopeID string, protocolMapper ProtocolMappers) error - // UpdateClientRepresentation updates the given client representation - UpdateClientRepresentation(ctx context.Context, accessToken, realm string, updatedClient Client) (*Client, error) - - // DeleteComponent deletes the given component - DeleteComponent(ctx context.Context, accessToken, realm, componentID string) error - // DeleteGroup deletes the given group - DeleteGroup(ctx context.Context, accessToken, realm, groupID string) error - // DeleteClient deletes the given client - DeleteClient(ctx context.Context, accessToken, realm, idOfClient string) error - // DeleteClientScope - DeleteClientScope(ctx context.Context, accessToken, realm, scopeID string) error - // DeleteClientScopeProtocolMapper deletes the given protocol mapper from the client scope - DeleteClientScopeProtocolMapper(ctx context.Context, accessToken, realm, scopeID, protocolMapperID string) error - // DeleteClientScopeMappingsRealmRoles deletes realm-level roles from the client’s scope - DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error - // DeleteClientScopeMappingsClientRoles deletes client-level roles from the client’s scope - DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error - // DeleteClientScopesScopeMappingsRealmRoles deletes realm-level roles from the client-scope - DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string, roles []Role) error - // DeleteClientScopesScopeMappingsClientRoles deletes client-level roles from the client-scope - DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, ifOfClient string, roles []Role) error - // DeleteClientRepresentation deletes a given client representation - DeleteClientRepresentation(ctx context.Context, accessToken, realm, clientID string) error - - // GetClient returns a client - GetClient(ctx context.Context, accessToken, realm, idOfClient string) (*Client, error) - // GetClientsDefaultScopes returns a list of the client's default scopes - GetClientsDefaultScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) - // AddDefaultScopeToClient adds a client scope to the list of client's default scopes - AddDefaultScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - // RemoveDefaultScopeFromClient removes a client scope from the list of client's default scopes - RemoveDefaultScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - // GetClientsOptionalScopes returns a list of the client's optional scopes - GetClientsOptionalScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) - // AddOptionalScopeToClient adds a client scope to the list of client's optional scopes - AddOptionalScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - // RemoveOptionalScopeFromClient deletes a client scope from the list of client's optional scopes - RemoveOptionalScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - // GetDefaultOptionalClientScopes returns a list of default realm optional scopes - GetDefaultOptionalClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) - // GetDefaultDefaultClientScopes returns a list of default realm default scopes - GetDefaultDefaultClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) - // GetClientScope returns a clientscope - GetClientScope(ctx context.Context, token, realm, scopeID string) (*ClientScope, error) - // GetClientScopes returns all client scopes - GetClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) - // GetClientScopeProtocolMappers returns all protocol mappers of a client scope - GetClientScopeProtocolMappers(ctx context.Context, token, realm, scopeID string) ([]*ProtocolMappers, error) - // GetClientScopeProtocolMapper returns a protocol mapper of a client scope - GetClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) (*ProtocolMappers, error) - // GetClientScopeMappings returns all scope mappings for the client - GetClientScopeMappings(ctx context.Context, token, realm, idOfClient string) (*MappingsRepresentation, error) - // GetClientScopeMappingsRealmRoles returns realm-level roles associated with the client’s scope - GetClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) - // GetClientScopeMappingsRealmRolesAvailable returns realm-level roles that are available to attach to this client’s scope - GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) - // GetClientScopesScopeMappingsRealmRolesAvailable returns realm-level roles that are available to attach to this client-scope - GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) - // GetClientScopesScopeMappingsClientRolesAvailable returns client-level roles that are available to attach to this client-scope - GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) - // GetClientScopeMappingsClientRoles returns roles associated with a client’s scope - GetClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) - // GetClientScopesScopeMappingsRealmRoles returns roles associated with a client-scope - GetClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) - // GetClientScopesScopeMappingsClientRoles returns client roles associated with a client-scope - GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) - // GetClientScopeMappingsClientRolesAvailable returns available roles associated with a client’s scope - GetClientScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) - // GetClientSecret returns a client's secret - GetClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) - // GetClientServiceAccount retrieves the service account "user" for a client if enabled - GetClientServiceAccount(ctx context.Context, token, realm, idOfClient string) (*User, error) - // RegenerateClientSecret creates a new client secret returning the updated CredentialRepresentation - RegenerateClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) - // GetKeyStoreConfig gets the keyStoreConfig - GetKeyStoreConfig(ctx context.Context, accessToken, realm string) (*KeyStoreConfig, error) - // GetComponents gets components of the given realm - GetComponents(ctx context.Context, accessToken, realm string) ([]*Component, error) - // GetComponentsWithParams get all components in realm with query params - GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error) - // GetComponent get exactly one component by ID - GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error) - // UpdateComponent updates the given component - UpdateComponent(ctx context.Context, token, realm string, component Component) error - // GetDefaultGroups returns a list of default groups - GetDefaultGroups(ctx context.Context, accessToken, realm string) ([]*Group, error) - // AddDefaultGroup adds group to the list of default groups - AddDefaultGroup(ctx context.Context, accessToken, realm, groupID string) error - // RemoveDefaultGroup removes group from the list of default groups - RemoveDefaultGroup(ctx context.Context, accessToken, realm, groupID string) error - // GetGroups gets all groups of the given realm - GetGroups(ctx context.Context, accessToken, realm string, params GetGroupsParams) ([]*Group, error) - // GetGroupsByRole gets groups with specified roles assigned of given realm - GetGroupsByRole(ctx context.Context, accessToken, realm string, roleName string) ([]*Group, error) - // GetGroupsByClientRole gets groups with specified roles assigned of given client within a realm - GetGroupsByClientRole(ctx context.Context, accessToken, realm string, roleName string, clientID string) ([]*Group, error) - // GetGroupsCount gets groups count of the given realm - GetGroupsCount(ctx context.Context, token, realm string, params GetGroupsParams) (int, error) - // GetGroup gets the given group - GetGroup(ctx context.Context, accessToken, realm, groupID string) (*Group, error) - // GetGroupByPath get group with path in realm - GetGroupByPath(ctx context.Context, token, realm, groupPath string) (*Group, error) - // GetGroupMembers get a list of users of group with id in realm - GetGroupMembers(ctx context.Context, accessToken, realm, groupID string, params GetGroupsParams) ([]*User, error) - // GetRoleMappingByGroupID gets the rolemapping for the given group id - GetRoleMappingByGroupID(ctx context.Context, accessToken, realm, groupID string) (*MappingsRepresentation, error) - // GetRoleMappingByUserID gets the rolemapping for the given user id - GetRoleMappingByUserID(ctx context.Context, accessToken, realm, userID string) (*MappingsRepresentation, error) - // GetClients gets the clients in the realm - GetClients(ctx context.Context, accessToken, realm string, params GetClientsParams) ([]*Client, error) - // GetClientOfflineSessions returns offline sessions associated with the client - GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) - // GetClientUserSessions returns user sessions associated with the client - GetClientUserSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) - // CreateClientProtocolMapper creates a protocol mapper in client scope - CreateClientProtocolMapper(ctx context.Context, token, realm, idOfClient string, mapper ProtocolMapperRepresentation) (string, error) - // CreateClientProtocolMapper updates a protocol mapper in client scope - UpdateClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string, mapper ProtocolMapperRepresentation) error - // DeleteClientProtocolMapper deletes a protocol mapper in client scope - DeleteClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string) error - // GetClientRepresentation return a client representation - GetClientRepresentation(ctx context.Context, accessToken, realm, clientID string) (*Client, error) - // GetAdapterConfiguration returns a adapter configuration - GetAdapterConfiguration(ctx context.Context, accessToken, realm, clientID string) (*AdapterConfiguration, error) - - // *** Realm Roles *** - - // CreateRealmRole creates a role in a realm - CreateRealmRole(ctx context.Context, token, realm string, role Role) (string, error) - // GetRealmRole returns a role from a realm by role's name - GetRealmRole(ctx context.Context, token, realm, roleName string) (*Role, error) - // GetRealmRoleByID returns a role from a realm by role's ID - GetRealmRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) - // GetRealmRoles get all roles of the given realm. It's an alias for the GetRoles function - GetRealmRoles(ctx context.Context, accessToken, realm string, params GetRoleParams) ([]*Role, error) - // GetRealmRolesByUserID returns all roles assigned to the given user - GetRealmRolesByUserID(ctx context.Context, accessToken, realm, userID string) ([]*Role, error) - // GetRealmRolesByGroupID returns all roles assigned to the given group - GetRealmRolesByGroupID(ctx context.Context, accessToken, realm, groupID string) ([]*Role, error) - // UpdateRealmRole updates a role in a realm - UpdateRealmRole(ctx context.Context, token, realm, roleName string, role Role) error - // UpdateRealmRoleByID updates a role in a realm by role's ID - UpdateRealmRoleByID(ctx context.Context, token, realm, roleID string, role Role) error - // DeleteRealmRole deletes a role in a realm by role's name - DeleteRealmRole(ctx context.Context, token, realm, roleName string) error - // AddRealmRoleToUser adds realm-level role mappings - AddRealmRoleToUser(ctx context.Context, token, realm, userID string, roles []Role) error - // DeleteRealmRoleFromUser deletes realm-level role mappings - DeleteRealmRoleFromUser(ctx context.Context, token, realm, userID string, roles []Role) error - // AddRealmRoleToGroup adds realm-level role mappings - AddRealmRoleToGroup(ctx context.Context, token, realm, groupID string, roles []Role) error - // DeleteRealmRoleFromGroup deletes realm-level role mappings - DeleteRealmRoleFromGroup(ctx context.Context, token, realm, groupID string, roles []Role) error - // AddRealmRoleComposite adds roles as composite - AddRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error - // AddRealmRoleComposite adds roles as composite - DeleteRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error - // GetCompositeRealmRoles returns all realm composite roles associated with the given realm role - GetCompositeRealmRoles(ctx context.Context, token, realm, roleName string) ([]*Role, error) - // GetCompositeRolesByRoleID returns all realm composite roles associated with the given client role - GetCompositeRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) - // GetCompositeRealmRolesByRoleID returns all realm composite roles associated with the given client role - GetCompositeRealmRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) - // GetCompositeRealmRolesByUserID returns all realm roles and composite roles assigned to the given user - GetCompositeRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) - // GetCompositeRealmRolesByGroupID returns all realm roles and composite roles assigned to the given group - GetCompositeRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) - // GetAvailableRealmRolesByUserID returns all available realm roles to the given user - GetAvailableRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) - // GetAvailableRealmRolesByGroupID returns all available realm roles to the given group - GetAvailableRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) - - // *** Client Roles *** - - // AddClientRoleToUser adds a client role to the user - AddClientRoleToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error - // AddClientRoleToGroup adds a client role to the group - AddClientRoleToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error - // CreateClientRole creates a new role for a client - CreateClientRole(ctx context.Context, accessToken, realm, idOfClient string, role Role) (string, error) - // DeleteClientRole deletes the given role - DeleteClientRole(ctx context.Context, accessToken, realm, idOfClient, roleName string) error - // DeleteClientRoleFromUser removes a client role from from the user - DeleteClientRoleFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error - // DeleteClientRoleFromGroup removes a client role from from the group - DeleteClientRoleFromGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error - // GetClientRoles gets roles for the given client - GetClientRoles(ctx context.Context, accessToken, realm, idOfClient string, params GetRoleParams) ([]*Role, error) - // GetClientRoleById gets role for the given client using role id - GetClientRoleByID(ctx context.Context, accessToken, realm, roleID string) (*Role, error) - // GetRealmRolesByUserID returns all client roles assigned to the given user - GetClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) - // GetClientRolesByGroupID returns all client roles assigned to the given group - GetClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) - // GetCompositeClientRolesByRoleID returns all client composite roles associated with the given client role - GetCompositeClientRolesByRoleID(ctx context.Context, token, realm, idOfClient, roleID string) ([]*Role, error) - // GetCompositeClientRolesByUserID returns all client roles and composite roles assigned to the given user - GetCompositeClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) - // GetCompositeClientRolesByGroupID returns all client roles and composite roles assigned to the given group - GetCompositeClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) - // GetAvailableClientRolesByUserID returns all available client roles to the given user - GetAvailableClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) - // GetAvailableClientRolesByGroupID returns all available client roles to the given group - GetAvailableClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) - - // GetClientRole get a role for the given client in a realm by role name - GetClientRole(ctx context.Context, token, realm, idOfClient, roleName string) (*Role, error) - // AddClientRoleComposite adds roles as composite - AddClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error - // DeleteClientRoleComposite deletes composites from a role - DeleteClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error - - // *** Realm *** - - // GetRealm returns top-level representation of the realm - GetRealm(ctx context.Context, token, realm string) (*RealmRepresentation, error) - // GetRealms returns top-level representation of all realms - GetRealms(ctx context.Context, token string) ([]*RealmRepresentation, error) - // CreateRealm creates a realm - CreateRealm(ctx context.Context, token string, realm RealmRepresentation) (string, error) - // UpdateRealm updates a given realm - UpdateRealm(ctx context.Context, token string, realm RealmRepresentation) error - // DeleteRealm removes a realm - DeleteRealm(ctx context.Context, token, realm string) error - // ClearRealmCache clears realm cache - ClearRealmCache(ctx context.Context, token, realm string) error - // ClearUserCache clears realm cache - ClearUserCache(ctx context.Context, token, realm string) error - // ClearKeysCache clears realm cache - ClearKeysCache(ctx context.Context, token, realm string) error - // GetAuthenticationFlows get all authentication flows from a realm - GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) - // Create a new Authentication flow in a realm - CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error - // DeleteAuthenticationFlow deletes a flow in a realm with the given ID - DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error - // GetAuthenticationExecutions retrieves all executions of a given flow - GetAuthenticationExecutions(ctx context.Context, token, realm, flow string) ([]*ModifyAuthenticationExecutionRepresentation, error) - // CreateAuthenticationExecution creates a new execution for the given flow name in the given realm - CreateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionRepresentation) error - // UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm - UpdateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution ModifyAuthenticationExecutionRepresentation) error - // 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) - // DeleteUser deletes the given user - DeleteUser(ctx context.Context, accessToken, realm, userID string) error - // GetUserByID gets the user with the given id - GetUserByID(ctx context.Context, accessToken, realm, userID string) (*User, error) - // GetUser count returns the userCount of the given realm - GetUserCount(ctx context.Context, accessToken, realm string, params GetUsersParams) (int, error) - // GetUsers gets all users of the given realm - GetUsers(ctx context.Context, accessToken, realm string, params GetUsersParams) ([]*User, error) - // GetUserGroups gets the groups of the given user - GetUserGroups(ctx context.Context, accessToken, realm, userID string, params GetGroupsParams) ([]*Group, error) - // GetUsersByRoleName returns all users have a given role - GetUsersByRoleName(ctx context.Context, token, realm, roleName string) ([]*User, error) - // GetUsersByClientRoleName returns all users have a given client role - GetUsersByClientRoleName(ctx context.Context, token, realm, idOfClient, roleName string, params GetUsersByRoleParams) ([]*User, error) - // SetPassword sets a new password for the user with the given id. Needs elevated privileges - SetPassword(ctx context.Context, token, userID, realm, password string, temporary bool) error - // UpdateUser updates the given user - UpdateUser(ctx context.Context, accessToken, realm string, user User) error - // AddUserToGroup puts given user to given group - AddUserToGroup(ctx context.Context, token, realm, userID, groupID string) error - // DeleteUserFromGroup deletes given user from given group - DeleteUserFromGroup(ctx context.Context, token, realm, userID, groupID string) error - // GetUserSessions returns user sessions associated with the user - GetUserSessions(ctx context.Context, token, realm, userID string) ([]*UserSessionRepresentation, error) - // GetUserOfflineSessionsForClient returns offline sessions associated with the user and client - GetUserOfflineSessionsForClient(ctx context.Context, token, realm, userID, idOfClient string) ([]*UserSessionRepresentation, error) - // GetUserFederatedIdentities gets all user federated identities - GetUserFederatedIdentities(ctx context.Context, token, realm, userID string) ([]*FederatedIdentityRepresentation, error) - // CreateUserFederatedIdentity creates an user federated identity - CreateUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string, federatedIdentityRep FederatedIdentityRepresentation) error - // DeleteUserFederatedIdentity deletes an user federated identity - DeleteUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string) error - - // *** Identity Provider ** - // CreateIdentityProvider creates an identity provider in a realm - CreateIdentityProvider(ctx context.Context, token, realm string, providerRep IdentityProviderRepresentation) (string, error) - // GetIdentityProviders gets identity providers in a realm - GetIdentityProviders(ctx context.Context, token, realm string) ([]*IdentityProviderRepresentation, error) - // GetIdentityProvider gets the identity provider in a realm - GetIdentityProvider(ctx context.Context, token, realm, alias string) (*IdentityProviderRepresentation, error) - // UpdateIdentityProvider updates the identity provider in a realm - UpdateIdentityProvider(ctx context.Context, token, realm, alias string, providerRep IdentityProviderRepresentation) error - // DeleteIdentityProvider deletes the identity provider in a realm - DeleteIdentityProvider(ctx context.Context, token, realm, alias string) error - // ImportIdentityProviderConfig parses and returns the identity provider config at a given URL - ImportIdentityProviderConfig(ctx context.Context, token, realm, fromURL, providerID string) (map[string]string, error) - // ImportIdentityProviderConfigFromFile parses and returns the identity provider config from a given file - ImportIdentityProviderConfigFromFile(ctx context.Context, token, realm, providerID, fileName string, fileBody io.Reader) (map[string]string, error) - // ExportIDPPublicBrokerConfig exports the broker config for a given alias - ExportIDPPublicBrokerConfig(ctx context.Context, token, realm, alias string) (*string, error) - // CreateIdentityProviderMapper creates an instance of an identity provider mapper associated with the given alias - CreateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) (string, error) - // GetIdentityProviderMapperByID gets the mapper of an identity provider - GetIdentityProviderMapperByID(ctx context.Context, token, realm, alias, mapperID string) (*IdentityProviderMapper, error) - // UpdateIdentityProviderMapper updates mapper of an identity provider - UpdateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error - // DeleteIdentityProviderMapper deletes an instance of an identity provider mapper associated with the given alias and mapper ID - DeleteIdentityProviderMapper(ctx context.Context, token, realm, alias, mapperID string) error - // GetIdentityProviderMappers returns list of mappers associated with an identity provider - GetIdentityProviderMappers(ctx context.Context, token, realm, alias string) ([]*IdentityProviderMapper, error) - - // *** Protection API *** - // GetResource returns a client's resource with the given id, using access token from client - GetResourceClient(ctx context.Context, token, realm, resourceID string) (*ResourceRepresentation, error) - // GetResources a returns resources associated with the client, using access token from client - GetResourcesClient(ctx context.Context, token, realm string, params GetResourceParams) ([]*ResourceRepresentation, error) - // CreateResource creates a resource associated with the client, using access token from client - CreateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) (*ResourceRepresentation, error) - // UpdateResource updates a resource associated with the client, using access token from client - UpdateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) error - // DeleteResource deletes a resource associated with the client, using access token from client - DeleteResourceClient(ctx context.Context, token, realm, resourceID string) error - - // GetResource returns a client's resource with the given id, using access token from admin - GetResource(ctx context.Context, token, realm, idOfClient, resourceID string) (*ResourceRepresentation, error) - // GetResources a returns resources associated with the client, using access token from admin - GetResources(ctx context.Context, token, realm, idOfClient string, params GetResourceParams) ([]*ResourceRepresentation, error) - // CreateResource creates a resource associated with the client, using access token from admin - CreateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) (*ResourceRepresentation, error) - // UpdateResource updates a resource associated with the client, using access token from admin - UpdateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) error - // DeleteResource deletes a resource associated with the client, using access token from admin - DeleteResource(ctx context.Context, token, realm, idOfClient, resourceID string) error - - // GetScope returns a client's scope with the given id, using access token from admin - GetScope(ctx context.Context, token, realm, idOfClient, scopeID string) (*ScopeRepresentation, error) - // GetScopes returns scopes associated with the client, using access token from admin - GetScopes(ctx context.Context, token, realm, idOfClient string, params GetScopeParams) ([]*ScopeRepresentation, error) - // CreateScope creates a scope associated with the client, using access token from admin - CreateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) (*ScopeRepresentation, error) - // UpdateScope updates a scope associated with the client, using access token from admin - UpdateScope(ctx context.Context, token, realm, idOfClient string, resource ScopeRepresentation) error - // DeleteScope deletes a scope associated with the client, using access token from admin - DeleteScope(ctx context.Context, token, realm, idOfClient, scopeID string) error - - // CreatePermissionTicket creates a permission ticket for a resource, using access token from client (typically a resource server) - CreatePermissionTicket(ctx context.Context, token, realm string, permissions []CreatePermissionTicketParams) (*PermissionTicketResponseRepresentation, error) - // GrantUserPermission lets resource owner grant permission for specific resource ID to specific user ID - GrantUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) - // GrantPermission lets resource owner update permission for specific resource ID to specific user ID - UpdateUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) - // GetUserPermission gets granted permissions according query parameters - GetUserPermissions(ctx context.Context, token, realm string, params GetUserPermissionParams) ([]*PermissionGrantResponseRepresentation, error) - // DeleteUserPermission lets resource owner delete permission for specific resource ID to specific user ID - DeleteUserPermission(ctx context.Context, token, realm, ticketID string) error - - // GetPermission returns a client's permission with the given id - GetPermission(ctx context.Context, token, realm, idOfClient, permissionID string) (*PermissionRepresentation, error) - // GetPermissions returns permissions associated with the client - GetPermissions(ctx context.Context, token, realm, idOfClient string, params GetPermissionParams) ([]*PermissionRepresentation, error) - // CreatePermission creates a permission associated with the client - CreatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) (*PermissionRepresentation, error) - // UpdatePermission updates a permission associated with the client - UpdatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) error - // DeletePermission deletes a permission associated with the client - DeletePermission(ctx context.Context, token, realm, idOfClient, permissionID string) error - // GetDependentPermissions returns client's permissions dependent on the policy with given ID - GetDependentPermissions(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PermissionRepresentation, error) - GetPermissionResources(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionResource, error) - GetPermissionScopes(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionScope, error) - - // GetPolicy returns a client's policy with the given id, using access token from admin - GetPolicy(ctx context.Context, token, realm, idOfClient, policyID string) (*PolicyRepresentation, error) - // GetPolicies returns policies associated with the client, using access token from admin - GetPolicies(ctx context.Context, token, realm, idOfClient string, params GetPolicyParams) ([]*PolicyRepresentation, error) - // CreatePolicy creates a policy associated with the client, using access token from admin - CreatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) (*PolicyRepresentation, error) - // UpdatePolicy updates a policy associated with the client, using access token from admin - UpdatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) error - // DeletePolicy deletes a policy associated with the client, using access token from admin - DeletePolicy(ctx context.Context, token, realm, idOfClient, policyID string) error - // GetPolicyAssociatedPolicies returns a client's policy associated policies with the given policy id, using access token from admin - GetAuthorizationPolicyAssociatedPolicies(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyRepresentation, error) - // GetPolicyResources returns a client's resources of specific policy with the given policy id, using access token from admin - GetAuthorizationPolicyResources(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyResourceRepresentation, error) - // GetPolicyScopes returns a client's scopes of specific policy with the given policy id, using access token from admin - GetAuthorizationPolicyScopes(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyScopeRepresentation, error) - - // GetResourcePolicy updates a permission for a specifc resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange - GetResourcePolicy(ctx context.Context, token, realm, permissionID string) (*ResourcePolicyRepresentation, error) - // GetResources returns resources associated with the client, using token obtained by Resource Owner Password Credentials Grant or Token exchange - GetResourcePolicies(ctx context.Context, token, realm string, params GetResourcePoliciesParams) ([]*ResourcePolicyRepresentation, error) - // GetResources returns all resources associated with the client, using token obtained by Resource Owner Password Credentials Grant or Token exchange - CreateResourcePolicy(ctx context.Context, token, realm, resourceID string, policy ResourcePolicyRepresentation) (*ResourcePolicyRepresentation, error) - // UpdateResourcePolicy updates a permission for a specifc resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange - UpdateResourcePolicy(ctx context.Context, token, realm, permissionID string, policy ResourcePolicyRepresentation) error - // DeleteResourcePolicy deletes a permission for a specifc resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange - DeleteResourcePolicy(ctx context.Context, token, realm, permissionID string) error - - // --------------- - // Credentials API - // --------------- - - // GetCredentialRegistrators returns credentials registrators - GetCredentialRegistrators(ctx context.Context, token, realm string) ([]string, error) - // GetConfiguredUserStorageCredentialTypes returns credential types, which are provided by the user storage where user is stored - GetConfiguredUserStorageCredentialTypes(ctx context.Context, token, realm, userID string) ([]string, error) - - // GetCredentials returns credentials available for a given user - GetCredentials(ctx context.Context, token, realm, UserID string) ([]*CredentialRepresentation, error) - // DeleteCredentials deletes the given credential for a given user - DeleteCredentials(ctx context.Context, token, realm, UserID, CredentialID string) error - // UpdateCredentialUserLabel updates label for the given credential for the given user - UpdateCredentialUserLabel(ctx context.Context, token, realm, userID, credentialID, userLabel string) error - // DisableAllCredentialsByType disables all credentials for a user of a specific type - DisableAllCredentialsByType(ctx context.Context, token, realm, userID string, types []string) error - // MoveCredentialBehind move a credential to a position behind another credential - MoveCredentialBehind(ctx context.Context, token, realm, userID, credentialID, newPreviousCredentialID string) error - // MoveCredentialToFirst move a credential to a first position in the credentials list of the user - MoveCredentialToFirst(ctx context.Context, token, realm, userID, credentialID string) error - - // --------------- - // 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 - RegisterRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error - // UpdateRequiredAction updates a required action for a given realm - UpdateRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error - // UpdateRequiredAction updates a required action for a given realm - GetRequiredAction(ctx context.Context, token string, realm string, alias string) (*RequiredActionProviderRepresentation, error) - // UpdateRequiredAction updates a required action for a given realm - GetRequiredActions(ctx context.Context, token string, realm string) ([]*RequiredActionProviderRepresentation, error) - // UpdateRequiredAction updates a required action for a given realm - DeleteRequiredAction(ctx context.Context, token string, realm string, alias string) error -} diff --git a/model_test.go b/model_test.go index ebda1396..ce342ba1 100644 --- a/model_test.go +++ b/model_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - "github.com/Nerzal/gocloak/v11" + "github.com/Nerzal/gocloak/v12" "github.com/stretchr/testify/assert" ) @@ -261,7 +261,7 @@ func TestStringerOmitEmpty(t *testing.T) { &gocloak.ResourcePermission{}, &gocloak.PermissionResource{}, &gocloak.PermissionScope{}, - &gocloak.RetrospecTokenResult{}, + &gocloak.IntroSpectTokenResult{}, &gocloak.User{}, &gocloak.SetPasswordRequest{}, &gocloak.Component{}, @@ -309,7 +309,7 @@ func TestStringerOmitEmpty(t *testing.T) { &gocloak.UserSessionRepresentation{}, &gocloak.SystemInfoRepresentation{}, &gocloak.MemoryInfoRepresentation{}, - &gocloak.ServerInfoRepesentation{}, + &gocloak.ServerInfoRepresentation{}, &gocloak.FederatedIdentityRepresentation{}, &gocloak.IdentityProviderRepresentation{}, &gocloak.GetResourceParams{}, diff --git a/models.go b/models.go index 36c360a5..089efb3b 100644 --- a/models.go +++ b/models.go @@ -182,8 +182,8 @@ type PermissionScope struct { ScopeName *string `json:"name,omitempty"` } -// RetrospecTokenResult is returned when a token was checked -type RetrospecTokenResult struct { +// IntroSpectTokenResult is returned when a token was checked +type IntroSpectTokenResult struct { Permissions *[]ResourcePermission `json:"permissions,omitempty"` Exp *int `json:"exp,omitempty"` Nbf *int `json:"nbf,omitempty"` @@ -317,6 +317,12 @@ type ExecuteActionsEmail struct { Actions *[]string `json:"-"` } +// SendVerificationMailParams is being used to send verification params +type SendVerificationMailParams struct { + ClientID *string + RedirectURI *string +} + // Group is a Group type Group struct { ID *string `json:"id,omitempty"` @@ -1060,8 +1066,8 @@ type BuiltinProtocolMappers struct { OpenIDConnect []ProtocolMapperRepresentation `json:"openid-connect,omitempty"` } -// ServerInfoRepesentation represents a server info -type ServerInfoRepesentation struct { +// ServerInfoRepresentation represents a server info +type ServerInfoRepresentation struct { SystemInfo *SystemInfoRepresentation `json:"systemInfo,omitempty"` MemoryInfo *MemoryInfoRepresentation `json:"memoryInfo,omitempty"` PasswordPolicies []*PasswordPolicy `json:"passwordPolicies,omitempty"` @@ -1383,7 +1389,7 @@ func (v *IssuerResponse) String() string { return pre func (v *ResourcePermission) String() string { return prettyStringStruct(v) } func (v *PermissionResource) String() string { return prettyStringStruct(v) } func (v *PermissionScope) String() string { return prettyStringStruct(v) } -func (v *RetrospecTokenResult) String() string { return prettyStringStruct(v) } +func (v *IntroSpectTokenResult) String() string { return prettyStringStruct(v) } func (v *User) String() string { return prettyStringStruct(v) } func (v *SetPasswordRequest) String() string { return prettyStringStruct(v) } func (v *Component) String() string { return prettyStringStruct(v) } @@ -1436,7 +1442,7 @@ func (v *RequestingPartyPermission) String() string { return pre func (v *UserSessionRepresentation) String() string { return prettyStringStruct(v) } func (v *SystemInfoRepresentation) String() string { return prettyStringStruct(v) } func (v *MemoryInfoRepresentation) String() string { return prettyStringStruct(v) } -func (v *ServerInfoRepesentation) String() string { return prettyStringStruct(v) } +func (v *ServerInfoRepresentation) String() string { return prettyStringStruct(v) } func (v *FederatedIdentityRepresentation) String() string { return prettyStringStruct(v) } func (v *IdentityProviderRepresentation) String() string { return prettyStringStruct(v) } func (v *GetResourceParams) String() string { return prettyStringStruct(v) } diff --git a/testdata/gocloak-realm.json b/testdata/gocloak-realm.json index 9095c40d..1f7aed8f 100644 --- a/testdata/gocloak-realm.json +++ b/testdata/gocloak-realm.json @@ -65,13 +65,45 @@ "webAuthnPolicyCreateTimeout": 0, "webAuthnPolicyAvoidSameAuthenticatorRegister": false, "webAuthnPolicyAcceptableAaguids": [], - "scopeMappings": [{ - "clientScope": "offline_access", - "roles": [ - "offline_access" - ] - }], - "clients": [{ + "users": [ + { + "id": "6ead694f-bf59-495d-a475-a3b0b9be50ed", + "createdTimestamp": 1666175342321, + "username": "service-account-gocloak", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "gocloak", + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-gocloak" + ], + "clientRoles": { + "realm-management": [ + "manage-clients", + "view-clients", + "query-clients", + "create-client" + ], + "gocloak": [ + "uma_protection" + ] + }, + "notBefore": 0, + "groups": [] + } + ], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clients": [ + { "id": "521554ab-23fb-46fa-a557-ab53f3a0498a", "clientId": "admin-cli", "name": "${client_admin-cli}", @@ -177,21 +209,23 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "protocolMappers": [{ - "id": "d68e7a07-4ad5-4d9d-81d1-70c03ceaaa59", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" + "protocolMappers": [ + { + "id": "d68e7a07-4ad5-4d9d-81d1-70c03ceaaa59", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } } - }], + ], "defaultClientScopes": [ "web-origins", "role_list", @@ -246,7 +280,8 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": true, "nodeReRegistrationTimeout": -1, - "protocolMappers": [{ + "protocolMappers": [ + { "id": "c213647e-cb4c-43c3-b06c-d9a573bea602", "name": "Client Host", "protocol": "openid-connect", @@ -308,37 +343,40 @@ "authorizationSettings": { "allowRemoteResourceManagement": true, "policyEnforcementMode": "ENFORCING", - "resources": [{ - "name": "Default Resource", - "type": "urn:gocloak:resources:default", - "ownerManagedAccess": false, - "attributes": {}, - "_id": "067438bb-1d4a-4c4d-b84f-a57344ef2b2b", - "uris": [ - "/*" - ] - }], - "policies": [{ - "id": "16fdc33a-7384-4735-8b7e-5d15b8e8bdaf", - "name": "Default Policy", - "description": "A policy that grants access only for users within this realm", - "type": "js", + "resources": [ + { + "name": "Default Resource", + "type": "urn:gocloak:resources:default", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "067438bb-1d4a-4c4d-b84f-a57344ef2b2b", + "uris": [ + "/*" + ] + } + ], + "policies": [ + { + "id": "4abda6f1-c621-414c-a97d-d8dbd422eabd", + "name": "default", + "description": "", + "type": "client", "logic": "POSITIVE", - "decisionStrategy": "AFFIRMATIVE", + "decisionStrategy": "UNANIMOUS", "config": { - "code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + "clients": "[\"gocloak\"]" } }, { - "id": "30cfeba8-79c4-493b-97c7-9e8c6e7c62c9", - "name": "Default Permission", - "description": "A permission that applies to the default resource type", + "id": "ddb430d2-368b-43f9-8917-edfa04a2d0d7", + "name": "test", + "description": "", "type": "resource", "logic": "POSITIVE", "decisionStrategy": "UNANIMOUS", "config": { - "defaultResourceType": "urn:gocloak:resources:default", - "applyPolicies": "[\"Default Policy\"]" + "resources": "[\"Default Resource\"]", + "applyPolicies": "[\"default\"]" } } ], @@ -430,7 +468,8 @@ ] } ], - "clientScopes": [{ + "clientScopes": [ + { "id": "fbf7672e-3883-492c-a9dd-a0e71b8e8f86", "name": "address", "description": "OpenID Connect built-in scope: address", @@ -440,24 +479,26 @@ "display.on.consent.screen": "true", "consent.screen.text": "${addressScopeConsentText}" }, - "protocolMappers": [{ - "id": "86b34081-1b15-47ef-8aa0-4b862055273a", - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" + "protocolMappers": [ + { + "id": "86b34081-1b15-47ef-8aa0-4b862055273a", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } } - }] + ] }, { "id": "507ac74e-6bb7-482a-b865-473bf3506b13", @@ -469,7 +510,8 @@ "display.on.consent.screen": "true", "consent.screen.text": "${emailScopeConsentText}" }, - "protocolMappers": [{ + "protocolMappers": [ + { "id": "394eb31a-4c45-47ff-b9f4-4f2e004d7bb1", "name": "email verified", "protocol": "openid-connect", @@ -510,7 +552,8 @@ "include.in.token.scope": "true", "display.on.consent.screen": "false" }, - "protocolMappers": [{ + "protocolMappers": [ + { "id": "fb5df9d7-960b-4880-a66e-ef59d5ef374f", "name": "groups", "protocol": "openid-connect", @@ -562,7 +605,8 @@ "display.on.consent.screen": "true", "consent.screen.text": "${phoneScopeConsentText}" }, - "protocolMappers": [{ + "protocolMappers": [ + { "id": "c3891454-29b0-473a-9d27-5811b5841329", "name": "phone number", "protocol": "openid-connect", @@ -604,7 +648,8 @@ "display.on.consent.screen": "true", "consent.screen.text": "${profileScopeConsentText}" }, - "protocolMappers": [{ + "protocolMappers": [ + { "id": "38f3d54f-5001-4ad9-a7a3-c46cbdba6204", "name": "website", "protocol": "openid-connect", @@ -823,7 +868,8 @@ "display.on.consent.screen": "true", "consent.screen.text": "${rolesScopeConsentText}" }, - "protocolMappers": [{ + "protocolMappers": [ + { "id": "ef3ae474-ca8a-4b50-a1ec-0a014554cac9", "name": "audience resolve", "protocol": "openid-connect", @@ -870,18 +916,20 @@ "consent.screen.text": "${samlRoleListScopeConsentText}", "display.on.consent.screen": "true" }, - "protocolMappers": [{ - "id": "71fa5c48-aab3-4d59-bc85-5a33e4c98e60", - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", - "consentRequired": false, - "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" + "protocolMappers": [ + { + "id": "71fa5c48-aab3-4d59-bc85-5a33e4c98e60", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } } - }] + ] }, { "id": "5d656d84-ec76-45fd-99e3-5f326831459c", @@ -893,14 +941,16 @@ "display.on.consent.screen": "false", "consent.screen.text": "" }, - "protocolMappers": [{ - "id": "ff3a575a-eda5-43ef-a907-3908f9438966", - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", - "consentRequired": false, - "config": {} - }] + "protocolMappers": [ + { + "id": "ff3a575a-eda5-43ef-a907-3908f9438966", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] } ], "defaultDefaultClientScopes": [ @@ -934,7 +984,8 @@ "adminEventsEnabled": false, "adminEventsDetailsEnabled": false, "components": { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [{ + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { "id": "749d8b66-5751-415a-8cca-e8ce66417de4", "name": "Max Clients Limit", "providerId": "max-clients", @@ -1025,7 +1076,8 @@ } } ], - "org.keycloak.keys.KeyProvider": [{ + "org.keycloak.keys.KeyProvider": [ + { "id": "7c9e0c14-d267-4e48-b26c-9d4197abd37e", "name": "rsa-generated", "providerId": "rsa-generated", @@ -1065,14 +1117,16 @@ }, "internationalizationEnabled": false, "supportedLocales": [], - "authenticationFlows": [{ + "authenticationFlows": [ + { "id": "f93eda62-488f-4090-acf1-9f3860f43afe", "alias": "Handle Existing Account", "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", "providerId": "basic-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "idp-confirm-link", "requirement": "REQUIRED", "priority": 10, @@ -1102,7 +1156,8 @@ "providerId": "basic-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "idp-username-password-form", "requirement": "REQUIRED", "priority": 10, @@ -1125,7 +1180,8 @@ "providerId": "basic-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "conditional-user-configured", "requirement": "REQUIRED", "priority": 10, @@ -1148,7 +1204,8 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "auth-cookie", "requirement": "ALTERNATIVE", "priority": 10, @@ -1185,7 +1242,8 @@ "providerId": "client-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "client-secret", "requirement": "ALTERNATIVE", "priority": 10, @@ -1222,7 +1280,8 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "direct-grant-validate-username", "requirement": "REQUIRED", "priority": 10, @@ -1252,7 +1311,8 @@ "providerId": "basic-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "conditional-user-configured", "requirement": "REQUIRED", "priority": 10, @@ -1275,13 +1335,15 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ - "authenticator": "docker-http-basic-authenticator", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }] + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] }, { "id": "8c133757-5745-4c3e-b408-43a3e6e00d51", @@ -1290,7 +1352,8 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticatorConfig": "review profile config", "authenticator": "idp-review-profile", "requirement": "REQUIRED", @@ -1322,7 +1385,8 @@ "providerId": "basic-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "auth-username-password-form", "requirement": "REQUIRED", "priority": 10, @@ -1345,7 +1409,8 @@ "providerId": "basic-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "conditional-user-configured", "requirement": "REQUIRED", "priority": 10, @@ -1368,7 +1433,8 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "no-cookie-redirect", "requirement": "REQUIRED", "priority": 10, @@ -1405,14 +1471,16 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ - "authenticator": "registration-page-form", - "requirement": "REQUIRED", - "priority": 10, - "flowAlias": "registration form", - "userSetupAllowed": false, - "autheticatorFlow": true - }] + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, { "id": "2a162eb4-830b-4719-b892-1b8748d75d77", @@ -1421,7 +1489,8 @@ "providerId": "form-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "registration-user-creation", "requirement": "REQUIRED", "priority": 20, @@ -1458,7 +1527,8 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "reset-credentials-choose-user", "requirement": "REQUIRED", "priority": 10, @@ -1495,7 +1565,8 @@ "providerId": "basic-flow", "topLevel": false, "builtIn": true, - "authenticationExecutions": [{ + "authenticationExecutions": [ + { "authenticator": "conditional-user-configured", "requirement": "REQUIRED", "priority": 10, @@ -1518,16 +1589,19 @@ "providerId": "basic-flow", "topLevel": true, "builtIn": true, - "authenticationExecutions": [{ - "authenticator": "http-basic-authenticator", - "requirement": "REQUIRED", - "priority": 10, - "userSetupAllowed": false, - "autheticatorFlow": false - }] + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] } ], - "authenticatorConfig": [{ + "authenticatorConfig": [ + { "id": "ae8a005d-8df1-4911-9289-7e507c6778d2", "alias": "create unique user config", "config": { @@ -1542,7 +1616,8 @@ } } ], - "requiredActions": [{ + "requiredActions": [ + { "alias": "CONFIGURE_TOTP", "name": "Configure OTP", "providerId": "CONFIGURE_TOTP", diff --git a/utils_test.go b/utils_test.go index 92cfa212..0e2d5c70 100644 --- a/utils_test.go +++ b/utils_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/Nerzal/gocloak/v11" + "github.com/Nerzal/gocloak/v12" ) func TestStringP(t *testing.T) { From c59ba6ef1f9f187bbb0f80cbda56222a36e77ac5 Mon Sep 17 00:00:00 2001 From: Bastian Date: Thu, 5 Jan 2023 14:34:40 +0100 Subject: [PATCH 33/60] fix(login): specify openid scope (#396) --- client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client.go b/client.go index 69d24b64..56482d7c 100644 --- a/client.go +++ b/client.go @@ -593,6 +593,7 @@ func (g *GoCloak) Login(ctx context.Context, clientID, clientSecret, realm, user GrantType: StringP("password"), Username: &username, Password: &password, + Scope: StringP("openid"), }) } From 94bb9404b0989b12ec89f0ea72f5de735f6d7fa1 Mon Sep 17 00:00:00 2001 From: amir4895 Date: Mon, 9 Jan 2023 15:28:25 +0200 Subject: [PATCH 34/60] =?UTF-8?q?Adding=20new=20function=20GetUserBruteFor?= =?UTF-8?q?ceDetectionStatus=20to=20retrieve=20the=20=E2=80=A6=20(#388)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adding new function GetUserBruteForceDetectionStatus to retrieve the brute force protection status per user * code convention * code convention * code convention Co-authored-by: amirlevinzon --- client.go | 23 ++++++++++++++ client_test.go | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ models.go | 9 ++++++ 3 files changed, 113 insertions(+) diff --git a/client.go b/client.go index 56482d7c..7e3d213c 100644 --- a/client.go +++ b/client.go @@ -34,6 +34,7 @@ type GoCloak struct { tokenEndpoint string logoutEndpoint string openIDConnect string + attackDetection string } } @@ -185,6 +186,7 @@ func NewClient(basePath string, options ...func(*GoCloak)) *GoCloak { c.Config.tokenEndpoint = makeURL("protocol", "openid-connect", "token") c.Config.logoutEndpoint = makeURL("protocol", "openid-connect", "logout") c.Config.openIDConnect = makeURL("protocol", "openid-connect") + c.Config.attackDetection = makeURL("attack-detection", "brute-force") for _, option := range options { option(&c) @@ -214,6 +216,11 @@ func (g *GoCloak) getAdminRealmURL(realm string, path ...string) string { return makeURL(path...) } +func (g *GoCloak) getAttackDetectionURL(realm string, user string, path ...string) string { + path = append([]string{g.basePath, g.Config.authAdminRealms, realm, g.Config.attackDetection, user}, path...) + return makeURL(path...) +} + // ==== Functional Options === // SetLegacyWildFlySupport maintain legacy WildFly support. @@ -2782,6 +2789,22 @@ func (g *GoCloak) DeleteUserFederatedIdentity(ctx context.Context, token, realm, return checkForError(resp, err, errMessage) } +// GetUserBruteForceDetectionStatus fetches a user status regarding brute force protection +func (g *GoCloak) GetUserBruteForceDetectionStatus(ctx context.Context, accessToken, realm, userID string) (*BruteForceStatus, error) { + const errMessage = "could not brute force detection Status" + var result BruteForceStatus + + resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + SetResult(&result). + Get(g.getAttackDetectionURL(realm, "users", userID)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, nil +} + // ------------------ // Identity Providers // ------------------ diff --git a/client_test.go b/client_test.go index 1312cd86..87d14648 100644 --- a/client_test.go +++ b/client_test.go @@ -3055,6 +3055,87 @@ func Test_CreateUser(t *testing.T) { defer tearDown() } +func Test_GetUserBruteForceDetectionStatus(t *testing.T) { + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + realm, err := client.GetRealm( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm) + require.NoError(t, err, "GetRealm failed") + + updatedRealm := realm + updatedRealm.BruteForceProtected = gocloak.BoolP(true) + updatedRealm.FailureFactor = gocloak.IntP(1) + updatedRealm.MaxFailureWaitSeconds = gocloak.IntP(2) + err = client.UpdateRealm( + context.Background(), + token.AccessToken, + *updatedRealm) + require.NoError(t, err, "UpdateRealm failed") + + tearDownUser, userID := CreateUser(t, client) + defer tearDownUser() + err = client.SetPassword( + context.Background(), + token.AccessToken, + userID, + *realm.ID, + cfg.GoCloak.Password, + false) + require.NoError(t, err, "CreateUser failed") + + fetchedUser, err := client.GetUserByID( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + userID) + require.NoError(t, err, "GetUserById failed") + + _, err = client.Login(context.Background(), + cfg.GoCloak.ClientID, + cfg.GoCloak.ClientSecret, + *realm.ID, + *fetchedUser.Username, + "wrong password") + require.Error(t, err, "401 Unauthorized: invalid_grant: Invalid user credentials") + bruteForceStatus, err := client.GetUserBruteForceDetectionStatus( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + userID) + require.NoError(t, err, "Getting attack log failed") + require.Equal(t, 1, *bruteForceStatus.NumFailures, "Should return one failure") + require.Equal(t, true, *bruteForceStatus.Disabled, "The user shouldn be locked") + + time.Sleep(2 * time.Second) + _, err = client.Login( + context.Background(), + cfg.GoCloak.ClientID, + cfg.GoCloak.ClientSecret, + *realm.ID, + *fetchedUser.Username, + cfg.GoCloak.Password) + require.NoError(t, err, "Login failed") + + bruteForceStatus, err = client.GetUserBruteForceDetectionStatus( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + userID) + require.NoError(t, err, "Getting attack status failed") + require.Equal(t, 0, *bruteForceStatus.NumFailures, "Should return zero failures") + require.Equal(t, false, *bruteForceStatus.Disabled, "The user shouldn't be locked") + + err = client.UpdateRealm( + context.Background(), + token.AccessToken, + *realm) + require.NoError(t, err, "UpdateRealm failed") + +} + func Test_CreateUserCustomAttributes(t *testing.T) { t.Parallel() cfg := GetConfig(t) diff --git a/models.go b/models.go index 089efb3b..02881e61 100644 --- a/models.go +++ b/models.go @@ -1360,6 +1360,14 @@ type CredentialRepresentation struct { UserLabel *string `json:"userLabel,omitempty"` } +// BruteForceStatus is a representation of realm user regarding brute force attack +type BruteForceStatus struct { + NumFailures *int `json:"numFailures,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + LastIPFailure *string `json:"lastIPFailure,omitempty"` + LastFailure *int `json:"lastFailure,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 { @@ -1464,3 +1472,4 @@ func (v *ResourcePolicyRepresentation) String() string { return pre func (v *GetResourcePoliciesParams) String() string { return prettyStringStruct(v) } func (v *CredentialRepresentation) String() string { return prettyStringStruct(v) } func (v *RequiredActionProviderRepresentation) String() string { return prettyStringStruct(v) } +func (v *BruteForceStatus) String() string { return prettyStringStruct(v) } From b2ed4a59a4cbf93f274f014375b1eebdf1216334 Mon Sep 17 00:00:00 2001 From: Upils <5464641+upils@users.noreply.github.com> Date: Wed, 15 Feb 2023 14:01:56 +0100 Subject: [PATCH 35/60] Add params to GetUsersByRoleName (#392) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add params to GetUsersByRoleName Signed-off-by: Paul MARS * ✅ Add a test case on GetUsersByRoleName Signed-off-by: Paul MARS * 📌 Pin keycloak version in test to avoid breaking test in newly release keycloak version Signed-off-by: Paul MARS --------- Signed-off-by: Paul MARS --- Dockerfile | 4 ++-- client.go | 8 +++++++- client_test.go | 12 +++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index fe10a523..9b883314 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/keycloak/keycloak:latest +FROM quay.io/keycloak/keycloak:19.0 COPY testdata data/import WORKDIR /opt/keycloak ENV KC_HOSTNAME=localhost @@ -8,4 +8,4 @@ ENV KEYCLOAK_ADMIN=admin ENV KEYCLOAK_ADMIN_PASSWORD=secret ENV KC_FEATURES=account-api,account2,authorization,client-policies,impersonation,docker,scripts,upload_scripts RUN /opt/keycloak/bin/kc.sh import --file /data/import/gocloak-realm.json -ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] \ No newline at end of file +ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] diff --git a/client.go b/client.go index 7e3d213c..48919e9f 100644 --- a/client.go +++ b/client.go @@ -2553,12 +2553,18 @@ func (g *GoCloak) GetUsers(ctx context.Context, token, realm string, params GetU } // GetUsersByRoleName returns all users have a given role -func (g *GoCloak) GetUsersByRoleName(ctx context.Context, token, realm, roleName string) ([]*User, error) { +func (g *GoCloak) GetUsersByRoleName(ctx context.Context, token, realm, roleName string, params GetUsersByRoleParams) ([]*User, error) { const errMessage = "could not get users by role name" var result []*User + queryParams, err := GetQueryParams(params) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + resp, err := g.getRequestWithBearerAuth(ctx, token). SetResult(&result). + SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "roles", roleName, "users")) if err := checkForError(resp, err, errMessage); err != nil { diff --git a/client_test.go b/client_test.go index 87d14648..82b248da 100644 --- a/client_test.go +++ b/client_test.go @@ -3450,10 +3450,20 @@ func Test_GetUsersByRoleName(t *testing.T) { context.Background(), token.AccessToken, cfg.GoCloak.Realm, - roleName) + roleName, + gocloak.GetUsersByRoleParams{}) require.NoError(t, err) require.NotEmpty(t, users) require.Equal(t, userID, *users[0].ID) + + users, err = client.GetUsersByRoleName( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + "unknown role", + gocloak.GetUsersByRoleParams{}) + require.Error(t, err, "GetUsersByRoleName no error on unknown role") + require.Empty(t, users) } func Test_GetUsersByClientRoleName(t *testing.T) { From 15d7b4eab07b4b4124f1c343ce8f8ee231f3dcf9 Mon Sep 17 00:00:00 2001 From: Thales Costa Date: Wed, 15 Feb 2023 13:10:31 +0000 Subject: [PATCH 36/60] Add Get/Update Authentication Flow (#398) * build(docker-compose.yml): adding healthcheck * feat(client.go): adding update/get authentication flow * fix(docker-compose.yml): changing true to string --- README.md | 9 ++++++++- client.go | 28 ++++++++++++++++++++++++++++ client_test.go | 46 +++++++++++++++++++++++++++++----------------- docker-compose.yml | 6 ++++++ 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b1d99fb8..301e6ce4 100644 --- a/README.md +++ b/README.md @@ -342,7 +342,14 @@ type GoCloak interface { MoveCredentialBehind(ctx context.Context, token, realm, userID, credentialID, newPreviousCredentialID string) error MoveCredentialToFirst(ctx context.Context, token, realm, userID, credentialID string) error - // *** Identity Providers *** +// *** Authentication Flows *** +GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) +GetAuthenticationFlow(ctx context.Context, token, realm string, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) +CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error +UpdateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) +DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error + +// *** Identity Providers *** CreateIdentityProvider(ctx context.Context, token, realm string, providerRep IdentityProviderRepresentation) (string, error) GetIdentityProvider(ctx context.Context, token, realm, alias string) (*IdentityProviderRepresentation, error) diff --git a/client.go b/client.go index 48919e9f..77560223 100644 --- a/client.go +++ b/client.go @@ -2365,6 +2365,20 @@ func (g *GoCloak) GetAuthenticationFlows(ctx context.Context, token, realm strin return result, nil } +// GetAuthenticationFlow get an authentication flow with the given ID +func (g *GoCloak) GetAuthenticationFlow(ctx context.Context, token, realm string, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) { + const errMessage = "could not retrieve authentication flows" + var result *AuthenticationFlowRepresentation + resp, err := g.getRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "authentication", "flows", authenticationFlowID)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + return result, nil +} + // CreateAuthenticationFlow creates a new Authentication flow in a realm func (g *GoCloak) CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error { const errMessage = "could not create authentication flows" @@ -2376,6 +2390,20 @@ func (g *GoCloak) CreateAuthenticationFlow(ctx context.Context, token, realm str return checkForError(resp, err, errMessage) } +// UpdateAuthenticationFlow a given Authentication Flow +func (g *GoCloak) UpdateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) { + const errMessage = "could not create authentication flows" + var result *AuthenticationFlowRepresentation + resp, err := g.getRequestWithBearerAuth(ctx, token). + SetResult(&result).SetBody(flow). + Put(g.getAdminRealmURL(realm, "authentication", "flows", authenticationFlowID)) + + if err = checkForError(resp, err, errMessage); err != nil { + return nil, err + } + return result, nil +} + // DeleteAuthenticationFlow deletes a flow in a realm with the given ID func (g *GoCloak) DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error { const errMessage = "could not delete authentication flows" diff --git a/client_test.go b/client_test.go index 82b248da..f4763b80 100644 --- a/client_test.go +++ b/client_test.go @@ -6534,6 +6534,7 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecutionAndFlo Description: gocloak.StringP("my test description"), TopLevel: gocloak.BoolP(true), ProviderID: gocloak.StringP("basic-flow"), + ID: gocloak.StringP("testauthflow2id"), } authExecFlow := gocloak.CreateAuthenticationExecutionFlowRepresentation{ @@ -6632,23 +6633,34 @@ func TestGocloak_CreateAuthenticationFlowsAndCreateAuthenticationExecutionAndFlo 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 - for _, flow := range flows { - if flow.Alias != nil && *flow.Alias == "testauthflow2" { - err = client.DeleteAuthenticationFlow( - context.Background(), - token.AccessToken, - cfg.GoCloak.Realm, - *flow.ID, - ) - require.NoError(t, err, "Failed to delete authentication flow") - deleted = true - break - } - } - require.True(t, deleted, "Failed to delete authentication flow, no flow was deleted") + authFlow.Description = gocloak.StringP("my-new-description") + _, err = client.UpdateAuthenticationFlow( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + authFlow, + *authFlow.ID, + ) + + require.NoError(t, err, "Failed to update authentication flow") + t.Logf("updated authentication flow: %+v", authFlow) + + retrievedAuthFlow, err := client.GetAuthenticationFlow( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *authFlow.ID, + ) + require.NoError(t, err, "Failed to fetch authentication flow") + t.Logf("retrieved authentication flow: %+v", retrievedAuthFlow) + require.Equal(t, "my-new-description", gocloak.PString(retrievedAuthFlow.Description)) + err = client.DeleteAuthenticationFlow( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *retrievedAuthFlow.ID, + ) + require.NoError(t, err, "Failed to delete authentication flow") } func TestGocloak_CreateAndGetRequiredAction(t *testing.T) { diff --git a/docker-compose.yml b/docker-compose.yml index 4f02c3e4..b422ddbb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,14 @@ services: KEYCLOAK_PASSWORD: secret KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: secret + KC_HEALTH_ENABLED: "true" ports: - "8080:8080" + healthcheck: + test: curl --fail --silent http://localhost:8080/health/ready 2>&1 || exit 1 + interval: 10s + timeout: 10s + retries: 5 volumes: - ./testdata/gocloak-realm.json:/opt/keycloak/data/import/gocloak-realm.json entrypoint: ["/opt/keycloak/bin/kc.sh", "start-dev --features=preview --import-realm"] From 9cd3f14839feea38219224ab49072e6dc71ca1e3 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Wed, 22 Feb 2023 12:09:23 +0100 Subject: [PATCH 37/60] update to glocloak v13 --- README.md | 4 ++-- client.go | 2 +- client_benchmark_test.go | 2 +- client_test.go | 2 +- go.mod | 2 +- model_test.go | 2 +- utils_test.go | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 301e6ce4..cd88b7e7 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ For release notes please consult the specific releases [here](https://github.com ### Installation ```shell -go get github.com/Nerzal/gocloak/v12 +go get github.com/Nerzal/gocloak/v13 ``` ### Importing ```go - import "github.com/Nerzal/gocloak/v12" + import "github.com/Nerzal/gocloak/v13" ``` ### Create New User diff --git a/client.go b/client.go index 77560223..9967e533 100644 --- a/client.go +++ b/client.go @@ -18,7 +18,7 @@ import ( "github.com/pkg/errors" "github.com/segmentio/ksuid" - "github.com/Nerzal/gocloak/v12/pkg/jwx" + "github.com/Nerzal/gocloak/v13/pkg/jwx" ) // GoCloak provides functionalities to talk to Keycloak. diff --git a/client_benchmark_test.go b/client_benchmark_test.go index cbd3ebab..dc8d9491 100644 --- a/client_benchmark_test.go +++ b/client_benchmark_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/Nerzal/gocloak/v12" + "github.com/Nerzal/gocloak/v13" "github.com/stretchr/testify/assert" ) diff --git a/client_test.go b/client_test.go index f4763b80..08bacd7e 100644 --- a/client_test.go +++ b/client_test.go @@ -26,7 +26,7 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/pkcs12" - "github.com/Nerzal/gocloak/v12" + "github.com/Nerzal/gocloak/v13" ) type configAdmin struct { diff --git a/go.mod b/go.mod index 3359f49d..52a14285 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/Nerzal/gocloak/v12 +module github.com/Nerzal/gocloak/v13 go 1.18 diff --git a/model_test.go b/model_test.go index ce342ba1..ad069f2d 100644 --- a/model_test.go +++ b/model_test.go @@ -5,7 +5,7 @@ import ( "errors" "testing" - "github.com/Nerzal/gocloak/v12" + "github.com/Nerzal/gocloak/v13" "github.com/stretchr/testify/assert" ) diff --git a/utils_test.go b/utils_test.go index 0e2d5c70..ec3af233 100644 --- a/utils_test.go +++ b/utils_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/Nerzal/gocloak/v12" + "github.com/Nerzal/gocloak/v13" ) func TestStringP(t *testing.T) { From b703322166ecf2bdbdd4c128847f4cb6160f4622 Mon Sep 17 00:00:00 2001 From: r3st <36693488+r3st@users.noreply.github.com> Date: Tue, 28 Feb 2023 12:18:24 +0100 Subject: [PATCH 38/60] fix(model): wrong value type (#402) Co-authored-by: Rene Stolle --- models.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models.go b/models.go index 02881e61..17922d9d 100644 --- a/models.go +++ b/models.go @@ -478,7 +478,7 @@ type Client struct { ProtocolMappers *[]ProtocolMapperRepresentation `json:"protocolMappers,omitempty"` PublicClient *bool `json:"publicClient,omitempty"` RedirectURIs *[]string `json:"redirectUris,omitempty"` - RegisteredNodes *map[string]string `json:"registeredNodes,omitempty"` + RegisteredNodes *map[string]int `json:"registeredNodes,omitempty"` RegistrationAccessToken *string `json:"registrationAccessToken,omitempty"` RootURL *string `json:"rootUrl,omitempty"` Secret *string `json:"secret,omitempty"` From 27921c7833f07a6752ba1d555ab35950bc929167 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Feb 2023 12:19:05 +0100 Subject: [PATCH 39/60] Bump golang.org/x/net from 0.0.0-20221019024206-cb67ada4b0ad to 0.7.0 (#401) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20221019024206-cb67ada4b0ad to 0.7.0. - [Release notes](https://github.com/golang/net/releases) - [Commits](https://github.com/golang/net/commits/v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 52a14285..16832968 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,6 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.0.0-20221019024206-cb67ada4b0ad // indirect + golang.org/x/net v0.7.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 01590474..ee6b3a73 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20221019024206-cb67ada4b0ad h1:Zx6wVVDwwNJFWXNIvDi7o952w3/1ckSwYk/7eykRmjM= -golang.org/x/net v0.0.0-20221019024206-cb67ada4b0ad/go.mod h1:RpDiru2p0u2F0lLpEoqnP2+7xs0ifAuOcJ442g6GU2s= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From 846cfda50dba49abe432cd092f70d4124c34a6ac Mon Sep 17 00:00:00 2001 From: Nerzal Date: Tue, 28 Feb 2023 12:41:43 +0100 Subject: [PATCH 40/60] update deps (#404) Co-authored-by: Tobias Theel --- go.mod | 6 +++--- go.sum | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 16832968..90f78f02 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.18 require ( github.com/go-resty/resty/v2 v2.7.0 - github.com/golang-jwt/jwt/v4 v4.4.2 + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 github.com/segmentio/ksuid v1.0.4 - github.com/stretchr/testify v1.8.0 - golang.org/x/crypto v0.0.0-20221012134737-56aed061732a + github.com/stretchr/testify v1.8.2 + golang.org/x/crypto v0.6.0 ) require ( diff --git a/go.sum b/go.sum index ee6b3a73..a8aaf844 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -15,12 +15,14 @@ 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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -golang.org/x/crypto v0.0.0-20221012134737-56aed061732a h1:NmSIgad6KjE6VvHciPZuNRTKxGhlPfD6OA87W/PLkqg= -golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= From 1f9ab90c97405cf95033e7f23033d4baf3c1c668 Mon Sep 17 00:00:00 2001 From: Mike <90835468+justmike1@users.noreply.github.com> Date: Fri, 17 Mar 2023 12:21:57 +0200 Subject: [PATCH 41/60] Added examples folder for code snippets that will help the user. (#407) * README examples * README examples * added section to main README * added missing parameter --------- Co-authored-by: Mike Joseph --- README.md | 12 + examples/ADD_CLIENT_ROLE_TO_USER.md | 117 ++++++++++ examples/USER_FEDERATION.md | 155 +++++++++++++ examples/USER_FEDERATION_GROUP_LDAP_MAPPER.md | 207 ++++++++++++++++++ examples/USER_FEDERATION_ROLE_LDAP_MAPPER.md | 206 +++++++++++++++++ ...R_FEDERATION_USER_ATTRIBUTE_LDAP_MAPPER.md | 200 +++++++++++++++++ 6 files changed, 897 insertions(+) create mode 100644 examples/ADD_CLIENT_ROLE_TO_USER.md create mode 100644 examples/USER_FEDERATION.md create mode 100644 examples/USER_FEDERATION_GROUP_LDAP_MAPPER.md create mode 100644 examples/USER_FEDERATION_ROLE_LDAP_MAPPER.md create mode 100644 examples/USER_FEDERATION_USER_ATTRIBUTE_LDAP_MAPPER.md diff --git a/README.md b/README.md index cd88b7e7..6fefe2ac 100644 --- a/README.md +++ b/README.md @@ -475,6 +475,18 @@ yields Note that empty parameters are not included, because of the use of ```omitempty``` in the type definitions. +## Examples + +* [Add client role to user](./examples/ADD_CLIENT_ROLE_TO_USER.md) + +* [Create User Federation & Sync](./examples/USER_FEDERATION.md) + +* [Create User Federation & Sync with group ldap mapper](./examples/USER_FEDERATION_GROUP_LDAP_MAPPER.md) + +* [Create User Federation & Sync with role ldap mapper](./examples/USER_FEDERATION_ROLE_LDAP_MAPPER.md) + +* [Create User Federation & Sync with user attribute ldap mapper](./examples/USER_FEDERATION_USER_ATTRIBUTE_LDAP_MAPPER.md) + ## License [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FNerzal%2Fgocloak.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FNerzal%2Fgocloak?ref=badge_large) diff --git a/examples/ADD_CLIENT_ROLE_TO_USER.md b/examples/ADD_CLIENT_ROLE_TO_USER.md new file mode 100644 index 00000000..dfcb1ebe --- /dev/null +++ b/examples/ADD_CLIENT_ROLE_TO_USER.md @@ -0,0 +1,117 @@ +```go +type Tkc struct { + realm string + token *gocloak.JWT + client *gocloak.GoCloak +} + +func (tkc *Tkc) getClientRolesByList(ctx context.Context, idClient string, roles []string) (clientRoles []gocloak.Role, getErr error) { + var notFoundRoles []string + + if roleObjects, tmpErr := tkc.client.GetClientRoles(ctx, tkc.token.AccessToken, tkc.realm, idClient, gocloak.GetRoleParams{}); tmpErr != nil { + getErr = fmt.Errorf("failed to get roles for client (error: %s)", tmpErr.Error()) + + return nil, getErr + } else { + searchRole: + for _, r := range roles { + for _, rb := range roleObjects { + if r == *rb.Name { + clientRoles = append(clientRoles, *rb) + continue searchRole + } + } + notFoundRoles = append(notFoundRoles, r) + } + } + + if len(notFoundRoles) > 0 { + getErr = fmt.Errorf("failed to found role(s) '%s' for client", strings.Join(notFoundRoles, ", ")) + } + + return clientRoles, getErr +} + +func (tkc *Tkc) getClients(ctx context.Context) (clients map[string]gocloak.Client, getErr error) { + var clientList []*gocloak.Client + + // init map + clients = make(map[string]gocloak.Client) + + // get all clients of realm + if clientList, getErr = tkc.client.GetClients(ctx, tkc.token.AccessToken, tkc.realm, gocloak.GetClientsParams{}); getErr != nil { + getErr = fmt.Errorf("get clients of realm failed (error: %s)", getErr.Error()) + return clients, getErr + } + + // transform to map with clientID as map key + for _, c := range clientList { + clients[*c.ClientID] = *c + } + + return clients, nil +} + +func (tkc *Tkc) addClientRolesToUser(idUser string, clientRoles map[string][]string) (addErr error) { + + var clients map[string]gocloak.Client + var userMappedClientRoles *gocloak.MappingsRepresentation + var newRoles []string + var clientRolesToAdd []gocloak.Role + // ctx for current try + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + + // get mapped roles of user to check if some role mus be added + if userMappedClientRoles, addErr = tkc.client.GetRoleMappingByUserID(ctx, tkc.token.AccessToken, tkc.realm, idUser); addErr != nil { + cancel() + } + + // get clients to check if needed clients already exist + if clients, addErr = tkc.getClients(ctx); addErr != nil { + cancel() + } + + // loop through given client role combination + for client, roles := range clientRoles { + // check client exist + if _, exist := clients[client]; !exist { + addErr = fmt.Errorf("client '%s' does not exist", client) + break + } + + // check if given role must be added + if mappedClientRoles, exist := userMappedClientRoles.ClientMappings[client]; exist { + SearchForMappedRoles: + for _, role := range roles { + for _, mappedClientRole := range *mappedClientRoles.Mappings { + if role == *mappedClientRole.Name { + // when role already mapped, continue with next role + continue SearchForMappedRoles + } + } + newRoles = append(newRoles, role) + } + } else { + newRoles = roles + } + + // add new roles otherwise do nothing + if len(newRoles) > 0 { + // get roles of client which should be added + if clientRolesToAdd, addErr = tkc.getClientRolesByList(ctx, *clients[client].ID, roles); addErr != nil { + break + } + + // add roles to user + if addErr = tkc.client.AddClientRolesToUser(ctx, tkc.token.AccessToken, tkc.realm, *clients[client].ID, idUser, clientRolesToAdd); addErr != nil { + break + } + } + } + + // cancel ctx + cancel() + + return nil +} +``` \ No newline at end of file diff --git a/examples/USER_FEDERATION.md b/examples/USER_FEDERATION.md new file mode 100644 index 00000000..68c0f7e8 --- /dev/null +++ b/examples/USER_FEDERATION.md @@ -0,0 +1,155 @@ +```go +type Tkc struct { + realm string + token *gocloak.JWT + client *gocloak.GoCloak +} + +func (tkc *Tkc) getRealms(ctx context.Context) (realms map[string]gocloak.RealmRepresentation, getErr error) { + var realmList []*gocloak.RealmRepresentation + + // init map + realms = make(map[string]gocloak.RealmRepresentation) + + // get all realms + if realmList, getErr = tkc.client.GetRealms(ctx, tkc.token.AccessToken); getErr != nil { + getErr = fmt.Errorf("get realms failed (error: %s)", getErr.Error()) + return realms, getErr + } + + // transform to map with realmID (meaning realm name) as map key + for _, r := range realmList { + realms[*r.Realm] = *r + } + + return realms, nil +} + +func (tkc *Tkc) newUserFederation(ctx context.Context) (userFederation gocloak.Component, newErr error) { + var idRealm string + + // get realm ID, is needed as ParentID in gocloak.Component + if realms, newErr := tkc.getRealms(ctx); newErr != nil { + return userFederation, newErr + } else { + idRealm = *realms[tkc.realm].ID + } + + userFederationConfig := make(map[string][]string) + + // keycloak self + userFederationConfig["enabled"] = []string{"true"} + userFederationConfig["priority"] = []string{"1"} + userFederationConfig["importUsers"] = []string{"true"} + + // sync options + userFederationConfig["fullSyncPeriod"] = []string{"-1"} + userFederationConfig["changedSyncPeriod"] = []string{"300"} + userFederationConfig["batchSizeForSync"] = []string{"1000"} + + // ldap connection + userFederationConfig["editMode"] = []string{"READ_ONLY"} + userFederationConfig["vendor"] = []string{"other"} + userFederationConfig["connectionUrl"] = []string{"ldap://ldap"} + userFederationConfig["bindDn"] = []string{"cn=XXX,dc=example,dc=com"} + userFederationConfig["bindCredential"] = []string{"YYYYYY"} + userFederationConfig["usersDn"] = []string{"ou=users,dc=example,dc=com"} + userFederationConfig["usernameLDAPAttribute"] = []string{"uid"} + userFederationConfig["uuidLDAPAttribute"] = []string{"entryUUID"} + userFederationConfig["authType"] = []string{"simple"} + userFederationConfig["userObjectClasses"] = []string{"person, uidObject"} + userFederationConfig["rdnLDAPAttribute"] = []string{"cn"} + userFederationConfig["searchScope"] = []string{"1"} + userFederationConfig["pagination"] = []string{"true"} + + userFederation = gocloak.Component{ + Name: gocloak.StringP("ldap"), + ProviderID: gocloak.StringP("ldap"), + ProviderType: gocloak.StringP("org.keycloak.storage.UserStorageProvider"), + ParentID: gocloak.StringP(idRealm), + ComponentConfig: &userFederationConfig, + } + + return userFederation, nil +} + +func (tkc *Tkc) RunCreateUserFederation() error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + + defer func() { + cancel() + }() + + // user federation is a keycloak component with type 'org.keycloak.storage.UserStorageProvider' + var userFederation gocloak.Component + + // get default new legacy user federation to create or update an existing one + if newUserFederation, runErr := tkc.newUserFederation(ctx); runErr != nil { + return runErr + } else { + userFederation = newUserFederation + } + + // search parameter to get exactly legacy user federation which belongs to given realm (parent) + ldapGetParams := gocloak.GetComponentsParams{ + Name: userFederation.Name, + ProviderType: userFederation.ProviderType, + ParentID: userFederation.ParentID, + } + + if comps, getErr := tkc.client.GetComponentsWithParams(ctx, tkc.token.AccessToken, tkc.realm, ldapGetParams); getErr != nil { + return getErr + } else { + // means user federation not found for given realm + if len(comps) == 0 { + if idUserFederation, createErr := tkc.client.CreateComponent(ctx, tkc.token.AccessToken, tkc.realm, userFederation); createErr != nil { + return createErr + } else { + // do full sync after creating new one + if syncErr := tkc.syncUserFederation(ctx, idUserFederation, true); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' created (%s), but sync failed", *userFederation.Name, idUserFederation) + return syncErr + } + } + } else { + // set ID of user federation for update exactly existing user federation + userFederation.ID = comps[0].ID + if updateErr := tkc.client.UpdateComponent(ctx, tkc.token.AccessToken, tkc.baseConfig.Realm, userFederation); updateErr != nil { + return updateErr + } else { + // do change sync only after update exiting one + if syncErr := tkc.syncUserFederation(ctx, *userFederation.ID, false); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' updated (%s), but sync failed", *userFederation.Name, *userFederation.ID) + return syncErr + } + } + } + } + + return nil +} + +func (tkc *Tkc) syncUserFederation(ctx context.Context, idUserFederation string, fullSync bool) error { + var url string + + url = tkc.baseConfig.Url + "/admin/realms/" + tkc.realm + "/user-storage/" + idUserFederation + "/sync" + + if fullSync { + url += "?action=triggerFullSync" + } else { + url += "?action=triggerChangedUsersSync" + } + + if response, postErr := tkc.client.RestyClient().NewRequest().SetAuthToken(tkc.token.AccessToken).Post(url); postErr != nil { + return postErr + } else { + if response.StatusCode() != 200 { + postErr = fmt.Errorf("got status code '%d' with response body '%s'", response.StatusCode(), response.String()) + return postErr + } + } + + return nil +} +} +``` diff --git a/examples/USER_FEDERATION_GROUP_LDAP_MAPPER.md b/examples/USER_FEDERATION_GROUP_LDAP_MAPPER.md new file mode 100644 index 00000000..22fed4ed --- /dev/null +++ b/examples/USER_FEDERATION_GROUP_LDAP_MAPPER.md @@ -0,0 +1,207 @@ +```go +type Tkc struct { + realm string + token *gocloak.JWT + client *gocloak.GoCloak +} + +// get all ldap mapper for given user federation +func (tk *Tkc) getLdapMapperOfUserFederation(ctx context.Context, idUserFederation string) (mappers map[string]gocloak.Component, getErr error) { + var mapperList []*gocloak.Component + mappers = make(map[string]gocloak.Component) + + // get only typed components for given id + mapperGetParameter := gocloak.GetComponentsParams{ + ProviderType: gocloak.StringP("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"), + ParentID: gocloak.StringP(idUserFederation), + } + + if mapperList, getErr = tk.client.GetComponentsWithParams(ctx, tk.token.AccessToken, tk.realm, mapperGetParameter); getErr != nil { + return mappers, getErr + } + + // transform to map with mapper name as map key + for _, mapper := range mapperList { + mappers[*mapper.Name] = *mapper + } + + return mappers, nil +} + +// create given group ldap mapper for given user federation +func (tk *Tkc) createGroupMapper(ctx context.Context, idUserFederation string, group string) (createErr error) { + var existingMappers map[string]gocloak.Component + var mapper gocloak.Component + var idMapper string + + if existingMappers, createErr = tk.getLdapMapperOfUserFederation(ctx, idUserFederation); createErr != nil { + return createErr + } + + mapper = prepareGroupLdapMapper(group, idUserFederation) + if existingMapper, exists := existingMappers[group]; exists { + mapper.ID = existingMapper.ID + if createErr = tk.client.UpdateComponent(ctx, tk.token.AccessToken, tk.realm, mapper); createErr != nil { + return createErr + } + log.Infof("group ldap mapper '%s' updated (%s)", *mapper.Name, *mapper.ID) + } else { + if idMapper, createErr = tk.client.CreateComponent(ctx, tk.token.AccessToken, tk.realm, mapper); createErr != nil { + return createErr + } + log.Infof("group ldap mapper '%s' created (%s)", *mapper.Name, idMapper) + } + + return nil +} + +// prepare component object of type 'org.keycloak.storage.ldap.mappers.LDAPStorageMapper' with config +func prepareGroupLdapMapper(name, idUserFederation string) (mapper gocloak.Component) { + mapperConfig := make(map[string][]string) + + mapperConfig["mode"] = []string{"LDAP_ONLY"} + mapperConfig["membership.attribute.type"] = []string{"DN"} + mapperConfig["user.roles.retrieve.strategy"] = []string{"LOAD_GROUPS_BY_MEMBER_ATTRIBUTE"} + mapperConfig["group.name.ldap.attribute"] = []string{"cn"} + mapperConfig["membership.ldap.attribute"] = []string{"member"} + mapperConfig["preserve.group.inheritance"] = []string{"true"} + mapperConfig["membership.user.ldap.attribute"] = []string{"uid"} + mapperConfig["ignore.missing.group"] = []string{"false"} + mapperConfig["memberof.ldap.attribute"] = []string{"memberOf"} + mapperConfig["groups.dn"] = []string{"ou=groups,dc=example,dc=com"} + mapperConfig["group.object.classes"] = []string{"groupOfNames"} + mapperConfig["drop.non.existing.groups.during.sync"] = []string{"false"} + + mapper = gocloak.Component{ + Name: gocloak.StringP(name), + ProviderID: gocloak.StringP("group-ldap-mapper"), + ProviderType: gocloak.StringP("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"), + ParentID: gocloak.StringP(idUserFederation), + ComponentConfig: &mapperConfig, + } + + return mapper +} + +// From last example: But with Mappers +func (tkc *Tkc) newUserFederation(ctx context.Context) (userFederation gocloak.Component, newErr error) { + var idRealm string + + // get realm ID, is needed as ParentID in gocloak.Component + if realms, newErr := tkc.getRealms(ctx); newErr != nil { + return userFederation, newErr + } else { + idRealm = *realms[tkc.realm].ID + } + + userFederationConfig := make(map[string][]string) + + // keycloak self + userFederationConfig["enabled"] = []string{"true"} + userFederationConfig["priority"] = []string{"1"} + + // sync options + userFederationConfig["fullSyncPeriod"] = []string{"-1"} + userFederationConfig["changedSyncPeriod"] = []string{"300"} + userFederationConfig["batchSizeForSync"] = []string{"1000"} + userFederationConfig["importUsers"] = []string{"true"} + + // ldap connection + userFederationConfig["editMode"] = []string{"READ_ONLY"} + userFederationConfig["vendor"] = []string{"other"} + userFederationConfig["connectionUrl"] = []string{"ldap://ldap"} + userFederationConfig["bindDn"] = []string{"cn=XXX,dc=example,dc=com"} + userFederationConfig["bindCredential"] = []string{"YYYYYY"} + userFederationConfig["usersDn"] = []string{"ou=users,dc=example,dc=com"} + userFederationConfig["usernameLDAPAttribute"] = []string{"uid"} + userFederationConfig["uuidLDAPAttribute"] = []string{"entryUUID"} + userFederationConfig["authType"] = []string{"simple"} + userFederationConfig["userObjectClasses"] = []string{"person, uidObject"} + userFederationConfig["rdnLDAPAttribute"] = []string{"cn"} + userFederationConfig["searchScope"] = []string{"1"} + userFederationConfig["pagination"] = []string{"true"} + + userFederation = gocloak.Component{ + Name: gocloak.StringP("ldap"), + ProviderID: gocloak.StringP("ldap"), + ProviderType: gocloak.StringP("org.keycloak.storage.UserStorageProvider"), + ParentID: gocloak.StringP(idRealm), + ComponentConfig: &userFederationConfig, + } + + return userFederation, nil +} + +func (tkc *Tkc) RunCreateUserFederation() error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + + defer func() { + cancel() + }() + + // user federation is a keycloak component with type 'org.keycloak.storage.UserStorageProvider' + var userFederation gocloak.Component + + // ldap mappers for legacy user federation + userModelAttributeMappers := make(map[string]string) + userModelAttributeMappers["office"] = "physicalDeliveryOfficeName" + userModelAttributeMappers["department"] = "destinationIndicator" + userModelAttributeMappers["address"] = "postalAddress" + userModelAttributeMappers["telephone"] = "telephoneNumber" + userModelAttributeMappers["fax"] = "facsimileTelephoneNumber" + userModelAttributeMappers["title"] = "title" + userModelAttributeMappers["firstName"] = "cn" + + // ldap group mapper name + groupMapper := "group" + + // get default new legacy user federation to create or update an existing one + if newUserFederation, runErr := tkc.newUserFederation(ctx); runErr != nil { + return runErr + } else { + userFederation = newUserFederation + } + + // search parameter to get exactly legacy user federation which belongs to given realm (parent) + ldapGetParams := gocloak.GetComponentsParams{ + Name: userFederation.Name, + ProviderType: userFederation.ProviderType, + ParentID: userFederation.ParentID, + } + + if comps, getErr := tkc.client.GetComponentsWithParams(ctx, tkc.token.AccessToken, tkc.realm, ldapGetParams); getErr != nil { + return getErr + } else { + // means user federation not found for given realm + if len(comps) == 0 { + if idUserFederation, createErr := tkc.client.CreateComponent(ctx, tkc.token.AccessToken, tkc.realm, userFederation); createErr != nil { + return createErr + } else { + // do create federation group ldap mappers + if createErr := tkc.createGroupMapper(ctx, idUserFederation, groupMapper); createErr != nil { + return createErr + } + // do full sync after creating new one + if syncErr := tkc.syncUserFederation(ctx, idUserFederation, true); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' created (%s), but sync failed", *userFederation.Name, idUserFederation) + return syncErr + } + } + } else { + // set ID of user federation for update exactly existing user federation + userFederation.ID = comps[0].ID + if updateErr := tkc.client.UpdateComponent(ctx, tkc.token.AccessToken, tkc.baseConfig.Realm, userFederation); updateErr != nil { + return updateErr + } else { + // do change sync only after update exiting one + if syncErr := tkc.syncUserFederation(ctx, *userFederation.ID, false); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' updated (%s), but sync failed", *userFederation.Name, *userFederation.ID) + return syncErr + } + } + } + } + + return nil +} +``` \ No newline at end of file diff --git a/examples/USER_FEDERATION_ROLE_LDAP_MAPPER.md b/examples/USER_FEDERATION_ROLE_LDAP_MAPPER.md new file mode 100644 index 00000000..6c0edbc1 --- /dev/null +++ b/examples/USER_FEDERATION_ROLE_LDAP_MAPPER.md @@ -0,0 +1,206 @@ +```go +type Tkc struct { + realm string + token *gocloak.JWT + client *gocloak.GoCloak +} + +// get all ldap mapper for given user federation +func (tk *Tkc) getLdapMapperOfUserFederation(ctx context.Context, idUserFederation string) (mappers map[string]gocloak.Component, getErr error) { + var mapperList []*gocloak.Component + mappers = make(map[string]gocloak.Component) + + // get only typed components for given id + mapperGetParameter := gocloak.GetComponentsParams{ + ProviderType: gocloak.StringP("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"), + ParentID: gocloak.StringP(idUserFederation), + } + + if mapperList, getErr = tk.client.GetComponentsWithParams(ctx, tk.token.AccessToken, tk.realm, mapperGetParameter); getErr != nil { + return mappers, getErr + } + + // transform to map with mapper name as map key + for _, mapper := range mapperList { + mappers[*mapper.Name] = *mapper + } + + return mappers, nil +} + +// create given role ldap mapper for given user federation +func (tk *Tkc) createRoleMapper(ctx context.Context, idUserFederation string, role string) (createErr error) { + var existingMappers map[string]gocloak.Component + var mapper gocloak.Component + var idMapper string + + if existingMappers, createErr = tk.getLdapMapperOfUserFederation(ctx, idUserFederation); createErr != nil { + return createErr + } + + mapper = prepareRoleLdapMapper(role, idUserFederation) + if existingMapper, exists := existingMappers[role]; exists { + mapper.ID = existingMapper.ID + if createErr = tk.client.UpdateComponent(ctx, tk.token.AccessToken, tk.realm, mapper); createErr != nil { + return createErr + } + log.Infof("role ldap mapper '%s' updated (%s)", *mapper.Name, *mapper.ID) + } else { + if idMapper, createErr = tk.client.CreateComponent(ctx, tk.token.AccessToken, tk.realm, mapper); createErr != nil { + return createErr + } + log.Infof("role ldap mapper '%s' created (%s)", *mapper.Name, idMapper) + } + + return nil +} + +// prepare component object of type 'org.keycloak.storage.ldap.mappers.LDAPStorageMapper' with config +func prepareRoleLdapMapper(name, idUserFederation string) (mapper gocloak.Component) { + mapperConfig := make(map[string][]string) + + mapperConfig["roles.dn"] = []string{"ou=roles,dc=example,dc=com"} + mapperConfig["role.name.ldap.attribute"] = []string{"cn"} + mapperConfig["role.object.classes"] = []string{"group"} + mapperConfig["membership.ldap.attribute"] = []string{"member"} + mapperConfig["membership.attribute.type"] = []string{"DN"} + mapperConfig["membership.user.ldap.attribute"] = []string{"cn"} + mapperConfig["mode"] = []string{"IMPORT"} + mapperConfig["user.roles.retrieve.strategy"] = []string{"LOAD_ROLES_BY_MEMBER_ATTRIBUTE"} + mapperConfig["memberof.ldap.attribute"] = []string{"memberOf"} + mapperConfig["use.realm.roles.mapping"] = []string{"true"} + mapperConfig["client.id"] = []string{"account"} + + mapper = gocloak.Component{ + Name: gocloak.StringP(name), + ProviderID: gocloak.StringP("role-ldap-mapper"), + ProviderType: gocloak.StringP("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"), + ParentID: gocloak.StringP(idUserFederation), + ComponentConfig: &mapperConfig, + } + + return mapper +} + +// From last example: But with Mappers +func (tkc *Tkc) newUserFederation(ctx context.Context) (userFederation gocloak.Component, newErr error) { + var idRealm string + + // get realm ID, is needed as ParentID in gocloak.Component + if realms, newErr := tkc.getRealms(ctx); newErr != nil { + return userFederation, newErr + } else { + idRealm = *realms[tkc.realm].ID + } + + userFederationConfig := make(map[string][]string) + + // keycloak self + userFederationConfig["enabled"] = []string{"true"} + userFederationConfig["priority"] = []string{"1"} + + // sync options + userFederationConfig["fullSyncPeriod"] = []string{"-1"} + userFederationConfig["changedSyncPeriod"] = []string{"300"} + userFederationConfig["batchSizeForSync"] = []string{"1000"} + userFederationConfig["importUsers"] = []string{"true"} + + // ldap connection + userFederationConfig["editMode"] = []string{"READ_ONLY"} + userFederationConfig["vendor"] = []string{"other"} + userFederationConfig["connectionUrl"] = []string{"ldap://ldap"} + userFederationConfig["bindDn"] = []string{"cn=XXX,dc=example,dc=com"} + userFederationConfig["bindCredential"] = []string{"YYYYYY"} + userFederationConfig["usersDn"] = []string{"ou=users,dc=example,dc=com"} + userFederationConfig["usernameLDAPAttribute"] = []string{"uid"} + userFederationConfig["uuidLDAPAttribute"] = []string{"entryUUID"} + userFederationConfig["authType"] = []string{"simple"} + userFederationConfig["userObjectClasses"] = []string{"person, uidObject"} + userFederationConfig["rdnLDAPAttribute"] = []string{"cn"} + userFederationConfig["searchScope"] = []string{"1"} + userFederationConfig["pagination"] = []string{"true"} + + userFederation = gocloak.Component{ + Name: gocloak.StringP("ldap"), + ProviderID: gocloak.StringP("ldap"), + ProviderType: gocloak.StringP("org.keycloak.storage.UserStorageProvider"), + ParentID: gocloak.StringP(idRealm), + ComponentConfig: &userFederationConfig, + } + + return userFederation, nil +} + +func (tkc *Tkc) RunCreateUserFederation() error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + + defer func() { + cancel() + }() + + // user federation is a keycloak component with type 'org.keycloak.storage.UserStorageProvider' + var userFederation gocloak.Component + + // ldap mappers for legacy user federation + userModelAttributeMappers := make(map[string]string) + userModelAttributeMappers["office"] = "physicalDeliveryOfficeName" + userModelAttributeMappers["department"] = "destinationIndicator" + userModelAttributeMappers["address"] = "postalAddress" + userModelAttributeMappers["telephone"] = "telephoneNumber" + userModelAttributeMappers["fax"] = "facsimileTelephoneNumber" + userModelAttributeMappers["title"] = "title" + userModelAttributeMappers["firstName"] = "cn" + + // ldap role mapper name + roleMapper := "role" + + // get default new legacy user federation to create or update an existing one + if newUserFederation, runErr := tkc.newUserFederation(ctx); runErr != nil { + return runErr + } else { + userFederation = newUserFederation + } + + // search parameter to get exactly legacy user federation which belongs to given realm (parent) + ldapGetParams := gocloak.GetComponentsParams{ + Name: userFederation.Name, + ProviderType: userFederation.ProviderType, + ParentID: userFederation.ParentID, + } + + if comps, getErr := tkc.client.GetComponentsWithParams(ctx, tkc.token.AccessToken, tkc.realm, ldapGetParams); getErr != nil { + return getErr + } else { + // means user federation not found for given realm + if len(comps) == 0 { + if idUserFederation, createErr := tkc.client.CreateComponent(ctx, tkc.token.AccessToken, tkc.realm, userFederation); createErr != nil { + return createErr + } else { + // do create federation role ldap mappers + if createErr := tkc.createRoleMapper(ctx, idUserFederation, roleMapper); createErr != nil { + return createErr + } + // do full sync after creating new one + if syncErr := tkc.syncUserFederation(ctx, idUserFederation, true); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' created (%s), but sync failed", *userFederation.Name, idUserFederation) + return syncErr + } + } + } else { + // set ID of user federation for update exactly existing user federation + userFederation.ID = comps[0].ID + if updateErr := tkc.client.UpdateComponent(ctx, tkc.token.AccessToken, tkc.baseConfig.Realm, userFederation); updateErr != nil { + return updateErr + } else { + // do change sync only after update exiting one + if syncErr := tkc.syncUserFederation(ctx, *userFederation.ID, false); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' updated (%s), but sync failed", *userFederation.Name, *userFederation.ID) + return syncErr + } + } + } + } + + return nil +} +``` \ No newline at end of file diff --git a/examples/USER_FEDERATION_USER_ATTRIBUTE_LDAP_MAPPER.md b/examples/USER_FEDERATION_USER_ATTRIBUTE_LDAP_MAPPER.md new file mode 100644 index 00000000..7ba5998e --- /dev/null +++ b/examples/USER_FEDERATION_USER_ATTRIBUTE_LDAP_MAPPER.md @@ -0,0 +1,200 @@ +```go +type Tkc struct { + realm string + token *gocloak.JWT + client *gocloak.GoCloak +} + +// get all ldap mapper for given user federation +func (tk *Tkc) getLdapMapperOfUserFederation(ctx context.Context, idUserFederation string) (mappers map[string]gocloak.Component, getErr error) { + var mapperList []*gocloak.Component + mappers = make(map[string]gocloak.Component) + + // get only typed components for given id + mapperGetParameter := gocloak.GetComponentsParams{ + ProviderType: gocloak.StringP("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"), + ParentID: gocloak.StringP(idUserFederation), + } + + if mapperList, getErr = tk.client.GetComponentsWithParams(ctx, tk.token.AccessToken, tk.realm, mapperGetParameter); getErr != nil { + return mappers, getErr + } + + // transform to map with mapper name as map key + for _, mapper := range mapperList { + mappers[*mapper.Name] = *mapper + } + + return mappers, nil +} + +// create given user ldap attribute mappers for given user federation +func (tk *Tkc) createUserModelAttributeMapper(ctx context.Context, idUserFederation string, mappers map[string]string) (createErr error) { + var existingMappers map[string]gocloak.Component + var mapper gocloak.Component + var idMapper string + + if existingMappers, createErr = tk.getLdapMapperOfUserFederation(ctx, idUserFederation); createErr != nil { + return createErr + } + + for userModelAttribute, ldapAttribute := range mappers { + mapper = prepareUserModelAttributeMapper(userModelAttribute, ldapAttribute, idUserFederation) + if existingMapper, exists := existingMappers[userModelAttribute]; exists { + mapper.ID = existingMapper.ID + if createErr = tk.client.UpdateComponent(ctx, tk.token.AccessToken, tk.realm, mapper); createErr != nil { + return createErr + } + log.Infof("user attribute ldap mapper '%s' updated (%s)", *mapper.Name, *mapper.ID) + } else { + if idMapper, createErr = tk.client.CreateComponent(ctx, tk.token.AccessToken, tk.realm, mapper); createErr != nil { + return createErr + } + log.Infof("user attribute ldap mapper '%s' created (%s)", *mapper.Name, idMapper) + } + } + + return nil +} + + +// prepare component object of type 'org.keycloak.storage.ldap.mappers.LDAPStorageMapper' and ProviderId 'user-attribute-ldap-mapper' with config +func prepareUserModelAttributeMapper(userModelAttribute, ldapAttribute, idUserFederation string) (mapper gocloak.Component) { + mapperConfig := make(map[string][]string) + + mapperConfig["ldap.attribute"] = []string{ldapAttribute} + mapperConfig["user.model.attribute"] = []string{userModelAttribute} + mapperConfig["is.mandatory.in.ldap"] = []string{"false"} + mapperConfig["always.read.value.from.ldap"] = []string{"false"} + mapperConfig["read.only"] = []string{"true"} + + mapper = gocloak.Component{ + Name: gocloak.StringP(userModelAttribute), + ProviderID: gocloak.StringP("user-attribute-ldap-mapper"), + ProviderType: gocloak.StringP("org.keycloak.storage.ldap.mappers.LDAPStorageMapper"), + ParentID: gocloak.StringP(idUserFederation), + ComponentConfig: &mapperConfig, + } + + return mapper +} + +// From last example: But with Mappers +func (tkc *Tkc) newUserFederation(ctx context.Context) (userFederation gocloak.Component, newErr error) { + var idRealm string + + // get realm ID, is needed as ParentID in gocloak.Component + if realms, newErr := tkc.getRealms(ctx); newErr != nil { + return userFederation, newErr + } else { + idRealm = *realms[tkc.realm].ID + } + + userFederationConfig := make(map[string][]string) + + // keycloak self + userFederationConfig["enabled"] = []string{"true"} + userFederationConfig["priority"] = []string{"1"} + + // sync options + userFederationConfig["fullSyncPeriod"] = []string{"-1"} + userFederationConfig["changedSyncPeriod"] = []string{"300"} + userFederationConfig["batchSizeForSync"] = []string{"1000"} + userFederationConfig["importUsers"] = []string{"true"} + + // ldap connection + userFederationConfig["editMode"] = []string{"READ_ONLY"} + userFederationConfig["vendor"] = []string{"other"} + userFederationConfig["connectionUrl"] = []string{"ldap://ldap"} + userFederationConfig["bindDn"] = []string{"cn=XXX,dc=example,dc=com"} + userFederationConfig["bindCredential"] = []string{"YYYYYY"} + userFederationConfig["usersDn"] = []string{"ou=users,dc=example,dc=com"} + userFederationConfig["usernameLDAPAttribute"] = []string{"uid"} + userFederationConfig["uuidLDAPAttribute"] = []string{"entryUUID"} + userFederationConfig["authType"] = []string{"simple"} + userFederationConfig["userObjectClasses"] = []string{"person, uidObject"} + userFederationConfig["rdnLDAPAttribute"] = []string{"cn"} + userFederationConfig["searchScope"] = []string{"1"} + userFederationConfig["pagination"] = []string{"true"} + + userFederation = gocloak.Component{ + Name: gocloak.StringP("ldap"), + ProviderID: gocloak.StringP("ldap"), + ProviderType: gocloak.StringP("org.keycloak.storage.UserStorageProvider"), + ParentID: gocloak.StringP(idRealm), + ComponentConfig: &userFederationConfig, + } + + return userFederation, nil +} + +func (tkc *Tkc) RunCreateUserFederation() error { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + + defer func() { + cancel() + }() + + // user federation is a keycloak component with type 'org.keycloak.storage.UserStorageProvider' + var userFederation gocloak.Component + + // ldap mappers for legacy user federation + userModelAttributeMappers := make(map[string]string) + userModelAttributeMappers["office"] = "physicalDeliveryOfficeName" + userModelAttributeMappers["department"] = "destinationIndicator" + userModelAttributeMappers["address"] = "postalAddress" + userModelAttributeMappers["telephone"] = "telephoneNumber" + userModelAttributeMappers["fax"] = "facsimileTelephoneNumber" + userModelAttributeMappers["title"] = "title" + userModelAttributeMappers["firstName"] = "cn" + + // get default new legacy user federation to create or update an existing one + if newUserFederation, runErr := tkc.newUserFederation(ctx); runErr != nil { + return runErr + } else { + userFederation = newUserFederation + } + + // search parameter to get exactly legacy user federation which belongs to given realm (parent) + ldapGetParams := gocloak.GetComponentsParams{ + Name: userFederation.Name, + ProviderType: userFederation.ProviderType, + ParentID: userFederation.ParentID, + } + + if comps, getErr := tkc.client.GetComponentsWithParams(ctx, tkc.token.AccessToken, tkc.realm, ldapGetParams); getErr != nil { + return getErr + } else { + // means user federation not found for given realm + if len(comps) == 0 { + if idUserFederation, createErr := tkc.client.CreateComponent(ctx, tkc.token.AccessToken, tkc.realm, userFederation); createErr != nil { + return createErr + } else { + // do create federation user attribute ldap mappers + if createErr := tkc.createUserModelAttributeMapper(ctx, idUserFederation, userModelAttributeMappers); createErr != nil { + return createErr + } + // do full sync after creating new one + if syncErr := tkc.syncUserFederation(ctx, idUserFederation, true); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' created (%s), but sync failed", *userFederation.Name, idUserFederation) + return syncErr + } + } + } else { + // set ID of user federation for update exactly existing user federation + userFederation.ID = comps[0].ID + if updateErr := tkc.client.UpdateComponent(ctx, tkc.token.AccessToken, tkc.baseConfig.Realm, userFederation); updateErr != nil { + return updateErr + } else { + // do change sync only after update exiting one + if syncErr := tkc.syncUserFederation(ctx, *userFederation.ID, false); syncErr != nil { + syncErr = fmt.Errorf("legacy user federation '%s' updated (%s), but sync failed", *userFederation.Name, *userFederation.ID) + return syncErr + } + } + } + } + + return nil +} +``` \ No newline at end of file From 64210723be229939e149f15e42616b7b77b74331 Mon Sep 17 00:00:00 2001 From: mattkeeler <19890779+mattkeeler@users.noreply.github.com> Date: Tue, 21 Mar 2023 06:17:02 -0400 Subject: [PATCH 42/60] Fix token introspection example (#408) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fefe2ac..9ab5ee24 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ go get github.com/Nerzal/gocloak/v13 panic("Inspection failed:"+ err.Error()) } - if !rptResult.Active { + if !*rptResult.Active { panic("Token is not active") } From a521bf02a43a487b0a3212aa3273eb5d15012862 Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 5 Apr 2023 03:39:55 -0700 Subject: [PATCH 43/60] initial (#412) Co-authored-by: Mike Osmian --- Makefile | 6 +++-- client_benchmark_test.go | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1664ecb4..0409e817 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ test: ./run-tests.sh -start-keycloak: +start-keycloak: stop-keycloak + docker-compose up -d + +stop-keycloak: docker-compose down - docker-compose up -d \ No newline at end of file diff --git a/client_benchmark_test.go b/client_benchmark_test.go index dc8d9491..2e9ae7e5 100644 --- a/client_benchmark_test.go +++ b/client_benchmark_test.go @@ -46,3 +46,57 @@ func BenchmarkLoginParallel(b *testing.B) { } }) } + +func BenchmarkGetGroups(b *testing.B) { + cfg := GetConfig(b) + client := gocloak.NewClient(cfg.HostName) + token := GetAdminToken(b, client) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := client.GetGroups( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloak.GetGroupsParams{}, + ) + assert.NoError(b, err) + } +} + +func BenchmarkGetGroupsFull(b *testing.B) { + cfg := GetConfig(b) + client := gocloak.NewClient(cfg.HostName) + token := GetAdminToken(b, client) + params := gocloak.GetGroupsParams{ + Full: gocloak.BoolP(true), + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := client.GetGroups( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + params, + ) + assert.NoError(b, err) + } +} + +func BenchmarkGetGroupsBrief(b *testing.B) { + cfg := GetConfig(b) + client := gocloak.NewClient(cfg.HostName) + params := gocloak.GetGroupsParams{ + BriefRepresentation: gocloak.BoolP(true), + } + token := GetAdminToken(b, client) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := client.GetGroups( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + params, + ) + assert.NoError(b, err) + } +} From 21898478be85b381d9c3aa9ebecf66ae21da02bb Mon Sep 17 00:00:00 2001 From: mattkeeler <19890779+mattkeeler@users.noreply.github.com> Date: Thu, 6 Apr 2023 10:50:40 -0400 Subject: [PATCH 44/60] add missing fields to GetGroupsParams struct (#413) --- models.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/models.go b/models.go index 17922d9d..21536ae2 100644 --- a/models.go +++ b/models.go @@ -342,11 +342,13 @@ type GroupsCount struct { // GetGroupsParams represents the optional parameters for getting groups type GetGroupsParams struct { + BriefRepresentation *bool `json:"briefRepresentation,string,omitempty"` + Exact *bool `json:"exact,string,omitempty"` First *int `json:"first,string,omitempty"` + Full *bool `json:"full,string,omitempty"` Max *int `json:"max,string,omitempty"` + Q *string `json:"q,omitempty"` Search *string `json:"search,omitempty"` - Full *bool `json:"full,string,omitempty"` - BriefRepresentation *bool `json:"briefRepresentation,string,omitempty"` } // MarshalJSON is a custom json marshaling function to automatically set the Full and BriefRepresentation properties From ff2d01beda367e68a08a55722a355988bf027821 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 13 Apr 2023 03:35:36 -0700 Subject: [PATCH 45/60] get group and get group by path benchmarks (#414) Co-authored-by: Mike Osmian --- client_benchmark_test.go | 38 ++++++++++++++++++++++++++++++++++++++ client_test.go | 6 ++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/client_benchmark_test.go b/client_benchmark_test.go index 2e9ae7e5..fca042d2 100644 --- a/client_benchmark_test.go +++ b/client_benchmark_test.go @@ -100,3 +100,41 @@ func BenchmarkGetGroupsBrief(b *testing.B) { assert.NoError(b, err) } } + +func BenchmarkGetGroup(b *testing.B) { + cfg := GetConfig(b) + client := gocloak.NewClient(cfg.HostName) + teardown, groupID := CreateGroup(b, client) + defer teardown() + token := GetAdminToken(b, client) + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := client.GetGroup( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + groupID, + ) + assert.NoError(b, err) + } +} + +func BenchmarkGetGroupByPath(b *testing.B) { + cfg := GetConfig(b) + client := gocloak.NewClient(cfg.HostName) + teardown, groupID := CreateGroup(b, client) + token := GetAdminToken(b, client) + group, err := client.GetGroup(context.Background(), token.AccessToken, cfg.GoCloak.Realm, groupID) + assert.NoError(b, err) + defer teardown() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := client.GetGroupByPath( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *group.Path, + ) + assert.NoError(b, err) + } +} diff --git a/client_test.go b/client_test.go index 08bacd7e..b59c9cf4 100644 --- a/client_test.go +++ b/client_test.go @@ -163,7 +163,7 @@ func GetClientByClientID(t *testing.T, client *gocloak.GoCloak, clientID string) return nil } -func CreateGroup(t *testing.T, client *gocloak.GoCloak) (func(), string) { +func CreateGroup(t testing.TB, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) group := gocloak.Group{ @@ -179,7 +179,9 @@ func CreateGroup(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg.GoCloak.Realm, group) require.NoError(t, err, "CreateGroup failed") - t.Logf("Created Group ID: %s ", groupID) + if _, isBenchmark := t.(*testing.B); !isBenchmark { + t.Logf("Created Group ID: %s ", groupID) + } tearDown := func() { err := client.DeleteGroup( From 781427a6df84d524cb60d9aa7d0f1c410eb130df Mon Sep 17 00:00:00 2001 From: Michael Weibel <307427+mweibel@users.noreply.github.com> Date: Thu, 13 Apr 2023 12:36:45 +0200 Subject: [PATCH 46/60] feat: expose getRequest* methods for custom endpoints (#405) keycloak is able to have extensions and it would be nice to not have to construct everything againn and just use a custom endpoint. fixes #219 --- client.go | 497 +++++++++++++++++++++++++++--------------------------- 1 file changed, 251 insertions(+), 246 deletions(-) diff --git a/client.go b/client.go index 9967e533..c7ac075d 100644 --- a/client.go +++ b/client.go @@ -47,7 +47,8 @@ func makeURL(path ...string) string { return strings.Join(path, urlSeparator) } -func (g *GoCloak) getRequest(ctx context.Context) *resty.Request { +// GetRequest returns a request for calling endpoints. +func (g *GoCloak) GetRequest(ctx context.Context) *resty.Request { var err HTTPErrorResponse return injectTracingHeaders( ctx, g.restyClient.R(). @@ -56,27 +57,31 @@ func (g *GoCloak) getRequest(ctx context.Context) *resty.Request { ) } -func (g *GoCloak) getRequestWithBearerAuthNoCache(ctx context.Context, token string) *resty.Request { - return g.getRequest(ctx). +// GetRequestWithBearerAuthNoCache returns a JSON base request configured with an auth token and no-cache header. +func (g *GoCloak) GetRequestWithBearerAuthNoCache(ctx context.Context, token string) *resty.Request { + return g.GetRequest(ctx). SetAuthToken(token). SetHeader("Content-Type", "application/json"). SetHeader("Cache-Control", "no-cache") } -func (g *GoCloak) getRequestWithBearerAuth(ctx context.Context, token string) *resty.Request { - return g.getRequest(ctx). +// GetRequestWithBearerAuth returns a JSON base request configured with an auth token. +func (g *GoCloak) GetRequestWithBearerAuth(ctx context.Context, token string) *resty.Request { + return g.GetRequest(ctx). SetAuthToken(token). SetHeader("Content-Type", "application/json") } -func (g *GoCloak) getRequestWithBearerAuthXMLHeader(ctx context.Context, token string) *resty.Request { - return g.getRequest(ctx). +// GetRequestWithBearerAuthXMLHeader returns an XML base request configured with an auth token. +func (g *GoCloak) GetRequestWithBearerAuthXMLHeader(ctx context.Context, token string) *resty.Request { + return g.GetRequest(ctx). SetAuthToken(token). SetHeader("Content-Type", "application/xml;charset=UTF-8") } -func (g *GoCloak) getRequestWithBasicAuth(ctx context.Context, clientID, clientSecret string) *resty.Request { - req := g.getRequest(ctx). +// GetRequestWithBasicAuth returns a form data base request configured with basic auth. +func (g *GoCloak) GetRequestWithBasicAuth(ctx context.Context, clientID, clientSecret string) *resty.Request { + req := g.GetRequest(ctx). SetHeader("Content-Type", "application/x-www-form-urlencoded") // Public client doesn't require Basic Auth if len(clientID) > 0 && len(clientSecret) > 0 { @@ -88,7 +93,7 @@ func (g *GoCloak) getRequestWithBasicAuth(ctx context.Context, clientID, clientS } func (g *GoCloak) getRequestingParty(ctx context.Context, token string, realm string, options RequestingPartyTokenOptions, res interface{}) (*resty.Response, error) { - return g.getRequestWithBearerAuth(ctx, token). + return g.GetRequestWithBearerAuth(ctx, token). SetFormData(options.FormData()). SetFormDataFromValues(url.Values{"permission": PStringSlice(options.Permissions)}). SetResult(&res). @@ -278,7 +283,7 @@ func (g *GoCloak) GetServerInfo(ctx context.Context, accessToken string) ([]*Ser errMessage := "could not get server info" var result []*ServerInfoRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). Get(makeURL(g.basePath, "admin", "realms")) @@ -294,7 +299,7 @@ func (g *GoCloak) GetUserInfo(ctx context.Context, accessToken, realm string) (* const errMessage = "could not get user info" var result UserInfo - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). Get(g.getRealmURL(realm, g.Config.openIDConnect, "userinfo")) @@ -310,7 +315,7 @@ func (g *GoCloak) GetRawUserInfo(ctx context.Context, accessToken, realm string) const errMessage = "could not get user info" var result map[string]interface{} - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). Get(g.getRealmURL(realm, g.Config.openIDConnect, "userinfo")) @@ -325,7 +330,7 @@ func (g *GoCloak) getNewCerts(ctx context.Context, realm string) (*CertResponse, const errMessage = "could not get newCerts" var result CertResponse - resp, err := g.getRequest(ctx). + resp, err := g.GetRequest(ctx). SetResult(&result). Get(g.getRealmURL(realm, g.Config.openIDConnect, "certs")) @@ -369,7 +374,7 @@ func (g *GoCloak) GetIssuer(ctx context.Context, realm string) (*IssuerResponse, const errMessage = "could not get issuer" var result IssuerResponse - resp, err := g.getRequest(ctx). + resp, err := g.GetRequest(ctx). SetResult(&result). Get(g.getRealmURL(realm)) @@ -385,7 +390,7 @@ func (g *GoCloak) RetrospectToken(ctx context.Context, accessToken, clientID, cl const errMessage = "could not introspect requesting party token" var result IntroSpectTokenResult - resp, err := g.getRequestWithBasicAuth(ctx, clientID, clientSecret). + resp, err := g.GetRequestWithBasicAuth(ctx, clientID, clientSecret). SetFormData(map[string]string{ "token_type_hint": "requesting_party_token", "token": accessToken, @@ -452,9 +457,9 @@ func (g *GoCloak) GetToken(ctx context.Context, realm string, options TokenOptio var req *resty.Request if !NilOrEmpty(options.ClientSecret) { - req = g.getRequestWithBasicAuth(ctx, *options.ClientID, *options.ClientSecret) + req = g.GetRequestWithBasicAuth(ctx, *options.ClientID, *options.ClientSecret) } else { - req = g.getRequest(ctx) + req = g.GetRequest(ctx) } resp, err := req.SetFormData(options.FormData()). @@ -620,7 +625,7 @@ func (g *GoCloak) LoginOtp(ctx context.Context, clientID, clientSecret, realm, u func (g *GoCloak) Logout(ctx context.Context, clientID, clientSecret, realm, refreshToken string) error { const errMessage = "could not logout" - resp, err := g.getRequestWithBasicAuth(ctx, clientID, clientSecret). + resp, err := g.GetRequestWithBasicAuth(ctx, clientID, clientSecret). SetFormData(map[string]string{ "client_id": clientID, "refresh_token": refreshToken, @@ -634,7 +639,7 @@ func (g *GoCloak) Logout(ctx context.Context, clientID, clientSecret, realm, ref func (g *GoCloak) LogoutPublicClient(ctx context.Context, clientID, realm, accessToken, refreshToken string) error { const errMessage = "could not logout public client" - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetFormData(map[string]string{ "client_id": clientID, "refresh_token": refreshToken, @@ -648,7 +653,7 @@ func (g *GoCloak) LogoutPublicClient(ctx context.Context, clientID, realm, acces func (g *GoCloak) LogoutAllSessions(ctx context.Context, accessToken, realm, userID string) error { const errMessage = "could not logout" - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). Post(g.getAdminRealmURL(realm, "users", userID, "logout")) return checkForError(resp, err, errMessage) @@ -658,7 +663,7 @@ func (g *GoCloak) LogoutAllSessions(ctx context.Context, accessToken, realm, use func (g *GoCloak) RevokeUserConsents(ctx context.Context, accessToken, realm, userID, clientID string) error { const errMessage = "could not revoke consents" - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). Delete(g.getAdminRealmURL(realm, "users", userID, "consents", clientID)) return checkForError(resp, err, errMessage) @@ -668,7 +673,7 @@ func (g *GoCloak) RevokeUserConsents(ctx context.Context, accessToken, realm, us func (g *GoCloak) LogoutUserSession(ctx context.Context, accessToken, realm, session string) error { const errMessage = "could not logout" - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). Delete(g.getAdminRealmURL(realm, "sessions", session)) return checkForError(resp, err, errMessage) @@ -683,7 +688,7 @@ func (g *GoCloak) ExecuteActionsEmail(ctx context.Context, token, realm string, return errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(params.Actions). SetQueryParams(queryParams). Put(g.getAdminRealmURL(realm, "users", *(params.UserID), "execute-actions-email")) @@ -706,7 +711,7 @@ func (g *GoCloak) SendVerifyEmail(ctx context.Context, token, userID, realm stri } } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetQueryParams(queryParams). Put(g.getAdminRealmURL(realm, "users", userID, "send-verify-email")) @@ -717,7 +722,7 @@ func (g *GoCloak) SendVerifyEmail(ctx context.Context, token, userID, realm stri func (g *GoCloak) CreateGroup(ctx context.Context, token, realm string, group Group) (string, error) { const errMessage = "could not create group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(group). Post(g.getAdminRealmURL(realm, "groups")) @@ -731,7 +736,7 @@ func (g *GoCloak) CreateGroup(ctx context.Context, token, realm string, group Gr func (g *GoCloak) CreateChildGroup(ctx context.Context, token, realm, groupID string, group Group) (string, error) { const errMessage = "could not create child group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(group). Post(g.getAdminRealmURL(realm, "groups", groupID, "children")) @@ -746,7 +751,7 @@ func (g *GoCloak) CreateChildGroup(ctx context.Context, token, realm, groupID st func (g *GoCloak) CreateComponent(ctx context.Context, token, realm string, component Component) (string, error) { const errMessage = "could not create component" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(component). Post(g.getAdminRealmURL(realm, "components")) @@ -761,7 +766,7 @@ func (g *GoCloak) CreateComponent(ctx context.Context, token, realm string, comp func (g *GoCloak) CreateClient(ctx context.Context, accessToken, realm string, newClient Client) (string, error) { const errMessage = "could not create client" - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetBody(newClient). Post(g.getAdminRealmURL(realm, "clients")) @@ -778,7 +783,7 @@ func (g *GoCloak) CreateClientRepresentation(ctx context.Context, token, realm s var result Client - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(newClient). Post(g.getRealmURL(realm, "clients-registrations", "default")) @@ -794,7 +799,7 @@ func (g *GoCloak) CreateClientRepresentation(ctx context.Context, token, realm s func (g *GoCloak) CreateClientRole(ctx context.Context, token, realm, idOfClient string, role Role) (string, error) { const errMessage = "could not create client role" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(role). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "roles")) @@ -809,7 +814,7 @@ func (g *GoCloak) CreateClientRole(ctx context.Context, token, realm, idOfClient func (g *GoCloak) CreateClientScope(ctx context.Context, token, realm string, scope ClientScope) (string, error) { const errMessage = "could not create client scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(scope). Post(g.getAdminRealmURL(realm, "client-scopes")) @@ -824,7 +829,7 @@ func (g *GoCloak) CreateClientScope(ctx context.Context, token, realm string, sc func (g *GoCloak) CreateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) (string, error) { const errMessage = "could not create client scope protocol mapper" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(protocolMapper). Post(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) @@ -842,7 +847,7 @@ func (g *GoCloak) UpdateGroup(ctx context.Context, token, realm string, updatedG if NilOrEmpty(updatedGroup.ID) { return errors.Wrap(errors.New("ID of a group required"), errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(updatedGroup). Put(g.getAdminRealmURL(realm, "groups", PString(updatedGroup.ID))) @@ -857,7 +862,7 @@ func (g *GoCloak) UpdateClient(ctx context.Context, token, realm string, updated return errors.Wrap(errors.New("ID of a client required"), errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(updatedClient). Put(g.getAdminRealmURL(realm, "clients", PString(updatedClient.ID))) @@ -874,7 +879,7 @@ func (g *GoCloak) UpdateClientRepresentation(ctx context.Context, accessToken, r var result Client - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). SetBody(updatedClient). Put(g.getRealmURL(realm, "clients-registrations", "default", PString(updatedClient.ClientID))) @@ -890,7 +895,7 @@ func (g *GoCloak) UpdateClientRepresentation(ctx context.Context, accessToken, r func (g *GoCloak) UpdateRole(ctx context.Context, token, realm, idOfClient string, role Role) error { const errMessage = "could not update role" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(role). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", PString(role.Name))) @@ -901,7 +906,7 @@ func (g *GoCloak) UpdateRole(ctx context.Context, token, realm, idOfClient strin func (g *GoCloak) UpdateClientScope(ctx context.Context, token, realm string, scope ClientScope) error { const errMessage = "could not update client scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(scope). Put(g.getAdminRealmURL(realm, "client-scopes", PString(scope.ID))) @@ -912,7 +917,7 @@ func (g *GoCloak) UpdateClientScope(ctx context.Context, token, realm string, sc func (g *GoCloak) UpdateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) error { const errMessage = "could not update client scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(protocolMapper). Put(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", PString(protocolMapper.ID))) @@ -923,7 +928,7 @@ func (g *GoCloak) UpdateClientScopeProtocolMapper(ctx context.Context, token, re func (g *GoCloak) DeleteGroup(ctx context.Context, token, realm, groupID string) error { const errMessage = "could not delete group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "groups", groupID)) return checkForError(resp, err, errMessage) @@ -933,7 +938,7 @@ func (g *GoCloak) DeleteGroup(ctx context.Context, token, realm, groupID string) func (g *GoCloak) DeleteClient(ctx context.Context, token, realm, idOfClient string) error { const errMessage = "could not delete client" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient)) return checkForError(resp, err, errMessage) @@ -943,7 +948,7 @@ func (g *GoCloak) DeleteClient(ctx context.Context, token, realm, idOfClient str func (g *GoCloak) DeleteComponent(ctx context.Context, token, realm, componentID string) error { const errMessage = "could not delete component" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "components", componentID)) return checkForError(resp, err, errMessage) @@ -953,7 +958,7 @@ func (g *GoCloak) DeleteComponent(ctx context.Context, token, realm, componentID func (g *GoCloak) DeleteClientRepresentation(ctx context.Context, accessToken, realm, clientID string) error { const errMessage = "could not delete client representation" - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). Delete(g.getRealmURL(realm, "clients-registrations", "default", clientID)) return checkForError(resp, err, errMessage) @@ -963,7 +968,7 @@ func (g *GoCloak) DeleteClientRepresentation(ctx context.Context, accessToken, r func (g *GoCloak) DeleteClientRole(ctx context.Context, token, realm, idOfClient, roleName string) error { const errMessage = "could not delete client role" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName)) return checkForError(resp, err, errMessage) @@ -973,7 +978,7 @@ func (g *GoCloak) DeleteClientRole(ctx context.Context, token, realm, idOfClient func (g *GoCloak) DeleteClientScope(ctx context.Context, token, realm, scopeID string) error { const errMessage = "could not delete client scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "client-scopes", scopeID)) return checkForError(resp, err, errMessage) @@ -983,7 +988,7 @@ func (g *GoCloak) DeleteClientScope(ctx context.Context, token, realm, scopeID s func (g *GoCloak) DeleteClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) error { const errMessage = "could not delete client scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) return checkForError(resp, err, errMessage) @@ -995,7 +1000,7 @@ func (g *GoCloak) GetClient(ctx context.Context, token, realm, idOfClient string var result Client - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient)) @@ -1012,7 +1017,7 @@ func (g *GoCloak) GetClientRepresentation(ctx context.Context, accessToken, real var result Client - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). Get(g.getRealmURL(realm, "clients-registrations", "default", clientID)) @@ -1029,7 +1034,7 @@ func (g *GoCloak) GetAdapterConfiguration(ctx context.Context, accessToken, real var result AdapterConfiguration - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). Get(g.getRealmURL(realm, "clients-registrations", "install", clientID)) @@ -1046,7 +1051,7 @@ func (g *GoCloak) GetClientsDefaultScopes(ctx context.Context, token, realm, idO var result []*ClientScope - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes")) @@ -1061,7 +1066,7 @@ func (g *GoCloak) GetClientsDefaultScopes(ctx context.Context, token, realm, idO func (g *GoCloak) AddDefaultScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not add default scope to client" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes", scopeID)) return checkForError(resp, err, errMessage) @@ -1071,7 +1076,7 @@ func (g *GoCloak) AddDefaultScopeToClient(ctx context.Context, token, realm, idO func (g *GoCloak) RemoveDefaultScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not remove default scope from client" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "default-client-scopes", scopeID)) return checkForError(resp, err, errMessage) @@ -1083,7 +1088,7 @@ func (g *GoCloak) GetClientsOptionalScopes(ctx context.Context, token, realm, id var result []*ClientScope - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes")) @@ -1098,7 +1103,7 @@ func (g *GoCloak) GetClientsOptionalScopes(ctx context.Context, token, realm, id func (g *GoCloak) AddOptionalScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not add optional scope to client" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes", scopeID)) return checkForError(resp, err, errMessage) @@ -1108,7 +1113,7 @@ func (g *GoCloak) AddOptionalScopeToClient(ctx context.Context, token, realm, id func (g *GoCloak) RemoveOptionalScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not remove optional scope from client" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "optional-client-scopes", scopeID)) return checkForError(resp, err, errMessage) @@ -1120,7 +1125,7 @@ func (g *GoCloak) GetDefaultOptionalClientScopes(ctx context.Context, token, rea var result []*ClientScope - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "default-optional-client-scopes")) @@ -1137,7 +1142,7 @@ func (g *GoCloak) GetDefaultDefaultClientScopes(ctx context.Context, token, real var result []*ClientScope - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "default-default-client-scopes")) @@ -1154,7 +1159,7 @@ func (g *GoCloak) GetClientScope(ctx context.Context, token, realm, scopeID stri var result ClientScope - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes", scopeID)) @@ -1171,7 +1176,7 @@ func (g *GoCloak) GetClientScopes(ctx context.Context, token, realm string) ([]* var result []*ClientScope - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes")) @@ -1188,7 +1193,7 @@ func (g *GoCloak) GetClientScopeProtocolMappers(ctx context.Context, token, real var result []*ProtocolMappers - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models")) @@ -1205,7 +1210,7 @@ func (g *GoCloak) GetClientScopeProtocolMapper(ctx context.Context, token, realm var result *ProtocolMappers - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes", scopeID, "protocol-mappers", "models", protocolMapperID)) @@ -1222,7 +1227,7 @@ func (g *GoCloak) GetClientScopeMappings(ctx context.Context, token, realm, idOf var result *MappingsRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings")) @@ -1239,7 +1244,7 @@ func (g *GoCloak) GetClientScopeMappingsRealmRoles(ctx context.Context, token, r var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) @@ -1256,7 +1261,7 @@ func (g *GoCloak) GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm", "available")) @@ -1271,7 +1276,7 @@ func (g *GoCloak) GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, func (g *GoCloak) CreateClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error { const errMessage = "could not create realm-level roles to the client’s scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) @@ -1282,7 +1287,7 @@ func (g *GoCloak) CreateClientScopeMappingsRealmRoles(ctx context.Context, token func (g *GoCloak) DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error { const errMessage = "could not delete realm-level roles from the client’s scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "realm")) @@ -1295,7 +1300,7 @@ func (g *GoCloak) GetClientScopeMappingsClientRoles(ctx context.Context, token, var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) @@ -1312,7 +1317,7 @@ func (g *GoCloak) GetClientScopeMappingsClientRolesAvailable(ctx context.Context var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient, "available")) @@ -1327,7 +1332,7 @@ func (g *GoCloak) GetClientScopeMappingsClientRolesAvailable(ctx context.Context func (g *GoCloak) CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error { const errMessage = "could not create client-level roles from the client’s scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) @@ -1338,7 +1343,7 @@ func (g *GoCloak) CreateClientScopeMappingsClientRoles(ctx context.Context, toke func (g *GoCloak) DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error { const errMessage = "could not delete client-level roles from the client’s scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "scope-mappings", "clients", idOfSelectedClient)) @@ -1351,7 +1356,7 @@ func (g *GoCloak) GetClientSecret(ctx context.Context, token, realm, idOfClient var result CredentialRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "client-secret")) @@ -1367,7 +1372,7 @@ func (g *GoCloak) GetClientServiceAccount(ctx context.Context, token, realm, idO const errMessage = "could not get client service account" var result User - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "service-account-user")) @@ -1383,7 +1388,7 @@ func (g *GoCloak) RegenerateClientSecret(ctx context.Context, token, realm, idOf const errMessage = "could not regenerate client secret" var result CredentialRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "client-secret")) @@ -1399,7 +1404,7 @@ func (g *GoCloak) GetClientOfflineSessions(ctx context.Context, token, realm, id const errMessage = "could not get client offline sessions" var res []*UserSessionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&res). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "offline-sessions")) @@ -1415,7 +1420,7 @@ func (g *GoCloak) GetClientUserSessions(ctx context.Context, token, realm, idOfC const errMessage = "could not get client user sessions" var res []*UserSessionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&res). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "user-sessions")) @@ -1430,7 +1435,7 @@ func (g *GoCloak) GetClientUserSessions(ctx context.Context, token, realm, idOfC func (g *GoCloak) CreateClientProtocolMapper(ctx context.Context, token, realm, idOfClient string, mapper ProtocolMapperRepresentation) (string, error) { const errMessage = "could not create client protocol mapper" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(mapper). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models")) @@ -1445,7 +1450,7 @@ func (g *GoCloak) CreateClientProtocolMapper(ctx context.Context, token, realm, func (g *GoCloak) UpdateClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string, mapper ProtocolMapperRepresentation) error { const errMessage = "could not update client protocol mapper" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(mapper). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models", mapperID)) @@ -1456,7 +1461,7 @@ func (g *GoCloak) UpdateClientProtocolMapper(ctx context.Context, token, realm, func (g *GoCloak) DeleteClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string) error { const errMessage = "could not delete client protocol mapper" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "protocol-mappers", "models", mapperID)) return checkForError(resp, err, errMessage) @@ -1467,7 +1472,7 @@ func (g *GoCloak) GetKeyStoreConfig(ctx context.Context, token, realm string) (* const errMessage = "could not get key store config" var result KeyStoreConfig - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "keys")) @@ -1483,7 +1488,7 @@ func (g *GoCloak) GetComponents(ctx context.Context, token, realm string) ([]*Co const errMessage = "could not get components" var result []*Component - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "components")) @@ -1503,7 +1508,7 @@ func (g *GoCloak) GetComponentsWithParams(ctx context.Context, token, realm stri if err != nil { return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "components")) @@ -1522,7 +1527,7 @@ func (g *GoCloak) GetComponent(ctx context.Context, token, realm string, compone componentURL := fmt.Sprintf("components/%s", componentID) - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, componentURL)) @@ -1537,7 +1542,7 @@ func (g *GoCloak) GetComponent(ctx context.Context, token, realm string, compone func (g *GoCloak) UpdateComponent(ctx context.Context, token, realm string, component Component) error { const errMessage = "could not update component" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(component). Put(g.getAdminRealmURL(realm, "components", PString(component.ID))) @@ -1550,7 +1555,7 @@ func (g *GoCloak) GetDefaultGroups(ctx context.Context, token, realm string) ([] var result []*Group - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "default-groups")) @@ -1565,7 +1570,7 @@ func (g *GoCloak) GetDefaultGroups(ctx context.Context, token, realm string) ([] func (g *GoCloak) AddDefaultGroup(ctx context.Context, token, realm, groupID string) error { const errMessage = "could not add default group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Put(g.getAdminRealmURL(realm, "default-groups", groupID)) return checkForError(resp, err, errMessage) @@ -1575,7 +1580,7 @@ func (g *GoCloak) AddDefaultGroup(ctx context.Context, token, realm, groupID str func (g *GoCloak) RemoveDefaultGroup(ctx context.Context, token, realm, groupID string) error { const errMessage = "could not remove default group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "default-groups", groupID)) return checkForError(resp, err, errMessage) @@ -1585,7 +1590,7 @@ func (g *GoCloak) getRoleMappings(ctx context.Context, token, realm, path, objec const errMessage = "could not get role mappings" var result MappingsRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, path, objectID, "role-mappings")) @@ -1612,7 +1617,7 @@ func (g *GoCloak) GetGroup(ctx context.Context, token, realm, groupID string) (* var result Group - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "groups", groupID)) @@ -1629,7 +1634,7 @@ func (g *GoCloak) GetGroupByPath(ctx context.Context, token, realm, groupPath st var result Group - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "group-by-path", groupPath)) @@ -1650,7 +1655,7 @@ func (g *GoCloak) GetGroups(ctx context.Context, token, realm string, params Get return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "groups")) @@ -1667,7 +1672,7 @@ func (g *GoCloak) GetGroupsByRole(ctx context.Context, token, realm string, role const errMessage = "could not get groups" var result []*Group - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles", roleName, "groups")) @@ -1683,7 +1688,7 @@ func (g *GoCloak) GetGroupsByClientRole(ctx context.Context, token, realm string const errMessage = "could not get groups" var result []*Group - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", clientID, "roles", roleName, "groups")) @@ -1703,7 +1708,7 @@ func (g *GoCloak) GetGroupsCount(ctx context.Context, token, realm string, param if err != nil { return 0, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "groups", "count")) @@ -1725,7 +1730,7 @@ func (g *GoCloak) GetGroupMembers(ctx context.Context, token, realm, groupID str return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "groups", groupID, "members")) @@ -1747,7 +1752,7 @@ func (g *GoCloak) GetClientRoles(ctx context.Context, token, realm, idOfClient s return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "roles")) @@ -1764,7 +1769,7 @@ func (g *GoCloak) GetClientRoleByID(ctx context.Context, token, realm, roleID st const errMessage = "could not get client role" var result Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles-by-id", roleID)) @@ -1780,7 +1785,7 @@ func (g *GoCloak) GetClientRolesByUserID(ctx context.Context, token, realm, idOf const errMessage = "could not client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) @@ -1796,7 +1801,7 @@ func (g *GoCloak) GetClientRolesByGroupID(ctx context.Context, token, realm, idO const errMessage = "could not get client roles by group id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) @@ -1812,7 +1817,7 @@ func (g *GoCloak) GetCompositeClientRolesByRoleID(ctx context.Context, token, re const errMessage = "could not get composite client roles by role id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites", "clients", idOfClient)) @@ -1828,7 +1833,7 @@ func (g *GoCloak) GetCompositeClientRolesByUserID(ctx context.Context, token, re const errMessage = "could not get composite client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient, "composite")) @@ -1844,7 +1849,7 @@ func (g *GoCloak) GetAvailableClientRolesByUserID(ctx context.Context, token, re const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient, "available")) @@ -1860,7 +1865,7 @@ func (g *GoCloak) GetAvailableClientRolesByGroupID(ctx context.Context, token, r const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient, "available")) @@ -1876,7 +1881,7 @@ func (g *GoCloak) GetCompositeClientRolesByGroupID(ctx context.Context, token, r const errMessage = "could not get composite client roles by group id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient, "composite")) @@ -1892,7 +1897,7 @@ func (g *GoCloak) GetClientRole(ctx context.Context, token, realm, idOfClient, r const errMessage = "could not get client role" var result Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName)) @@ -1912,7 +1917,7 @@ func (g *GoCloak) GetClients(ctx context.Context, token, realm string, params Ge if err != nil { return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "clients")) @@ -1942,7 +1947,7 @@ func UserAttributeContains(attributes map[string][]string, attribute, value stri func (g *GoCloak) CreateRealmRole(ctx context.Context, token string, realm string, role Role) (string, error) { const errMessage = "could not create realm role" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(role). Post(g.getAdminRealmURL(realm, "roles")) @@ -1959,7 +1964,7 @@ func (g *GoCloak) GetRealmRole(ctx context.Context, token, realm, roleName strin var result Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles", roleName)) @@ -1975,7 +1980,7 @@ func (g *GoCloak) GetRealmRoleByID(ctx context.Context, token, realm, roleID str const errMessage = "could not get realm role" var result Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles-by-id", roleID)) @@ -1996,7 +2001,7 @@ func (g *GoCloak) GetRealmRoles(ctx context.Context, token, realm string, params return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "roles")) @@ -2013,7 +2018,7 @@ func (g *GoCloak) GetRealmRolesByUserID(ctx context.Context, token, realm, userI const errMessage = "could not get realm roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) @@ -2029,7 +2034,7 @@ func (g *GoCloak) GetRealmRolesByGroupID(ctx context.Context, token, realm, grou const errMessage = "could not get realm roles by group id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) @@ -2044,7 +2049,7 @@ func (g *GoCloak) GetRealmRolesByGroupID(ctx context.Context, token, realm, grou func (g *GoCloak) UpdateRealmRole(ctx context.Context, token, realm, roleName string, role Role) error { const errMessage = "could not update realm role" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(role). Put(g.getAdminRealmURL(realm, "roles", roleName)) @@ -2055,7 +2060,7 @@ func (g *GoCloak) UpdateRealmRole(ctx context.Context, token, realm, roleName st func (g *GoCloak) UpdateRealmRoleByID(ctx context.Context, token, realm, roleID string, role Role) error { const errMessage = "could not update realm role" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(role). Put(g.getAdminRealmURL(realm, "roles-by-id", roleID)) @@ -2066,7 +2071,7 @@ func (g *GoCloak) UpdateRealmRoleByID(ctx context.Context, token, realm, roleID func (g *GoCloak) DeleteRealmRole(ctx context.Context, token, realm, roleName string) error { const errMessage = "could not delete realm role" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "roles", roleName)) return checkForError(resp, err, errMessage) @@ -2076,7 +2081,7 @@ func (g *GoCloak) DeleteRealmRole(ctx context.Context, token, realm, roleName st func (g *GoCloak) AddRealmRoleToUser(ctx context.Context, token, realm, userID string, roles []Role) error { const errMessage = "could not add realm role to user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) @@ -2087,7 +2092,7 @@ func (g *GoCloak) AddRealmRoleToUser(ctx context.Context, token, realm, userID s func (g *GoCloak) DeleteRealmRoleFromUser(ctx context.Context, token, realm, userID string, roles []Role) error { const errMessage = "could not delete realm role from user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm")) @@ -2098,7 +2103,7 @@ func (g *GoCloak) DeleteRealmRoleFromUser(ctx context.Context, token, realm, use func (g *GoCloak) AddRealmRoleToGroup(ctx context.Context, token, realm, groupID string, roles []Role) error { const errMessage = "could not add realm role to group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) @@ -2109,7 +2114,7 @@ func (g *GoCloak) AddRealmRoleToGroup(ctx context.Context, token, realm, groupID func (g *GoCloak) DeleteRealmRoleFromGroup(ctx context.Context, token, realm, groupID string, roles []Role) error { const errMessage = "could not delete realm role from group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm")) @@ -2120,7 +2125,7 @@ func (g *GoCloak) DeleteRealmRoleFromGroup(ctx context.Context, token, realm, gr func (g *GoCloak) AddRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error { const errMessage = "could not add realm role composite" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "roles", roleName, "composites")) @@ -2131,7 +2136,7 @@ func (g *GoCloak) AddRealmRoleComposite(ctx context.Context, token, realm, roleN func (g *GoCloak) DeleteRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error { const errMessage = "could not delete realm role composite" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "roles", roleName, "composites")) @@ -2143,7 +2148,7 @@ func (g *GoCloak) GetCompositeRealmRoles(ctx context.Context, token, realm, role const errMessage = "could not get composite realm roles by role" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles", roleName, "composites")) @@ -2159,7 +2164,7 @@ func (g *GoCloak) GetCompositeRolesByRoleID(ctx context.Context, token, realm, r const errMessage = "could not get composite client roles by role id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) @@ -2175,7 +2180,7 @@ func (g *GoCloak) GetCompositeRealmRolesByRoleID(ctx context.Context, token, rea const errMessage = "could not get composite client roles by role id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites", "realm")) @@ -2191,7 +2196,7 @@ func (g *GoCloak) GetCompositeRealmRolesByUserID(ctx context.Context, token, rea const errMessage = "could not get composite client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm", "composite")) @@ -2207,7 +2212,7 @@ func (g *GoCloak) GetCompositeRealmRolesByGroupID(ctx context.Context, token, re const errMessage = "could not get composite client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm", "composite")) @@ -2223,7 +2228,7 @@ func (g *GoCloak) GetAvailableRealmRolesByUserID(ctx context.Context, token, rea const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "realm", "available")) @@ -2239,7 +2244,7 @@ func (g *GoCloak) GetAvailableRealmRolesByGroupID(ctx context.Context, token, re const errMessage = "could not get available client roles by user id" var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "realm", "available")) @@ -2259,7 +2264,7 @@ func (g *GoCloak) GetRealm(ctx context.Context, token, realm string) (*RealmRepr const errMessage = "could not get realm" var result RealmRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm)) @@ -2275,7 +2280,7 @@ func (g *GoCloak) GetRealms(ctx context.Context, token string) ([]*RealmRepresen const errMessage = "could not get realms" var result []*RealmRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL("")) @@ -2290,7 +2295,7 @@ func (g *GoCloak) GetRealms(ctx context.Context, token string) ([]*RealmRepresen func (g *GoCloak) CreateRealm(ctx context.Context, token string, realm RealmRepresentation) (string, error) { const errMessage = "could not create realm" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(&realm). Post(g.getAdminRealmURL("")) @@ -2304,7 +2309,7 @@ func (g *GoCloak) CreateRealm(ctx context.Context, token string, realm RealmRepr func (g *GoCloak) UpdateRealm(ctx context.Context, token string, realm RealmRepresentation) error { const errMessage = "could not update realm" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(realm). Put(g.getAdminRealmURL(PString(realm.Realm))) @@ -2315,7 +2320,7 @@ func (g *GoCloak) UpdateRealm(ctx context.Context, token string, realm RealmRepr func (g *GoCloak) DeleteRealm(ctx context.Context, token, realm string) error { const errMessage = "could not delete realm" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm)) return checkForError(resp, err, errMessage) @@ -2325,7 +2330,7 @@ func (g *GoCloak) DeleteRealm(ctx context.Context, token, realm string) error { func (g *GoCloak) ClearRealmCache(ctx context.Context, token, realm string) error { const errMessage = "could not clear realm cache" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Post(g.getAdminRealmURL(realm, "clear-realm-cache")) return checkForError(resp, err, errMessage) @@ -2335,7 +2340,7 @@ func (g *GoCloak) ClearRealmCache(ctx context.Context, token, realm string) erro func (g *GoCloak) ClearUserCache(ctx context.Context, token, realm string) error { const errMessage = "could not clear user cache" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Post(g.getAdminRealmURL(realm, "clear-user-cache")) return checkForError(resp, err, errMessage) @@ -2345,7 +2350,7 @@ func (g *GoCloak) ClearUserCache(ctx context.Context, token, realm string) error func (g *GoCloak) ClearKeysCache(ctx context.Context, token, realm string) error { const errMessage = "could not clear keys cache" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Post(g.getAdminRealmURL(realm, "clear-keys-cache")) return checkForError(resp, err, errMessage) @@ -2355,7 +2360,7 @@ func (g *GoCloak) ClearKeysCache(ctx context.Context, token, realm string) error func (g *GoCloak) GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) { const errMessage = "could not retrieve authentication flows" var result []*AuthenticationFlowRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "authentication", "flows")) @@ -2369,7 +2374,7 @@ func (g *GoCloak) GetAuthenticationFlows(ctx context.Context, token, realm strin func (g *GoCloak) GetAuthenticationFlow(ctx context.Context, token, realm string, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) { const errMessage = "could not retrieve authentication flows" var result *AuthenticationFlowRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "authentication", "flows", authenticationFlowID)) @@ -2383,7 +2388,7 @@ func (g *GoCloak) GetAuthenticationFlow(ctx context.Context, token, realm string func (g *GoCloak) CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error { const errMessage = "could not create authentication flows" var result []*AuthenticationFlowRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result).SetBody(flow). Post(g.getAdminRealmURL(realm, "authentication", "flows")) @@ -2394,7 +2399,7 @@ func (g *GoCloak) CreateAuthenticationFlow(ctx context.Context, token, realm str func (g *GoCloak) UpdateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) { const errMessage = "could not create authentication flows" var result *AuthenticationFlowRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result).SetBody(flow). Put(g.getAdminRealmURL(realm, "authentication", "flows", authenticationFlowID)) @@ -2407,7 +2412,7 @@ func (g *GoCloak) UpdateAuthenticationFlow(ctx context.Context, token, realm str // DeleteAuthenticationFlow deletes a flow in a realm with the given ID func (g *GoCloak) DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error { const errMessage = "could not delete authentication flows" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "authentication", "flows", flowID)) return checkForError(resp, err, errMessage) @@ -2417,7 +2422,7 @@ func (g *GoCloak) DeleteAuthenticationFlow(ctx context.Context, token, realm, fl func (g *GoCloak) GetAuthenticationExecutions(ctx context.Context, token, realm, flow string) ([]*ModifyAuthenticationExecutionRepresentation, error) { const errMessage = "could not retrieve authentication flows" var result []*ModifyAuthenticationExecutionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions")) @@ -2430,7 +2435,7 @@ func (g *GoCloak) GetAuthenticationExecutions(ctx context.Context, token, realm, // CreateAuthenticationExecution creates a new execution for the given flow name in the given realm func (g *GoCloak) CreateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionRepresentation) error { const errMessage = "could not create authentication execution" - resp, err := g.getRequestWithBearerAuth(ctx, token).SetBody(execution). + resp, err := g.GetRequestWithBearerAuth(ctx, token).SetBody(execution). Post(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions", "execution")) return checkForError(resp, err, errMessage) @@ -2439,7 +2444,7 @@ func (g *GoCloak) CreateAuthenticationExecution(ctx context.Context, token, real // UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm func (g *GoCloak) UpdateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution ModifyAuthenticationExecutionRepresentation) error { const errMessage = "could not update authentication execution" - resp, err := g.getRequestWithBearerAuth(ctx, token).SetBody(execution). + resp, err := g.GetRequestWithBearerAuth(ctx, token).SetBody(execution). Put(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions")) return checkForError(resp, err, errMessage) @@ -2448,7 +2453,7 @@ func (g *GoCloak) UpdateAuthenticationExecution(ctx context.Context, token, real // DeleteAuthenticationExecution delete a single execution with the given ID func (g *GoCloak) DeleteAuthenticationExecution(ctx context.Context, token, realm, executionID string) error { const errMessage = "could not delete authentication execution" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "authentication", "executions", executionID)) return checkForError(resp, err, errMessage) @@ -2457,7 +2462,7 @@ func (g *GoCloak) DeleteAuthenticationExecution(ctx context.Context, token, real // CreateAuthenticationExecutionFlow creates a new execution for the given flow name in the given realm func (g *GoCloak) CreateAuthenticationExecutionFlow(ctx context.Context, token, realm, flow string, executionFlow CreateAuthenticationExecutionFlowRepresentation) error { const errMessage = "could not create authentication execution flow" - resp, err := g.getRequestWithBearerAuth(ctx, token).SetBody(executionFlow). + resp, err := g.GetRequestWithBearerAuth(ctx, token).SetBody(executionFlow). Post(g.getAdminRealmURL(realm, "authentication", "flows", flow, "executions", "flow")) return checkForError(resp, err, errMessage) @@ -2473,7 +2478,7 @@ func (g *GoCloak) CreateAuthenticationExecutionFlow(ctx context.Context, token, func (g *GoCloak) CreateUser(ctx context.Context, token, realm string, user User) (string, error) { const errMessage = "could not create user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(user). Post(g.getAdminRealmURL(realm, "users")) @@ -2488,7 +2493,7 @@ func (g *GoCloak) CreateUser(ctx context.Context, token, realm string, user User func (g *GoCloak) DeleteUser(ctx context.Context, token, realm, userID string) error { const errMessage = "could not delete user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "users", userID)) return checkForError(resp, err, errMessage) @@ -2503,7 +2508,7 @@ func (g *GoCloak) GetUserByID(ctx context.Context, accessToken, realm, userID st } var result User - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID)) @@ -2524,7 +2529,7 @@ func (g *GoCloak) GetUserCount(ctx context.Context, token string, realm string, return 0, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "users", "count")) @@ -2546,7 +2551,7 @@ func (g *GoCloak) GetUserGroups(ctx context.Context, token, realm, userID string return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "users", userID, "groups")) @@ -2568,7 +2573,7 @@ func (g *GoCloak) GetUsers(ctx context.Context, token, realm string, params GetU return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "users")) @@ -2590,7 +2595,7 @@ func (g *GoCloak) GetUsersByRoleName(ctx context.Context, token, realm, roleName return nil, errors.Wrap(err, errMessage) } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "roles", roleName, "users")) @@ -2612,7 +2617,7 @@ func (g *GoCloak) GetUsersByClientRoleName(ctx context.Context, token, realm, id return nil, err } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "roles", roleName, "users")) @@ -2629,7 +2634,7 @@ func (g *GoCloak) SetPassword(ctx context.Context, token, userID, realm, passwor const errMessage = "could not set password" requestBody := SetPasswordRequest{Password: &password, Temporary: &temporary, Type: StringP("password")} - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(requestBody). Put(g.getAdminRealmURL(realm, "users", userID, "reset-password")) @@ -2640,7 +2645,7 @@ func (g *GoCloak) SetPassword(ctx context.Context, token, userID, realm, passwor func (g *GoCloak) UpdateUser(ctx context.Context, token, realm string, user User) error { const errMessage = "could not update user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(user). Put(g.getAdminRealmURL(realm, "users", PString(user.ID))) @@ -2651,7 +2656,7 @@ func (g *GoCloak) UpdateUser(ctx context.Context, token, realm string, user User func (g *GoCloak) AddUserToGroup(ctx context.Context, token, realm, userID, groupID string) error { const errMessage = "could not add user to group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Put(g.getAdminRealmURL(realm, "users", userID, "groups", groupID)) return checkForError(resp, err, errMessage) @@ -2661,7 +2666,7 @@ func (g *GoCloak) AddUserToGroup(ctx context.Context, token, realm, userID, grou func (g *GoCloak) DeleteUserFromGroup(ctx context.Context, token, realm, userID, groupID string) error { const errMessage = "could not delete user from group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "users", userID, "groups", groupID)) return checkForError(resp, err, errMessage) @@ -2672,7 +2677,7 @@ func (g *GoCloak) GetUserSessions(ctx context.Context, token, realm, userID stri const errMessage = "could not get user sessions" var res []*UserSessionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&res). Get(g.getAdminRealmURL(realm, "users", userID, "sessions")) @@ -2688,7 +2693,7 @@ func (g *GoCloak) GetUserOfflineSessionsForClient(ctx context.Context, token, re const errMessage = "could not get user offline sessions for client" var res []*UserSessionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&res). Get(g.getAdminRealmURL(realm, "users", userID, "offline-sessions", idOfClient)) @@ -2703,7 +2708,7 @@ func (g *GoCloak) GetUserOfflineSessionsForClient(ctx context.Context, token, re func (g *GoCloak) AddClientRolesToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { const errMessage = "could not add client role to user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) @@ -2721,7 +2726,7 @@ func (g *GoCloak) AddClientRoleToUser(ctx context.Context, token, realm, idOfCli func (g *GoCloak) AddClientRolesToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error { const errMessage = "could not add client role to group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) @@ -2739,7 +2744,7 @@ func (g *GoCloak) AddClientRoleToGroup(ctx context.Context, token, realm, idOfCl func (g *GoCloak) DeleteClientRolesFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error { const errMessage = "could not delete client role from user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "users", userID, "role-mappings", "clients", idOfClient)) @@ -2757,7 +2762,7 @@ func (g *GoCloak) DeleteClientRoleFromUser(ctx context.Context, token, realm, id func (g *GoCloak) DeleteClientRoleFromGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error { const errMessage = "could not client role from group" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "groups", groupID, "role-mappings", "clients", idOfClient)) @@ -2768,7 +2773,7 @@ func (g *GoCloak) DeleteClientRoleFromGroup(ctx context.Context, token, realm, i func (g *GoCloak) AddClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error { const errMessage = "could not add client role composite" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) @@ -2779,7 +2784,7 @@ func (g *GoCloak) AddClientRoleComposite(ctx context.Context, token, realm, role func (g *GoCloak) DeleteClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error { const errMessage = "could not delete client role composite" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "roles-by-id", roleID, "composites")) @@ -2791,7 +2796,7 @@ func (g *GoCloak) GetUserFederatedIdentities(ctx context.Context, token, realm, const errMessage = "could not get user federated identities" var res []*FederatedIdentityRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&res). Get(g.getAdminRealmURL(realm, "users", userID, "federated-identity")) @@ -2806,7 +2811,7 @@ func (g *GoCloak) GetUserFederatedIdentities(ctx context.Context, token, realm, func (g *GoCloak) CreateUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string, federatedIdentityRep FederatedIdentityRepresentation) error { const errMessage = "could not create user federeated identity" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(federatedIdentityRep). Post(g.getAdminRealmURL(realm, "users", userID, "federated-identity", providerID)) @@ -2817,7 +2822,7 @@ func (g *GoCloak) CreateUserFederatedIdentity(ctx context.Context, token, realm, func (g *GoCloak) DeleteUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string) error { const errMessage = "could not delete user federeated identity" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "users", userID, "federated-identity", providerID)) return checkForError(resp, err, errMessage) @@ -2828,7 +2833,7 @@ func (g *GoCloak) GetUserBruteForceDetectionStatus(ctx context.Context, accessTo const errMessage = "could not brute force detection Status" var result BruteForceStatus - resp, err := g.getRequestWithBearerAuth(ctx, accessToken). + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). Get(g.getAttackDetectionURL(realm, "users", userID)) @@ -2847,7 +2852,7 @@ func (g *GoCloak) GetUserBruteForceDetectionStatus(ctx context.Context, accessTo func (g *GoCloak) CreateIdentityProvider(ctx context.Context, token string, realm string, providerRep IdentityProviderRepresentation) (string, error) { const errMessage = "could not create identity provider" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(providerRep). Post(g.getAdminRealmURL(realm, "identity-provider", "instances")) @@ -2863,7 +2868,7 @@ func (g *GoCloak) GetIdentityProviders(ctx context.Context, token, realm string) const errMessage = "could not get identity providers" var result []*IdentityProviderRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "identity-provider", "instances")) @@ -2879,7 +2884,7 @@ func (g *GoCloak) GetIdentityProvider(ctx context.Context, token, realm, alias s const errMessage = "could not get identity provider" var result IdentityProviderRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias)) @@ -2894,7 +2899,7 @@ func (g *GoCloak) GetIdentityProvider(ctx context.Context, token, realm, alias s func (g *GoCloak) UpdateIdentityProvider(ctx context.Context, token, realm, alias string, providerRep IdentityProviderRepresentation) error { const errMessage = "could not update identity provider" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(providerRep). Put(g.getAdminRealmURL(realm, "identity-provider", "instances", alias)) @@ -2905,7 +2910,7 @@ func (g *GoCloak) UpdateIdentityProvider(ctx context.Context, token, realm, alia func (g *GoCloak) DeleteIdentityProvider(ctx context.Context, token, realm, alias string) error { const errMessage = "could not delete identity provider" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "identity-provider", "instances", alias)) return checkForError(resp, err, errMessage) @@ -2915,7 +2920,7 @@ func (g *GoCloak) DeleteIdentityProvider(ctx context.Context, token, realm, alia func (g *GoCloak) ExportIDPPublicBrokerConfig(ctx context.Context, token, realm, alias string) (*string, error) { const errMessage = "could not get public identity provider configuration" - resp, err := g.getRequestWithBearerAuthXMLHeader(ctx, token). + resp, err := g.GetRequestWithBearerAuthXMLHeader(ctx, token). Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "export")) if err := checkForError(resp, err, errMessage); err != nil { @@ -2931,7 +2936,7 @@ func (g *GoCloak) ImportIdentityProviderConfig(ctx context.Context, token, realm const errMessage = "could not import config" result := make(map[string]string) - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(map[string]string{ "fromUrl": fromURL, @@ -2951,7 +2956,7 @@ func (g *GoCloak) ImportIdentityProviderConfigFromFile(ctx context.Context, toke const errMessage = "could not import config" result := make(map[string]string) - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetFileReader("file", fileName, fileBody). SetFormData(map[string]string{ @@ -2970,7 +2975,7 @@ func (g *GoCloak) ImportIdentityProviderConfigFromFile(ctx context.Context, toke func (g *GoCloak) CreateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) (string, error) { const errMessage = "could not create mapper for identity provider" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(mapper). Post(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers")) @@ -2986,7 +2991,7 @@ func (g *GoCloak) GetIdentityProviderMapper(ctx context.Context, token string, r const errMessage = "could not get identity provider mapper" result := IdentityProviderMapper{} - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) @@ -3001,7 +3006,7 @@ func (g *GoCloak) GetIdentityProviderMapper(ctx context.Context, token string, r func (g *GoCloak) DeleteIdentityProviderMapper(ctx context.Context, token, realm, alias, mapperID string) error { const errMessage = "could not delete mapper for identity provider" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) return checkForError(resp, err, errMessage) @@ -3012,7 +3017,7 @@ func (g *GoCloak) GetIdentityProviderMappers(ctx context.Context, token, realm, const errMessage = "could not get identity provider mappers" var result []*IdentityProviderMapper - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers")) @@ -3028,7 +3033,7 @@ func (g *GoCloak) GetIdentityProviderMapperByID(ctx context.Context, token, real const errMessage = "could not get identity provider mappers" var result IdentityProviderMapper - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", mapperID)) @@ -3043,7 +3048,7 @@ func (g *GoCloak) GetIdentityProviderMapperByID(ctx context.Context, token, real func (g *GoCloak) UpdateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error { const errMessage = "could not update identity provider mapper" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(mapper). Put(g.getAdminRealmURL(realm, "identity-provider", "instances", alias, "mappers", PString(mapper.ID))) @@ -3059,7 +3064,7 @@ func (g *GoCloak) GetResource(ctx context.Context, token, realm, idOfClient, res const errMessage = "could not get resource" var result ResourceRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", resourceID)) @@ -3075,7 +3080,7 @@ func (g *GoCloak) GetResourceClient(ctx context.Context, token, realm, resourceI const errMessage = "could not get resource" var result ResourceRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getRealmURL(realm, "authz", "protection", "resource_set", resourceID)) @@ -3098,7 +3103,7 @@ func (g *GoCloak) GetResources(ctx context.Context, token, realm, idOfClient str } var result []*ResourceRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource")) @@ -3121,7 +3126,7 @@ func (g *GoCloak) GetResourcesClient(ctx context.Context, token, realm string, p var result []*ResourceRepresentation var resourceIDs []string - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&resourceIDs). SetQueryParams(queryParams). Get(g.getRealmURL(realm, "authz", "protection", "resource_set")) @@ -3148,7 +3153,7 @@ func (g *GoCloak) UpdateResource(ctx context.Context, token, realm, idOfClient s return errors.New("ID of a resource required") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(resource). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", *(resource.ID))) @@ -3163,7 +3168,7 @@ func (g *GoCloak) UpdateResourceClient(ctx context.Context, token, realm string, return errors.New("ID of a resource required") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(resource). Put(g.getRealmURL(realm, "authz", "protection", "resource_set", *(resource.ID))) @@ -3175,7 +3180,7 @@ func (g *GoCloak) CreateResource(ctx context.Context, token, realm string, idOfC const errMessage = "could not create resource" var result ResourceRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(resource). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource")) @@ -3192,7 +3197,7 @@ func (g *GoCloak) CreateResourceClient(ctx context.Context, token, realm string, const errMessage = "could not create resource" var result ResourceRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(resource). Post(g.getRealmURL(realm, "authz", "protection", "resource_set")) @@ -3208,7 +3213,7 @@ func (g *GoCloak) CreateResourceClient(ctx context.Context, token, realm string, func (g *GoCloak) DeleteResource(ctx context.Context, token, realm, idOfClient, resourceID string) error { const errMessage = "could not delete resource" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "resource", resourceID)) return checkForError(resp, err, errMessage) @@ -3218,7 +3223,7 @@ func (g *GoCloak) DeleteResource(ctx context.Context, token, realm, idOfClient, func (g *GoCloak) DeleteResourceClient(ctx context.Context, token, realm, resourceID string) error { const errMessage = "could not delete resource" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getRealmURL(realm, "authz", "protection", "resource_set", resourceID)) return checkForError(resp, err, errMessage) @@ -3229,7 +3234,7 @@ func (g *GoCloak) GetScope(ctx context.Context, token, realm, idOfClient, scopeI const errMessage = "could not get scope" var result ScopeRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", scopeID)) @@ -3249,7 +3254,7 @@ func (g *GoCloak) GetScopes(ctx context.Context, token, realm, idOfClient string return nil, err } var result []*ScopeRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope")) @@ -3266,7 +3271,7 @@ func (g *GoCloak) CreateScope(ctx context.Context, token, realm, idOfClient stri const errMessage = "could not create scope" var result ScopeRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(scope). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope")) @@ -3286,7 +3291,7 @@ func (g *GoCloak) UpdateScope(ctx context.Context, token, realm, idOfClient stri return errors.New("ID of a scope required") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(scope). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", *(scope.ID))) @@ -3297,7 +3302,7 @@ func (g *GoCloak) UpdateScope(ctx context.Context, token, realm, idOfClient stri func (g *GoCloak) DeleteScope(ctx context.Context, token, realm, idOfClient, scopeID string) error { const errMessage = "could not delete scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", scopeID)) return checkForError(resp, err, errMessage) @@ -3308,7 +3313,7 @@ func (g *GoCloak) GetPolicy(ctx context.Context, token, realm, idOfClient, polic const errMessage = "could not get policy" var result PolicyRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID)) @@ -3334,7 +3339,7 @@ func (g *GoCloak) GetPolicies(ctx context.Context, token, realm, idOfClient stri } var result []*PolicyRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, path...)) @@ -3355,7 +3360,7 @@ func (g *GoCloak) CreatePolicy(ctx context.Context, token, realm, idOfClient str } var result PolicyRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(policy). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", *(policy.Type))) @@ -3375,7 +3380,7 @@ func (g *GoCloak) UpdatePolicy(ctx context.Context, token, realm, idOfClient str return errors.New("ID of a policy required") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(policy). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", *(policy.Type), *(policy.ID))) @@ -3386,7 +3391,7 @@ func (g *GoCloak) UpdatePolicy(ctx context.Context, token, realm, idOfClient str func (g *GoCloak) DeletePolicy(ctx context.Context, token, realm, idOfClient, policyID string) error { const errMessage = "could not delete policy" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID)) return checkForError(resp, err, errMessage) @@ -3397,7 +3402,7 @@ func (g *GoCloak) GetAuthorizationPolicyAssociatedPolicies(ctx context.Context, const errMessage = "could not get policy associated policies" var result []*PolicyRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "associatedPolicies")) @@ -3413,7 +3418,7 @@ func (g *GoCloak) GetAuthorizationPolicyResources(ctx context.Context, token, re const errMessage = "could not get policy resources" var result []*PolicyResourceRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "resources")) @@ -3429,7 +3434,7 @@ func (g *GoCloak) GetAuthorizationPolicyScopes(ctx context.Context, token, realm const errMessage = "could not get policy scopes" var result []*PolicyScopeRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "scopes")) @@ -3445,7 +3450,7 @@ func (g *GoCloak) GetResourcePolicy(ctx context.Context, token, realm, permissio const errMessage = "could not get resource policy" var result ResourcePolicyRepresentation - resp, err := g.getRequestWithBearerAuthNoCache(ctx, token). + resp, err := g.GetRequestWithBearerAuthNoCache(ctx, token). SetResult(&result). Get(g.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) @@ -3466,7 +3471,7 @@ func (g *GoCloak) GetResourcePolicies(ctx context.Context, token, realm string, } var result []*ResourcePolicyRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getRealmURL(realm, "authz", "protection", "uma-policy")) @@ -3483,7 +3488,7 @@ func (g *GoCloak) CreateResourcePolicy(ctx context.Context, token, realm, resour const errMessage = "could not create resource policy" var result ResourcePolicyRepresentation - resp, err := g.getRequestWithBearerAuthNoCache(ctx, token). + resp, err := g.GetRequestWithBearerAuthNoCache(ctx, token). SetResult(&result). SetBody(policy). Post(g.getRealmURL(realm, "authz", "protection", "uma-policy", resourceID)) @@ -3499,7 +3504,7 @@ func (g *GoCloak) CreateResourcePolicy(ctx context.Context, token, realm, resour func (g *GoCloak) UpdateResourcePolicy(ctx context.Context, token, realm, permissionID string, policy ResourcePolicyRepresentation) error { const errMessage = "could not update resource policy" - resp, err := g.getRequestWithBearerAuthNoCache(ctx, token). + resp, err := g.GetRequestWithBearerAuthNoCache(ctx, token). SetBody(policy). Put(g.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) @@ -3510,7 +3515,7 @@ func (g *GoCloak) UpdateResourcePolicy(ctx context.Context, token, realm, permis func (g *GoCloak) DeleteResourcePolicy(ctx context.Context, token, realm, permissionID string) error { const errMessage = "could not delete resource policy" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getRealmURL(realm, "authz", "protection", "uma-policy", permissionID)) return checkForError(resp, err, errMessage) @@ -3521,7 +3526,7 @@ func (g *GoCloak) GetPermission(ctx context.Context, token, realm, idOfClient, p const errMessage = "could not get permission" var result PermissionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID)) @@ -3537,7 +3542,7 @@ func (g *GoCloak) GetDependentPermissions(ctx context.Context, token, realm, idO const errMessage = "could not get permission" var result []*PermissionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "policy", policyID, "dependentPolicies")) @@ -3553,7 +3558,7 @@ func (g *GoCloak) GetPermissionResources(ctx context.Context, token, realm, idOf const errMessage = "could not get permission resource" var result []*PermissionResource - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID, "resources")) @@ -3569,7 +3574,7 @@ func (g *GoCloak) GetPermissionScopes(ctx context.Context, token, realm, idOfCli const errMessage = "could not get permission scopes" var result []*PermissionScope - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID, "scopes")) @@ -3595,7 +3600,7 @@ func (g *GoCloak) GetPermissions(ctx context.Context, token, realm, idOfClient s } var result []*PermissionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, path...)) @@ -3636,7 +3641,7 @@ func (g *GoCloak) CreatePermissionTicket(ctx context.Context, token, realm strin } var result PermissionTicketResponseRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permissions). Post(g.getRealmURL(realm, "authz", "protection", "permission")) @@ -3676,7 +3681,7 @@ func (g *GoCloak) GrantUserPermission(ctx context.Context, token, realm string, var result PermissionGrantResponseRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permission). Post(g.getRealmURL(realm, "authz", "protection", "permission", "ticket")) @@ -3712,7 +3717,7 @@ func (g *GoCloak) UpdateUserPermission(ctx context.Context, token, realm string, var result PermissionGrantResponseRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permission). Put(g.getRealmURL(realm, "authz", "protection", "permission", "ticket")) @@ -3738,7 +3743,7 @@ func (g *GoCloak) GetUserPermissions(ctx context.Context, token, realm string, p } var result []*PermissionGrantResponseRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getRealmURL(realm, "authz", "protection", "permission", "ticket")) @@ -3754,7 +3759,7 @@ func (g *GoCloak) GetUserPermissions(ctx context.Context, token, realm string, p func (g *GoCloak) DeleteUserPermission(ctx context.Context, token, realm, ticketID string) error { const errMessage = "could not delete user permission" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getRealmURL(realm, "authz", "protection", "permission", "ticket", ticketID)) return checkForError(resp, err, errMessage) @@ -3769,7 +3774,7 @@ func (g *GoCloak) CreatePermission(ctx context.Context, token, realm, idOfClient } var result PermissionRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetBody(permission). Post(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", *(permission.Type))) @@ -3788,7 +3793,7 @@ func (g *GoCloak) UpdatePermission(ctx context.Context, token, realm, idOfClient if NilOrEmpty(permission.ID) { return errors.New("ID of a permission required") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(permission). Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", *permission.Type, *permission.ID)) @@ -3799,7 +3804,7 @@ func (g *GoCloak) UpdatePermission(ctx context.Context, token, realm, idOfClient func (g *GoCloak) DeletePermission(ctx context.Context, token, realm, idOfClient, permissionID string) error { const errMessage = "could not delete permission" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", permissionID)) return checkForError(resp, err, errMessage) @@ -3814,7 +3819,7 @@ func (g *GoCloak) GetCredentialRegistrators(ctx context.Context, token, realm st const errMessage = "could not get user credential registrators" var result []string - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "credential-registrators")) @@ -3830,7 +3835,7 @@ func (g *GoCloak) GetConfiguredUserStorageCredentialTypes(ctx context.Context, t const errMessage = "could not get user credential registrators" var result []string - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "configured-user-storage-credential-types")) @@ -3846,7 +3851,7 @@ func (g *GoCloak) GetCredentials(ctx context.Context, token, realm, userID strin const errMessage = "could not get user credentials" var result []*CredentialRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "users", userID, "credentials")) @@ -3861,7 +3866,7 @@ func (g *GoCloak) GetCredentials(ctx context.Context, token, realm, userID strin func (g *GoCloak) DeleteCredentials(ctx context.Context, token, realm, userID, credentialID string) error { const errMessage = "could not delete user credentials" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID)) return checkForError(resp, err, errMessage) @@ -3871,7 +3876,7 @@ func (g *GoCloak) DeleteCredentials(ctx context.Context, token, realm, userID, c func (g *GoCloak) UpdateCredentialUserLabel(ctx context.Context, token, realm, userID, credentialID, userLabel string) error { const errMessage = "could not update credential label for a user" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetHeader("Content-Type", "text/plain"). SetBody(userLabel). Put(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "userLabel")) @@ -3883,7 +3888,7 @@ func (g *GoCloak) UpdateCredentialUserLabel(ctx context.Context, token, realm, u func (g *GoCloak) DisableAllCredentialsByType(ctx context.Context, token, realm, userID string, types []string) error { const errMessage = "could not update disable credentials" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(types). Put(g.getAdminRealmURL(realm, "users", userID, "disable-credential-types")) @@ -3894,7 +3899,7 @@ func (g *GoCloak) DisableAllCredentialsByType(ctx context.Context, token, realm, func (g *GoCloak) MoveCredentialBehind(ctx context.Context, token, realm, userID, credentialID, newPreviousCredentialID string) error { const errMessage = "could not move credential" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Post(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "moveAfter", newPreviousCredentialID)) return checkForError(resp, err, errMessage) @@ -3904,7 +3909,7 @@ func (g *GoCloak) MoveCredentialBehind(ctx context.Context, token, realm, userID func (g *GoCloak) MoveCredentialToFirst(ctx context.Context, token, realm, userID, credentialID string) error { const errMessage = "could not move credential" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Post(g.getAdminRealmURL(realm, "users", userID, "credentials", credentialID, "moveToFirst")) return checkForError(resp, err, errMessage) @@ -3920,7 +3925,7 @@ func (g *GoCloak) GetEvents(ctx context.Context, token string, realm string, par } var result []*EventRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "events")) @@ -3938,7 +3943,7 @@ func (g *GoCloak) GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Co var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm", "available")) @@ -3955,7 +3960,7 @@ func (g *GoCloak) GetClientScopesScopeMappingsRealmRoles(ctx context.Context, to var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) @@ -3970,7 +3975,7 @@ func (g *GoCloak) GetClientScopesScopeMappingsRealmRoles(ctx context.Context, to func (g *GoCloak) DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error { const errMessage = "could not delete realm-level roles from the client-scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) @@ -3981,7 +3986,7 @@ func (g *GoCloak) DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, func (g *GoCloak) CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error { const errMessage = "could not create realm-level roles to the client-scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "client-scopes", clientScopeID, "scope-mappings", "realm")) @@ -3992,7 +3997,7 @@ func (g *GoCloak) CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, func (g *GoCloak) RegisterRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error { const errMessage = "could not create required action" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(requiredAction). Post(g.getAdminRealmURL(realm, "authentication", "register-required-action")) @@ -4008,7 +4013,7 @@ func (g *GoCloak) GetRequiredActions(ctx context.Context, token string, realm st const errMessage = "could not get required actions" var result []*RequiredActionProviderRepresentation - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "authentication", "required-actions")) @@ -4028,7 +4033,7 @@ func (g *GoCloak) GetRequiredAction(ctx context.Context, token string, realm str return nil, errors.New("alias is required for getting a required action") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "authentication", "required-actions", alias)) @@ -4046,7 +4051,7 @@ func (g *GoCloak) UpdateRequiredAction(ctx context.Context, token string, realm if NilOrEmpty(requiredAction.ProviderID) { return errors.New("providerId is required for updating a required action") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(requiredAction). Put(g.getAdminRealmURL(realm, "authentication", "required-actions", *requiredAction.ProviderID)) @@ -4060,7 +4065,7 @@ func (g *GoCloak) DeleteRequiredAction(ctx context.Context, token string, realm if alias == "" { return errors.New("alias is required for deleting a required action") } - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). Delete(g.getAdminRealmURL(realm, "authentication", "required-actions", alias)) if err := checkForError(resp, err, errMessage); err != nil { @@ -4076,7 +4081,7 @@ func (g *GoCloak) CreateClientScopesScopeMappingsClientRoles( ) error { const errMessage = "could not create client-level roles to the client-scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Post(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) @@ -4091,7 +4096,7 @@ func (g *GoCloak) GetClientScopesScopeMappingsClientRolesAvailable(ctx context.C var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient, "available")) @@ -4109,7 +4114,7 @@ func (g *GoCloak) GetClientScopesScopeMappingsClientRoles(ctx context.Context, t var result []*Role - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&result). Get(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) @@ -4125,7 +4130,7 @@ func (g *GoCloak) GetClientScopesScopeMappingsClientRoles(ctx context.Context, t func (g *GoCloak) DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error { const errMessage = "could not delete client-level roles from the client-scope" - resp, err := g.getRequestWithBearerAuth(ctx, token). + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetBody(roles). Delete(g.getAdminRealmURL(realm, "client-scopes", idOfClientScope, "scope-mappings", "clients", idOfClient)) From aeb6613a205eeb2e26251e6f4455383540a7d5c5 Mon Sep 17 00:00:00 2001 From: Achmad Hardiansyah <67630674+hardyrarso@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:38:42 +0700 Subject: [PATCH 47/60] add method to revoke token (#390) * add method to revoke token * update module name * Update go.mod --------- Co-authored-by: Nerzal --- client.go | 28 ++++++++++++++++++++++++++++ client_test.go | 16 ++++++++++++++++ models.go | 22 ++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/client.go b/client.go index c7ac075d..481b3ef4 100644 --- a/client.go +++ b/client.go @@ -32,6 +32,7 @@ type GoCloak struct { authAdminRealms string authRealms string tokenEndpoint string + revokeEndpoint string logoutEndpoint string openIDConnect string attackDetection string @@ -190,6 +191,7 @@ func NewClient(basePath string, options ...func(*GoCloak)) *GoCloak { c.Config.authRealms = makeURL("realms") c.Config.tokenEndpoint = makeURL("protocol", "openid-connect", "token") c.Config.logoutEndpoint = makeURL("protocol", "openid-connect", "logout") + c.Config.revokeEndpoint = makeURL("protocol", "openid-connect", "revoke") c.Config.openIDConnect = makeURL("protocol", "openid-connect") c.Config.attackDetection = makeURL("attack-detection", "brute-force") @@ -257,6 +259,13 @@ func SetTokenEndpoint(url string) func(g *GoCloak) { } } +// SetRevokeEndpoint sets the revoke endpoint +func SetRevokeEndpoint(url string) func(g *GoCloak) { + return func(g *GoCloak) { + g.Config.revokeEndpoint = url + } +} + // SetLogoutEndpoint sets the logout func SetLogoutEndpoint(url string) func(g *GoCloak) { return func(g *GoCloak) { @@ -4136,3 +4145,22 @@ func (g *GoCloak) DeleteClientScopesScopeMappingsClientRoles(ctx context.Context return checkForError(resp, err, errMessage) } + +// RevokeToken revokes the passed token. The token can either be an access or refresh token. +func (g *GoCloak) RevokeToken(ctx context.Context, realm, clientID, clientSecret, refreshToken string) error { + const errMessage = "could not revoke token" + + resp, err := g.getRequestWithBasicAuth(ctx, clientID, clientSecret). + SetFormData(map[string]string{ + "client_id": clientID, + "client_secret": clientSecret, + "token": refreshToken, + }). + Post(g.getRealmURL(realm, g.Config.revokeEndpoint)) + + if err := checkForError(resp, err, errMessage); err != nil { + return err + } + + return nil +} diff --git a/client_test.go b/client_test.go index b59c9cf4..c43597c2 100644 --- a/client_test.go +++ b/client_test.go @@ -6854,3 +6854,19 @@ func Test_UpdateComponent(t *testing.T) { ) } } + +func Test_RevokeToken(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + SetUpTestUser(t, client) + token := GetUserToken(t, client) + err := client.RevokeToken( + context.Background(), + cfg.GoCloak.Realm, + cfg.GoCloak.ClientID, + cfg.GoCloak.ClientSecret, + token.RefreshToken, + ) + require.NoError(t, err, "Revoke failed") +} diff --git a/models.go b/models.go index 21536ae2..90079b6f 100644 --- a/models.go +++ b/models.go @@ -895,6 +895,28 @@ type MultiValuedHashMap struct { Threshold *int32 `json:"threshold,omitempty"` } +// AuthorizationParameters represents the options to obtain get an authorization +type AuthorizationParameters struct { + ResponseType *string `json:"code,omitempty"` + ClientID *string `json:"client_id,omitempty"` + Scope *string `json:"scope,omitempty"` + RedirectURI *string `json:"redirect_uri,omitempty"` + State *string `json:"state,omitempty"` + Nonce *string `json:"nonce,omitempty"` + IDTokenHint *string `json:"id_token_hint,omitempty"` +} + +// FormData returns a map of options to be used in SetFormData function +func (p *AuthorizationParameters) FormData() map[string]string { + m, _ := json.Marshal(p) + var res map[string]string + _ = json.Unmarshal(m, &res) + return res +} + +type AuthorizationResponse struct { +} + // TokenOptions represents the options to obtain a token type TokenOptions struct { ClientID *string `json:"client_id,omitempty"` From 89f3dc34f36e2a05f6dfbb3b7a43b62945ee783d Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Thu, 13 Apr 2023 12:39:33 +0200 Subject: [PATCH 48/60] fix revoke token call --- client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.go b/client.go index 481b3ef4..c4fdfbb7 100644 --- a/client.go +++ b/client.go @@ -4150,7 +4150,7 @@ func (g *GoCloak) DeleteClientScopesScopeMappingsClientRoles(ctx context.Context func (g *GoCloak) RevokeToken(ctx context.Context, realm, clientID, clientSecret, refreshToken string) error { const errMessage = "could not revoke token" - resp, err := g.getRequestWithBasicAuth(ctx, clientID, clientSecret). + resp, err := g.GetRequestWithBasicAuth(ctx, clientID, clientSecret). SetFormData(map[string]string{ "client_id": clientID, "client_secret": clientSecret, From b1dd4a7001d0032341ac678c07d9e4a99ab7147c Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Thu, 13 Apr 2023 12:42:40 +0200 Subject: [PATCH 49/60] add comment to public struct --- models.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models.go b/models.go index 90079b6f..2be8db19 100644 --- a/models.go +++ b/models.go @@ -914,6 +914,7 @@ func (p *AuthorizationParameters) FormData() map[string]string { return res } +// AuthorizationResponse represents the response to an authorization request. type AuthorizationResponse struct { } From de1cf0b4d7298bbc47da5e74edc5f815e8740e66 Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Thu, 13 Apr 2023 13:23:56 +0200 Subject: [PATCH 50/60] fix lint issue --- client.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/client.go b/client.go index c4fdfbb7..82db51b7 100644 --- a/client.go +++ b/client.go @@ -4158,9 +4158,5 @@ func (g *GoCloak) RevokeToken(ctx context.Context, realm, clientID, clientSecret }). Post(g.getRealmURL(realm, g.Config.revokeEndpoint)) - if err := checkForError(resp, err, errMessage); err != nil { - return err - } - - return nil + return checkForError(resp, err, errMessage) } From 70f6ad9988a208b1ee57cd053af1c7ea6506bd40 Mon Sep 17 00:00:00 2001 From: Bastian Date: Wed, 3 May 2023 13:54:00 +0200 Subject: [PATCH 51/60] fix(client): correct serverinfo endpoint (#382) --- client.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index 82db51b7..2bc75fe5 100644 --- a/client.go +++ b/client.go @@ -288,13 +288,13 @@ func SetCertCacheInvalidationTime(duration time.Duration) func(g *GoCloak) { } // GetServerInfo fetches the server info. -func (g *GoCloak) GetServerInfo(ctx context.Context, accessToken string) ([]*ServerInfoRepresentation, error) { +func (g *GoCloak) GetServerInfo(ctx context.Context, accessToken string) (*ServerInfoRepresentation, error) { errMessage := "could not get server info" - var result []*ServerInfoRepresentation + var result *ServerInfoRepresentation resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). SetResult(&result). - Get(makeURL(g.basePath, "admin", "realms")) + Get(makeURL(g.basePath, "admin", "serverinfo")) if err := checkForError(resp, err, errMessage); err != nil { return nil, err From 640934dd78692930603e556a389a4a6f660d4ac9 Mon Sep 17 00:00:00 2001 From: Brendan Le Glaunec Date: Thu, 4 May 2023 04:47:47 -0700 Subject: [PATCH 52/60] feat: add support for resource server settings endpoint (#421) * feat: add support for resource server settings endpoint * fix: endpoint URL * test: add unit test --- client.go | 18 ++++++++++++++++++ client_test.go | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/client.go b/client.go index 2bc75fe5..119722d1 100644 --- a/client.go +++ b/client.go @@ -3154,6 +3154,24 @@ func (g *GoCloak) GetResourcesClient(ctx context.Context, token, realm string, p return result, nil } +// GetResourceServer returns resource server settings. +// The access token must have the realm view_clients role on its service +// account to be allowed to call this endpoint. +func (g *GoCloak) GetResourceServer(ctx context.Context, token, realm, idOfClient string) (*ResourceServerRepresentation, error) { + const errMessage = "could not get resource server settings" + + var result *ResourceServerRepresentation + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "settings")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + // UpdateResource updates a resource associated with the client, using access token from admin func (g *GoCloak) UpdateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) error { const errMessage = "could not update resource" diff --git a/client_test.go b/client_test.go index c43597c2..441313b6 100644 --- a/client_test.go +++ b/client_test.go @@ -4986,6 +4986,23 @@ func Test_CreateListGetUpdateDeleteResourceClient(t *testing.T) { require.Equal(t, *(createdResource.Name), *(updatedResource.Name)) } +func Test_GetResourceServer(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + rs, err := client.GetResourceServer( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloakClientID, + ) + require.NoError(t, err, "GetResourceServer failed") + require.NotNil(t, rs) + t.Logf("Resource server settings: %+v", rs) +} + func Test_CreateListGetUpdateDeleteResource(t *testing.T) { t.Parallel() cfg := GetConfig(t) From f054fd2bdd84045482369ee2abc9d9890f525c61 Mon Sep 17 00:00:00 2001 From: Patrick Kavajin Date: Wed, 10 May 2023 13:40:58 +0200 Subject: [PATCH 53/60] Allow scripts to be setup for script protocol mappers (#423) --- models.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models.go b/models.go index 2be8db19..4ec83fc7 100644 --- a/models.go +++ b/models.go @@ -447,6 +447,7 @@ type ProtocolMappersConfig struct { AttributeName *string `json:"attribute.name,omitempty"` AttributeNameFormat *string `json:"attribute.nameformat,omitempty"` Single *string `json:"single,omitempty"` + Script *string `json:"script,omitempty"` } // Client is a ClientRepresentation From 7b1503f561fde71a03183a7ef761ecb0f8bc9d9c Mon Sep 17 00:00:00 2001 From: Nerzal Date: Wed, 24 May 2023 15:32:51 +0200 Subject: [PATCH 54/60] Add optional scope(s) to LoginClient function (#424) Co-authored-by: Tobias Theel --- client.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index 119722d1..1a94c3d7 100644 --- a/client.go +++ b/client.go @@ -550,12 +550,18 @@ func (g *GoCloak) LoginAdmin(ctx context.Context, username, password, realm stri } // LoginClient performs a login with client credentials -func (g *GoCloak) LoginClient(ctx context.Context, clientID, clientSecret, realm string) (*JWT, error) { - return g.GetToken(ctx, realm, TokenOptions{ +func (g *GoCloak) LoginClient(ctx context.Context, clientID, clientSecret, realm string, scopes ...string) (*JWT, error) { + opts := TokenOptions{ ClientID: &clientID, ClientSecret: &clientSecret, GrantType: StringP("client_credentials"), - }) + } + + if len(scopes) > 0 { + opts.Scope = &scopes[0] + } + + return g.GetToken(ctx, realm, opts) } // LoginClientTokenExchange will exchange the presented token for a user's token From 166f4421c779f1ff62256fcbbc0f6cea2c4a169b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Vinicius=20Gon=C3=A7alves=20Cunha?= Date: Wed, 24 May 2023 10:36:58 -0300 Subject: [PATCH 55/60] fix: fix RealmRepresentation (#422) --- models.go | 230 +++++++++++++++++++++++++++--------------------------- 1 file changed, 116 insertions(+), 114 deletions(-) diff --git a/models.go b/models.go index 4ec83fc7..070d8a54 100644 --- a/models.go +++ b/models.go @@ -720,120 +720,122 @@ type RolesRepresentation struct { // RealmRepresentation represents a realm type RealmRepresentation struct { - AccessCodeLifespan *int `json:"accessCodeLifespan,omitempty"` - AccessCodeLifespanLogin *int `json:"accessCodeLifespanLogin,omitempty"` - AccessCodeLifespanUserAction *int `json:"accessCodeLifespanUserAction,omitempty"` - AccessTokenLifespan *int `json:"accessTokenLifespan,omitempty"` - AccessTokenLifespanForImplicitFlow *int `json:"accessTokenLifespanForImplicitFlow,omitempty"` - AccountTheme *string `json:"accountTheme,omitempty"` - ActionTokenGeneratedByAdminLifespan *int `json:"actionTokenGeneratedByAdminLifespan,omitempty"` - ActionTokenGeneratedByUserLifespan *int `json:"actionTokenGeneratedByUserLifespan,omitempty"` - AdminEventsDetailsEnabled *bool `json:"adminEventsDetailsEnabled,omitempty"` - AdminEventsEnabled *bool `json:"adminEventsEnabled,omitempty"` - AdminTheme *string `json:"adminTheme,omitempty"` - Attributes *map[string]string `json:"attributes,omitempty"` - AuthenticationFlows *[]interface{} `json:"authenticationFlows,omitempty"` - AuthenticatorConfig *[]interface{} `json:"authenticatorConfig,omitempty"` - BrowserFlow *string `json:"browserFlow,omitempty"` - BrowserSecurityHeaders *map[string]string `json:"browserSecurityHeaders,omitempty"` - BruteForceProtected *bool `json:"bruteForceProtected,omitempty"` - ClientAuthenticationFlow *string `json:"clientAuthenticationFlow,omitempty"` - ClientScopeMappings *map[string]string `json:"clientScopeMappings,omitempty"` - ClientScopes *[]ClientScope `json:"clientScopes,omitempty"` - Clients *[]Client `json:"clients,omitempty"` - Components interface{} `json:"components,omitempty"` - DefaultDefaultClientScopes *[]string `json:"defaultDefaultClientScopes,omitempty"` - DefaultGroups *[]string `json:"defaultGroups,omitempty"` - DefaultLocale *string `json:"defaultLocale,omitempty"` - DefaultOptionalClientScopes *[]string `json:"defaultOptionalClientScopes,omitempty"` - DefaultRole *Role `json:"defaultRole,omitempty"` - DefaultRoles *[]string `json:"defaultRoles,omitempty"` - DefaultSignatureAlgorithm *string `json:"defaultSignatureAlgorithm,omitempty"` - DirectGrantFlow *string `json:"directGrantFlow,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - DisplayNameHTML *string `json:"displayNameHtml,omitempty"` - DockerAuthenticationFlow *string `json:"dockerAuthenticationFlow,omitempty"` - DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"` - EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"` - EmailTheme *string `json:"emailTheme,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - EnabledEventTypes *[]string `json:"enabledEventTypes,omitempty"` - EventsEnabled *bool `json:"eventsEnabled,omitempty"` - EventsExpiration *int64 `json:"eventsExpiration,omitempty"` - EventsListeners *[]string `json:"eventsListeners,omitempty"` - FailureFactor *int `json:"failureFactor,omitempty"` - FederatedUsers *[]interface{} `json:"federatedUsers,omitempty"` - Groups *[]interface{} `json:"groups,omitempty"` - ID *string `json:"id,omitempty"` - IdentityProviderMappers *[]interface{} `json:"identityProviderMappers,omitempty"` - IdentityProviders *[]interface{} `json:"identityProviders,omitempty"` - InternationalizationEnabled *bool `json:"internationalizationEnabled,omitempty"` - KeycloakVersion *string `json:"keycloakVersion,omitempty"` - LoginTheme *string `json:"loginTheme,omitempty"` - LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"` - MaxDeltaTimeSeconds *int `json:"maxDeltaTimeSeconds,omitempty"` - MaxFailureWaitSeconds *int `json:"maxFailureWaitSeconds,omitempty"` - MinimumQuickLoginWaitSeconds *int `json:"minimumQuickLoginWaitSeconds,omitempty"` - NotBefore *int `json:"notBefore,omitempty"` - OfflineSessionIdleTimeout *int `json:"offlineSessionIdleTimeout,omitempty"` - OfflineSessionMaxLifespan *int `json:"offlineSessionMaxLifespan,omitempty"` - OfflineSessionMaxLifespanEnabled *bool `json:"offlineSessionMaxLifespanEnabled,omitempty"` - OtpPolicyAlgorithm *string `json:"otpPolicyAlgorithm,omitempty"` - OtpPolicyDigits *int `json:"otpPolicyDigits,omitempty"` - OtpPolicyInitialCounter *int `json:"otpPolicyInitialCounter,omitempty"` - OtpPolicyLookAheadWindow *int `json:"otpPolicyLookAheadWindow,omitempty"` - OtpPolicyPeriod *int `json:"otpPolicyPeriod,omitempty"` - OtpPolicyType *string `json:"otpPolicyType,omitempty"` - OtpSupportedApplications *[]string `json:"otpSupportedApplications,omitempty"` - PasswordPolicy *string `json:"passwordPolicy,omitempty"` - PermanentLockout *bool `json:"permanentLockout,omitempty"` - ProtocolMappers *[]interface{} `json:"protocolMappers,omitempty"` - QuickLoginCheckMilliSeconds *int64 `json:"quickLoginCheckMilliSeconds,omitempty"` - Realm *string `json:"realm,omitempty"` - RefreshTokenMaxReuse *int `json:"refreshTokenMaxReuse,omitempty"` - RegistrationAllowed *bool `json:"registrationAllowed,omitempty"` - RegistrationEmailAsUsername *bool `json:"registrationEmailAsUsername,omitempty"` - RegistrationFlow *string `json:"registrationFlow,omitempty"` - RememberMe *bool `json:"rememberMe,omitempty"` - RequiredActions *[]interface{} `json:"requiredActions,omitempty"` - ResetCredentialsFlow *string `json:"resetCredentialsFlow,omitempty"` - ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"` - RevokeRefreshToken *bool `json:"revokeRefreshToken,omitempty"` - Roles *RolesRepresentation `json:"roles,omitempty"` - ScopeMappings *[]interface{} `json:"scopeMappings,omitempty"` - SMTPServer *map[string]string `json:"smtpServer,omitempty"` - SslRequired *string `json:"sslRequired,omitempty"` - SsoSessionIdleTimeout *int `json:"ssoSessionIdleTimeout,omitempty"` - SsoSessionIdleTimeoutRememberMe *int `json:"ssoSessionIdleTimeoutRememberMe,omitempty"` - SsoSessionMaxLifespan *int `json:"ssoSessionMaxLifespan,omitempty"` - SsoSessionMaxLifespanRememberMe *int `json:"ssoSessionMaxLifespanRememberMe,omitempty"` - SupportedLocales *[]string `json:"supportedLocales,omitempty"` - UserFederationMappers *[]interface{} `json:"userFederationMappers,omitempty"` - UserFederationProviders *[]interface{} `json:"userFederationProviders,omitempty"` - UserManagedAccessAllowed *bool `json:"userManagedAccessAllowed,omitempty"` - Users *[]User `json:"users,omitempty"` - VerifyEmail *bool `json:"verifyEmail,omitempty"` - WaitIncrementSeconds *int `json:"waitIncrementSeconds,omitempty"` - WebAuthnPolicyAcceptableAaguids *[]string `json:"webAuthnPolicyAcceptableAaguids,omitempty"` - WebAuthnPolicyAttestationConveyancePreference *string `json:"webAuthnPolicyAttestationConveyancePreference,omitempty"` - WebAuthnPolicyAuthenticatorAttachment *string `json:"webAuthnPolicyAuthenticatorAttachment,omitempty"` - WebAuthnPolicyAvoidSameAuthenticatorRegister *bool `json:"webAuthnPolicyAvoidSameAuthenticatorRegister,omitempty"` - WebAuthnPolicyCreateTimeout *int `json:"webAuthnPolicyCreateTimeout,omitempty"` - WebAuthnPolicyPasswordlessAcceptableAaguids *[]string `json:"webAuthnPolicyPasswordlessAcceptableAaguids,omitempty"` - WebAuthnPolicyPasswordlessAttestationConveyancePreference *string `json:"webAuthnPolicyPasswordlessAttestationConveyancePreference,omitempty"` - WebAuthnPolicyPasswordlessAuthenticatorAttachment *string `json:"webAuthnPolicyPasswordlessAuthenticatorAttachment,omitempty"` - WebAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister *bool `json:"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister,omitempty"` - WebAuthnPolicyPasswordlessCreateTimeout *int `json:"webAuthnPolicyPasswordlessCreateTimeout,omitempty"` - WebAuthnPolicyPasswordlessRequireResidentKey *string `json:"webAuthnPolicyPasswordlessRequireResidentKey,omitempty"` - WebAuthnPolicyPasswordlessRpEntityName *string `json:"webAuthnPolicyPasswordlessRpEntityName,omitempty"` - WebAuthnPolicyPasswordlessRpID *string `json:"webAuthnPolicyPasswordlessRpId,omitempty"` - WebAuthnPolicyPasswordlessSignatureAlgorithms *[]string `json:"webAuthnPolicyPasswordlessSignatureAlgorithms,omitempty"` - WebAuthnPolicyPasswordlessUserVerificationRequirement *string `json:"webAuthnPolicyPasswordlessUserVerificationRequirement,omitempty"` - WebAuthnPolicyRequireResidentKey *string `json:"webAuthnPolicyRequireResidentKey,omitempty"` - WebAuthnPolicyRpEntityName *string `json:"webAuthnPolicyRpEntityName,omitempty"` - WebAuthnPolicyRpID *string `json:"webAuthnPolicyRpId,omitempty"` - WebAuthnPolicySignatureAlgorithms *[]string `json:"webAuthnPolicySignatureAlgorithms,omitempty"` - WebAuthnPolicyUserVerificationRequirement *string `json:"webAuthnPolicyUserVerificationRequirement,omitempty"` + AccessCodeLifespan *int `json:"accessCodeLifespan,omitempty"` + AccessCodeLifespanLogin *int `json:"accessCodeLifespanLogin,omitempty"` + AccessCodeLifespanUserAction *int `json:"accessCodeLifespanUserAction,omitempty"` + AccessTokenLifespan *int `json:"accessTokenLifespan,omitempty"` + AccessTokenLifespanForImplicitFlow *int `json:"accessTokenLifespanForImplicitFlow,omitempty"` + AccountTheme *string `json:"accountTheme,omitempty"` + ActionTokenGeneratedByAdminLifespan *int `json:"actionTokenGeneratedByAdminLifespan,omitempty"` + ActionTokenGeneratedByUserLifespan *int `json:"actionTokenGeneratedByUserLifespan,omitempty"` + AdminEventsDetailsEnabled *bool `json:"adminEventsDetailsEnabled,omitempty"` + AdminEventsEnabled *bool `json:"adminEventsEnabled,omitempty"` + AdminTheme *string `json:"adminTheme,omitempty"` + Attributes *map[string]string `json:"attributes,omitempty"` + AuthenticationFlows *[]interface{} `json:"authenticationFlows,omitempty"` + AuthenticatorConfig *[]interface{} `json:"authenticatorConfig,omitempty"` + BrowserFlow *string `json:"browserFlow,omitempty"` + BrowserSecurityHeaders *map[string]string `json:"browserSecurityHeaders,omitempty"` + BruteForceProtected *bool `json:"bruteForceProtected,omitempty"` + ClientAuthenticationFlow *string `json:"clientAuthenticationFlow,omitempty"` + ClientPolicies *map[string][]interface{} `json:"clientPolicies,omitempty"` + ClientProfiles *map[string][]interface{} `json:"clientProfiles,omitempty"` + ClientScopeMappings *map[string][]interface{} `json:"clientScopeMappings,omitempty"` + ClientScopes *[]ClientScope `json:"clientScopes,omitempty"` + Clients *[]Client `json:"clients,omitempty"` + Components interface{} `json:"components,omitempty"` + DefaultDefaultClientScopes *[]string `json:"defaultDefaultClientScopes,omitempty"` + DefaultGroups *[]string `json:"defaultGroups,omitempty"` + DefaultLocale *string `json:"defaultLocale,omitempty"` + DefaultOptionalClientScopes *[]string `json:"defaultOptionalClientScopes,omitempty"` + DefaultRole *Role `json:"defaultRole,omitempty"` + DefaultRoles *[]string `json:"defaultRoles,omitempty"` + DefaultSignatureAlgorithm *string `json:"defaultSignatureAlgorithm,omitempty"` + DirectGrantFlow *string `json:"directGrantFlow,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + DisplayNameHTML *string `json:"displayNameHtml,omitempty"` + DockerAuthenticationFlow *string `json:"dockerAuthenticationFlow,omitempty"` + DuplicateEmailsAllowed *bool `json:"duplicateEmailsAllowed,omitempty"` + EditUsernameAllowed *bool `json:"editUsernameAllowed,omitempty"` + EmailTheme *string `json:"emailTheme,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + EnabledEventTypes *[]string `json:"enabledEventTypes,omitempty"` + EventsEnabled *bool `json:"eventsEnabled,omitempty"` + EventsExpiration *int64 `json:"eventsExpiration,omitempty"` + EventsListeners *[]string `json:"eventsListeners,omitempty"` + FailureFactor *int `json:"failureFactor,omitempty"` + FederatedUsers *[]interface{} `json:"federatedUsers,omitempty"` + Groups *[]interface{} `json:"groups,omitempty"` + ID *string `json:"id,omitempty"` + IdentityProviderMappers *[]interface{} `json:"identityProviderMappers,omitempty"` + IdentityProviders *[]interface{} `json:"identityProviders,omitempty"` + InternationalizationEnabled *bool `json:"internationalizationEnabled,omitempty"` + KeycloakVersion *string `json:"keycloakVersion,omitempty"` + LoginTheme *string `json:"loginTheme,omitempty"` + LoginWithEmailAllowed *bool `json:"loginWithEmailAllowed,omitempty"` + MaxDeltaTimeSeconds *int `json:"maxDeltaTimeSeconds,omitempty"` + MaxFailureWaitSeconds *int `json:"maxFailureWaitSeconds,omitempty"` + MinimumQuickLoginWaitSeconds *int `json:"minimumQuickLoginWaitSeconds,omitempty"` + NotBefore *int `json:"notBefore,omitempty"` + OfflineSessionIdleTimeout *int `json:"offlineSessionIdleTimeout,omitempty"` + OfflineSessionMaxLifespan *int `json:"offlineSessionMaxLifespan,omitempty"` + OfflineSessionMaxLifespanEnabled *bool `json:"offlineSessionMaxLifespanEnabled,omitempty"` + OtpPolicyAlgorithm *string `json:"otpPolicyAlgorithm,omitempty"` + OtpPolicyDigits *int `json:"otpPolicyDigits,omitempty"` + OtpPolicyInitialCounter *int `json:"otpPolicyInitialCounter,omitempty"` + OtpPolicyLookAheadWindow *int `json:"otpPolicyLookAheadWindow,omitempty"` + OtpPolicyPeriod *int `json:"otpPolicyPeriod,omitempty"` + OtpPolicyType *string `json:"otpPolicyType,omitempty"` + OtpSupportedApplications *[]string `json:"otpSupportedApplications,omitempty"` + PasswordPolicy *string `json:"passwordPolicy,omitempty"` + PermanentLockout *bool `json:"permanentLockout,omitempty"` + ProtocolMappers *[]interface{} `json:"protocolMappers,omitempty"` + QuickLoginCheckMilliSeconds *int64 `json:"quickLoginCheckMilliSeconds,omitempty"` + Realm *string `json:"realm,omitempty"` + RefreshTokenMaxReuse *int `json:"refreshTokenMaxReuse,omitempty"` + RegistrationAllowed *bool `json:"registrationAllowed,omitempty"` + RegistrationEmailAsUsername *bool `json:"registrationEmailAsUsername,omitempty"` + RegistrationFlow *string `json:"registrationFlow,omitempty"` + RememberMe *bool `json:"rememberMe,omitempty"` + RequiredActions *[]interface{} `json:"requiredActions,omitempty"` + ResetCredentialsFlow *string `json:"resetCredentialsFlow,omitempty"` + ResetPasswordAllowed *bool `json:"resetPasswordAllowed,omitempty"` + RevokeRefreshToken *bool `json:"revokeRefreshToken,omitempty"` + Roles *RolesRepresentation `json:"roles,omitempty"` + ScopeMappings *[]interface{} `json:"scopeMappings,omitempty"` + SMTPServer *map[string]string `json:"smtpServer,omitempty"` + SslRequired *string `json:"sslRequired,omitempty"` + SsoSessionIdleTimeout *int `json:"ssoSessionIdleTimeout,omitempty"` + SsoSessionIdleTimeoutRememberMe *int `json:"ssoSessionIdleTimeoutRememberMe,omitempty"` + SsoSessionMaxLifespan *int `json:"ssoSessionMaxLifespan,omitempty"` + SsoSessionMaxLifespanRememberMe *int `json:"ssoSessionMaxLifespanRememberMe,omitempty"` + SupportedLocales *[]string `json:"supportedLocales,omitempty"` + UserFederationMappers *[]interface{} `json:"userFederationMappers,omitempty"` + UserFederationProviders *[]interface{} `json:"userFederationProviders,omitempty"` + UserManagedAccessAllowed *bool `json:"userManagedAccessAllowed,omitempty"` + Users *[]User `json:"users,omitempty"` + VerifyEmail *bool `json:"verifyEmail,omitempty"` + WaitIncrementSeconds *int `json:"waitIncrementSeconds,omitempty"` + WebAuthnPolicyAcceptableAaguids *[]string `json:"webAuthnPolicyAcceptableAaguids,omitempty"` + WebAuthnPolicyAttestationConveyancePreference *string `json:"webAuthnPolicyAttestationConveyancePreference,omitempty"` + WebAuthnPolicyAuthenticatorAttachment *string `json:"webAuthnPolicyAuthenticatorAttachment,omitempty"` + WebAuthnPolicyAvoidSameAuthenticatorRegister *bool `json:"webAuthnPolicyAvoidSameAuthenticatorRegister,omitempty"` + WebAuthnPolicyCreateTimeout *int `json:"webAuthnPolicyCreateTimeout,omitempty"` + WebAuthnPolicyPasswordlessAcceptableAaguids *[]string `json:"webAuthnPolicyPasswordlessAcceptableAaguids,omitempty"` + WebAuthnPolicyPasswordlessAttestationConveyancePreference *string `json:"webAuthnPolicyPasswordlessAttestationConveyancePreference,omitempty"` + WebAuthnPolicyPasswordlessAuthenticatorAttachment *string `json:"webAuthnPolicyPasswordlessAuthenticatorAttachment,omitempty"` + WebAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister *bool `json:"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister,omitempty"` + WebAuthnPolicyPasswordlessCreateTimeout *int `json:"webAuthnPolicyPasswordlessCreateTimeout,omitempty"` + WebAuthnPolicyPasswordlessRequireResidentKey *string `json:"webAuthnPolicyPasswordlessRequireResidentKey,omitempty"` + WebAuthnPolicyPasswordlessRpEntityName *string `json:"webAuthnPolicyPasswordlessRpEntityName,omitempty"` + WebAuthnPolicyPasswordlessRpID *string `json:"webAuthnPolicyPasswordlessRpId,omitempty"` + WebAuthnPolicyPasswordlessSignatureAlgorithms *[]string `json:"webAuthnPolicyPasswordlessSignatureAlgorithms,omitempty"` + WebAuthnPolicyPasswordlessUserVerificationRequirement *string `json:"webAuthnPolicyPasswordlessUserVerificationRequirement,omitempty"` + WebAuthnPolicyRequireResidentKey *string `json:"webAuthnPolicyRequireResidentKey,omitempty"` + WebAuthnPolicyRpEntityName *string `json:"webAuthnPolicyRpEntityName,omitempty"` + WebAuthnPolicyRpID *string `json:"webAuthnPolicyRpId,omitempty"` + WebAuthnPolicySignatureAlgorithms *[]string `json:"webAuthnPolicySignatureAlgorithms,omitempty"` + WebAuthnPolicyUserVerificationRequirement *string `json:"webAuthnPolicyUserVerificationRequirement,omitempty"` } // AuthenticationFlowRepresentation represents an authentication flow of a realm From f08754e193a8043bfc884b4cd95b78eb668ade31 Mon Sep 17 00:00:00 2001 From: Daniele Martinoli <86618610+dmartinol@users.noreply.github.com> Date: Mon, 10 Jul 2023 11:18:02 +0200 Subject: [PATCH 56/60] Added APIs to support fine-grained authorization (#432) * Added APIs to support fine-grained authorization * fixed linting error * Added test cases Enabled admin-fine-grained-authz feature Replaced sleep 10 with loop to wait for health endpoint availability * Added test cases Enabled admin-fine-grained-authz feature Replaced sleep 10 with loop to wait for health endpoint availability --- Dockerfile | 2 +- client.go | 98 ++++++++++++++++++++++++++++++++++++ client_test.go | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ models.go | 8 +++ run-tests.sh | 14 +++++- 5 files changed, 252 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9b883314..1590f824 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,6 @@ ENV KEYCLOAK_USER=admin ENV KEYCLOAK_PASSWORD=secret ENV KEYCLOAK_ADMIN=admin ENV KEYCLOAK_ADMIN_PASSWORD=secret -ENV KC_FEATURES=account-api,account2,authorization,client-policies,impersonation,docker,scripts,upload_scripts +ENV KC_FEATURES=account-api,account2,authorization,client-policies,impersonation,docker,scripts,upload_scripts,admin-fine-grained-authz RUN /opt/keycloak/bin/kc.sh import --file /data/import/gocloak-realm.json ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] diff --git a/client.go b/client.go index 1a94c3d7..c1853edf 100644 --- a/client.go +++ b/client.go @@ -869,6 +869,24 @@ func (g *GoCloak) UpdateGroup(ctx context.Context, token, realm string, updatedG return checkForError(resp, err, errMessage) } +// UpdateGroupManagementPermissions updates the given group management permissions +func (g *GoCloak) UpdateGroupManagementPermissions(ctx context.Context, accessToken, realm string, idOfGroup string, managementPermissions ManagementPermissionRepresentation) (*ManagementPermissionRepresentation, error) { + const errMessage = "could not update group management permissions" + + var result ManagementPermissionRepresentation + + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). + SetResult(&result). + SetBody(managementPermissions). + Put(g.getAdminRealmURL(realm, "groups", idOfGroup, "management", "permissions")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, nil +} + // UpdateClient updates the given Client func (g *GoCloak) UpdateClient(ctx context.Context, token, realm string, updatedClient Client) error { const errMessage = "could not update client" @@ -906,6 +924,24 @@ func (g *GoCloak) UpdateClientRepresentation(ctx context.Context, accessToken, r return &result, nil } +// UpdateClientManagementPermissions updates the given client management permissions +func (g *GoCloak) UpdateClientManagementPermissions(ctx context.Context, accessToken, realm string, idOfClient string, managementPermissions ManagementPermissionRepresentation) (*ManagementPermissionRepresentation, error) { + const errMessage = "could not update client management permissions" + + var result ManagementPermissionRepresentation + + resp, err := g.GetRequestWithBearerAuth(ctx, accessToken). + SetResult(&result). + SetBody(managementPermissions). + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "management", "permissions")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, nil +} + // UpdateRole updates the given role. func (g *GoCloak) UpdateRole(ctx context.Context, token, realm, idOfClient string, role Role) error { const errMessage = "could not update role" @@ -1682,6 +1718,23 @@ func (g *GoCloak) GetGroups(ctx context.Context, token, realm string, params Get return result, nil } +// GetGroupManagementPermissions returns whether group Authorization permissions have been initialized or not and a reference +// to the managed permissions +func (g *GoCloak) GetGroupManagementPermissions(ctx context.Context, token, realm string, idOfGroup string) (*ManagementPermissionRepresentation, error) { + const errMessage = "could not get management permissions" + + var result ManagementPermissionRepresentation + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "groups", idOfGroup, "management", "permissions")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, nil +} + // GetGroupsByRole gets groups assigned with a specific role of a realm func (g *GoCloak) GetGroupsByRole(ctx context.Context, token, realm string, roleName string) ([]*Group, error) { const errMessage = "could not get groups" @@ -1944,6 +1997,23 @@ func (g *GoCloak) GetClients(ctx context.Context, token, realm string, params Ge return result, nil } +// GetClientManagementPermissions returns whether client Authorization permissions have been initialized or not and a reference +// to the managed permissions +func (g *GoCloak) GetClientManagementPermissions(ctx context.Context, token, realm string, idOfClient string) (*ManagementPermissionRepresentation, error) { + const errMessage = "could not get management permissions" + + var result ManagementPermissionRepresentation + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "management", "permissions")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, nil +} + // UserAttributeContains checks if the given attribute value is set func UserAttributeContains(attributes map[string][]string, attribute, value string) bool { for _, item := range attributes[attribute] { @@ -3316,6 +3386,34 @@ func (g *GoCloak) CreateScope(ctx context.Context, token, realm, idOfClient stri return &result, nil } +// GetPermissionScope gets the permission scope associated with the client +func (g *GoCloak) GetPermissionScope(ctx context.Context, token, realm, idOfClient string, idOfScope string) (*PolicyRepresentation, error) { + const errMessage = "could not get permission scope" + + var result PolicyRepresentation + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + SetBody(result). + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", "scope", idOfScope)) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return &result, nil +} + +// UpdatePermissionScope updates a permission scope associated with the client +func (g *GoCloak) UpdatePermissionScope(ctx context.Context, token, realm, idOfClient string, idOfScope string, policy PolicyRepresentation) error { + const errMessage = "could not create permission scope" + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetBody(policy). + Put(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "permission", "scope", idOfScope)) + + return checkForError(resp, err, errMessage) +} + // UpdateScope updates a scope associated with the client func (g *GoCloak) UpdateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) error { const errMessage = "could not update scope" diff --git a/client_test.go b/client_test.go index 441313b6..3693cf78 100644 --- a/client_test.go +++ b/client_test.go @@ -1196,6 +1196,103 @@ func Test_CreateListGetUpdateDeleteGetChildGroup(t *testing.T) { require.NoError(t, err, "GetGroup failed") } +func Test_GroupPermissions(t *testing.T) { + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + // Create + tearDown, groupID := CreateGroup(t, client) + // Delete + defer tearDown() + + groupPermission, err := client.GetGroupManagementPermissions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + groupID, + ) + require.NoError(t, err, "GetGroupManagementPermissions failed") + require.Equal(t, false, *groupPermission.Enabled) + + groupPermission.Enabled = gocloak.BoolP(true) + updatedGroupPermission, err := client.UpdateGroupManagementPermissions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + groupID, + *groupPermission, + ) + require.NoError(t, err, "UpdateGroupManagementPermissions failed") + require.Equal(t, true, *updatedGroupPermission.Enabled) + + clients, err := client.GetClients( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloak.GetClientsParams{ + ClientID: gocloak.StringP("realm-management"), + }, + ) + require.NoError(t, err, "GetClients failed") + require.Equal(t, 1, len(clients)) + realManagementClient := clients[0] + + _, policyID := CreatePolicy(t, client, gocloakClientID, gocloak.PolicyRepresentation{ + Name: GetRandomNameP("PolicyName"), + Description: gocloak.StringP("Policy Description"), + Type: gocloak.StringP("client"), + Logic: gocloak.POSITIVE, + ClientPolicyRepresentation: gocloak.ClientPolicyRepresentation{ + Clients: &[]string{ + gocloakClientID, + }, + }, + }) + + for _, scopeID := range *updatedGroupPermission.ScopePermissions { + permissionScope, err := client.GetPermissionScope( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *realManagementClient.ID, + scopeID) + require.NoError(t, err, "GetPermissionScope failed for %s", scopeID) + + scopePolicies, err := client.GetAuthorizationPolicyScopes( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *realManagementClient.ID, + scopeID) + require.NoError(t, err, "GetAuthorizationPolicyScopes failed for %s", scopeID) + require.Equal(t, 1, len(scopePolicies), "GetAuthorizationPolicyScopes found more than 1 policies") + scopePolicy := scopePolicies[0] + + policyResources, err := client.GetAuthorizationPolicyResources( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *realManagementClient.ID, + scopeID) + require.NoError(t, err, "GetAuthorizationPolicyResources failed for %s", scopeID) + require.Equal(t, 1, len(policyResources), "GetAuthorizationPolicyResources found more than 1 policies") + policyResource := policyResources[0] + + permissionScope.Policies = &[]string{policyID} + permissionScope.Resources = &[]string{*policyResource.ID} + permissionScope.Scopes = &[]string{*scopePolicy.ID} + err = client.UpdatePermissionScope( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + *realManagementClient.ID, + scopeID, + *permissionScope) + require.NoError(t, err, "UpdatePermissionScope failed for %s", scopeID) + } +} + func CreateClientRole(t *testing.T, client *gocloak.GoCloak) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -1226,6 +1323,42 @@ func CreateClientRole(t *testing.T, client *gocloak.GoCloak) (func(), string) { return tearDown, roleName } +func Test_ClientPermissions(t *testing.T) { + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + t.Logf("Checking Client Permission") + testClient := gocloak.Client{ + ClientID: GetRandomNameP("ClientID"), + BaseURL: gocloak.StringP("https://example.com"), + FullScopeAllowed: gocloak.BoolP(false), + } + // Creating client + tearDownClient, idOfClient := CreateClient(t, client, &testClient) + defer tearDownClient() + + clientPermissions, err := client.GetClientManagementPermissions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + idOfClient, + ) + require.NoError(t, err, "GetClientManagementPermissions failed") + require.Equal(t, false, *clientPermissions.Enabled) + + clientPermissions.Enabled = gocloak.BoolP(true) + updatedClientPermissions, err := client.UpdateClientManagementPermissions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + idOfClient, + *clientPermissions, + ) + require.NoError(t, err, "UpdateClientManagementPermissions failed") + require.Equal(t, true, *updatedClientPermissions.Enabled) +} + func Test_CreateClientRole(t *testing.T) { t.Parallel() client := NewClientWithDebug(t) diff --git a/models.go b/models.go index 070d8a54..afd2e65e 100644 --- a/models.go +++ b/models.go @@ -1408,6 +1408,14 @@ type RequiredActionProviderRepresentation struct { ProviderID *string `json:"providerId,omitempty"` } +// ManagementPermissionRepresentation is a representation of management permissions +// v18: https://www.keycloak.org/docs-api/18.0/rest-api/#_managementpermissionreference +type ManagementPermissionRepresentation struct { + Enabled *bool `json:"enabled,omitempty"` + Resource *string `json:"resource,omitempty"` + ScopePermissions *map[string]string `json:"scopePermissions,omitempty"` +} + // prettyStringStruct returns struct formatted into pretty string func prettyStringStruct(t interface{}) string { json, err := json.MarshalIndent(t, "", "\t") diff --git a/run-tests.sh b/run-tests.sh index ed2de6ce..57875f8e 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -3,7 +3,17 @@ docker-compose down docker-compose up -d -sleep 10 +keycloakServer=http://localhost:8080 +url="${keycloakServer}/health" +echo "Checking service availability at $url (CTRL+C to exit)" +while true; do + response=$(curl -s -o /dev/null -w "%{http_code}" $url) + if [ $response -eq 200 ]; then + break + fi + sleep 1 +done +echo "Service is now available at ${keycloakServer}" ARGS=() if [ $# -gt 0 ]; then @@ -13,4 +23,4 @@ fi go test -failfast -race -cover -coverprofile=coverage.out -covermode=atomic -p 10 -cpu 1,2 -bench . -benchmem ${ARGS[@]} -docker-compose down \ No newline at end of file +docker-compose down From 7f490d92f4de1b756fa848ee32b3289a6b9d48ec Mon Sep 17 00:00:00 2001 From: Dmitry Zakovyrin Date: Tue, 25 Jul 2023 11:26:00 +0300 Subject: [PATCH 57/60] Added params for getting sessions associated with client (#436) * Added params GetClientUserSessionsParams for GetClientUserSessions and GetClientOfflineSessions * Made the params for the GetClientUserSessions and GetClientOfflineSessions variadic functions --------- Co-authored-by: Dmitry Zakovyrin --- README.md | 4 ++-- client.go | 30 +++++++++++++++++++++++++---- client_test.go | 52 +++++++++++++++++++++++++++++++++++++++++++++++++- model_test.go | 1 + models.go | 7 +++++++ 5 files changed, 87 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9ab5ee24..6f4d7c09 100644 --- a/README.md +++ b/README.md @@ -280,8 +280,8 @@ type GoCloak interface { ClearUserCache(ctx context.Context, token, realm string) error ClearKeysCache(ctx context.Context, token, realm string) error - GetClientUserSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) - GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) +GetClientUserSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) +GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) GetUserSessions(ctx context.Context, token, realm, userID string) ([]*UserSessionRepresentation, error) GetUserOfflineSessionsForClient(ctx context.Context, token, realm, userID, idOfClient string) ([]*UserSessionRepresentation, error) diff --git a/client.go b/client.go index c1853edf..9f06b215 100644 --- a/client.go +++ b/client.go @@ -1451,12 +1451,23 @@ func (g *GoCloak) RegenerateClientSecret(ctx context.Context, token, realm, idOf } // GetClientOfflineSessions returns offline sessions associated with the client -func (g *GoCloak) GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) { +func (g *GoCloak) GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) { const errMessage = "could not get client offline sessions" - var res []*UserSessionRepresentation + + queryParams := map[string]string{} + if params != nil && len(params) > 0 { + var err error + + queryParams, err = GetQueryParams(params[0]) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + } + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&res). + SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "offline-sessions")) if err := checkForError(resp, err, errMessage); err != nil { @@ -1467,12 +1478,23 @@ func (g *GoCloak) GetClientOfflineSessions(ctx context.Context, token, realm, id } // GetClientUserSessions returns user sessions associated with the client -func (g *GoCloak) GetClientUserSessions(ctx context.Context, token, realm, idOfClient string) ([]*UserSessionRepresentation, error) { +func (g *GoCloak) GetClientUserSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) { const errMessage = "could not get client user sessions" - var res []*UserSessionRepresentation + + queryParams := map[string]string{} + if params != nil && len(params) > 0 { + var err error + + queryParams, err = GetQueryParams(params[0]) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + } + resp, err := g.GetRequestWithBearerAuth(ctx, token). SetResult(&res). + SetQueryParams(queryParams). Get(g.getAdminRealmURL(realm, "clients", idOfClient, "user-sessions")) if err := checkForError(resp, err, errMessage); err != nil { diff --git a/client_test.go b/client_test.go index 3693cf78..9ceebeab 100644 --- a/client_test.go +++ b/client_test.go @@ -3719,14 +3719,52 @@ func Test_GetClientUserSessions(t *testing.T) { ) require.NoError(t, err, "Login failed") token := GetAdminToken(t, client) + allSessionsWithoutParams, err := client.GetClientUserSessions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloakClientID, + ) + require.NoError(t, err, "GetClientUserSessions failed") + require.NotEmpty(t, allSessionsWithoutParams, "GetClientUserSessions returned an empty list") + + allSessions, err := client.GetClientUserSessions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloakClientID, + gocloak.GetClientUserSessionsParams{}, + ) + require.NoError(t, err, "GetClientUserSessions failed") + require.NotEmpty(t, allSessions, "GetClientUserSessions returned an empty list") + require.Equal(t, allSessionsWithoutParams, allSessions, + "GetClientUserSessions with and without params are not the same") + sessions, err := client.GetClientUserSessions( context.Background(), token.AccessToken, cfg.GoCloak.Realm, gocloakClientID, + gocloak.GetClientUserSessionsParams{ + Max: gocloak.IntP(1), + }, ) require.NoError(t, err, "GetClientUserSessions failed") - require.NotEmpty(t, sessions, "GetClientUserSessions returned an empty list") + require.Len(t, sessions, 1) + + sessions, err = client.GetClientUserSessions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloakClientID, + gocloak.GetClientUserSessionsParams{ + Max: gocloak.IntP(1), + First: gocloak.IntP(1), + }, + ) + require.NoError(t, err, "GetClientUserSessions failed") + require.Len(t, sessions, 1) + require.Equal(t, *allSessions[1].ID, *sessions[0].ID) } func findProtocolMapperByID(t *testing.T, client *gocloak.Client, id string) *gocloak.ProtocolMapperRepresentation { @@ -3865,9 +3903,21 @@ func Test_GetClientOfflineSessions(t *testing.T) { token.AccessToken, cfg.GoCloak.Realm, gocloakClientID, + gocloak.GetClientUserSessionsParams{}, + ) + require.NoError(t, err, "GetClientOfflineSessions failed") + require.NotEmpty(t, sessions, "GetClientOfflineSessions returned an empty list") + + sessionsWithoutParams, err := client.GetClientOfflineSessions( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + gocloakClientID, ) require.NoError(t, err, "GetClientOfflineSessions failed") require.NotEmpty(t, sessions, "GetClientOfflineSessions returned an empty list") + require.Equal(t, sessions, sessionsWithoutParams, + "GetClientOfflineSessions with and without params are not the same") } func Test_ClientSecret(t *testing.T) { diff --git a/model_test.go b/model_test.go index ad069f2d..d14acf60 100644 --- a/model_test.go +++ b/model_test.go @@ -335,6 +335,7 @@ func TestStringerOmitEmpty(t *testing.T) { &gocloak.GetClientsParams{}, &gocloak.RequestingPartyTokenOptions{}, &gocloak.RequestingPartyPermission{}, + &gocloak.GetClientUserSessionsParams{}, } for _, custom := range customs { diff --git a/models.go b/models.go index afd2e65e..ee051217 100644 --- a/models.go +++ b/models.go @@ -1416,6 +1416,12 @@ type ManagementPermissionRepresentation struct { ScopePermissions *map[string]string `json:"scopePermissions,omitempty"` } +// GetClientUserSessionsParams represents the optional parameters for getting user sessions associated with the client +type GetClientUserSessionsParams struct { + First *int `json:"first,string,omitempty"` + Max *int `json:"max,string,omitempty"` +} + // prettyStringStruct returns struct formatted into pretty string func prettyStringStruct(t interface{}) string { json, err := json.MarshalIndent(t, "", "\t") @@ -1509,3 +1515,4 @@ func (v *GetResourcePoliciesParams) String() string { return pre func (v *CredentialRepresentation) String() string { return prettyStringStruct(v) } func (v *RequiredActionProviderRepresentation) String() string { return prettyStringStruct(v) } func (v *BruteForceStatus) String() string { return prettyStringStruct(v) } +func (v *GetClientUserSessionsParams) String() string { return prettyStringStruct(v) } From 2302a5019aec69af2eac4e0a2ad0b183a2e32a06 Mon Sep 17 00:00:00 2001 From: guangwu Date: Fri, 29 Sep 2023 15:55:40 +0800 Subject: [PATCH 58/60] chore: omit nil check (#440) --- client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client.go b/client.go index 9f06b215..5c8bc50d 100644 --- a/client.go +++ b/client.go @@ -1456,7 +1456,7 @@ func (g *GoCloak) GetClientOfflineSessions(ctx context.Context, token, realm, id var res []*UserSessionRepresentation queryParams := map[string]string{} - if params != nil && len(params) > 0 { + if len(params) > 0 { var err error queryParams, err = GetQueryParams(params[0]) @@ -1483,7 +1483,7 @@ func (g *GoCloak) GetClientUserSessions(ctx context.Context, token, realm, idOfC var res []*UserSessionRepresentation queryParams := map[string]string{} - if params != nil && len(params) > 0 { + if len(params) > 0 { var err error queryParams, err = GetQueryParams(params[0]) From 08a69ff6f3ced539fa378c1a93a90e1da524bc95 Mon Sep 17 00:00:00 2001 From: John Rowley Date: Wed, 18 Oct 2023 00:54:25 -0700 Subject: [PATCH 59/60] chore: upgraded to golang-jwt v5 (#446) --- client.go | 2 +- client_test.go | 4 ++-- go.mod | 6 +++--- go.sum | 12 ++++++------ models.go | 4 ++-- pkg/jwx/jwx.go | 2 +- pkg/jwx/jwx_test.go | 2 +- pkg/jwx/models.go | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/client.go b/client.go index 5c8bc50d..96790969 100644 --- a/client.go +++ b/client.go @@ -13,7 +13,7 @@ import ( "time" "github.com/go-resty/resty/v2" - "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v5" "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/segmentio/ksuid" diff --git a/client_test.go b/client_test.go index 9ceebeab..0cda97c3 100644 --- a/client_test.go +++ b/client_test.go @@ -22,7 +22,7 @@ import ( "time" "github.com/go-resty/resty/v2" - "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/require" "golang.org/x/crypto/pkcs12" @@ -6258,7 +6258,7 @@ func Test_CreatePermissionTicket(t *testing.T) { }) // we're expecting validity error because we didn't supply secret - require.Equal(t, "signature is invalid", err.Error()) + require.ErrorIs(t, err, jwt.ErrTokenSignatureInvalid) claims, ok := pt.Claims.(*gocloak.PermissionTicketRepresentation) // ticketClaims) require.Equal(t, true, ok) diff --git a/go.mod b/go.mod index 90f78f02..2c989b71 100644 --- a/go.mod +++ b/go.mod @@ -4,17 +4,17 @@ go 1.18 require ( github.com/go-resty/resty/v2 v2.7.0 - github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/golang-jwt/jwt/v5 v5.0.0 github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 github.com/segmentio/ksuid v1.0.4 github.com/stretchr/testify v1.8.2 - golang.org/x/crypto v0.6.0 + golang.org/x/crypto v0.14.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.7.0 // indirect + golang.org/x/net v0.17.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index a8aaf844..5f81ea7f 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -21,11 +21,11 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/models.go b/models.go index ee051217..fc26d208 100644 --- a/models.go +++ b/models.go @@ -5,7 +5,7 @@ import ( "encoding/json" "strings" - "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v5" ) // GetQueryParams converts the struct to map[string]string @@ -1258,7 +1258,7 @@ type PermissionTicketRepresentation struct { AZP *string `json:"azp,omitempty"` Claims *map[string][]string `json:"claims,omitempty"` Permissions *[]PermissionTicketPermissionRepresentation `json:"permissions,omitempty"` - jwt.StandardClaims + jwt.RegisteredClaims } // PermissionTicketPermissionRepresentation represents the individual permissions in a permission ticket diff --git a/pkg/jwx/jwx.go b/pkg/jwx/jwx.go index ccf000f5..8eeefada 100644 --- a/pkg/jwx/jwx.go +++ b/pkg/jwx/jwx.go @@ -12,7 +12,7 @@ import ( "math/big" "strings" - "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v5" "github.com/pkg/errors" ) diff --git a/pkg/jwx/jwx_test.go b/pkg/jwx/jwx_test.go index 97a6ba98..4862d746 100644 --- a/pkg/jwx/jwx_test.go +++ b/pkg/jwx/jwx_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v5" ) var claims = jwt.MapClaims{ diff --git a/pkg/jwx/models.go b/pkg/jwx/models.go index 48b7449a..c5ccfb7d 100644 --- a/pkg/jwx/models.go +++ b/pkg/jwx/models.go @@ -1,6 +1,6 @@ package jwx -import jwt "github.com/golang-jwt/jwt/v4" +import jwt "github.com/golang-jwt/jwt/v5" // DecodedAccessTokenHeader is the decoded header from the access token type DecodedAccessTokenHeader struct { @@ -11,7 +11,7 @@ type DecodedAccessTokenHeader struct { // Claims served by keycloak inside the accessToken type Claims struct { - jwt.StandardClaims + jwt.RegisteredClaims Typ string `json:"typ,omitempty"` Azp string `json:"azp,omitempty"` AuthTime int `json:"auth_time,omitempty"` From 0246ee953b290243d31f7d444270b14988a41106 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 09:54:54 +0200 Subject: [PATCH 60/60] Bump golang.org/x/net from 0.7.0 to 0.17.0 (#447) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.7.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.7.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>