Browse Source

Access token provided for each request

master
harture 7 years ago
parent
commit
93716aa74d
  1. 122
      Gopkg.lock
  2. 3
      README.md
  3. 12
      attack_detection.go
  4. 116
      authentication_management.go
  5. 24
      client_attribute_certificate.go
  6. 12
      client_initial_access.go
  7. 4
      client_registration_policy.go
  8. 12
      client_role_mappings.go
  9. 1
      client_templates.go
  10. 12
      clients.go
  11. 53
      clients_test.go
  12. 1
      component.go
  13. 1
      groups.go
  14. 1
      identity_providers.go
  15. BIN
      integration/integration
  16. 60
      integration/integration.go
  17. 1
      key.go
  18. 117
      keycloak_client.go
  19. 40
      keycloak_client_test.go
  20. 24
      realm.go
  21. 25
      realm_test.go
  22. 1
      realms_admin.go
  23. 1
      role_mapper.go
  24. 1
      roles.go
  25. 1
      root.go
  26. 1
      scope_mappings.go
  27. 1
      user_storage_provider.go
  28. 24
      users.go
  29. 23
      users_test.go

122
Gopkg.lock

@ -3,97 +3,199 @@
[[projects]] [[projects]]
branch = "v2" branch = "v2"
digest = "1:e193a6789a00fd6fee10f8e5d070eb3f1dcf19d7fdaff61f23ffdcd42dae7d9e"
name = "github.com/coreos/go-oidc" name = "github.com/coreos/go-oidc"
packages = ["."] packages = ["."]
pruneopts = ""
revision = "065b426bd41667456c1a924468f507673629c46b" revision = "065b426bd41667456c1a924468f507673629c46b"
[[projects]] [[projects]]
digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b"
name = "github.com/davecgh/go-spew" name = "github.com/davecgh/go-spew"
packages = ["spew"] packages = ["spew"]
pruneopts = ""
revision = "346938d642f2ec3594ed81d874461961cd0faa76" revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0" version = "v1.1.0"
[[projects]] [[projects]]
digest = "1:bcb38c8fc9b21bb8682ce2d605a7d4aeb618abc7f827e3ac0b27c0371fdb23fb"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
packages = ["proto"] packages = ["proto"]
pruneopts = ""
revision = "925541529c1fa6821df4e44ce2723319eb2be768" revision = "925541529c1fa6821df4e44ce2723319eb2be768"
version = "v1.0.0" version = "v1.0.0"
[[projects]] [[projects]]
digest = "1:7365acd48986e205ccb8652cc746f09c8b7876030d53710ea6ef7d0bd0dcd7ca"
name = "github.com/pkg/errors" name = "github.com/pkg/errors"
packages = ["."] packages = ["."]
pruneopts = ""
revision = "645ef00459ed84a119197bfb8d8205042c6df63d" revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0" version = "v0.8.0"
[[projects]] [[projects]]
digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411"
name = "github.com/pmezard/go-difflib" name = "github.com/pmezard/go-difflib"
packages = ["difflib"] packages = ["difflib"]
pruneopts = ""
revision = "792786c7400a136282c1664665ae0a8db921c6c2" revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0" version = "v1.0.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:386e12afcfd8964907c92dffd106860c0dedd71dbefae14397b77b724a13343b"
name = "github.com/pquerna/cachecontrol" name = "github.com/pquerna/cachecontrol"
packages = [".","cacheobject"] packages = [
".",
"cacheobject",
]
pruneopts = ""
revision = "0dec1b30a0215bb68605dfc568e8855066c9202d" revision = "0dec1b30a0215bb68605dfc568e8855066c9202d"
[[projects]] [[projects]]
digest = "1:261bc565833ef4f02121450d74eb88d5ae4bd74bfe5d0e862cddb8550ec35000"
name = "github.com/spf13/pflag" name = "github.com/spf13/pflag"
packages = ["."] packages = ["."]
pruneopts = ""
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
version = "v1.0.0" version = "v1.0.0"
[[projects]] [[projects]]
digest = "1:a30066593578732a356dc7e5d7f78d69184ca65aeeff5939241a3ab10559bb06"
name = "github.com/stretchr/testify" name = "github.com/stretchr/testify"
packages = ["assert","require"] packages = [
"assert",
"require",
]
pruneopts = ""
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.1" version = "v1.2.1"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:2ea6df0f542cc95a5e374e9cdd81eaa599ed0d55366eef92d2f6b9efa2795c07"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = ["ed25519","ed25519/internal/edwards25519"] packages = [
"ed25519",
"ed25519/internal/edwards25519",
]
pruneopts = ""
revision = "432090b8f568c018896cd8a0fb0345872bbac6ce" revision = "432090b8f568c018896cd8a0fb0345872bbac6ce"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:b4ba046df563f56fe42b6270b20039107a37e1ab47c97aa47a16f848aa5b6d9a"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = ["context","context/ctxhttp","idna","publicsuffix"] packages = [
"context",
"context/ctxhttp",
"idna",
"publicsuffix",
]
pruneopts = ""
revision = "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb" revision = "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:dd57134ebff8e1a1a77c9f145a28cad8470da6bb9053d6ff2bc552ecd7f8bc92"
name = "golang.org/x/oauth2" name = "golang.org/x/oauth2"
packages = [".","internal"] packages = [
".",
"internal",
]
pruneopts = ""
revision = "543e37812f10c46c622c9575afd7ad22f22a12ba" revision = "543e37812f10c46c622c9575afd7ad22f22a12ba"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:31985a0ed491dba5ba7fe92e18be008acd92ca9435ed9b35b06f3e6c00fd82cb"
name = "golang.org/x/text" name = "golang.org/x/text"
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] packages = [
"collate",
"collate/build",
"internal/colltab",
"internal/gen",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"secure/bidirule",
"transform",
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable",
]
pruneopts = ""
revision = "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1" revision = "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1"
[[projects]] [[projects]]
digest = "1:934fb8966f303ede63aa405e2c8d7f0a427a05ea8df335dfdc1833dd4d40756f"
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
packages = ["internal","internal/base","internal/datastore","internal/log","internal/remote_api","internal/urlfetch","urlfetch"] packages = [
"internal",
"internal/base",
"internal/datastore",
"internal/log",
"internal/remote_api",
"internal/urlfetch",
"urlfetch",
]
pruneopts = ""
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a" revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
version = "v1.0.0" version = "v1.0.0"
[[projects]] [[projects]]
digest = "1:e3250d192192f02fbb143d50de437cbe967d6be7bd9fad671600942a33269d08"
name = "gopkg.in/h2non/gentleman.v2" name = "gopkg.in/h2non/gentleman.v2"
packages = [".","context","middleware","mux","plugin","plugins/body","plugins/bodytype","plugins/cookies","plugins/headers","plugins/multipart","plugins/query","plugins/timeout","plugins/url","utils"] packages = [
".",
"context",
"middleware",
"mux",
"plugin",
"plugins/body",
"plugins/bodytype",
"plugins/cookies",
"plugins/headers",
"plugins/multipart",
"plugins/query",
"plugins/timeout",
"plugins/url",
"utils",
]
pruneopts = ""
revision = "e0f81be2f4064ea7aa7470e9daddd2dc8e8152c7" revision = "e0f81be2f4064ea7aa7470e9daddd2dc8e8152c7"
version = "v2.0.3" version = "v2.0.3"
[[projects]] [[projects]]
digest = "1:be4ed0a2b15944dd777a663681a39260ed05f9c4e213017ed2e2255622c8820c"
name = "gopkg.in/square/go-jose.v2" name = "gopkg.in/square/go-jose.v2"
packages = [".","cipher","json"] packages = [
".",
"cipher",
"json",
]
pruneopts = ""
revision = "f8f38de21b4dcd69d0413faf231983f5fd6634b1" revision = "f8f38de21b4dcd69d0413faf231983f5fd6634b1"
version = "v2.1.3" version = "v2.1.3"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "bcd4dc5f3937d83e106e1a9999b3a7f5a9544ba495a3375c920688c9e73afce8" input-imports = [
"github.com/coreos/go-oidc",
"github.com/davecgh/go-spew/spew",
"github.com/pkg/errors",
"github.com/spf13/pflag",
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/require",
"gopkg.in/h2non/gentleman.v2",
"gopkg.in/h2non/gentleman.v2/plugin",
"gopkg.in/h2non/gentleman.v2/plugins/body",
"gopkg.in/h2non/gentleman.v2/plugins/query",
"gopkg.in/h2non/gentleman.v2/plugins/timeout",
"gopkg.in/h2non/gentleman.v2/plugins/url",
]
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

