Browse Source

[CLOUDTRUST-1502] Multi-token API

master
harture 6 years ago
committed by GitHub
parent
commit
c5e13ab423
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 80
      account.go
  2. 64
      credentials.go
  3. 15
      definitions.go
  4. 25
      keycloak_client.go
  5. 9
      realm.go
  6. 54
      users.go

80
account.go

@ -0,0 +1,80 @@
package keycloak
import (
"gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/headers"
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
accountPath = "/auth/realms/:realm/account"
accountExtensionAPIPath = "/auth/realms/master/api/account/realms/:realm"
accountPasswordPath = accountExtensionAPIPath + "/credentials/password"
accountCredentialsPath = accountPath + "/credentials"
accountCredentialsRegistratorsPath = accountCredentialsPath + "/registrators"
accountCredentialIDPath = accountCredentialsPath + "/:credentialID"
accountCredentialLabelPath = accountCredentialIDPath + "/label"
accountMoveFirstPath = accountCredentialIDPath + "/moveToFirst"
accountMoveAfterPath = accountCredentialIDPath + "/moveAfter/:previousCredentialID"
)
// GetCredentials returns the list of credentials of the user
func (c *AccountClient) GetCredentials(accessToken string, realmName string) ([]CredentialRepresentation, error) {
var resp = []CredentialRepresentation{}
var err = c.client.get(accessToken, &resp, url.Path(accountCredentialsPath), url.Param("realm", realmName), headers.Set("Accept", "application/json"))
return resp, err
}
// GetCredentialRegistrators returns list of credentials types available for the user
func (c *AccountClient) GetCredentialRegistrators(accessToken string, realmName string) ([]string, error) {
var resp = []string{}
var err = c.client.get(accessToken, &resp, url.Path(accountCredentialsRegistratorsPath), url.Param("realm", realmName), headers.Set("Accept", "application/json"))
return resp, err
}
// UpdateLabelCredential updates the label of credential
func (c *AccountClient) UpdateLabelCredential(accessToken string, realmName string, credentialID string, label string) error {
return c.client.put(accessToken, url.Path(accountCredentialLabelPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), body.String(label), headers.Set("Accept", "application/json"), headers.Set("Content-Type", "text/plain"))
}
// DeleteCredential deletes the credential
func (c *AccountClient) DeleteCredential(accessToken string, realmName string, credentialID string) error {
return c.client.delete(accessToken, url.Path(accountCredentialIDPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), headers.Set("Accept", "application/json"))
}
// MoveToFirst moves the credential at the top of the list
func (c *AccountClient) MoveToFirst(accessToken string, realmName string, credentialID string) error {
_, err := c.client.post(accessToken, nil, url.Path(accountMoveFirstPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), headers.Set("Accept", "application/json"))
return err
}
// MoveAfter moves the credential after the specified one into the list
func (c *AccountClient) MoveAfter(accessToken string, realmName string, credentialID string, previousCredentialID string) error {
_, err := c.client.post(accessToken, nil, url.Path(accountMoveAfterPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), url.Param("previousCredentialID", previousCredentialID), headers.Set("Accept", "application/json"))
return err
}
// UpdatePassword updates the user's password
// Parameters: realm, currentPassword, newPassword, confirmPassword
func (c *AccountClient) UpdatePassword(accessToken, realm, currentPassword, newPassword, confirmPassword string) (string, error) {
var m = map[string]string{"currentPassword": currentPassword, "newPassword": newPassword, "confirmation": confirmPassword}
return c.client.post(accessToken, nil, url.Path(accountPasswordPath), url.Param("realm", realm), body.JSON(m))
}
// GetAccount provides the user's information
func (c *AccountClient) GetAccount(accessToken string, realm string) (UserRepresentation, error) {
var resp = UserRepresentation{}
var err = c.client.get(accessToken, &resp, url.Path(accountExtensionAPIPath), url.Param("realm", realm), headers.Set("Accept", "application/json"))
return resp, err
}
// UpdateAccount updates the user's information
func (c *AccountClient) UpdateAccount(accessToken string, realm string, user UserRepresentation) error {
_, err := c.client.post(accessToken, nil, url.Path(accountExtensionAPIPath), url.Param("realm", realm), body.JSON(user))
return err
}
// DeleteAccount delete current user
func (c *AccountClient) DeleteAccount(accessToken string, realmName string) error {
return c.client.delete(accessToken, url.Path(accountExtensionAPIPath), url.Param("realm", realmName), headers.Set("Accept", "application/json"))
}

64
credentials.go

