diff --git a/Gopkg.lock b/Gopkg.lock index ca42fb3..5bd387a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,97 +3,199 @@ [[projects]] branch = "v2" + digest = "1:e193a6789a00fd6fee10f8e5d070eb3f1dcf19d7fdaff61f23ffdcd42dae7d9e" name = "github.com/coreos/go-oidc" packages = ["."] + pruneopts = "" revision = "065b426bd41667456c1a924468f507673629c46b" [[projects]] + digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "" revision = "346938d642f2ec3594ed81d874461961cd0faa76" version = "v1.1.0" [[projects]] + digest = "1:bcb38c8fc9b21bb8682ce2d605a7d4aeb618abc7f827e3ac0b27c0371fdb23fb" name = "github.com/golang/protobuf" packages = ["proto"] + pruneopts = "" revision = "925541529c1fa6821df4e44ce2723319eb2be768" version = "v1.0.0" [[projects]] + digest = "1:7365acd48986e205ccb8652cc746f09c8b7876030d53710ea6ef7d0bd0dcd7ca" name = "github.com/pkg/errors" packages = ["."] + pruneopts = "" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] + digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411" name = "github.com/pmezard/go-difflib" packages = ["difflib"] + pruneopts = "" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] branch = "master" + digest = "1:386e12afcfd8964907c92dffd106860c0dedd71dbefae14397b77b724a13343b" name = "github.com/pquerna/cachecontrol" - packages = [".","cacheobject"] + packages = [ + ".", + "cacheobject", + ] + pruneopts = "" revision = "0dec1b30a0215bb68605dfc568e8855066c9202d" [[projects]] + digest = "1:261bc565833ef4f02121450d74eb88d5ae4bd74bfe5d0e862cddb8550ec35000" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "" revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66" version = "v1.0.0" [[projects]] + digest = "1:a30066593578732a356dc7e5d7f78d69184ca65aeeff5939241a3ab10559bb06" name = "github.com/stretchr/testify" - packages = ["assert","require"] + packages = [ + "assert", + "require", + ] + pruneopts = "" revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" version = "v1.2.1" [[projects]] branch = "master" + digest = "1:2ea6df0f542cc95a5e374e9cdd81eaa599ed0d55366eef92d2f6b9efa2795c07" name = "golang.org/x/crypto" - packages = ["ed25519","ed25519/internal/edwards25519"] + packages = [ + "ed25519", + "ed25519/internal/edwards25519", + ] + pruneopts = "" revision = "432090b8f568c018896cd8a0fb0345872bbac6ce" [[projects]] branch = "master" + digest = "1:b4ba046df563f56fe42b6270b20039107a37e1ab47c97aa47a16f848aa5b6d9a" name = "golang.org/x/net" - packages = ["context","context/ctxhttp","idna","publicsuffix"] + packages = [ + "context", + "context/ctxhttp", + "idna", + "publicsuffix", + ] + pruneopts = "" revision = "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb" [[projects]] branch = "master" + digest = "1:dd57134ebff8e1a1a77c9f145a28cad8470da6bb9053d6ff2bc552ecd7f8bc92" name = "golang.org/x/oauth2" - packages = [".","internal"] + packages = [ + ".", + "internal", + ] + pruneopts = "" revision = "543e37812f10c46c622c9575afd7ad22f22a12ba" [[projects]] branch = "master" + digest = "1:31985a0ed491dba5ba7fe92e18be008acd92ca9435ed9b35b06f3e6c00fd82cb" 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" [[projects]] + digest = "1:934fb8966f303ede63aa405e2c8d7f0a427a05ea8df335dfdc1833dd4d40756f" 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" version = "v1.0.0" [[projects]] + digest = "1:e3250d192192f02fbb143d50de437cbe967d6be7bd9fad671600942a33269d08" 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" version = "v2.0.3" [[projects]] + digest = "1:be4ed0a2b15944dd777a663681a39260ed05f9c4e213017ed2e2255622c8820c" name = "gopkg.in/square/go-jose.v2" - packages = [".","cipher","json"] + packages = [ + ".", + "cipher", + "json", + ] + pruneopts = "" revision = "f8f38de21b4dcd69d0413faf231983f5fd6634b1" version = "v2.1.3" [solve-meta] analyzer-name = "dep" 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-version = 1 diff --git a/README.md b/README.md index bc1f55b..607ecac 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ ## 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. + diff --git a/attack_detection.go b/attack_detection.go index 28e099e..d137d57 100644 --- a/attack_detection.go +++ b/attack_detection.go @@ -10,18 +10,18 @@ const ( ) // ClearAllLoginFailures clears any user login failures for all users. This can release temporary disabled users. -func (c *Client) ClearAllLoginFailures(realmName string) error { - return c.delete(url.Path(attackDetectionPath), url.Param("realm", realmName)) +func (c *Client) ClearAllLoginFailures(accessToken string, realmName string) error { + return c.delete(accessToken, url.Path(attackDetectionPath), url.Param("realm", realmName)) } // 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 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 } // ClearUserLoginFailures clear any user login failures for the user. This can release temporary disabled user. -func (c *Client) ClearUserLoginFailures(realmName, userID string) error { - return c.delete(url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID)) +func (c *Client) ClearUserLoginFailures(accessToken string, realmName, userID string) error { + return c.delete(accessToken, url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID)) } diff --git a/authentication_management.go b/authentication_management.go index c13e4f8..c6e6387 100644 --- a/authentication_management.go +++ b/authentication_management.go @@ -10,180 +10,180 @@ const ( ) // 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 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 } // 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 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 } // 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 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 } // 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 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 } // UpdateAuthenticatorConfig updates the authenticator configuration. -func (c *Client) UpdateAuthenticatorConfig(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)) +func (c *Client) UpdateAuthenticatorConfig(accessToken string, realmName, configID string, config AuthenticatorConfigRepresentation) error { + 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. -func (c *Client) DeleteAuthenticatorConfig(realmName, configID string) error { - return c.delete(url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID)) +func (c *Client) DeleteAuthenticatorConfig(accessToken string, realmName, configID string) error { + return c.delete(accessToken, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID)) } // CreateAuthenticationExecution add new authentication execution -func (c *Client) CreateAuthenticationExecution(realmName string, authExec AuthenticationExecutionRepresentation) error { - return c.post(nil, url.Path(authenticationManagementPath+"/executions"), url.Param("realm", realmName), body.JSON(authExec)) +func (c *Client) CreateAuthenticationExecution(accessToken string, realmName string, authExec AuthenticationExecutionRepresentation) error { + return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/executions"), url.Param("realm", realmName), body.JSON(authExec)) } // DeleteAuthenticationExecution deletes the execution. -func (c *Client) DeleteAuthenticationExecution(realmName, executionID string) error { - return c.delete(url.Path(authenticationManagementPath+"/executions/:id"), url.Param("realm", realmName), url.Param("id", executionID)) +func (c *Client) DeleteAuthenticationExecution(accessToken string, realmName, executionID string) error { + return c.delete(accessToken, url.Path(authenticationManagementPath+"/executions/:id"), url.Param("realm", realmName), url.Param("id", executionID)) } // UpdateAuthenticationExecution update execution with new configuration. -func (c *Client) UpdateAuthenticationExecution(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)) +func (c *Client) UpdateAuthenticationExecution(accessToken string, realmName, executionID string, authConfig AuthenticatorConfigRepresentation) error { + 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. -func (c *Client) LowerExecutionPriority(realmName, executionID string) error { - return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/lower-priority"), url.Param("realm", realmName), url.Param("id", executionID)) +func (c *Client) LowerExecutionPriority(accessToken string, realmName, executionID string) error { + 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. -func (c *Client) RaiseExecutionPriority(realmName, executionID string) error { - return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/raise-priority"), url.Param("realm", realmName), url.Param("id", executionID)) +func (c *Client) RaiseExecutionPriority(accessToken string, realmName, executionID string) error { + 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. -func (c *Client) CreateAuthenticationFlow(realmName string, authFlow AuthenticationFlowRepresentation) error { - return c.post(nil, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName), body.JSON(authFlow)) +func (c *Client) CreateAuthenticationFlow(accessToken string, realmName string, authFlow AuthenticationFlowRepresentation) error { + return c.post(accessToken, nil, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName), body.JSON(authFlow)) } // 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 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 } // CopyExistingAuthenticationFlow copy the existing authentication flow under a new name. // 'flowAlias' is the name of the existing 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} - 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. -func (c *Client) GetAuthenticationExecutionForFlow(realmName, flowAlias string) (AuthenticationExecutionInfoRepresentation, error) { +func (c *Client) GetAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string) (AuthenticationExecutionInfoRepresentation, error) { 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 } // UpdateAuthenticationExecutionForFlow updates the authentication executions of a flow. -func (c *Client) UpdateAuthenticationExecutionForFlow(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)) +func (c *Client) UpdateAuthenticationExecutionForFlow(accessToken string, realmName, flowAlias string, authExecInfo AuthenticationExecutionInfoRepresentation) error { + 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. // '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} - 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. // '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} - 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. -func (c *Client) GetAuthenticationFlow(realmName, flowID string) (AuthenticationFlowRepresentation, error) { +func (c *Client) GetAuthenticationFlow(accessToken string, realmName, flowID string) (AuthenticationFlowRepresentation, error) { 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 } // DeleteAuthenticationFlow deletes an authentication flow. -func (c *Client) DeleteAuthenticationFlow(realmName, flowID string) error { - return c.delete(url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID)) +func (c *Client) DeleteAuthenticationFlow(accessToken string, realmName, flowID string) error { + 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. -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 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 } // 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 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 } // 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 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 } // 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} - 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. -func (c *Client) GetRequiredActions(realmName string) ([]RequiredActionProviderRepresentation, error) { +func (c *Client) GetRequiredActions(accessToken string, realmName string) ([]RequiredActionProviderRepresentation, error) { 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 } // 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 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 } // UpdateRequiredAction updates the required action. -func (c *Client) UpdateRequiredAction(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)) +func (c *Client) UpdateRequiredAction(accessToken string, realmName, actionAlias string, action RequiredActionProviderRepresentation) error { + 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. -func (c *Client) DeleteRequiredAction(realmName, actionAlias string) error { - return c.delete(url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias)) +func (c *Client) DeleteRequiredAction(accessToken string, realmName, actionAlias string) error { + 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. -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 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 } diff --git a/client_attribute_certificate.go b/client_attribute_certificate.go index e6b166f..8a0317e 100644 --- a/client_attribute_certificate.go +++ b/client_attribute_certificate.go @@ -12,43 +12,43 @@ const ( ) // 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 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 } // 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 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 } // 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 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 } // 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 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 } // 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 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 } // 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 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 } diff --git a/client_initial_access.go b/client_initial_access.go index 46aeb2d..942d4ee 100644 --- a/client_initial_access.go +++ b/client_initial_access.go @@ -10,20 +10,20 @@ const ( ) // 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 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 } // 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 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 } // DeleteClientInitialAccess deletes the client initial access. -func (c *Client) DeleteClientInitialAccess(realmName, accessID string) error { - return c.delete(url.Path(clientInitialAccessPath+"/:id"), url.Param("realm", realmName), url.Param("id", accessID)) +func (c *Client) DeleteClientInitialAccess(accessToken string, realmName, accessID string) error { + return c.delete(accessToken, url.Path(clientInitialAccessPath+"/:id"), url.Param("realm", realmName), url.Param("id", accessID)) } diff --git a/client_registration_policy.go b/client_registration_policy.go index a1b6d39..72f8fdb 100644 --- a/client_registration_policy.go +++ b/client_registration_policy.go @@ -7,8 +7,8 @@ const ( ) // 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 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 } diff --git a/client_role_mappings.go b/client_role_mappings.go index 0692f73..bf96db3 100644 --- a/client_role_mappings.go +++ b/client_role_mappings.go @@ -10,18 +10,18 @@ const ( ) // CreateClientsRoleMapping add client-level roles to the user role mapping. -func (c *Client) CreateClientsRoleMapping(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)) +func (c *Client) CreateClientsRoleMapping(accessToken string, realmName, groupID, clientID string, roles []RoleRepresentation) error { + 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. -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 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 } // DeleteClientsRoleMapping deletes client-level roles from user role mapping. -func (c *Client) DeleteClientsRoleMapping(realmName, groupID, clientID string) error { - return c.delete(url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID)) +func (c *Client) DeleteClientsRoleMapping(accessToken string, realmName, groupID, clientID string) error { + return c.delete(accessToken, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID)) } diff --git a/client_templates.go b/client_templates.go deleted file mode 100644 index cf172a0..0000000 --- a/client_templates.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/clients.go b/clients.go index d22a02c..28c033f 100644 --- a/clients.go +++ b/clients.go @@ -15,27 +15,27 @@ const ( // GetClients returns a list of clients belonging to the realm. // Parameters: clientId (filter by clientId), // 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 { return nil, fmt.Errorf("the number of key/val parameters should be even") } var resp = []ClientRepresentation{} 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 } // 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 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 } // 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 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 } diff --git a/clients_test.go b/clients_test.go deleted file mode 100644 index 0daf50c..0000000 --- a/clients_test.go +++ /dev/null @@ -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() -} diff --git a/component.go b/component.go deleted file mode 100644 index cf172a0..0000000 --- a/component.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/groups.go b/groups.go deleted file mode 100644 index cf172a0..0000000 --- a/groups.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/identity_providers.go b/identity_providers.go deleted file mode 100644 index cf172a0..0000000 --- a/identity_providers.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/integration/integration b/integration/integration new file mode 100755 index 0000000..f473963 Binary files /dev/null and b/integration/integration differ diff --git a/integration/integration.go b/integration/integration.go index e2db0b9..81c4cb5 100644 --- a/integration/integration.go +++ b/integration/integration.go @@ -22,14 +22,20 @@ func main() { 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 - client.DeleteRealm(tstRealm) + client.DeleteRealm(accessToken, tstRealm) // Check existing realms var initialRealms []keycloak.RealmRepresentation { var err error - initialRealms, err = client.GetRealms() + initialRealms, err = client.GetRealms(accessToken) if err != nil { log.Fatalf("could not get realms: %v", err) } @@ -43,7 +49,7 @@ func main() { // Create test realm. { var realm = tstRealm - var err = client.CreateRealm(keycloak.RealmRepresentation{ + var err = client.CreateRealm(accessToken, keycloak.RealmRepresentation{ Realm: &realm, }) if err != nil { @@ -54,7 +60,7 @@ func main() { // Check getRealm. { - var realmR, err = client.GetRealm(tstRealm) + var realmR, err = client.GetRealm(accessToken, tstRealm) if err != nil { log.Fatalf("could not get test realm: %v", err) } @@ -70,7 +76,7 @@ func main() { // Update Realm { var displayName = "updated realm" - var err = client.UpdateRealm(tstRealm, keycloak.RealmRepresentation{ + var err = client.UpdateRealm(accessToken, tstRealm, keycloak.RealmRepresentation{ DisplayName: &displayName, }) if err != nil { @@ -78,7 +84,7 @@ func main() { } // Check update { - var realmR, err = client.GetRealm(tstRealm) + var realmR, err = client.GetRealm(accessToken, tstRealm) if err != nil { log.Fatalf("could not get test realm: %v", err) } @@ -91,7 +97,7 @@ func main() { // Count users. { - var nbrUser, err = client.CountUsers(tstRealm) + var nbrUser, err = client.CountUsers(accessToken, tstRealm) if err != nil { log.Fatalf("could not count users: %v", err) } @@ -105,7 +111,7 @@ func main() { for _, u := range tstUsers { var username = strings.ToLower(u.firstname + "." + u.lastname) var email = username + "@cloudtrust.ch" - var err = client.CreateUser(tstRealm, keycloak.UserRepresentation{ + var err = client.CreateUser(accessToken, tstRealm, keycloak.UserRepresentation{ Username: &username, FirstName: &u.firstname, LastName: &u.lastname, @@ -117,7 +123,7 @@ func main() { } // Check that all users where created. { - var nbrUser, err = client.CountUsers(tstRealm) + var nbrUser, err = client.CountUsers(accessToken, tstRealm) if err != nil { log.Fatalf("could not count users: %v", err) } @@ -132,7 +138,7 @@ func main() { { { // No parameters. - var users, err = client.GetUsers(tstRealm) + var users, err = client.GetUsers(accessToken, tstRealm) if err != nil { log.Fatalf("could not get users: %v", err) } @@ -142,7 +148,7 @@ func main() { } { // 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 { log.Fatalf("could not get users: %v", err) } @@ -152,7 +158,7 @@ func main() { } { // firstname. - var users, err = client.GetUsers(tstRealm, "firstName", "John") + var users, err = client.GetUsers(accessToken, tstRealm, "firstName", "John") if err != nil { log.Fatalf("could not get users: %v", err) } @@ -163,7 +169,7 @@ func main() { } { // lastname. - var users, err = client.GetUsers(tstRealm, "lastName", "Wells") + var users, err = client.GetUsers(accessToken, tstRealm, "lastName", "Wells") if err != nil { log.Fatalf("could not get users: %v", err) } @@ -173,7 +179,7 @@ func main() { } { // username. - var users, err = client.GetUsers(tstRealm, "username", "lucia.nelson") + var users, err = client.GetUsers(accessToken, tstRealm, "username", "lucia.nelson") if err != nil { log.Fatalf("could not get users: %v", err) } @@ -183,7 +189,7 @@ func main() { } { // first. - var users, err = client.GetUsers(tstRealm, "max", "7") + var users, err = client.GetUsers(accessToken, tstRealm, "max", "7") if err != nil { log.Fatalf("could not get users: %v", err) } @@ -193,7 +199,7 @@ func main() { } { // search. - var users, err = client.GetUsers(tstRealm, "search", "le") + var users, err = client.GetUsers(accessToken, tstRealm, "search", "le") if err != nil { log.Fatalf("could not get users: %v", err) } @@ -209,7 +215,7 @@ func main() { // Get user ID. var userID string { - var users, err = client.GetUsers(tstRealm, "search", "Maria") + var users, err = client.GetUsers(accessToken, tstRealm, "search", "Maria") if err != nil { log.Fatalf("could not get Maria: %v", err) } @@ -226,7 +232,7 @@ func main() { var updatedLastname = "updated" { - var err = client.UpdateUser(tstRealm, userID, keycloak.UserRepresentation{ + var err = client.UpdateUser(accessToken, tstRealm, userID, keycloak.UserRepresentation{ FirstName: &username, LastName: &updatedLastname, }) @@ -236,7 +242,7 @@ func main() { } // 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 { log.Fatalf("could not get Maria: %v", err) } @@ -255,7 +261,7 @@ func main() { // Get user ID. var userID string { - var users, err = client.GetUsers(tstRealm, "search", "Toni") + var users, err = client.GetUsers(accessToken, tstRealm, "search", "Toni") if err != nil { log.Fatalf("could not get Toni: %v", err) } @@ -269,14 +275,14 @@ func main() { } // Delete user. { - var err = client.DeleteUser(tstRealm, userID) + var err = client.DeleteUser(accessToken, tstRealm, userID) if err != nil { log.Fatalf("could not delete user: %v", err) } } // Check that user was deleted. { - var nbrUser, err = client.CountUsers(tstRealm) + var nbrUser, err = client.CountUsers(accessToken, tstRealm) if err != nil { log.Fatalf("could not count users: %v", err) } @@ -289,13 +295,13 @@ func main() { // Delete test realm. { - var err = client.DeleteRealm(tstRealm) + var err = client.DeleteRealm(accessToken, tstRealm) if err != nil { log.Fatalf("could not delete test realm: %v", err) } // Check that the realm was deleted. { - var realms, err = client.GetRealms() + var realms, err = client.GetRealms(accessToken) if err != nil { log.Fatalf("could not get realms: %v", err) } @@ -331,15 +337,11 @@ func (c *Client) DeleteUser(realmName, userID string) error { */ func getKeycloakConfig() *keycloak.Config { - var adr = pflag.String("url", "localhost:8080", "keycloak address") - var username = pflag.String("username", "admin", "keycloak username") - var password = pflag.String("password", "admin", "keycloak password") + var adr = pflag.String("url", "http://localhost:8080", "keycloak address") pflag.Parse() return &keycloak.Config{ Addr: *adr, - Username: *username, - Password: *password, Timeout: 10 * time.Second, } } diff --git a/key.go b/key.go deleted file mode 100644 index cf172a0..0000000 --- a/key.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/keycloak_client.go b/keycloak_client.go index b9b16cf..d751bf2 100644 --- a/keycloak_client.go +++ b/keycloak_client.go @@ -17,18 +17,13 @@ import ( // Config is the keycloak client http config. type Config struct { - Addr string - Username string - Password string - Timeout time.Duration + Addr string + Timeout time.Duration } // Client is the keycloak client. type Client struct { - username string - password string - accessToken string - oidcProvider *oidc.Provider + url *url.URL 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() { httpClient = httpClient.URL(u.String()) 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{ - username: config.Username, - password: config.Password, - oidcProvider: oidcProvider, - httpClient: httpClient, + url: u, + httpClient: httpClient, }, nil } -// getToken get a token from keycloak. -func (c *Client) getToken() error { +// getToken returns a valid token from keycloak. +func (c *Client) GetToken(realm string, username string, password string) (string, error) { 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 = req.SetHeader("Content-Type", "application/x-www-form-urlencoded") req = req.Path(authPath) 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 @@ -88,17 +67,20 @@ func (c *Client) getToken() error { var err error resp, err = req.Do() if err != nil { - return errors.Wrap(err, "could not get token") + return "", errors.Wrap(err, "could not get token") } } defer resp.Close() + titi := string(resp.Bytes()) + fmt.Printf(titi) + var unmarshalledBody map[string]interface{} { var err error err = resp.JSON(&unmarshalledBody) 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 accessToken, ok = unmarshalledBody["access_token"] 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 nil + return accessToken.(string), nil } // verifyToken token verify a token. It returns an error it is malformed, expired,... -func (c *Client) verifyToken() error { - var v = c.oidcProvider.Verifier(&oidc.Config{SkipClientIDCheck: true}) +func (c *Client) VerifyToken(realmName string, accessToken string) error { + 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 - _, err = v.Verify(context.Background(), c.accessToken) + _, err = v.Verify(context.Background(), accessToken) return err } // 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() - req = applyPlugins(req, c.accessToken, plugins...) + req = applyPlugins(req, accessToken, plugins...) var resp *gentleman.Response { @@ -140,16 +131,9 @@ func (c *Client) get(data interface{}, plugins ...plugin.Plugin) error { switch { case resp.StatusCode == http.StatusUnauthorized: - // If the token is not valid (expired, ...) ask a new one. - 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...) + return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String()) 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: switch resp.Header.Get("Content-Type") { 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() - req = applyPlugins(req, c.accessToken, plugins...) + req = applyPlugins(req, accessToken, plugins...) var resp *gentleman.Response { var err error @@ -179,14 +163,7 @@ func (c *Client) post(data interface{}, plugins ...plugin.Plugin) error { switch { case resp.StatusCode == http.StatusUnauthorized: - // If the token is not valid (expired, ...) ask a new one. - 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...) + return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String()) case resp.StatusCode >= 400: return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes())) case resp.StatusCode >= 200: @@ -197,7 +174,7 @@ func (c *Client) post(data interface{}, plugins ...plugin.Plugin) error { data = resp.Bytes() return nil default: - return fmt.Errorf("unkown http content-type: %v", resp.Header.Get("Content-Type")) + return nil } default: 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() - req = applyPlugins(req, c.accessToken, plugins...) + req = applyPlugins(req, accessToken, plugins...) var resp *gentleman.Response { @@ -219,14 +196,7 @@ func (c *Client) delete(plugins ...plugin.Plugin) error { switch { case resp.StatusCode == http.StatusUnauthorized: - // If the token is not valid (expired, ...) ask a new one. - 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...) + return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String()) case resp.StatusCode >= 400: return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes())) 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() - req = applyPlugins(req, c.accessToken, plugins...) + req = applyPlugins(req, accessToken, plugins...) var resp *gentleman.Response { @@ -251,14 +221,7 @@ func (c *Client) put(plugins ...plugin.Plugin) error { switch { case resp.StatusCode == http.StatusUnauthorized: - // If the token is not valid (expired, ...) ask a new one. - 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...) + return fmt.Errorf("unauthorized request: '%v': %v", resp.RawResponse.Status, resp.String()) case resp.StatusCode >= 400: return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes())) case resp.StatusCode >= 200: diff --git a/keycloak_client_test.go b/keycloak_client_test.go deleted file mode 100644 index 1220810..0000000 --- a/keycloak_client_test.go +++ /dev/null @@ -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 -} diff --git a/realm.go b/realm.go index 3e048a8..9e61091 100644 --- a/realm.go +++ b/realm.go @@ -13,39 +13,39 @@ const ( // GetRealms get the top level represention of all the realms. Nested information like users are // not included. -func (c *Client) GetRealms() ([]RealmRepresentation, error) { +func (c *Client) GetRealms(accessToken string) ([]RealmRepresentation, error){ var resp = []RealmRepresentation{} - var err = c.get(&resp, url.Path(realmRootPath)) + var err = c.get(accessToken, &resp, url.Path(realmRootPath)) return resp, err } // CreateRealm creates the realm from its RealmRepresentation. -func (c *Client) CreateRealm(realm RealmRepresentation) error { - return c.post(nil, url.Path(realmRootPath), body.JSON(realm)) +func (c *Client) CreateRealm(accessToken string, realm RealmRepresentation) error { + 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 // not included. -func (c *Client) GetRealm(realmName string) (RealmRepresentation, error) { +func (c *Client) GetRealm(accessToken string, realmName string) (RealmRepresentation, error) { 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 } // UpdateRealm update the top lovel information of the realm. Any user, role or client information // from the realm representation will be ignored. -func (c *Client) UpdateRealm(realmName string, realm RealmRepresentation) error { - return c.put(url.Path(realmPath), url.Param("realm", realmName), body.JSON(realm)) +func (c *Client) UpdateRealm(accessToken string, realmName string, realm RealmRepresentation) error { + return c.put(accessToken, url.Path(realmPath), url.Param("realm", realmName), body.JSON(realm)) } // DeleteRealm deletes the realm. -func (c *Client) DeleteRealm(realmName string) error { - return c.delete(url.Path(realmPath), url.Param("realm", realmName)) +func (c *Client) DeleteRealm(accessToken string, realmName string) error { + return c.delete(accessToken, url.Path(realmPath), url.Param("realm", realmName)) } // 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 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 } diff --git a/realm_test.go b/realm_test.go deleted file mode 100644 index b4cc783..0000000 --- a/realm_test.go +++ /dev/null @@ -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) - } -} diff --git a/realms_admin.go b/realms_admin.go deleted file mode 100644 index cf172a0..0000000 --- a/realms_admin.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/role_mapper.go b/role_mapper.go deleted file mode 100644 index cf172a0..0000000 --- a/role_mapper.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/roles.go b/roles.go deleted file mode 100644 index cf172a0..0000000 --- a/roles.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/root.go b/root.go deleted file mode 100644 index cf172a0..0000000 --- a/root.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/scope_mappings.go b/scope_mappings.go deleted file mode 100644 index cf172a0..0000000 --- a/scope_mappings.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/user_storage_provider.go b/user_storage_provider.go deleted file mode 100644 index cf172a0..0000000 --- a/user_storage_provider.go +++ /dev/null @@ -1 +0,0 @@ -package keycloak diff --git a/users.go b/users.go index 676b3de..d6dc7ca 100644 --- a/users.go +++ b/users.go @@ -17,42 +17,42 @@ const ( // Parameters: email, first (paging offset, int), firstName, lastName, username, // max (maximum result size, default = 100), // 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 { return nil, fmt.Errorf("the number of key/val parameters should be even") } var resp = []UserRepresentation{} 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 } // CreateUser creates the user from its UserRepresentation. The username must be unique. -func (c *Client) CreateUser(realmName string, user UserRepresentation) error { - return c.post(nil, url.Path(userPath), url.Param("realm", realmName), body.JSON(user)) +func (c *Client) CreateUser(accessToken string, realmName string, user UserRepresentation) error { + return c.post(accessToken, nil, url.Path(userPath), url.Param("realm", realmName), body.JSON(user)) } // 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 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 } // 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 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 } // UpdateUser updates the user. -func (c *Client) UpdateUser(realmName, userID string, user UserRepresentation) error { - return c.put(url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(user)) +func (c *Client) UpdateUser(accessToken string, realmName, userID string, user UserRepresentation) error { + return c.put(accessToken, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(user)) } // DeleteUser deletes the user. -func (c *Client) DeleteUser(realmName, userID string) error { - return c.delete(url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID)) +func (c *Client) DeleteUser(accessToken string, realmName, userID string) error { + return c.delete(accessToken, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID)) } diff --git a/users_test.go b/users_test.go deleted file mode 100644 index d3452b5..0000000 --- a/users_test.go +++ /dev/null @@ -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) - } -}