3
README.md

@ -1,3 +1,4 @@
## Basic keycloak client in go ## Basic keycloak client in go
This repo provides a basic keycloak client in go, and utilities to parse the html docs into usable schema files because I wasn't good enough to make maven give me ascii documentation. I should try again at some point. It uses swagger, so it SHOULD be doable, it was just easier at that time to write an html parser to quickly prototype something. This repo provides a basic keycloak client in go.

12
attack_detection.go

@ -10,18 +10,18 @@ const (
) )
// ClearAllLoginFailures clears any user login failures for all users. This can release temporary disabled users. // ClearAllLoginFailures clears any user login failures for all users. This can release temporary disabled users.
func (c *Client) ClearAllLoginFailures(realmName string) error { func (c *Client) ClearAllLoginFailures(accessToken string, realmName string) error {
return c.delete(url.Path(attackDetectionPath), url.Param("realm", realmName)) return c.delete(accessToken, url.Path(attackDetectionPath), url.Param("realm", realmName))
} }
// GetAttackDetectionStatus gets the status of a username in brute force detection. // GetAttackDetectionStatus gets the status of a username in brute force detection.
func (c *Client) GetAttackDetectionStatus(realmName, userID string) (map[string]interface{}, error) { func (c *Client) GetAttackDetectionStatus(accessToken string, realmName, userID string) (map[string]interface{}, error) {
var resp = map[string]interface{}{} var resp = map[string]interface{}{}
var err = c.get(&resp, url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID)) var err = c.get(accessToken, &resp, url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID))
return resp, err return resp, err
} }
// ClearUserLoginFailures clear any user login failures for the user. This can release temporary disabled user. // ClearUserLoginFailures clear any user login failures for the user. This can release temporary disabled user.
func (c *Client) ClearUserLoginFailures(realmName, userID string) error { func (c *Client) ClearUserLoginFailures(accessToken string, realmName, userID string) error {
return c.delete(url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID)) return c.delete(accessToken, url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID))
} }

116
authentication_management.go