@ -0,0 +1,64 @@
package keycloak
import (
"gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
resetPasswordPath = userIDPath + "/reset-password"
credentialsPath = userIDPath + "/credentials"
credentialsTypesPath = realmPath + "/credentialTypes"
credentialIDPath = "/:credentialID"
moveFirstPath = credentialIDPath + "/moveToFirst"
moveAfterPath = credentialIDPath + "/moveAfter/:previousCredentialID"
)
// ResetPassword resets password of the user.
func (c *Client) ResetPassword(accessToken string, realmName, userID string, cred CredentialRepresentation) error {
return c.put(accessToken, url.Path(resetPasswordPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(cred))
}
// GetCredentials returns the list of credentials of the user
func (c *Client) GetCredentials(accessToken string, realmName string, userID string) ([]CredentialRepresentation, error) {
var resp = []CredentialRepresentation{}
var err = c.get(accessToken, &resp, url.Path(credentialsPath), url.Param("realm", realmName), url.Param("id", userID))
return resp, err
}
// GetCredentialTypes returns list of credentials types available for the realm
func (c *Client) GetCredentialTypes(accessToken string, realmName string) ([]string, error) {
var resp = []string{}
var err = c.get(accessToken, &resp, url.Path(credentialsTypesPath), url.Param("realm", realmName))
return resp, err
}
// UpdateCredential updates the credential
func (c *Client) UpdateCredential(accessToken string, realmName string, userID string, credentialID string, credential CredentialRepresentation) error {
return c.put(accessToken, url.Path(credentialIDPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("credentialID", credentialID), body.JSON(credential))
}
// DeleteCredential deletes the credential
func (c *Client) DeleteCredential(accessToken string, realmName string, userID string, credentialID string) error {
return c.delete(accessToken, url.Path(credentialIDPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("credentialID", credentialID))
}
// MoveToFirst moves the credential at the top of the list
func (c *Client) MoveToFirst(accessToken string, realmName string, userID string, credentialID string) error {
_, err := c.post(accessToken, url.Path(moveFirstPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("credentialID", credentialID))
return err
}
// MoveAfter moves the credential after the specified one into the list
func (c *Client) MoveAfter(accessToken string, realmName string, userID string, credentialID string, previousCredentialID string) error {
_, err := c.post(accessToken, url.Path(moveAfterPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("credentialID", credentialID), url.Param("previousCredentialID", previousCredentialID))
return err
}
// UpdatePassword updates the user's password
// Parameters: realm, currentPassword, newPassword, confirmPassword
func (c *Client) UpdatePassword(accessToken, realm, currentPassword, newPassword, confirmPassword string) (string, error) {
var m = map[string]string{"currentPassword": currentPassword, "newPassword": newPassword, "confirmation": confirmPassword}
return c.post(accessToken, nil, url.Path(accountPasswordPath), url.Param("realm", realm), body.JSON(m))
}

15
definitions.go

@ -202,19 +202,12 @@ type ConfigPropertyRepresentation struct {
type CredentialRepresentation struct { type CredentialRepresentation struct {
Id *string `json:"id,omitempty"` Id *string `json:"id,omitempty"`
Algorithm *string `json:"algorithm,omitempty"`
Config *map[string][]string `json:"config,omitempty"`
Counter *int32 `json:"counter,omitempty"`
CreatedDate *int64 `json:"createdDate,omitempty"`
Device *string `json:"device,omitempty"`
Digits *int32 `json:"digits,omitempty"`
HashIterations *int32 `json:"hashIterations,omitempty"`
HashedSaltedValue *string `json:"hashedSaltedValue,omitempty"`
Period *int32 `json:"period,omitempty"`
Salt *string `json:"salt,omitempty"`
Temporary *bool `json:"temporary,omitempty"`
Type *string `json:"type,omitempty"` Type *string `json:"type,omitempty"`
UserLabel *string `json:"userLabel,omitempty"`
CreatedDate *int64 `json:"createdDate,omitempty"`
CredentialData *string `json:"credentialData,omitempty"`
Value *string `json:"value,omitempty"` Value *string `json:"value,omitempty"`
Temporary *bool `json:"temporary,omitempty"`
} }
type EventRepresentation struct { type EventRepresentation struct {

25
keycloak_client.go

@ -32,9 +32,14 @@ type Config struct {
type Client struct { type Client struct {
apiURL *url.URL apiURL *url.URL
httpClient *gentleman.Client httpClient *gentleman.Client
account *AccountClient
verifierProvider OidcVerifierProvider verifierProvider OidcVerifierProvider
} }
type AccountClient struct {
client *Client
}
// HTTPError is returned when an error occured while contacting the keycloak instance. // HTTPError is returned when an error occured while contacting the keycloak instance.
type HTTPError struct { type HTTPError struct {
HTTPStatus int HTTPStatus int
@ -65,12 +70,6 @@ func New(config Config) (*Client, error) {
} }
} }
var httpClient = gentleman.New()
{
httpClient = httpClient.URL(uAPI.String())
httpClient = httpClient.Use(timeout.Request(config.Timeout))
}
// Use default values when clients are not initializing these values // Use default values when clients are not initializing these values
cacheTTL := config.CacheTTL cacheTTL := config.CacheTTL
if cacheTTL == 0 { if cacheTTL == 0 {
@ -81,12 +80,22 @@ func New(config Config) (*Client, error) {
errTolerance = time.Minute errTolerance = time.Minute
} }
var httpClient = gentleman.New()
{
httpClient = httpClient.URL(uAPI.String())
httpClient = httpClient.Use(timeout.Request(config.Timeout))
}
var client = &Client{ var client = &Client{
apiURL: uAPI, apiURL: uAPI,
httpClient: httpClient, httpClient: httpClient,
verifierProvider: NewVerifierCache(uToken, cacheTTL, errTolerance), verifierProvider: NewVerifierCache(uToken, cacheTTL, errTolerance),
} }
client.account = &AccountClient{
client: client,
}
return client, nil return client, nil
} }
@ -145,6 +154,10 @@ func (c *Client) VerifyToken(realmName string, accessToken string) error {
return verifier.Verify(accessToken) return verifier.Verify(accessToken)
} }
func (c *Client) AccountClient() *AccountClient {
return c.account
}
// get is a HTTP get method. // get is a HTTP get method.
func (c *Client) get(accessToken string, data interface{}, plugins ...plugin.Plugin) error { func (c *Client) get(accessToken string, data interface{}, plugins ...plugin.Plugin) error {
var err error var err error

9
realm.go

@ -2,12 +2,14 @@ package keycloak
import ( import (
"gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/headers"
"gopkg.in/h2non/gentleman.v2/plugins/url" "gopkg.in/h2non/gentleman.v2/plugins/url"
) )
const ( const (
realmRootPath = "/auth/admin/realms" realmRootPath = "/auth/admin/realms"
realmPath = realmRootPath + "/:realm" realmPath = realmRootPath + "/:realm"
realmCredentialRegistrators = realmPath + "/credential-registrators"
exportRealmPath = "/auth/realms/:realm/export/realm" exportRealmPath = "/auth/realms/:realm/export/realm"
) )
@ -49,3 +51,10 @@ func (c *Client) ExportRealm(accessToken string, realmName string) (RealmReprese
var err = c.get(accessToken, &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
} }
// GetRealmCredentialRegistrators returns list of credentials types available for the realm
func (c *Client) GetRealmCredentialRegistrators(accessToken string, realmName string) ([]string, error) {
var resp = []string{}
var err = c.get(accessToken, &resp, url.Path(realmCredentialRegistrators), url.Param("realm", realmName), headers.Set("Accept", "application/json"))
return resp, err
}

54
users.go

@ -4,26 +4,20 @@ import (
"errors" "errors"
"gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/headers"
"gopkg.in/h2non/gentleman.v2/plugins/url" "gopkg.in/h2non/gentleman.v2/plugins/url"
) )
const ( const (
userPath = "/auth/admin/realms/:realm/users" userPath = "/auth/admin/realms/:realm/users"
usersAdminExtensionApiPath = "/auth/realms/:realmReq/api/admin/realms/:realm/users" usersAdminExtensionAPIPath = "/auth/realms/:realmReq/api/admin/realms/:realm/users"
userCountPath = userPath + "/count" userCountPath = userPath + "/count"
userIDPath = userPath + "/:id" userIDPath = userPath + "/:id"
userGroupsPath = userIDPath + "/groups" userGroupsPath = userIDPath + "/groups"
resetPasswordPath = userIDPath + "/reset-password"
sendVerifyEmailPath = userIDPath + "/send-verify-email" sendVerifyEmailPath = userIDPath + "/send-verify-email"
executeActionsEmailPath = userIDPath + "/execute-actions-email" executeActionsEmailPath = userIDPath + "/execute-actions-email"
sendReminderEmailPath = "/auth/realms/:realm/onboarding/sendReminderEmail" sendReminderEmailPath = "/auth/realms/:realm/onboarding/sendReminderEmail"
smsAPI = "/auth/realms/:realm/smsApi" smsAPI = "/auth/realms/:realm/smsApi"
sendNewEnrolmentCode = smsAPI + "/sendNewCode" sendNewEnrolmentCode = smsAPI + "/sendNewCode"
getCredentialsForUserPath = usersAdminExtensionApiPath + "/:id/credentials"
deleteCredentialsForUserPath = getCredentialsForUserPath + "/:credid"
accountPasswordPath = "/auth/realms/master/api/account/realms/:realm/credentials/password"
accountPath = "/auth/realms/master/api/account/realms/:realm/"
) )
// GetUsers returns a list of users, filtered according to the query parameters. // GetUsers returns a list of users, filtered according to the query parameters.
@ -36,14 +30,14 @@ func (c *Client) GetUsers(accessToken string, reqRealmName, targetRealmName stri
return resp, errors.New(MsgErrInvalidParam + "." + EvenParams) return resp, errors.New(MsgErrInvalidParam + "." + EvenParams)
} }
var plugins = append(createQueryPlugins(paramKV...), url.Path(usersAdminExtensionApiPath), url.Param("realmReq", reqRealmName), url.Param("realm", targetRealmName)) var plugins = append(createQueryPlugins(paramKV...), url.Path(usersAdminExtensionAPIPath), url.Param("realmReq", reqRealmName), url.Param("realm", targetRealmName))
var err = c.get(accessToken, &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(accessToken string, reqRealmName, targetRealmName string, user UserRepresentation) (string, error) { func (c *Client) CreateUser(accessToken string, reqRealmName, targetRealmName string, user UserRepresentation) (string, error) {
return c.post(accessToken, nil, url.Path(usersAdminExtensionApiPath), url.Param("realmReq", reqRealmName), url.Param("realm", targetRealmName), body.JSON(user)) return c.post(accessToken, nil, url.Path(usersAdminExtensionAPIPath), url.Param("realmReq", reqRealmName), url.Param("realm", targetRealmName), body.JSON(user))
} }
// CountUsers returns the number of users in the realm. // CountUsers returns the number of users in the realm.
@ -77,11 +71,6 @@ 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)) return c.delete(accessToken, url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID))
} }
// ResetPassword resets password of the user.
func (c *Client) ResetPassword(accessToken string, realmName, userID string, cred CredentialRepresentation) error {
return c.put(accessToken, url.Path(resetPasswordPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(cred))
}
// SendVerifyEmail sends an email-verification email to the user An email contains a link the user can click to verify their email address. // SendVerifyEmail sends an email-verification email to the user An email contains a link the user can click to verify their email address.
func (c *Client) SendVerifyEmail(accessToken string, realmName string, userID string, paramKV ...string) error { func (c *Client) SendVerifyEmail(accessToken string, realmName string, userID string, paramKV ...string) error {
if len(paramKV)%2 != 0 { if len(paramKV)%2 != 0 {
@ -128,40 +117,3 @@ func (c *Client) SendReminderEmail(accessToken string, realmName string, userID
_, err := c.post(accessToken, nil, plugins...) _, err := c.post(accessToken, nil, plugins...)
return err return err
} }
// GetCredentialsForUser gets the credential list for a user
func (c *Client) GetCredentialsForUser(accessToken string, realmReq, realmName string, userID string) ([]CredentialRepresentation, error) {
var resp = []CredentialRepresentation{}
var err = c.get(accessToken, &resp, url.Path(getCredentialsForUserPath), url.Param("realmReq", realmReq), url.Param("realm", realmName), url.Param("id", userID))
return resp, err
}
// DeleteCredentialsForUser remove credentials for a user
func (c *Client) DeleteCredentialsForUser(accessToken string, realmReq, realmName string, userID string, credentialID string) error {
return c.delete(accessToken, url.Path(deleteCredentialsForUserPath), url.Param("realmReq", realmReq), url.Param("realm", realmName), url.Param("id", userID), url.Param("credid", credentialID))
}
// UpdatePassword updates the user's password
// Parameters: realm, currentPassword, newPassword, confirmPassword
func (c *Client) UpdatePassword(accessToken, realm, currentPassword, newPassword, confirmPassword string) (string, error) {
var m = map[string]string{"currentPassword": currentPassword, "newPassword": newPassword, "confirmation": confirmPassword}
return c.post(accessToken, nil, url.Path(accountPasswordPath), url.Param("realm", realm), body.JSON(m))
}
// GetAccount provides the user's information
func (c *Client) GetAccount(accessToken string, realm string) (UserRepresentation, error) {
var resp = UserRepresentation{}
var err = c.get(accessToken, &resp, url.Path(accountPath), url.Param("realm", realm), headers.Set("Accept", "application/json"))
return resp, err
}
// UpdateAccount updates the user's information
func (c *Client) UpdateAccount(accessToken string, realm string, user UserRepresentation) error {
_, err := c.post(accessToken, nil, url.Path(accountPath), url.Param("realm", realm), body.JSON(user))
return err
}
// DeleteAccount delete current user
func (c *Client) DeleteAccount(accessToken string, realmName string) error {
return c.delete(accessToken, url.Path(accountPath), url.Param("realm", realmName), headers.Set("Accept", "application/json"))
}

Loading…
Cancel
Save