@ -10,180 +10,180 @@ const (
) )
// GetAuthenticatorProviders returns a list of authenticator providers. // GetAuthenticatorProviders returns a list of authenticator providers.
func (c *Client) GetAuthenticatorProviders(realmName string) ([]map[string]interface{}, error) { func (c *Client) GetAuthenticatorProviders(accessToken string, realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{} var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/authenticator-providers"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/authenticator-providers"), url.Param("realm", realmName))
return resp, err return resp, err
} }
// GetClientAuthenticatorProviders returns a list of client authenticator providers. // GetClientAuthenticatorProviders returns a list of client authenticator providers.
func (c *Client) GetClientAuthenticatorProviders(realmName string) ([]map[string]interface{}, error) { func (c *Client) GetClientAuthenticatorProviders(accessToken string, realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{} var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/client-authenticator-providers"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/client-authenticator-providers"), url.Param("realm", realmName))
return resp, err return resp, err
} }
// GetAuthenticatorProviderConfig returns the authenticator provider’s configuration description. // GetAuthenticatorProviderConfig returns the authenticator provider’s configuration description.
func (c *Client) GetAuthenticatorProviderConfig(realmName, providerID string) (AuthenticatorConfigInfoRepresentation, error) { func (c *Client) GetAuthenticatorProviderConfig(accessToken string, realmName, providerID string) (AuthenticatorConfigInfoRepresentation, error) {
var resp = AuthenticatorConfigInfoRepresentation{} var resp = AuthenticatorConfigInfoRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/config-description/:providerID"), url.Param("realm", realmName), url.Param("providerID", providerID)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/config-description/:providerID"), url.Param("realm", realmName), url.Param("providerID", providerID))
return resp, err return resp, err
} }
// GetAuthenticatorConfig returns the authenticator configuration. // GetAuthenticatorConfig returns the authenticator configuration.
func (c *Client) GetAuthenticatorConfig(realmName, configID string) (AuthenticatorConfigRepresentation, error) { func (c *Client) GetAuthenticatorConfig(accessToken string, realmName, configID string) (AuthenticatorConfigRepresentation, error) {
var resp = AuthenticatorConfigRepresentation{} var resp = AuthenticatorConfigRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID))
return resp, err return resp, err
} }
// UpdateAuthenticatorConfig updates the authenticator configuration. // UpdateAuthenticatorConfig updates the authenticator configuration.
func (c *Client) UpdateAuthenticatorConfig(realmName, configID string, config AuthenticatorConfigRepresentation) error { func (c *Client) UpdateAuthenticatorConfig(accessToken string, realmName, configID string, config AuthenticatorConfigRepresentation) error {
return c.put(url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID), body.JSON(config)) return c.put(accessToken, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID), body.JSON(config))
} }
// DeleteAuthenticatorConfig deletes the authenticator configuration. // DeleteAuthenticatorConfig deletes the authenticator configuration.
func (c *Client) DeleteAuthenticatorConfig(realmName, configID string) error { func (c *Client) DeleteAuthenticatorConfig(accessToken string, realmName, configID string) error {
return c.delete(url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID)) return c.delete(accessToken, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID))
} }
// CreateAuthenticationExecution add new authentication execution // CreateAuthenticationExecution add new authentication execution
func (c *Client) CreateAuthenticationExecution(realmName string, authExec AuthenticationExecutionRepresentation) error { func (c *Client) CreateAuthenticationExecution(accessToken string, realmName string, authExec AuthenticationExecutionRepresentation) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions"), url.Param("realm", realmName), body.JSON(authExec)) return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/executions"), url.Param("realm", realmName), body.JSON(authExec))
} }
// DeleteAuthenticationExecution deletes the execution. // DeleteAuthenticationExecution deletes the execution.
func (c *Client) DeleteAuthenticationExecution(realmName, executionID string) error { func (c *Client) DeleteAuthenticationExecution(accessToken string, realmName, executionID string) error {
return c.delete(url.Path(authenticationManagementPath+"/executions/:id"), url.Param("realm", realmName), url.Param("id", executionID)) return c.delete(accessToken, url.Path(authenticationManagementPath+"/executions/:id"), url.Param("realm", realmName), url.Param("id", executionID))
} }
// UpdateAuthenticationExecution update execution with new configuration. // UpdateAuthenticationExecution update execution with new configuration.
func (c *Client) UpdateAuthenticationExecution(realmName, executionID string, authConfig AuthenticatorConfigRepresentation) error { func (c *Client) UpdateAuthenticationExecution(accessToken string, realmName, executionID string, authConfig AuthenticatorConfigRepresentation) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/config"), url.Param("realm", realmName), url.Param("id", executionID), body.JSON(authConfig)) return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/executions/:id/config"), url.Param("realm", realmName), url.Param("id", executionID), body.JSON(authConfig))
} }
// LowerExecutionPriority lowers the execution’s priority. // LowerExecutionPriority lowers the execution’s priority.
func (c *Client) LowerExecutionPriority(realmName, executionID string) error { func (c *Client) LowerExecutionPriority(accessToken string, realmName, executionID string) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/lower-priority"), url.Param("realm", realmName), url.Param("id", executionID)) return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/executions/:id/lower-priority"), url.Param("realm", realmName), url.Param("id", executionID))
} }
// RaiseExecutionPriority raise the execution’s priority. // RaiseExecutionPriority raise the execution’s priority.
func (c *Client) RaiseExecutionPriority(realmName, executionID string) error { func (c *Client) RaiseExecutionPriority(accessToken string, realmName, executionID string) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/raise-priority"), url.Param("realm", realmName), url.Param("id", executionID)) return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/executions/:id/raise-priority"), url.Param("realm", realmName), url.Param("id", executionID))
} }
// CreateAuthenticationFlow creates a new authentication flow. // CreateAuthenticationFlow creates a new authentication flow.
func (c *Client) CreateAuthenticationFlow(realmName string, authFlow AuthenticationFlowRepresentation) error { func (c *Client) CreateAuthenticationFlow(accessToken string, realmName string, authFlow AuthenticationFlowRepresentation) error {
return c.post(nil, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName), body.JSON(authFlow)) return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName), body.JSON(authFlow))
} }
// GetAuthenticationFlows returns a list of authentication flows. // GetAuthenticationFlows returns a list of authentication flows.
func (c *Client) GetAuthenticationFlows(realmName string) ([]AuthenticationFlowRepresentation, error) { func (c *Client) GetAuthenticationFlows(accessToken string, realmName string) ([]AuthenticationFlowRepresentation, error) {
var resp = []AuthenticationFlowRepresentation{} var resp = []AuthenticationFlowRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName))
return resp, err return resp, err
} }
// CopyExistingAuthenticationFlow copy the existing authentication flow under a new name. // CopyExistingAuthenticationFlow copy the existing authentication flow under a new name.
// 'flowAlias' is the name of the existing authentication flow, // 'flowAlias' is the name of the existing authentication flow,
// 'newName' is the new name of the authentication flow. // 'newName' is the new name of the authentication flow.
func (c *Client) CopyExistingAuthenticationFlow(realmName, flowAlias, newName string) error { func (c *Client) CopyExistingAuthenticationFlow(accessToken string, realmName, flowAlias, newName string) error {
var m = map[string]string{"newName": newName} var m = map[string]string{"newName": newName}
return c.post(nil, url.Path(authenticationManagementPath+"/flows/:flowAlias/copy"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m)) return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/flows/:flowAlias/copy"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m))
} }
// GetAuthenticationExecutionForFlow returns the authentication executions for a flow. // GetAuthenticationExecutionForFlow returns the authentication executions for a flow.
func (c *Client) GetAuthenticationExecutionForFlow(realmName, flowAlias string) (AuthenticationExecutionInfoRepresentation, error) { func (c *Client) GetAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string) (AuthenticationExecutionInfoRepresentation, error) {
var resp = AuthenticationExecutionInfoRepresentation{} var resp = AuthenticationExecutionInfoRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias))
return resp, err return resp, err
} }
// UpdateAuthenticationExecutionForFlow updates the authentication executions of a flow. // UpdateAuthenticationExecutionForFlow updates the authentication executions of a flow.
func (c *Client) UpdateAuthenticationExecutionForFlow(realmName, flowAlias string, authExecInfo AuthenticationExecutionInfoRepresentation) error { func (c *Client) UpdateAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string, authExecInfo AuthenticationExecutionInfoRepresentation) error {
return c.put(url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(authExecInfo)) return c.put(accessToken, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(authExecInfo))
} }
// CreateAuthenticationExecutionForFlow add a new authentication execution to a flow. // CreateAuthenticationExecutionForFlow add a new authentication execution to a flow.
// 'flowAlias' is the alias of the parent flow. // 'flowAlias' is the alias of the parent flow.
func (c *Client) CreateAuthenticationExecutionForFlow(realmName, flowAlias, provider string) error { func (c *Client) CreateAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias, provider string) error {
var m = map[string]string{"provider": provider} var m = map[string]string{"provider": provider}
return c.post(url.Path(authenticationManagementPath+"/flows/:flowAlias/executions/execution"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m)) return c.post(accessToken, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions/execution"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m))
} }
// CreateFlowWithExecutionForExistingFlow add a new flow with a new execution to an existing flow. // CreateFlowWithExecutionForExistingFlow add a new flow with a new execution to an existing flow.
// 'flowAlias' is the alias of the parent authentication flow. // 'flowAlias' is the alias of the parent authentication flow.
func (c *Client) CreateFlowWithExecutionForExistingFlow(realmName, flowAlias, alias, flowType, provider, description string) error { func (c *Client) CreateFlowWithExecutionForExistingFlow(accessToken string, realmName, flowAlias, alias, flowType, provider, description string) error {
var m = map[string]string{"alias": alias, "type": flowType, "provider": provider, "description": description} var m = map[string]string{"alias": alias, "type": flowType, "provider": provider, "description": description}
return c.post(url.Path(authenticationManagementPath+"/flows/:flowAlias/executions/flow"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m)) return c.post(accessToken, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions/flow"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m))
} }
// GetAuthenticationFlow gets the authentication flow for id. // GetAuthenticationFlow gets the authentication flow for id.
func (c *Client) GetAuthenticationFlow(realmName, flowID string) (AuthenticationFlowRepresentation, error) { func (c *Client) GetAuthenticationFlow(accessToken string, realmName, flowID string) (AuthenticationFlowRepresentation, error) {
var resp = AuthenticationFlowRepresentation{} var resp = AuthenticationFlowRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID))
return resp, err return resp, err
} }
// DeleteAuthenticationFlow deletes an authentication flow. // DeleteAuthenticationFlow deletes an authentication flow.
func (c *Client) DeleteAuthenticationFlow(realmName, flowID string) error { func (c *Client) DeleteAuthenticationFlow(accessToken string, realmName, flowID string) error {
return c.delete(url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID)) return c.delete(accessToken, url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID))
} }
// GetFormActionProviders returns a list of form action providers. // GetFormActionProviders returns a list of form action providers.
func (c *Client) GetFormActionProviders(realmName string) ([]map[string]interface{}, error) { func (c *Client) GetFormActionProviders(accessToken string, realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{} var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/form-action-providers"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/form-action-providers"), url.Param("realm", realmName))
return resp, err return resp, err
} }
// GetFormProviders returns a list of form providers. // GetFormProviders returns a list of form providers.
func (c *Client) GetFormProviders(realmName string) ([]map[string]interface{}, error) { func (c *Client) GetFormProviders(accessToken string, realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{} var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/form-providers"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/form-providers"), url.Param("realm", realmName))
return resp, err return resp, err
} }
// GetConfigDescriptionForClients returns the configuration descriptions for all clients. // GetConfigDescriptionForClients returns the configuration descriptions for all clients.
func (c *Client) GetConfigDescriptionForClients(realmName string) (map[string]interface{}, error) { func (c *Client) GetConfigDescriptionForClients(accessToken string, realmName string) (map[string]interface{}, error) {
var resp = map[string]interface{}{} var resp = map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/per-client-config-description"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/per-client-config-description"), url.Param("realm", realmName))
return resp, err return resp, err
} }
// RegisterRequiredAction register a new required action. // RegisterRequiredAction register a new required action.
func (c *Client) RegisterRequiredAction(realmName, providerID, name string) error { func (c *Client) RegisterRequiredAction(accessToken string, realmName, providerID, name string) error {
var m = map[string]string{"providerId": providerID, "name": name} var m = map[string]string{"providerId": providerID, "name": name}
return c.post(url.Path(authenticationManagementPath+"/register-required-action"), url.Param("realm", realmName), body.JSON(m)) return c.post(accessToken, url.Path(authenticationManagementPath+"/register-required-action"), url.Param("realm", realmName), body.JSON(m))
} }
// GetRequiredActions returns a list of required actions. // GetRequiredActions returns a list of required actions.
func (c *Client) GetRequiredActions(realmName string) ([]RequiredActionProviderRepresentation, error) { func (c *Client) GetRequiredActions(accessToken string, realmName string) ([]RequiredActionProviderRepresentation, error) {
var resp = []RequiredActionProviderRepresentation{} var resp = []RequiredActionProviderRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/required-actions"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/required-actions"), url.Param("realm", realmName))
return resp, err return resp, err
} }
// GetRequiredAction returns the required action for the alias. // GetRequiredAction returns the required action for the alias.
func (c *Client) GetRequiredAction(realmName, actionAlias string) (RequiredActionProviderRepresentation, error) { func (c *Client) GetRequiredAction(accessToken string, realmName, actionAlias string) (RequiredActionProviderRepresentation, error) {
var resp = RequiredActionProviderRepresentation{} var resp = RequiredActionProviderRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias))
return resp, err return resp, err
} }
// UpdateRequiredAction updates the required action. // UpdateRequiredAction updates the required action.
func (c *Client) UpdateRequiredAction(realmName, actionAlias string, action RequiredActionProviderRepresentation) error { func (c *Client) UpdateRequiredAction(accessToken string, realmName, actionAlias string, action RequiredActionProviderRepresentation) error {
return c.put(url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias), body.JSON(action)) return c.put(accessToken, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias), body.JSON(action))
} }
// DeleteRequiredAction deletes the required action. // DeleteRequiredAction deletes the required action.
func (c *Client) DeleteRequiredAction(realmName, actionAlias string) error { func (c *Client) DeleteRequiredAction(accessToken string, realmName, actionAlias string) error {
return c.delete(url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias)) return c.delete(accessToken, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias))
} }
// GetUnregisteredRequiredActions returns a list of unregistered required actions. // GetUnregisteredRequiredActions returns a list of unregistered required actions.
func (c *Client) GetUnregisteredRequiredActions(realmName string) ([]map[string]interface{}, error) { func (c *Client) GetUnregisteredRequiredActions(accessToken string, realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{} var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/unregistered-required-actions"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/unregistered-required-actions"), url.Param("realm", realmName))
return resp, err return resp, err
} }

24
client_attribute_certificate.go

@ -12,43 +12,43 @@ const (
) )
// GetKeyInfo returns the key info. idClient is the id of client (not client-id). // GetKeyInfo returns the key info. idClient is the id of client (not client-id).
func (c *Client) GetKeyInfo(realmName, idClient, attr string) (CertificateRepresentation, error) { func (c *Client) GetKeyInfo(accessToken string, realmName, idClient, attr string) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{} var resp = CertificateRepresentation{}
var err = c.get(&resp, url.Path(clientAttrCertPath), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr)) var err = c.get(accessToken, &resp, url.Path(clientAttrCertPath), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr))
return resp, err return resp, err
} }
// GetKeyStore returns a keystore file for the client, containing private key and public certificate. idClient is the id of client (not client-id). // GetKeyStore returns a keystore file for the client, containing private key and public certificate. idClient is the id of client (not client-id).
func (c *Client) GetKeyStore(realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) { func (c *Client) GetKeyStore(accessToken string, realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) {
var resp = []byte{} var resp = []byte{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig)) var err = c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig))
return resp, err return resp, err
} }
// GenerateCertificate generates a new certificate with new key pair. idClient is the id of client (not client-id). // GenerateCertificate generates a new certificate with new key pair. idClient is the id of client (not client-id).
func (c *Client) GenerateCertificate(realmName, idClient, attr string) (CertificateRepresentation, error) { func (c *Client) GenerateCertificate(accessToken string, realmName, idClient, attr string) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{} var resp = CertificateRepresentation{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/generate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr)) var err = c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/generate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr))
return resp, err return resp, err
} }
// GenerateKeyPairAndCertificate generates a keypair and certificate and serves the private key in a specified keystore format. // GenerateKeyPairAndCertificate generates a keypair and certificate and serves the private key in a specified keystore format.
func (c *Client) GenerateKeyPairAndCertificate(realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) { func (c *Client) GenerateKeyPairAndCertificate(accessToken string, realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) {
var resp = []byte{} var resp = []byte{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/generate-and-download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig)) var err = c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/generate-and-download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig))
return resp, err return resp, err
} }
// UploadCertificatePrivateKey uploads a certificate and eventually a private key. // UploadCertificatePrivateKey uploads a certificate and eventually a private key.
func (c *Client) UploadCertificatePrivateKey(realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) { func (c *Client) UploadCertificatePrivateKey(accessToken string, realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{} var resp = CertificateRepresentation{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/upload"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file))) var err = c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/upload"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file)))
return resp, err return resp, err
} }
// UploadCertificate uploads only a certificate, not the private key. // UploadCertificate uploads only a certificate, not the private key.
func (c *Client) UploadCertificate(realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) { func (c *Client) UploadCertificate(accessToken string, realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{} var resp = CertificateRepresentation{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/upload-certificate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file))) var err = c.post(accessToken, &resp, url.Path(clientAttrCertPath+"/upload-certificate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file)))
return resp, err return resp, err
} }

12
client_initial_access.go

@ -10,20 +10,20 @@ const (
) )
// CreateClientInitialAccess creates a new initial access token. // CreateClientInitialAccess creates a new initial access token.
func (c *Client) CreateClientInitialAccess(realmName string, access ClientInitialAccessCreatePresentation) (ClientInitialAccessPresentation, error) { func (c *Client) CreateClientInitialAccess(accessToken string, realmName string, access ClientInitialAccessCreatePresentation) (ClientInitialAccessPresentation, error) {
var resp = ClientInitialAccessPresentation{} var resp = ClientInitialAccessPresentation{}
var err = c.post(&resp, url.Path(clientInitialAccessPath), url.Param("realm", realmName), body.JSON(access)) var err = c.post(accessToken, &resp, url.Path(clientInitialAccessPath), url.Param("realm", realmName), body.JSON(access))
return resp, err return resp, err
} }
// GetClientInitialAccess returns a list of clients initial access. // GetClientInitialAccess returns a list of clients initial access.
func (c *Client) GetClientInitialAccess(realmName string) ([]ClientInitialAccessPresentation, error) { func (c *Client) GetClientInitialAccess(accessToken string, realmName string) ([]ClientInitialAccessPresentation, error) {
var resp = []ClientInitialAccessPresentation{} var resp = []ClientInitialAccessPresentation{}
var err = c.get(&resp, url.Path(clientInitialAccessPath), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(clientInitialAccessPath), url.Param("realm", realmName))
return resp, err return resp, err
} }
// DeleteClientInitialAccess deletes the client initial access. // DeleteClientInitialAccess deletes the client initial access.
func (c *Client) DeleteClientInitialAccess(realmName, accessID string) error { func (c *Client) DeleteClientInitialAccess(accessToken string, realmName, accessID string) error {
return c.delete(url.Path(clientInitialAccessPath+"/:id"), url.Param("realm", realmName), url.Param("id", accessID)) return c.delete(accessToken, url.Path(clientInitialAccessPath+"/:id"), url.Param("realm", realmName), url.Param("id", accessID))
} }

4
client_registration_policy.go

@ -7,8 +7,8 @@ const (
) )
// GetClientRegistrationPolicy is the base path to retrieve providers with the configProperties properly filled. // GetClientRegistrationPolicy is the base path to retrieve providers with the configProperties properly filled.
func (c *Client) GetClientRegistrationPolicy(realmName, configID string) ([]ComponentTypeRepresentation, error) { func (c *Client) GetClientRegistrationPolicy(accessToken string, realmName, configID string) ([]ComponentTypeRepresentation, error) {
var resp = []ComponentTypeRepresentation{} var resp = []ComponentTypeRepresentation{}
var err = c.get(&resp, url.Path(clientRegistrationPolicyPath), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(clientRegistrationPolicyPath), url.Param("realm", realmName))
return resp, err return resp, err
} }

12
client_role_mappings.go

@ -10,18 +10,18 @@ const (
) )
// CreateClientsRoleMapping add client-level roles to the user role mapping. // CreateClientsRoleMapping add client-level roles to the user role mapping.
func (c *Client) CreateClientsRoleMapping(realmName, groupID, clientID string, roles []RoleRepresentation) error { func (c *Client) CreateClientsRoleMapping(accessToken string, realmName, groupID, clientID string, roles []RoleRepresentation) error {
return c.post(nil, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID), body.JSON(roles)) return c.post(accessToken, nil, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID), body.JSON(roles))
} }
// GetClientsRoleMapping gets client-level role mappings for the user, and the app. // GetClientsRoleMapping gets client-level role mappings for the user, and the app.
func (c *Client) GetClientsRoleMapping(realmName, groupID, clientID string) ([]RoleRepresentation, error) { func (c *Client) GetClientsRoleMapping(accessToken string, realmName, groupID, clientID string) ([]RoleRepresentation, error) {
var resp = []RoleRepresentation{} var resp = []RoleRepresentation{}
var err = c.get(&resp, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID)) var err = c.get(accessToken, &resp, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID))
return resp, err return resp, err
} }
// DeleteClientsRoleMapping deletes client-level roles from user role mapping. // DeleteClientsRoleMapping deletes client-level roles from user role mapping.
func (c *Client) DeleteClientsRoleMapping(realmName, groupID, clientID string) error { func (c *Client) DeleteClientsRoleMapping(accessToken string, realmName, groupID, clientID string) error {
return c.delete(url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID)) return c.delete(accessToken, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID))
} }

1
client_templates.go

@ -1 +0,0 @@
package keycloak

12
clients.go

@ -15,27 +15,27 @@ const (
// GetClients returns a list of clients belonging to the realm. // GetClients returns a list of clients belonging to the realm.
// Parameters: clientId (filter by clientId), // Parameters: clientId (filter by clientId),
// viewableOnly (filter clients that cannot be viewed in full by admin, default="false") // viewableOnly (filter clients that cannot be viewed in full by admin, default="false")
func (c *Client) GetClients(realmName string, paramKV ...string) ([]ClientRepresentation, error) { func (c *Client) GetClients(accessToken string, realmName string, paramKV ...string) ([]ClientRepresentation, error) {
if len(paramKV)%2 != 0 { if len(paramKV)%2 != 0 {
return nil, fmt.Errorf("the number of key/val parameters should be even") return nil, fmt.Errorf("the number of key/val parameters should be even")
} }
var resp = []ClientRepresentation{} var resp = []ClientRepresentation{}
var plugins = append(createQueryPlugins(paramKV...), url.Path(clientsPath), url.Param("realm", realmName)) var plugins = append(createQueryPlugins(paramKV...), url.Path(clientsPath), url.Param("realm", realmName))
var err = c.get(&resp, plugins...) var err = c.get(accessToken, &resp, plugins...)
return resp, err return resp, err
} }
// GetClient get the representation of the client. idClient is the id of client (not client-id). // GetClient get the representation of the client. idClient is the id of client (not client-id).
func (c *Client) GetClient(realmName, idClient string) (ClientRepresentation, error) { func (c *Client) GetClient(accessToken string, realmName, idClient string) (ClientRepresentation, error) {
var resp = ClientRepresentation{} var resp = ClientRepresentation{}
var err = c.get(&resp, url.Path(clientIDPath), url.Param("realm", realmName), url.Param("id", idClient)) var err = c.get(accessToken, &resp, url.Path(clientIDPath), url.Param("realm", realmName), url.Param("id", idClient))
return resp, err return resp, err
} }
// GetSecret get the client secret. idClient is the id of client (not client-id). // GetSecret get the client secret. idClient is the id of client (not client-id).
func (c *Client) GetSecret(realmName, idClient string) (CredentialRepresentation, error) { func (c *Client) GetSecret(accessToken string, realmName, idClient string) (CredentialRepresentation, error) {
var resp = CredentialRepresentation{} var resp = CredentialRepresentation{}
var err = c.get(&resp, url.Path(clientSecret), url.Param("realm", realmName), url.Param("id", idClient)) var err = c.get(accessToken, &resp, url.Path(clientSecret), url.Param("realm", realmName), url.Param("id", idClient))
return resp, err return resp, err
} }

53
clients_test.go

@ -1,53 +0,0 @@
package keycloak
import (
"encoding/json"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestPlayground(t *testing.T) {
var client = initTest(t)
var clients, err = client.GetClients("master")
for _, c := range clients {
printStruct(c)
}
assert.Nil(t, err)
}
func TestCreateRealm(t *testing.T) {
var client = initTest(t)
var clients, err = client.GetClients("master")
for i, c := range clients {
fmt.Println(i, *(c.Id), *c.ClientId)
}
assert.Nil(t, err)
}
func TestGetClient(t *testing.T) {
var client = initTest(t)
var c, err = client.GetClient("318ab6db-c056-4d2f-b4f6-c0b585ee45b3", "master")
fmt.Println(*(c.Id), *c.ClientId, c.Secret)
assert.Nil(t, err)
}
func TestGetSecret(t *testing.T) {
var client = initTest(t)
var c, err = client.GetSecret("318ab6db-c056-4d2f-b4f6-c0b585ee45b3", "master")
fmt.Println(*(c.Value))
assert.Nil(t, err)
}
func printStruct(data interface{}) {
var s, err = json.Marshal(data)
if err != nil {
fmt.Println("could not marshal json")
return
}
fmt.Println(string(s))
fmt.Println()
}

1
component.go

@ -1 +0,0 @@
package keycloak

1
groups.go

@ -1 +0,0 @@
package keycloak

1
identity_providers.go

@ -1 +0,0 @@
package keycloak

BIN
integration/integration

Binary file not shown.

60
integration/integration.go

@ -22,14 +22,20 @@ func main() {
log.Fatalf("could not create keycloak client: %v", err) log.Fatalf("could not create keycloak client: %v", err)
} }
// Get access token
accessToken, err := client.GetToken("master", "admin", "admin")
if err != nil {
log.Fatalf("could not get access token: %v", err)
}
// Delete test realm // Delete test realm
client.DeleteRealm(tstRealm) client.DeleteRealm(accessToken, tstRealm)
// Check existing realms // Check existing realms
var initialRealms []keycloak.RealmRepresentation var initialRealms []keycloak.RealmRepresentation
{ {
var err error var err error
initialRealms, err = client.GetRealms() initialRealms, err = client.GetRealms(accessToken)
if err != nil { if err != nil {
log.Fatalf("could not get realms: %v", err) log.Fatalf("could not get realms: %v", err)
} }
@ -43,7 +49,7 @@ func main() {
// Create test realm. // Create test realm.
{ {
var realm = tstRealm var realm = tstRealm
var err = client.CreateRealm(keycloak.RealmRepresentation{ var err = client.CreateRealm(accessToken, keycloak.RealmRepresentation{
Realm: &realm, Realm: &realm,
}) })
if err != nil { if err != nil {
@ -54,7 +60,7 @@ func main() {
// Check getRealm. // Check getRealm.
{ {
var realmR, err = client.GetRealm(tstRealm) var realmR, err = client.GetRealm(accessToken, tstRealm)
if err != nil { if err != nil {
log.Fatalf("could not get test realm: %v", err) log.Fatalf("could not get test realm: %v", err)
} }
@ -70,7 +76,7 @@ func main() {
// Update Realm // Update Realm
{ {
var displayName = "updated realm" var displayName = "updated realm"
var err = client.UpdateRealm(tstRealm, keycloak.RealmRepresentation{ var err = client.UpdateRealm(accessToken, tstRealm, keycloak.RealmRepresentation{
DisplayName: &displayName, DisplayName: &displayName,
}) })
if err != nil { if err != nil {
@ -78,7 +84,7 @@ func main() {
} }
// Check update // Check update
{ {
var realmR, err = client.GetRealm(tstRealm) var realmR, err = client.GetRealm(accessToken, tstRealm)
if err != nil { if err != nil {
log.Fatalf("could not get test realm: %v", err) log.Fatalf("could not get test realm: %v", err)
} }
@ -91,7 +97,7 @@ func main() {
// Count users. // Count users.
{ {
var nbrUser, err = client.CountUsers(tstRealm) var nbrUser, err = client.CountUsers(accessToken, tstRealm)
if err != nil { if err != nil {
log.Fatalf("could not count users: %v", err) log.Fatalf("could not count users: %v", err)
} }
@ -105,7 +111,7 @@ func main() {
for _, u := range tstUsers { for _, u := range tstUsers {
var username = strings.ToLower(u.firstname + "." + u.lastname) var username = strings.ToLower(u.firstname + "." + u.lastname)
var email = username + "@cloudtrust.ch" var email = username + "@cloudtrust.ch"
var err = client.CreateUser(tstRealm, keycloak.UserRepresentation{ var err = client.CreateUser(accessToken, tstRealm, keycloak.UserRepresentation{
Username: &username, Username: &username,
FirstName: &u.firstname, FirstName: &u.firstname,
LastName: &u.lastname, LastName: &u.lastname,
@ -117,7 +123,7 @@ func main() {
} }
// Check that all users where created. // Check that all users where created.
{ {
var nbrUser, err = client.CountUsers(tstRealm) var nbrUser, err = client.CountUsers(accessToken, tstRealm)
if err != nil { if err != nil {
log.Fatalf("could not count users: %v", err) log.Fatalf("could not count users: %v", err)
} }
@ -132,7 +138,7 @@ func main() {
{ {
{ {
// No parameters. // No parameters.
var users, err = client.GetUsers(tstRealm) var users, err = client.GetUsers(accessToken, tstRealm)
if err != nil { if err != nil {
log.Fatalf("could not get users: %v", err) log.Fatalf("could not get users: %v", err)
} }
@ -142,7 +148,7 @@ func main() {
} }
{ {
// email. // email.
var users, err = client.GetUsers(tstRealm, "email", "john.doe@cloudtrust.ch") var users, err = client.GetUsers(accessToken, tstRealm, "email", "john.doe@cloudtrust.ch")
if err != nil { if err != nil {
log.Fatalf("could not get users: %v", err) log.Fatalf("could not get users: %v", err)
} }
@ -152,7 +158,7 @@ func main() {
} }
{ {
// firstname. // firstname.
var users, err = client.GetUsers(tstRealm, "firstName", "John") var users, err = client.GetUsers(accessToken, tstRealm, "firstName", "John")
if err != nil { if err != nil {
log.Fatalf("could not get users: %v", err) log.Fatalf("could not get users: %v", err)
} }
@ -163,7 +169,7 @@ func main() {
} }
{ {
// lastname. // lastname.
var users, err = client.GetUsers(tstRealm, "lastName", "Wells") var users, err = client.GetUsers(accessToken, tstRealm, "lastName", "Wells")
if err != nil { if err != nil {
log.Fatalf("could not get users: %v", err) log.Fatalf("could not get users: %v", err)
} }
@ -173,7 +179,7 @@ func main() {
} }
{ {
// username. // username.
var users, err = client.GetUsers(tstRealm, "username", "lucia.nelson") var users, err = client.GetUsers(accessToken, tstRealm, "username", "lucia.nelson")
if err != nil { if err != nil {
log.Fatalf("could not get users: %v", err) log.Fatalf("could not get users: %v", err)
} }
@ -183,7 +189,7 @@ func main() {
} }
{ {
// first. // first.
var users, err = client.GetUsers(tstRealm, "max", "7") var users, err = client.GetUsers(accessToken, tstRealm, "max", "7")
if err != nil { if err != nil {
log.Fatalf("could not get users: %v", err) log.Fatalf("could not get users: %v", err)
} }
@ -193,7 +199,7 @@ func main() {
} }
{ {
// search. // search.
var users, err = client.GetUsers(tstRealm, "search", "le") var users, err = client.GetUsers(accessToken, tstRealm, "search", "le")
if err != nil { if err != nil {
log.Fatalf("could not get users: %v", err) log.Fatalf("could not get users: %v", err)
} }
@ -209,7 +215,7 @@ func main() {
// Get user ID. // Get user ID.
var userID string var userID string
{ {
var users, err = client.GetUsers(tstRealm, "search", "Maria") var users, err = client.GetUsers(accessToken, tstRealm, "search", "Maria")
if err != nil { if err != nil {
log.Fatalf("could not get Maria: %v", err) log.Fatalf("could not get Maria: %v", err)
} }
@ -226,7 +232,7 @@ func main() {
var updatedLastname = "updated" var updatedLastname = "updated"
{ {
var err = client.UpdateUser(tstRealm, userID, keycloak.UserRepresentation{ var err = client.UpdateUser(accessToken, tstRealm, userID, keycloak.UserRepresentation{
FirstName: &username, FirstName: &username,
LastName: &updatedLastname, LastName: &updatedLastname,
}) })
@ -236,7 +242,7 @@ func main() {
} }
// Check that user was updated. // Check that user was updated.
{ {
var users, err = client.GetUsers(tstRealm, "search", "Maria") var users, err = client.GetUsers(accessToken, tstRealm, "search", "Maria")
if err != nil { if err != nil {
log.Fatalf("could not get Maria: %v", err) log.Fatalf("could not get Maria: %v", err)
} }
@ -255,7 +261,7 @@ func main() {
// Get user ID. // Get user ID.
var userID string var userID string
{ {
var users, err = client.GetUsers(tstRealm, "search", "Toni") var users, err = client.GetUsers(accessToken, tstRealm, "search", "Toni")
if err != nil { if err != nil {
log.Fatalf("could not get Toni: %v", err) log.Fatalf("could not get Toni: %v", err)
} }
@ -269,14 +275,14 @@ func main() {
} }
// Delete user. // Delete user.
{ {
var err = client.DeleteUser(tstRealm, userID) var err = client.DeleteUser(accessToken, tstRealm, userID)
if err != nil { if err != nil {
log.Fatalf("could not delete user: %v", err) log.Fatalf("could not delete user: %v", err)
} }
} }
// Check that user was deleted. // Check that user was deleted.
{ {
var nbrUser, err = client.CountUsers(tstRealm) var nbrUser, err = client.CountUsers(accessToken, tstRealm)
if err != nil { if err != nil {
log.Fatalf("could not count users: %v", err) log.Fatalf("could not count users: %v", err)
} }
@ -289,13 +295,13 @@ func main() {
// Delete test realm. // Delete test realm.
{ {
var err = client.DeleteRealm(tstRealm) var err = client.DeleteRealm(accessToken, tstRealm)
if err != nil { if err != nil {
log.Fatalf("could not delete test realm: %v", err) log.Fatalf("could not delete test realm: %v", err)
} }
// Check that the realm was deleted. // Check that the realm was deleted.
{ {
var realms, err = client.GetRealms() var realms, err = client.GetRealms(accessToken)
if err != nil { if err != nil {
log.Fatalf("could not get realms: %v", err) log.Fatalf("could not get realms: %v", err)
} }
@ -331,15 +337,11 @@ func (c *Client) DeleteUser(realmName, userID string) error {
*/ */
func getKeycloakConfig() *keycloak.Config { func getKeycloakConfig() *keycloak.Config {
var adr = pflag.String("url", "localhost:8080", "keycloak address") var adr = pflag.String("url", "http://localhost:8080", "keycloak address")
var username = pflag.String("username", "admin", "keycloak username")
var password = pflag.String("password", "admin", "keycloak password")
pflag.Parse() pflag.Parse()
return &keycloak.Config{ return &keycloak.Config{
Addr: *adr, Addr: *adr,
Username: *username,
Password: *password,
Timeout: 10 * time.Second, Timeout: 10 * time.Second,
} }
} }

1
key.go

@ -1 +0,0 @@
package keycloak

117
keycloak_client.go

@ -18,17 +18,12 @@ import (
// Config is the keycloak client http config. // Config is the keycloak client http config.
type Config struct { type Config struct {
Addr string Addr string
Username string
Password string
Timeout time.Duration Timeout time.Duration
} }
// Client is the keycloak client. // Client is the keycloak client.
type Client struct { type Client struct {
username string url *url.URL
password string
accessToken string
oidcProvider *oidc.Provider
httpClient *gentleman.Client httpClient *gentleman.Client
} }
@ -43,44 +38,28 @@ func New(config Config) (*Client, error) {
} }
} }
// if u.Scheme != "http" {
// return nil, fmt.Errorf("protocol not supported, your address must start with http://, not %v", u.Scheme)
// }
var httpClient = gentleman.New() var httpClient = gentleman.New()
{ {
httpClient = httpClient.URL(u.String()) httpClient = httpClient.URL(u.String())
httpClient = httpClient.Use(timeout.Request(config.Timeout)) httpClient = httpClient.Use(timeout.Request(config.Timeout))
} }
var oidcProvider *oidc.Provider
{
var err error
var issuer = fmt.Sprintf("%s/auth/realms/master", u.String())
oidcProvider, err = oidc.NewProvider(context.Background(), issuer)
if err != nil {
return nil, errors.Wrap(err, "could not create oidc provider")
}
}
return &Client{ return &Client{
username: config.Username, url: u,
password: config.Password,
oidcProvider: oidcProvider,
httpClient: httpClient, httpClient: httpClient,
}, nil }, nil
} }
// getToken get a token from keycloak. // getToken returns a valid token from keycloak.
func (c *Client) getToken() error { func (c *Client) GetToken(realm string, username string, password string) (string, error) {
var req *gentleman.Request var req *gentleman.Request
{ {
var authPath = "/auth/realms/master/protocol/openid-connect/token" var authPath = fmt.Sprintf("/auth/realms/%s/protocol/openid-connect/token", realm)
req = c.httpClient.Post() req = c.httpClient.Post()
req = req.SetHeader("Content-Type", "application/x-www-form-urlencoded") req = req.SetHeader("Content-Type", "application/x-www-form-urlencoded")
req = req.Path(authPath) req = req.Path(authPath)
req = req.Type("urlencoded") req = req.Type("urlencoded")
req = req.BodyString(fmt.Sprintf("username=%s&password=%s&grant_type=password&client_id=admin-cli", c.username, c.password)) req = req.BodyString(fmt.Sprintf("username=%s&password=%s&grant_type=password&client_id=admin-cli", username, password))
} }
var resp *gentleman.Response var resp *gentleman.Response
@ -88,17 +67,20 @@ func (c *Client) getToken() error {
var err error var err error
resp, err = req.Do() resp, err = req.Do()
if err != nil { if err != nil {
return errors.Wrap(err, "could not get token") return "", errors.Wrap(err, "could not get token")
} }
} }
defer resp.Close() defer resp.Close()
titi := string(resp.Bytes())
fmt.Printf(titi)
var unmarshalledBody map[string]interface{} var unmarshalledBody map[string]interface{}
{ {
var err error var err error
err = resp.JSON(&unmarshalledBody) err = resp.JSON(&unmarshalledBody)
if err != nil { if err != nil {
return errors.Wrap(err, "could not unmarshal response") return "", errors.Wrap(err, "could not unmarshal response")
} }
} }
@ -107,28 +89,37 @@ func (c *Client) getToken() error {
var ok bool var ok bool
accessToken, ok = unmarshalledBody["access_token"] accessToken, ok = unmarshalledBody["access_token"]
if !ok { if !ok {
return fmt.Errorf("could not find access token in response body") return "", fmt.Errorf("could not find access token in response body")
} }
} }
c.accessToken = accessToken.(string) return accessToken.(string), nil
return nil
} }
// verifyToken token verify a token. It returns an error it is malformed, expired,... // verifyToken token verify a token. It returns an error it is malformed, expired,...
func (c *Client) verifyToken() error { func (c *Client) VerifyToken(realmName string, accessToken string) error {
var v = c.oidcProvider.Verifier(&oidc.Config{SkipClientIDCheck: true}) var oidcProvider *oidc.Provider
{
var err error
var issuer = fmt.Sprintf("%s/auth/realms/%s", c.url.String(), realmName)
oidcProvider, err = oidc.NewProvider(context.Background(), issuer)
if err != nil {
return errors.Wrap(err, "could not create oidc provider")
}
}
var v = oidcProvider.Verifier(&oidc.Config{SkipClientIDCheck: true})
var err error var err error
_, err = v.Verify(context.Background(), c.accessToken) _, err = v.Verify(context.Background(), accessToken)
return err return err
} }
// get is a HTTP get method. // get is a HTTP get method.
func (c *Client) get(data interface{}, plugins ...plugin.Plugin) error { func (c *Client) get(accessToken string, data interface{}, plugins ...plugin.Plugin) error {
var req = c.httpClient.Get() var req = c.httpClient.Get()
req = applyPlugins(req, c.accessToken, plugins...) req = applyPlugins(req, accessToken, plugins...)
var resp *gentleman.Response var resp *gentleman.Response
{ {
@ -140,16 +131,9 @@ func (c *Client) get(data interface{}, plugins ...plugin.Plugin) error {
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
// If the token is not valid (expired, ...) ask a new one. return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String())
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return errors.Wrap(err, "could not get token: %v")
}
}
return c.get(data, plugins...)
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes())) return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, resp.String())
case resp.StatusCode >= 200: case resp.StatusCode >= 200:
switch resp.Header.Get("Content-Type") { switch resp.Header.Get("Content-Type") {
case "application/json": case "application/json":
@ -166,9 +150,9 @@ func (c *Client) get(data interface{}, plugins ...plugin.Plugin) error {
} }
} }
func (c *Client) post(data interface{}, plugins ...plugin.Plugin) error { func (c *Client) post(accessToken string, data interface{}, plugins ...plugin.Plugin) error {
var req = c.httpClient.Post() var req = c.httpClient.Post()
req = applyPlugins(req, c.accessToken, plugins...) req = applyPlugins(req, accessToken, plugins...)
var resp *gentleman.Response var resp *gentleman.Response
{ {
var err error var err error
@ -179,14 +163,7 @@ func (c *Client) post(data interface{}, plugins ...plugin.Plugin) error {
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
// If the token is not valid (expired, ...) ask a new one. return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String())
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return errors.Wrap(err, "could not get token")
}
}
return c.post(data, plugins...)
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes())) return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes()))
case resp.StatusCode >= 200: case resp.StatusCode >= 200:
@ -197,7 +174,7 @@ func (c *Client) post(data interface{}, plugins ...plugin.Plugin) error {
data = resp.Bytes() data = resp.Bytes()
return nil return nil
default: default:
return fmt.Errorf("unkown http content-type: %v", resp.Header.Get("Content-Type")) return nil
} }
default: default:
return fmt.Errorf("unknown response status code: %v", resp.StatusCode) return fmt.Errorf("unknown response status code: %v", resp.StatusCode)
@ -205,9 +182,9 @@ func (c *Client) post(data interface{}, plugins ...plugin.Plugin) error {
} }
} }
func (c *Client) delete(plugins ...plugin.Plugin) error { func (c *Client) delete(accessToken string, plugins ...plugin.Plugin) error {
var req = c.httpClient.Delete() var req = c.httpClient.Delete()
req = applyPlugins(req, c.accessToken, plugins...) req = applyPlugins(req, accessToken, plugins...)
var resp *gentleman.Response var resp *gentleman.Response
{ {
@ -219,14 +196,7 @@ func (c *Client) delete(plugins ...plugin.Plugin) error {
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
// If the token is not valid (expired, ...) ask a new one. return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String())
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return errors.Wrap(err, "could not get token")
}
}
return c.delete(plugins...)
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes())) return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes()))
case resp.StatusCode >= 200: case resp.StatusCode >= 200:
@ -237,9 +207,9 @@ func (c *Client) delete(plugins ...plugin.Plugin) error {
} }
} }
func (c *Client) put(plugins ...plugin.Plugin) error { func (c *Client) put(accessToken string, plugins ...plugin.Plugin) error {
var req = c.httpClient.Put() var req = c.httpClient.Put()
req = applyPlugins(req, c.accessToken, plugins...) req = applyPlugins(req, accessToken, plugins...)
var resp *gentleman.Response var resp *gentleman.Response
{ {
@ -251,14 +221,7 @@ func (c *Client) put(plugins ...plugin.Plugin) error {
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
// If the token is not valid (expired, ...) ask a new one. return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String())
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return errors.Wrap(err, "could not get token: %v")
}
}
return c.put(plugins...)
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes())) return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes()))
case resp.StatusCode >= 200: case resp.StatusCode >= 200:

40
keycloak_client_test.go

@ -1,40 +0,0 @@
package keycloak
import (
"flag"
"fmt"
"os"
"testing"
"time"
"github.com/stretchr/testify/require"
)
var (
hostPort = flag.String("hostport", "10.244.18.2:80", "keycloak host:port")
username = flag.String("username", "admin", "keycloak user name")
password = flag.String("password", "admin", "keycloak password")
to = flag.Int("timeout", 20, "timeout in seconds")
)
func TestMain(m *testing.M) {
flag.Parse()
result := m.Run()
os.Exit(result)
}
func initTest(t *testing.T) *Client {
var config = Config{
Addr: fmt.Sprintf("http://%s", *hostPort),
Username: *username,
Password: *password,
Timeout: time.Duration(*to) * time.Second,
}
var client *Client
{
var err error
client, err = New(config)
require.Nil(t, err, "could not create client")
}
return client
}

24
realm.go

@ -13,39 +13,39 @@ const (
// GetRealms get the top level represention of all the realms. Nested information like users are // GetRealms get the top level represention of all the realms. Nested information like users are
// not included. // not included.
func (c *Client) GetRealms() ([]RealmRepresentation, error) { func (c *Client) GetRealms(accessToken string) ([]RealmRepresentation, error){
var resp = []RealmRepresentation{} var resp = []RealmRepresentation{}
var err = c.get(&resp, url.Path(realmRootPath)) var err = c.get(accessToken, &resp, url.Path(realmRootPath))
return resp, err return resp, err
} }
// CreateRealm creates the realm from its RealmRepresentation. // CreateRealm creates the realm from its RealmRepresentation.
func (c *Client) CreateRealm(realm RealmRepresentation) error { func (c *Client) CreateRealm(accessToken string, realm RealmRepresentation) error {
return c.post(nil, url.Path(realmRootPath), body.JSON(realm)) return c.post(accessToken, nil, url.Path(realmRootPath), body.JSON(realm))
} }
// GetRealm get the top level represention of the realm. Nested information like users are // GetRealm get the top level represention of the realm. Nested information like users are
// not included. // not included.
func (c *Client) GetRealm(realmName string) (RealmRepresentation, error) { func (c *Client) GetRealm(accessToken string, realmName string) (RealmRepresentation, error) {
var resp = RealmRepresentation{} var resp = RealmRepresentation{}
var err = c.get(&resp, url.Path(realmPath), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(realmPath), url.Param("realm", realmName))
return resp, err return resp, err
} }
// UpdateRealm update the top lovel information of the realm. Any user, role or client information // UpdateRealm update the top lovel information of the realm. Any user, role or client information
// from the realm representation will be ignored. // from the realm representation will be ignored.
func (c *Client) UpdateRealm(realmName string, realm RealmRepresentation) error { func (c *Client) UpdateRealm(accessToken string, realmName string, realm RealmRepresentation) error {
return c.put(url.Path(realmPath), url.Param("realm", realmName), body.JSON(realm)) return c.put(accessToken, url.Path(realmPath), url.Param("realm", realmName), body.JSON(realm))
} }
// DeleteRealm deletes the realm. // DeleteRealm deletes the realm.
func (c *Client) DeleteRealm(realmName string) error { func (c *Client) DeleteRealm(accessToken string, realmName string) error {
return c.delete(url.Path(realmPath), url.Param("realm", realmName)) return c.delete(accessToken, url.Path(realmPath), url.Param("realm", realmName))
} }
// ExportRealm recovers the full realm. // ExportRealm recovers the full realm.
func (c *Client) ExportRealm(realmName string) (RealmRepresentation, error) { func (c *Client) ExportRealm(accessToken string, realmName string) (RealmRepresentation, error) {
var resp = RealmRepresentation{} var resp = RealmRepresentation{}
var err = c.get(&resp, url.Path(exportRealmPath), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(exportRealmPath), url.Param("realm", realmName))
return resp, err return resp, err
} }

25
realm_test.go

@ -1,25 +0,0 @@
package keycloak
import (
"testing"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/stretchr/testify/require"
)
func TestExportRealms(t *testing.T) {
var client, err = New(Config{
Addr: "http://keycloak:80",
Username: "admin",
Password: "admin",
Timeout: 10 * time.Second,
})
require.Nil(t, err, "Err wasnt nil!", err)
{
var realm, err = client.ExportRealm("master")
require.Nil(t, err, "Err isnt nil!", err)
spew.Dump(realm)
}
}

1
realms_admin.go

@ -1 +0,0 @@
package keycloak

1
role_mapper.go

@ -1 +0,0 @@
package keycloak

1
roles.go

@ -1 +0,0 @@
package keycloak

1
root.go

@ -1 +0,0 @@
package keycloak

1
scope_mappings.go

@ -1 +0,0 @@
package keycloak

1
user_storage_provider.go

@ -1 +0,0 @@
package keycloak

24
users.go

@ -17,42 +17,42 @@ const (
// Parameters: email, first (paging offset, int), firstName, lastName, username, // Parameters: email, first (paging offset, int), firstName, lastName, username,
// max (maximum result size, default = 100), // max (maximum result size, default = 100),
// search (string contained in username, firstname, lastname or email) // search (string contained in username, firstname, lastname or email)
func (c *Client) GetUsers(realmName string, paramKV ...string) ([]UserRepresentation, error) { func (c *Client) GetUsers(accessToken string, realmName string, paramKV ...string) ([]UserRepresentation, error) {
if len(paramKV)%2 != 0 { if len(paramKV)%2 != 0 {
return nil, fmt.Errorf("the number of key/val parameters should be even") return nil, fmt.Errorf("the number of key/val parameters should be even")
} }
var resp = []UserRepresentation{} var resp = []UserRepresentation{}
var plugins = append(createQueryPlugins(paramKV...), url.Path(userPath), url.Param("realm", realmName)) var plugins = append(createQueryPlugins(paramKV...), url.Path(userPath), url.Param("realm", realmName))
var err = c.get(&resp, plugins...) var err = c.get(accessToken, &resp, plugins...)
return resp, err return resp, err
} }
// CreateUser creates the user from its UserRepresentation. The username must be unique. // CreateUser creates the user from its UserRepresentation. The username must be unique.
func (c *Client) CreateUser(realmName string, user UserRepresentation) error { func (c *Client) CreateUser(accessToken string, realmName string, user UserRepresentation) error {
return c.post(nil, url.Path(userPath), url.Param("realm", realmName), body.JSON(user)) return c.post(accessToken, nil, url.Path(userPath), url.Param("realm", realmName), body.JSON(user))
} }
// CountUsers returns the number of users in the realm. // CountUsers returns the number of users in the realm.
func (c *Client) CountUsers(realmName string) (int, error) { func (c *Client) CountUsers(accessToken string, realmName string) (int, error) {
var resp = 0 var resp = 0
var err = c.get(&resp, url.Path(userCountPath), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(userCountPath), url.Param("realm", realmName))
return resp, err return resp, err
} }
// GetUser get the represention of the user. // GetUser get the represention of the user.
func (c *Client) GetUser(realmName, userID string) (UserRepresentation, error) { func (c *Client) GetUser(accessToken string, realmName, userID string) (UserRepresentation, error) {
var resp = UserRepresentation{} var resp = UserRepresentation{}
var err = c.get(&resp, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID)) var err = c.get(accessToken, &resp, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID))
return resp, err return resp, err
} }
// UpdateUser updates the user. // UpdateUser updates the user.
func (c *Client) UpdateUser(realmName, userID string, user UserRepresentation) error { func (c *Client) UpdateUser(accessToken string, realmName, userID string, user UserRepresentation) error {
return c.put(url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(user)) return c.put(accessToken, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(user))
} }
// DeleteUser deletes the user. // DeleteUser deletes the user.
func (c *Client) DeleteUser(realmName, userID string) error { func (c *Client) DeleteUser(accessToken string, realmName, userID string) error {
return c.delete(url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID)) return c.delete(accessToken, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID))
} }

23
users_test.go

@ -1,23 +0,0 @@
package keycloak
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetUsers(t *testing.T) {
var c = initTest(t)
var users []UserRepresentation
{
var err error
users, err = c.GetUsers("master")
require.Nil(t, err, "could not get users")
}
for _, i := range users {
fmt.Println(i.Credentials)
assert.NotZero(t, *i.Username)
}
}
Loading…
Cancel
Save