From 64f3ba0945040eb96a0a8c69e95fb9c48aa99130 Mon Sep 17 00:00:00 2001 From: Ryan Caught Date: Tue, 5 Nov 2024 19:34:28 +1000 Subject: [PATCH 1/8] feat: adds GoCloakIface and general dep upgrades (#482) * chore: update workflows and lint fixes * chore: update golang version and dependencies * feat: provide generated and verified interface Related https://github.com/Nerzal/gocloak/issues/438 Generates interface from struct and verifies implementation. This doesn't modify `NewClient` as that requires a larger refactor. * test: fix message to match logic * test: fix up codeQL --- .github/workflows/codeql-analysis.yml | 101 +++-- .github/workflows/go.yml | 12 +- .golangci.yml | 8 +- Makefile | 8 +- README.md | 253 +----------- client.go | 3 + client_test.go | 61 +-- docker-compose.yml | 2 - go.mod | 12 +- go.sum | 91 +++- gocloak_iface.go | 570 ++++++++++++++++++++++++++ model_test.go | 2 +- run-tests.sh | 6 +- 13 files changed, 764 insertions(+), 365 deletions(-) create mode 100644 gocloak_iface.go diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4ad47cb5..0131c2d9 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -9,63 +9,84 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: "CodeQL" +name: "CodeQL Advanced" on: push: - branches: [ main ] + branches: ["main"] pull_request: - # The branches below must be a subset of the branches above - branches: [ main ] + branches: ["main"] schedule: - - cron: '15 16 * * 1' + - cron: "15 16 * * 1" jobs: analyze: - name: Analyze - runs-on: ubuntu-latest + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ 'ubuntu-latest' }} permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories actions: read contents: read - security-events: write strategy: fail-fast: false matrix: - language: [ 'go' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - + include: + - language: go + build-mode: autobuild + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 + - name: Checkout repository + uses: actions/checkout@v4 - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality - #- run: | - # make bootstrap - # make release + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 9dc4aacc..e8383359 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -7,13 +7,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Go environment - uses: actions/setup-go@v3.0.0 + uses: actions/setup-go@v5.0.2 with: - go-version: 1.19 + go-version: 1.23 - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4.1.7 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v3.1.0 + uses: golangci/golangci-lint-action@v6.1.0 - name: WriteGoList run: go list -json -m all > go.list - name: nancy @@ -33,14 +33,14 @@ jobs: docker ps docker logs keycloak - name: CodeCov - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v4.5.0 with: file: ./coverage.txt # Publish benchmarks for the main branch only - name: Store Benchmark Result if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: rhysd/github-action-benchmark@v1 + uses: rhysd/github-action-benchmark@v1.20.3 with: # What benchmark tool the output.txt came from tool: "go" diff --git a/.golangci.yml b/.golangci.yml index d59a6c32..d5d49ce9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,8 +1,3 @@ -run: - skip-dirs: - - (^|/)testdata($|/) - skip-dirs-use-default: false - linters: enable: - goimports @@ -32,6 +27,9 @@ linters-settings: simplify: true issues: + exclude-dirs: + - (^|/)testdata($|/) + exclude-dirs-use-default: false exclude-use-default: false exclude-rules: - path: _test\.go diff --git a/Makefile b/Makefile index 0409e817..b32a0b54 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,11 @@ test: ./run-tests.sh start-keycloak: stop-keycloak - docker-compose up -d + docker compose up -d stop-keycloak: - docker-compose down + docker compose down + +generate-gocloak-interface: + @echo "Remember to: go install github.com/vburenin/ifacemaker@latest" + @$(shell go env GOPATH)/bin/ifacemaker -f client.go -s GoCloak -i GoCloakIface -p gocloak -o gocloak_iface.go diff --git a/README.md b/README.md index 6f4d7c09..6eb6b687 100644 --- a/README.md +++ b/README.md @@ -116,258 +116,7 @@ To get the `clientId` from `id`, use `GetClients` method with `GetClientsParams{ ## Features -```go -// GoCloak holds all methods a client should fulfill -type GoCloak interface { - - RestyClient() *resty.Client - SetRestyClient(restyClient *resty.Client) - - GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error) - GetRequestingPartyToken(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*JWT, error) - GetRequestingPartyPermissions(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*[]RequestingPartyPermission, error) - GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error) - - Login(ctx context.Context, clientID, clientSecret, realm, username, password string) (*JWT, error) - LoginOtp(ctx context.Context, clientID, clientSecret, realm, username, password, totp string) (*JWT, error) - Logout(ctx context.Context, clientID, clientSecret, realm, refreshToken string) error - LogoutPublicClient(ctx context.Context, clientID, realm, accessToken, refreshToken string) error - LogoutAllSessions(ctx context.Context, accessToken, realm, userID string) error - RevokeUserConsents(ctx context.Context, accessToken, realm, userID, clientID string) error - LogoutUserSession(ctx context.Context, accessToken, realm, session string) error - LoginClient(ctx context.Context, clientID, clientSecret, realm string) (*JWT, error) - LoginClientSignedJWT(ctx context.Context, clientID, realm string, key interface{}, signedMethod jwt.SigningMethod, expiresAt *jwt.Time) (*JWT, error) - LoginAdmin(ctx context.Context, username, password, realm string) (*JWT, error) - RefreshToken(ctx context.Context, refreshToken, clientID, clientSecret, realm string) (*JWT, error) - DecodeAccessToken(ctx context.Context, accessToken, realm, expectedAudience string) (*jwt.Token, *jwt.MapClaims, error) - DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm, expectedAudience string, claims jwt.Claims) (*jwt.Token, error) - RetrospectToken(ctx context.Context, accessToken, clientID, clientSecret, realm string) (*RetrospecTokenResult, error) - GetIssuer(ctx context.Context, realm string) (*IssuerResponse, error) - GetCerts(ctx context.Context, realm string) (*CertResponse, error) - GetServerInfo(ctx context.Context, accessToken string) (*ServerInfoRepesentation, error) - GetUserInfo(ctx context.Context, accessToken, realm string) (*UserInfo, error) - GetRawUserInfo(ctx context.Context, accessToken, realm string) (map[string]interface{}, error) - SetPassword(ctx context.Context, token, userID, realm, password string, temporary bool) error - ExecuteActionsEmail(ctx context.Context, token, realm string, params ExecuteActionsEmail) error - - CreateUser(ctx context.Context, token, realm string, user User) (string, error) - CreateGroup(ctx context.Context, accessToken, realm string, group Group) (string, error) - CreateChildGroup(ctx context.Context, token, realm, groupID string, group Group) (string, error) - CreateClientRole(ctx context.Context, accessToken, realm, idOfClient string, role Role) (string, error) - CreateClient(ctx context.Context, accessToken, realm string, newClient Client) (string, error) - CreateClientScope(ctx context.Context, accessToken, realm string, scope ClientScope) (string, error) - CreateComponent(ctx context.Context, accessToken, realm string, component Component) (string, error) - CreateClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error - CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error - CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfCLientScope string, roles []Role) error - CreateClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error - - UpdateUser(ctx context.Context, accessToken, realm string, user User) error - UpdateGroup(ctx context.Context, accessToken, realm string, updatedGroup Group) error - UpdateRole(ctx context.Context, accessToken, realm, idOfClient string, role Role) error - UpdateClient(ctx context.Context, accessToken, realm string, updatedClient Client) error - UpdateClientScope(ctx context.Context, accessToken, realm string, scope ClientScope) error - - DeleteUser(ctx context.Context, accessToken, realm, userID string) error - DeleteComponent(ctx context.Context, accessToken, realm, componentID string) error - DeleteGroup(ctx context.Context, accessToken, realm, groupID string) error - DeleteClientRole(ctx context.Context, accessToken, realm, idOfClient, roleName string) error - DeleteClientRoleFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error - DeleteClient(ctx context.Context, accessToken, realm, idOfClient string) error - DeleteClientScope(ctx context.Context, accessToken, realm, scopeID string) error - DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error - DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error - DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfCLientScope string, roles []Role) error - DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, ifOfClient string, roles []Role) error - - GetClient(ctx context.Context, accessToken, realm, idOfClient string) (*Client, error) - GetClientsDefaultScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) - AddDefaultScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - RemoveDefaultScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - GetClientsOptionalScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) - AddOptionalScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - RemoveOptionalScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error - GetDefaultOptionalClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) - GetDefaultDefaultClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) - GetClientScope(ctx context.Context, token, realm, scopeID string) (*ClientScope, error) - GetClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) - GetClientScopeMappings(ctx context.Context, token, realm, idOfClient string) (*MappingsRepresentation, error) - GetClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) - GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) - GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) - GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) - GetClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) - GetClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClientScope string) ([]*Role, error) - GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) - GetClientScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) - GetClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) - GetClientServiceAccount(ctx context.Context, token, realm, idOfClient string) (*User, error) - RegenerateClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) - GetKeyStoreConfig(ctx context.Context, accessToken, realm string) (*KeyStoreConfig, error) - GetUserByID(ctx context.Context, accessToken, realm, userID string) (*User, error) - GetUserCount(ctx context.Context, accessToken, realm string, params GetUsersParams) (int, error) - GetUsers(ctx context.Context, accessToken, realm string, params GetUsersParams) ([]*User, error) - GetUserGroups(ctx context.Context, accessToken, realm, userID string, params GetGroupsParams) ([]*UserGroup, error) - AddUserToGroup(ctx context.Context, token, realm, userID, groupID string) error - DeleteUserFromGroup(ctx context.Context, token, realm, userID, groupID string) error - GetComponents(ctx context.Context, accessToken, realm string) ([]*Component, error) - GetGroups(ctx context.Context, accessToken, realm string, params GetGroupsParams) ([]*Group, error) - GetGroupsCount(ctx context.Context, token, realm string, params GetGroupsParams) (int, error) - GetGroup(ctx context.Context, accessToken, realm, groupID string) (*Group, error) - GetDefaultGroups(ctx context.Context, accessToken, realm string) ([]*Group, error) - AddDefaultGroup(ctx context.Context, accessToken, realm, groupID string) error - RemoveDefaultGroup(ctx context.Context, accessToken, realm, groupID string) error - GetGroupMembers(ctx context.Context, accessToken, realm, groupID string, params GetGroupsParams) ([]*User, error) - GetRoleMappingByGroupID(ctx context.Context, accessToken, realm, groupID string) (*MappingsRepresentation, error) - GetRoleMappingByUserID(ctx context.Context, accessToken, realm, userID string) (*MappingsRepresentation, error) - GetClientRoles(ctx context.Context, accessToken, realm, idOfClient string, params GetRoleParams) ([]*Role, error) - GetClientRole(ctx context.Context, token, realm, idOfClient, roleName string) (*Role, error) - GetClientRoleByID(ctx context.Context, accessToken, realm, roleID string) (*Role, error) - GetClients(ctx context.Context, accessToken, realm string, params GetClientsParams) ([]*Client, error) - AddClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error - DeleteClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error - GetUsersByRoleName(ctx context.Context, token, realm, roleName string) ([]*User, error) - GetUsersByClientRoleName(ctx context.Context, token, realm, idOfClient, roleName string, params GetUsersByRoleParams) ([]*User, error) - CreateClientProtocolMapper(ctx context.Context, token, realm, idOfClient string, mapper ProtocolMapperRepresentation) (string, error) - UpdateClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string, mapper ProtocolMapperRepresentation) error - DeleteClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string) error - - // *** Realm Roles *** - - CreateRealmRole(ctx context.Context, token, realm string, role Role) (string, error) - GetRealmRole(ctx context.Context, token, realm, roleName string) (*Role, error) - GetRealmRoles(ctx context.Context, accessToken, realm string, params GetRoleParams) ([]*Role, error) - GetRealmRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) - GetRealmRolesByUserID(ctx context.Context, accessToken, realm, userID string) ([]*Role, error) - GetRealmRolesByGroupID(ctx context.Context, accessToken, realm, groupID string) ([]*Role, error) - UpdateRealmRole(ctx context.Context, token, realm, roleName string, role Role) error - UpdateRealmRoleByID(ctx context.Context, token, realm, roleID string, role Role) error - DeleteRealmRole(ctx context.Context, token, realm, roleName string) error - AddRealmRoleToUser(ctx context.Context, token, realm, userID string, roles []Role) error - DeleteRealmRoleFromUser(ctx context.Context, token, realm, userID string, roles []Role) error - AddRealmRoleToGroup(ctx context.Context, token, realm, groupID string, roles []Role) error - DeleteRealmRoleFromGroup(ctx context.Context, token, realm, groupID string, roles []Role) error - AddRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error - DeleteRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error - GetCompositeRealmRoles(ctx context.Context, token, realm, roleName string) ([]*Role, error) - GetCompositeRealmRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) - GetCompositeRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) - GetCompositeRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) - GetAvailableRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) - GetAvailableRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) - - // *** Client Roles *** - - AddClientRoleToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error - AddClientRoleToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error - DeleteClientRoleFromGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error - GetCompositeClientRolesByRoleID(ctx context.Context, token, realm, idOfClient, roleID string) ([]*Role, error) - GetClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) - GetClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) - GetCompositeClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) - GetCompositeClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) - GetAvailableClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) - GetAvailableClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) - - // *** Realm *** - - GetRealm(ctx context.Context, token, realm string) (*RealmRepresentation, error) - GetRealms(ctx context.Context, token string) ([]*RealmRepresentation, error) - CreateRealm(ctx context.Context, token string, realm RealmRepresentation) (string, error) - UpdateRealm(ctx context.Context, token string, realm RealmRepresentation) error - DeleteRealm(ctx context.Context, token, realm string) error - ClearRealmCache(ctx context.Context, token, realm string) error - ClearUserCache(ctx context.Context, token, realm string) error - ClearKeysCache(ctx context.Context, token, realm string) error - -GetClientUserSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) -GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) - GetUserSessions(ctx context.Context, token, realm, userID string) ([]*UserSessionRepresentation, error) - GetUserOfflineSessionsForClient(ctx context.Context, token, realm, userID, idOfClient string) ([]*UserSessionRepresentation, error) - - // *** Protection API *** - GetResource(ctx context.Context, token, realm, idOfClient, resourceID string) (*ResourceRepresentation, error) - GetResources(ctx context.Context, token, realm, idOfClient string, params GetResourceParams) ([]*ResourceRepresentation, error) - CreateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) (*ResourceRepresentation, error) - UpdateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) error - DeleteResource(ctx context.Context, token, realm, idOfClient, resourceID string) error - - GetResourceClient(ctx context.Context, token, realm, resourceID string) (*ResourceRepresentation, error) - GetResourcesClient(ctx context.Context, token, realm string, params GetResourceParams) ([]*ResourceRepresentation, error) - CreateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) (*ResourceRepresentation, error) - UpdateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) error - DeleteResourceClient(ctx context.Context, token, realm, resourceID string) error - - GetScope(ctx context.Context, token, realm, idOfClient, scopeID string) (*ScopeRepresentation, error) - GetScopes(ctx context.Context, token, realm, idOfClient string, params GetScopeParams) ([]*ScopeRepresentation, error) - CreateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) (*ScopeRepresentation, error) - UpdateScope(ctx context.Context, token, realm, idOfClient string, resource ScopeRepresentation) error - DeleteScope(ctx context.Context, token, realm, idOfClient, scopeID string) error - - GetPolicy(ctx context.Context, token, realm, idOfClient, policyID string) (*PolicyRepresentation, error) - GetPolicies(ctx context.Context, token, realm, idOfClient string, params GetPolicyParams) ([]*PolicyRepresentation, error) - CreatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) (*PolicyRepresentation, error) - UpdatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) error - DeletePolicy(ctx context.Context, token, realm, idOfClient, policyID string) error - - GetResourcePolicy(ctx context.Context, token, realm, permissionID string) (*ResourcePolicyRepresentation, error) - GetResourcePolicies(ctx context.Context, token, realm string, params GetResourcePoliciesParams) ([]*ResourcePolicyRepresentation, error) - CreateResourcePolicy(ctx context.Context, token, realm, resourceID string, policy ResourcePolicyRepresentation) (*ResourcePolicyRepresentation, error) - UpdateResourcePolicy(ctx context.Context, token, realm, permissionID string, policy ResourcePolicyRepresentation) error - DeleteResourcePolicy(ctx context.Context, token, realm, permissionID string) error - - GetPermission(ctx context.Context, token, realm, idOfClient, permissionID string) (*PermissionRepresentation, error) - GetPermissions(ctx context.Context, token, realm, idOfClient string, params GetPermissionParams) ([]*PermissionRepresentation, error) - GetPermissionResources(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionResource, error) - GetPermissionScopes(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionScope, error) - GetDependentPermissions(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PermissionRepresentation, error) - CreatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) (*PermissionRepresentation, error) - UpdatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) error - DeletePermission(ctx context.Context, token, realm, idOfClient, permissionID string) error - - CreatePermissionTicket(ctx context.Context, token, realm string, permissions []CreatePermissionTicketParams) (*PermissionTicketResponseRepresentation, error) - GrantUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) - UpdateUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) - GetUserPermissions(ctx context.Context, token, realm string, params GetUserPermissionParams) ([]*PermissionGrantResponseRepresentation, error) - DeleteUserPermission(ctx context.Context, token, realm, ticketID string) error - - // *** Credentials API *** - - GetCredentialRegistrators(ctx context.Context, token, realm string) ([]string, error) - GetConfiguredUserStorageCredentialTypes(ctx context.Context, token, realm, userID string) ([]string, error) - GetCredentials(ctx context.Context, token, realm, UserID string) ([]*CredentialRepresentation, error) - DeleteCredentials(ctx context.Context, token, realm, UserID, CredentialID string) error - UpdateCredentialUserLabel(ctx context.Context, token, realm, userID, credentialID, userLabel string) error - DisableAllCredentialsByType(ctx context.Context, token, realm, userID string, types []string) error - MoveCredentialBehind(ctx context.Context, token, realm, userID, credentialID, newPreviousCredentialID string) error - MoveCredentialToFirst(ctx context.Context, token, realm, userID, credentialID string) error - -// *** Authentication Flows *** -GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) -GetAuthenticationFlow(ctx context.Context, token, realm string, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) -CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error -UpdateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) -DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error - -// *** Identity Providers *** - - CreateIdentityProvider(ctx context.Context, token, realm string, providerRep IdentityProviderRepresentation) (string, error) - GetIdentityProvider(ctx context.Context, token, realm, alias string) (*IdentityProviderRepresentation, error) - GetIdentityProviders(ctx context.Context, token, realm string) ([]*IdentityProviderRepresentation, error) - UpdateIdentityProvider(ctx context.Context, token, realm, alias string, providerRep IdentityProviderRepresentation) error - DeleteIdentityProvider(ctx context.Context, token, realm, alias string) error - - CreateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) (string, error) - GetIdentityProviderMapper(ctx context.Context, token string, realm string, alias string, mapperID string) (*IdentityProviderMapper, error) - CreateUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string, federatedIdentityRep FederatedIdentityRepresentation) error - GetUserFederatedIdentities(ctx context.Context, token, realm, userID string) ([]*FederatedIdentityRepresentation, error) - DeleteUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string) error - - // *** Events API *** - GetEvents(ctx context.Context, token string, realm string, params GetEventsParams) ([]*EventRepresentation, error) - -} -``` +[GoCloakIface](gocloak_iface.go) holds all methods a client should fulfil. ## Configure gocloak to skip TLS Insecure Verification diff --git a/client.go b/client.go index ccff45fc..e2f2dfef 100644 --- a/client.go +++ b/client.go @@ -39,6 +39,9 @@ type GoCloak struct { } } +// Verify struct implements interface +var _ GoCloakIface = &GoCloak{} + const ( adminClientID string = "admin-cli" urlSeparator string = "/" diff --git a/client_test.go b/client_test.go index 0cda97c3..05f78718 100644 --- a/client_test.go +++ b/client_test.go @@ -74,7 +74,7 @@ func GetConfig(t testing.TB) *Config { err := configFile.Close() require.NoError(t, err, "cannot close config file") }() - data, err := ioutil.ReadAll(configFile) + data, err := io.ReadAll(configFile) require.NoError(t, err, "cannot read config.json") config = &Config{} err = json.Unmarshal(data, config) @@ -92,7 +92,7 @@ func GetConfig(t testing.TB) *Config { return config } -func GetClientToken(t *testing.T, client *gocloak.GoCloak) *gocloak.JWT { +func GetClientToken(t *testing.T, client gocloak.GoCloakIface) *gocloak.JWT { cfg := GetConfig(t) token, err := client.LoginClient( context.Background(), @@ -103,7 +103,7 @@ func GetClientToken(t *testing.T, client *gocloak.GoCloak) *gocloak.JWT { return token } -func GetUserToken(t *testing.T, client *gocloak.GoCloak) *gocloak.JWT { +func GetUserToken(t *testing.T, client gocloak.GoCloakIface) *gocloak.JWT { SetUpTestUser(t, client) cfg := GetConfig(t) token, err := client.Login( @@ -117,7 +117,7 @@ func GetUserToken(t *testing.T, client *gocloak.GoCloak) *gocloak.JWT { return token } -func GetAdminToken(t testing.TB, client *gocloak.GoCloak) *gocloak.JWT { +func GetAdminToken(t testing.TB, client gocloak.GoCloakIface) *gocloak.JWT { cfg := GetConfig(t) token, err := client.LoginAdmin( context.Background(), @@ -140,7 +140,7 @@ func GetRandomNameP(name string) *string { return &r } -func GetClientByClientID(t *testing.T, client *gocloak.GoCloak, clientID string) *gocloak.Client { +func GetClientByClientID(t *testing.T, client gocloak.GoCloakIface, clientID string) *gocloak.Client { cfg := GetConfig(t) token := GetAdminToken(t, client) clients, err := client.GetClients( @@ -163,7 +163,7 @@ func GetClientByClientID(t *testing.T, client *gocloak.GoCloak, clientID string) return nil } -func CreateGroup(t testing.TB, client *gocloak.GoCloak) (func(), string) { +func CreateGroup(t testing.TB, client gocloak.GoCloakIface) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) group := gocloak.Group{ @@ -194,7 +194,7 @@ func CreateGroup(t testing.TB, client *gocloak.GoCloak) (func(), string) { return tearDown, groupID } -func CreateResource(t *testing.T, client *gocloak.GoCloak, idOfClient string) (func(), string) { +func CreateResource(t *testing.T, client gocloak.GoCloakIface, idOfClient string) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) resource := gocloak.ResourceRepresentation{ @@ -233,7 +233,7 @@ func CreateResource(t *testing.T, client *gocloak.GoCloak, idOfClient string) (f return tearDown, *createdResource.ID } -func CreateResourceClientWithScopes(t *testing.T, client *gocloak.GoCloak) (func(), string) { +func CreateResourceClientWithScopes(t *testing.T, client gocloak.GoCloakIface) (func(), string) { cfg := GetConfig(t) token := GetClientToken(t, client) resource := gocloak.ResourceRepresentation{ @@ -277,7 +277,7 @@ func CreateResourceClientWithScopes(t *testing.T, client *gocloak.GoCloak) (func return tearDown, *createdResource.ID } -func CreateResourceClient(t *testing.T, client *gocloak.GoCloak) (func(), string) { +func CreateResourceClient(t *testing.T, client gocloak.GoCloakIface) (func(), string) { cfg := GetConfig(t) token := GetClientToken(t, client) resource := gocloak.ResourceRepresentation{ @@ -314,7 +314,7 @@ func CreateResourceClient(t *testing.T, client *gocloak.GoCloak) (func(), string return tearDown, *createdResource.ID } -func CreateScope(t *testing.T, client *gocloak.GoCloak, idOfClient string) (func(), string) { +func CreateScope(t *testing.T, client gocloak.GoCloakIface, idOfClient string) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) scope := gocloak.ScopeRepresentation{ @@ -343,7 +343,7 @@ func CreateScope(t *testing.T, client *gocloak.GoCloak, idOfClient string) (func return tearDown, *createdScope.ID } -func CreatePolicy(t *testing.T, client *gocloak.GoCloak, idOfClient string, policy gocloak.PolicyRepresentation) (func(), string) { +func CreatePolicy(t *testing.T, client gocloak.GoCloakIface, idOfClient string, policy gocloak.PolicyRepresentation) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) createdPolicy, err := client.CreatePolicy( @@ -368,7 +368,7 @@ func CreatePolicy(t *testing.T, client *gocloak.GoCloak, idOfClient string, poli return tearDown, *createdPolicy.ID } -func CreatePermission(t *testing.T, client *gocloak.GoCloak, idOfClient string, permission gocloak.PermissionRepresentation) (func(), string) { +func CreatePermission(t *testing.T, client gocloak.GoCloakIface, idOfClient string, permission gocloak.PermissionRepresentation) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) createdPermission, err := client.CreatePermission( @@ -392,7 +392,7 @@ func CreatePermission(t *testing.T, client *gocloak.GoCloak, idOfClient string, return tearDown, *createdPermission.ID } -func CreateClient(t *testing.T, client *gocloak.GoCloak, newClient *gocloak.Client) (func(), string) { +func CreateClient(t *testing.T, client gocloak.GoCloakIface, newClient *gocloak.Client) (func(), string) { if newClient == nil { newClient = &gocloak.Client{ ClientID: GetRandomNameP("ClientID"), @@ -420,7 +420,7 @@ func CreateClient(t *testing.T, client *gocloak.GoCloak, newClient *gocloak.Clie return tearDown, createdID } -func SetUpTestUser(t testing.TB, client *gocloak.GoCloak) { +func SetUpTestUser(t testing.TB, client gocloak.GoCloakIface) { setupOnce.Do(func() { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -495,7 +495,7 @@ func (w *RestyLogWriter) write(format string, v ...interface{}) { func NewClientWithDebug(t testing.TB) *gocloak.GoCloak { cfg := GetConfig(t) client := gocloak.NewClient(cfg.HostName) - cond := func(resp *resty.Response, err error) bool { + cond := func(resp *resty.Response, _ error) bool { if resp != nil && resp.IsError() { if e, ok := resp.Error().(*gocloak.HTTPErrorResponse); ok { msg := e.String() @@ -536,7 +536,7 @@ func NewClientWithDebug(t testing.TB) *gocloak.GoCloak { // skipN = number of requests to be executed and not failed by this function func FailRequest(client *gocloak.GoCloak, err error, failN, skipN int) *gocloak.GoCloak { client.RestyClient().OnBeforeRequest( - func(c *resty.Client, r *resty.Request) error { + func(_ *resty.Client, r *resty.Request) error { if skipN > 0 { skipN-- return nil @@ -554,7 +554,7 @@ func FailRequest(client *gocloak.GoCloak, err error, failN, skipN int) *gocloak. return client } -func ClearRealmCache(t testing.TB, client *gocloak.GoCloak, realm ...string) { +func ClearRealmCache(t testing.TB, client gocloak.GoCloakIface, realm ...string) { cfg := GetConfig(t) token := GetAdminToken(t, client) if len(realm) == 0 { @@ -1293,7 +1293,7 @@ func Test_GroupPermissions(t *testing.T) { } } -func CreateClientRole(t *testing.T, client *gocloak.GoCloak) (func(), string) { +func CreateClientRole(t *testing.T, client gocloak.GoCloakIface) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -1404,7 +1404,7 @@ func Test_GetClientRole(t *testing.T) { require.Nil(t, role) } -func CreateClientScope(t *testing.T, client *gocloak.GoCloak, scope *gocloak.ClientScope) (func(), string) { +func CreateClientScope(t *testing.T, client gocloak.GoCloakIface, scope *gocloak.ClientScope) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -1445,7 +1445,7 @@ func Test_CreateClientScope_DeleteClientScope(t *testing.T) { tearDown() } -func CreateUpdateClientScopeProtocolMapper(t *testing.T, client *gocloak.GoCloak, scopeID string, protocolMapper *gocloak.ProtocolMappers) (func(), string) { +func CreateUpdateClientScopeProtocolMapper(t *testing.T, client gocloak.GoCloakIface, scopeID string, protocolMapper *gocloak.ProtocolMappers) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -1738,7 +1738,7 @@ func Test_GetClientScopeProtocolMappers(t *testing.T) { require.NotNil(t, protocolMappers) } -func CreateClientScopeMappingsRealmRoles(t *testing.T, client *gocloak.GoCloak, idOfClient string, roles []gocloak.Role) func() { +func CreateClientScopeMappingsRealmRoles(t *testing.T, client gocloak.GoCloakIface, idOfClient string, roles []gocloak.Role) func() { token := GetAdminToken(t, client) cfg := GetConfig(t) @@ -1765,7 +1765,7 @@ func CreateClientScopeMappingsRealmRoles(t *testing.T, client *gocloak.GoCloak, return tearDown } -func CreateClientScopeMappingsClientRoles(t *testing.T, client *gocloak.GoCloak, idOfClient, clients string, roles []gocloak.Role) func() { +func CreateClientScopeMappingsClientRoles(t *testing.T, client gocloak.GoCloakIface, idOfClient, clients string, roles []gocloak.Role) func() { token := GetAdminToken(t, client) cfg := GetConfig(t) @@ -1948,7 +1948,7 @@ func Test_ClientScopeMappingsRealmRoles(t *testing.T) { } func CreateClientScopesMappingsClientRoles( - t *testing.T, client *gocloak.GoCloak, scopeID, idOfClient string, roles []gocloak.Role, + t *testing.T, client gocloak.GoCloakIface, scopeID, idOfClient string, roles []gocloak.Role, ) func() { token := GetAdminToken(t, client) cfg := GetConfig(t) @@ -2723,7 +2723,7 @@ func Test_GetRealms(t *testing.T) { // Realm // ----------- -func CreateRealm(t *testing.T, client *gocloak.GoCloak) (func(), string) { +func CreateRealm(t *testing.T, client gocloak.GoCloakIface) (func(), string) { token := GetAdminToken(t, client) realmName := GetRandomName("Realm") @@ -2800,7 +2800,7 @@ func Test_ClearRealmCache(t *testing.T) { // Realm Roles // ----------- -func CreateRealmRole(t *testing.T, client *gocloak.GoCloak) (func(), string) { +func CreateRealmRole(t *testing.T, client gocloak.GoCloakIface) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -3146,7 +3146,7 @@ func Test_AddRealmRoleComposite_DeleteRealmRoleComposite(t *testing.T) { // Users // ----- -func CreateUser(t *testing.T, client *gocloak.GoCloak) (func(), string) { +func CreateUser(t *testing.T, client gocloak.GoCloakIface) (func(), string) { cfg := GetConfig(t) token := GetAdminToken(t, client) @@ -3737,8 +3737,9 @@ func Test_GetClientUserSessions(t *testing.T) { ) require.NoError(t, err, "GetClientUserSessions failed") require.NotEmpty(t, allSessions, "GetClientUserSessions returned an empty list") + require.Equal(t, allSessionsWithoutParams, allSessions, - "GetClientUserSessions with and without params are not the same") + "GetClientUserSessions with and without params are the same") sessions, err := client.GetClientUserSessions( context.Background(), @@ -3917,7 +3918,7 @@ func Test_GetClientOfflineSessions(t *testing.T) { require.NoError(t, err, "GetClientOfflineSessions failed") require.NotEmpty(t, sessions, "GetClientOfflineSessions returned an empty list") require.Equal(t, sessions, sessionsWithoutParams, - "GetClientOfflineSessions with and without params are not the same") + "GetClientOfflineSessions with and without params are the same") } func Test_ClientSecret(t *testing.T) { @@ -6253,7 +6254,7 @@ func Test_CreatePermissionTicket(t *testing.T) { require.NoError(t, err, "CreatePermissionTicket failed") t.Logf("Created PermissionTicket: %+v", *(ticket.Ticket)) - pt, err := jwt.ParseWithClaims(*(ticket.Ticket), &gocloak.PermissionTicketRepresentation{}, func(token *jwt.Token) (interface{}, error) { + pt, err := jwt.ParseWithClaims(*(ticket.Ticket), &gocloak.PermissionTicketRepresentation{}, func(_ *jwt.Token) (interface{}, error) { return []byte(""), nil }) @@ -6945,7 +6946,7 @@ func TestGocloak_UpdateRequiredAction(t *testing.T) { require.NoError(t, err, "Failed to update required action") } -func CreateComponent(t *testing.T, client *gocloak.GoCloak) (func(), *gocloak.Component) { +func CreateComponent(t *testing.T, client gocloak.GoCloakIface) (func(), *gocloak.Component) { newComponent := &gocloak.Component{ Name: GetRandomNameP("CreateComponent"), ProviderID: gocloak.StringP("rsa-generated"), diff --git a/docker-compose.yml b/docker-compose.yml index b422ddbb..01bdf32d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3' - services: keycloak: build: . diff --git a/go.mod b/go.mod index cde01123..7af6422a 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,20 @@ module github.com/Nerzal/gocloak/v13 -go 1.18 +go 1.23 require ( - github.com/go-resty/resty/v2 v2.7.0 - github.com/golang-jwt/jwt/v5 v5.0.0 + github.com/go-resty/resty/v2 v2.14.0 + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 github.com/segmentio/ksuid v1.0.4 - github.com/stretchr/testify v1.8.2 - golang.org/x/crypto v0.17.0 + github.com/stretchr/testify v1.9.0 + golang.org/x/crypto v0.26.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.28.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 86853e21..d9d6167e 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,11 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= -github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= -github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= -github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/go-resty/resty/v2 v2.14.0 h1:/rhkzsAqGQkozwfKS5aFAbb6TyKd3zyFRWcdRXLPCAU= +github.com/go-resty/resty/v2 v2.14.0/go.mod h1:IW6mekUOsElt9C7oWr0XRt9BNSD6D5rr9mhk6NjmNHg= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -14,25 +15,79 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gocloak_iface.go b/gocloak_iface.go new file mode 100644 index 00000000..be49353c --- /dev/null +++ b/gocloak_iface.go @@ -0,0 +1,570 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package gocloak + +import ( + "context" + "io" + + "github.com/go-resty/resty/v2" + "github.com/golang-jwt/jwt/v5" +) + +// GoCloakIface ... +type GoCloakIface interface { + // GetRequest returns a request for calling endpoints. + GetRequest(ctx context.Context) *resty.Request + // GetRequestWithBearerAuthNoCache returns a JSON base request configured with an auth token and no-cache header. + GetRequestWithBearerAuthNoCache(ctx context.Context, token string) *resty.Request + // GetRequestWithBearerAuth returns a JSON base request configured with an auth token. + GetRequestWithBearerAuth(ctx context.Context, token string) *resty.Request + // GetRequestWithBearerAuthXMLHeader returns an XML base request configured with an auth token. + GetRequestWithBearerAuthXMLHeader(ctx context.Context, token string) *resty.Request + // GetRequestWithBasicAuth returns a form data base request configured with basic auth. + GetRequestWithBasicAuth(ctx context.Context, clientID, clientSecret string) *resty.Request + // RestyClient returns the internal resty g. + // This can be used to configure the g. + RestyClient() *resty.Client + // SetRestyClient overwrites the internal resty g. + SetRestyClient(restyClient *resty.Client) + // GetServerInfo fetches the server info. + GetServerInfo(ctx context.Context, accessToken string) (*ServerInfoRepresentation, error) + // GetUserInfo calls the UserInfo endpoint + GetUserInfo(ctx context.Context, accessToken, realm string) (*UserInfo, error) + // GetRawUserInfo calls the UserInfo endpoint and returns a raw json object + GetRawUserInfo(ctx context.Context, accessToken, realm string) (map[string]interface{}, error) + // GetCerts fetches certificates for the given realm from the public /open-id-connect/certs endpoint + GetCerts(ctx context.Context, realm string) (*CertResponse, error) + // GetIssuer gets the issuer of the given realm + GetIssuer(ctx context.Context, realm string) (*IssuerResponse, error) + // RetrospectToken calls the openid-connect introspect endpoint + RetrospectToken(ctx context.Context, accessToken, clientID, clientSecret, realm string) (*IntroSpectTokenResult, error) + // DecodeAccessToken decodes the accessToken + DecodeAccessToken(ctx context.Context, accessToken, realm string) (*jwt.Token, *jwt.MapClaims, error) + // DecodeAccessTokenCustomClaims decodes the accessToken and writes claims into the given claims + DecodeAccessTokenCustomClaims(ctx context.Context, accessToken, realm string, claims jwt.Claims) (*jwt.Token, error) + // GetToken uses TokenOptions to fetch a token. + GetToken(ctx context.Context, realm string, options TokenOptions) (*JWT, error) + // GetRequestingPartyToken returns a requesting party token with permissions granted by the server + GetRequestingPartyToken(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*JWT, error) + // GetRequestingPartyPermissions returns a requesting party permissions granted by the server + GetRequestingPartyPermissions(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*[]RequestingPartyPermission, error) + // GetRequestingPartyPermissionDecision returns a requesting party permission decision granted by the server + GetRequestingPartyPermissionDecision(ctx context.Context, token, realm string, options RequestingPartyTokenOptions) (*RequestingPartyPermissionDecision, error) + // RefreshToken refreshes the given token. + // May return a *APIError with further details about the issue. + RefreshToken(ctx context.Context, refreshToken, clientID, clientSecret, realm string) (*JWT, error) + // LoginAdmin performs a login with Admin client + LoginAdmin(ctx context.Context, username, password, realm string) (*JWT, error) + // LoginClient performs a login with client credentials + LoginClient(ctx context.Context, clientID, clientSecret, realm string, scopes ...string) (*JWT, error) + // LoginClientTokenExchange will exchange the presented token for a user's token + // Requires Token-Exchange is enabled: https://www.keycloak.org/docs/latest/securing_apps/index.html#_token-exchange + LoginClientTokenExchange(ctx context.Context, clientID, token, clientSecret, realm, targetClient, userID string) (*JWT, error) + // LoginClientSignedJWT performs a login with client credentials and signed jwt claims + LoginClientSignedJWT(ctx context.Context, clientID, realm string, key interface{}, signedMethod jwt.SigningMethod, expiresAt *jwt.NumericDate) (*JWT, error) + // Login performs a login with user credentials and a client + Login(ctx context.Context, clientID, clientSecret, realm, username, password string) (*JWT, error) + // LoginOtp performs a login with user credentials and otp token + LoginOtp(ctx context.Context, clientID, clientSecret, realm, username, password, totp string) (*JWT, error) + // Logout logs out users with refresh token + Logout(ctx context.Context, clientID, clientSecret, realm, refreshToken string) error + // LogoutPublicClient performs a logout using a public client and the accessToken. + LogoutPublicClient(ctx context.Context, clientID, realm, accessToken, refreshToken string) error + // LogoutAllSessions logs out all sessions of a user given an id. + LogoutAllSessions(ctx context.Context, accessToken, realm, userID string) error + // RevokeUserConsents revokes the given user consent. + RevokeUserConsents(ctx context.Context, accessToken, realm, userID, clientID string) error + // LogoutUserSession logs out a single sessions of a user given a session id + LogoutUserSession(ctx context.Context, accessToken, realm, session string) error + // ExecuteActionsEmail executes an actions email + ExecuteActionsEmail(ctx context.Context, token, realm string, params ExecuteActionsEmail) error + // SendVerifyEmail sends a verification e-mail to a user. + SendVerifyEmail(ctx context.Context, token, userID, realm string, params ...SendVerificationMailParams) error + // CreateGroup creates a new group. + CreateGroup(ctx context.Context, token, realm string, group Group) (string, error) + // CreateChildGroup creates a new child group + CreateChildGroup(ctx context.Context, token, realm, groupID string, group Group) (string, error) + // CreateComponent creates the given component. + CreateComponent(ctx context.Context, token, realm string, component Component) (string, error) + // CreateClient creates the given g. + CreateClient(ctx context.Context, accessToken, realm string, newClient Client) (string, error) + // CreateClientRepresentation creates a new client representation + CreateClientRepresentation(ctx context.Context, token, realm string, newClient Client) (*Client, error) + // CreateClientRole creates a new role for a client + CreateClientRole(ctx context.Context, token, realm, idOfClient string, role Role) (string, error) + // CreateClientScope creates a new client scope + CreateClientScope(ctx context.Context, token, realm string, scope ClientScope) (string, error) + // CreateClientScopeProtocolMapper creates a new protocolMapper under the given client scope + CreateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) (string, error) + // UpdateGroup updates the given group. + UpdateGroup(ctx context.Context, token, realm string, updatedGroup Group) error + // UpdateGroupManagementPermissions updates the given group management permissions + UpdateGroupManagementPermissions(ctx context.Context, accessToken, realm string, idOfGroup string, managementPermissions ManagementPermissionRepresentation) (*ManagementPermissionRepresentation, error) + // UpdateClient updates the given Client + UpdateClient(ctx context.Context, token, realm string, updatedClient Client) error + // UpdateClientRepresentation updates the given client representation + UpdateClientRepresentation(ctx context.Context, accessToken, realm string, updatedClient Client) (*Client, error) + // UpdateClientManagementPermissions updates the given client management permissions + UpdateClientManagementPermissions(ctx context.Context, accessToken, realm string, idOfClient string, managementPermissions ManagementPermissionRepresentation) (*ManagementPermissionRepresentation, error) + // UpdateRole updates the given role. + UpdateRole(ctx context.Context, token, realm, idOfClient string, role Role) error + // UpdateClientScope updates the given client scope. + UpdateClientScope(ctx context.Context, token, realm string, scope ClientScope) error + // UpdateClientScopeProtocolMapper updates the given protocol mapper for a client scope + UpdateClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID string, protocolMapper ProtocolMappers) error + // DeleteGroup deletes the group with the given groupID. + DeleteGroup(ctx context.Context, token, realm, groupID string) error + // DeleteClient deletes a given client + DeleteClient(ctx context.Context, token, realm, idOfClient string) error + // DeleteComponent deletes the component with the given id. + DeleteComponent(ctx context.Context, token, realm, componentID string) error + // DeleteClientRepresentation deletes a given client representation. + DeleteClientRepresentation(ctx context.Context, accessToken, realm, clientID string) error + // DeleteClientRole deletes a given role. + DeleteClientRole(ctx context.Context, token, realm, idOfClient, roleName string) error + // DeleteClientScope deletes the scope with the given id. + DeleteClientScope(ctx context.Context, token, realm, scopeID string) error + // DeleteClientScopeProtocolMapper deletes the given protocol mapper from the client scope + DeleteClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) error + // GetClient returns a client + GetClient(ctx context.Context, token, realm, idOfClient string) (*Client, error) + // GetClientRepresentation returns a client representation + GetClientRepresentation(ctx context.Context, accessToken, realm, clientID string) (*Client, error) + // GetAdapterConfiguration returns a adapter configuration + GetAdapterConfiguration(ctx context.Context, accessToken, realm, clientID string) (*AdapterConfiguration, error) + // GetClientsDefaultScopes returns a list of the client's default scopes + GetClientsDefaultScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) + // AddDefaultScopeToClient adds a client scope to the list of client's default scopes + AddDefaultScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error + // RemoveDefaultScopeFromClient removes a client scope from the list of client's default scopes + RemoveDefaultScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error + // GetClientsOptionalScopes returns a list of the client's optional scopes + GetClientsOptionalScopes(ctx context.Context, token, realm, idOfClient string) ([]*ClientScope, error) + // AddOptionalScopeToClient adds a client scope to the list of client's optional scopes + AddOptionalScopeToClient(ctx context.Context, token, realm, idOfClient, scopeID string) error + // RemoveOptionalScopeFromClient deletes a client scope from the list of client's optional scopes + RemoveOptionalScopeFromClient(ctx context.Context, token, realm, idOfClient, scopeID string) error + // GetDefaultOptionalClientScopes returns a list of default realm optional scopes + GetDefaultOptionalClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) + // GetDefaultDefaultClientScopes returns a list of default realm default scopes + GetDefaultDefaultClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) + // GetClientScope returns a clientscope + GetClientScope(ctx context.Context, token, realm, scopeID string) (*ClientScope, error) + // GetClientScopes returns all client scopes + GetClientScopes(ctx context.Context, token, realm string) ([]*ClientScope, error) + // GetClientScopeProtocolMappers returns all protocol mappers of a client scope + GetClientScopeProtocolMappers(ctx context.Context, token, realm, scopeID string) ([]*ProtocolMappers, error) + // GetClientScopeProtocolMapper returns a protocol mapper of a client scope + GetClientScopeProtocolMapper(ctx context.Context, token, realm, scopeID, protocolMapperID string) (*ProtocolMappers, error) + // GetClientScopeMappings returns all scope mappings for the client + GetClientScopeMappings(ctx context.Context, token, realm, idOfClient string) (*MappingsRepresentation, error) + // GetClientScopeMappingsRealmRoles returns realm-level roles associated with the client’s scope + GetClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) + // GetClientScopeMappingsRealmRolesAvailable returns realm-level roles that are available to attach to this client’s scope + GetClientScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) + // CreateClientScopeMappingsRealmRoles create realm-level roles to the client’s scope + CreateClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error + // DeleteClientScopeMappingsRealmRoles deletes realm-level roles from the client’s scope + DeleteClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string, roles []Role) error + // GetClientScopeMappingsClientRoles returns roles associated with a client’s scope + GetClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) + // GetClientScopeMappingsClientRolesAvailable returns available roles associated with a client’s scope + GetClientScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string) ([]*Role, error) + // CreateClientScopeMappingsClientRoles creates client-level roles from the client’s scope + CreateClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error + // DeleteClientScopeMappingsClientRoles deletes client-level roles from the client’s scope + DeleteClientScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClient, idOfSelectedClient string, roles []Role) error + // GetClientSecret returns a client's secret + GetClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) + // GetClientServiceAccount retrieves the service account "user" for a client if enabled + GetClientServiceAccount(ctx context.Context, token, realm, idOfClient string) (*User, error) + // RegenerateClientSecret triggers the creation of the new client secret. + RegenerateClientSecret(ctx context.Context, token, realm, idOfClient string) (*CredentialRepresentation, error) + // GetClientOfflineSessions returns offline sessions associated with the client + GetClientOfflineSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) + // GetClientUserSessions returns user sessions associated with the client + GetClientUserSessions(ctx context.Context, token, realm, idOfClient string, params ...GetClientUserSessionsParams) ([]*UserSessionRepresentation, error) + // CreateClientProtocolMapper creates a protocol mapper in client scope + CreateClientProtocolMapper(ctx context.Context, token, realm, idOfClient string, mapper ProtocolMapperRepresentation) (string, error) + // UpdateClientProtocolMapper updates a protocol mapper in client scope + UpdateClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string, mapper ProtocolMapperRepresentation) error + // DeleteClientProtocolMapper deletes a protocol mapper in client scope + DeleteClientProtocolMapper(ctx context.Context, token, realm, idOfClient, mapperID string) error + // GetKeyStoreConfig get keystoreconfig of the realm + GetKeyStoreConfig(ctx context.Context, token, realm string) (*KeyStoreConfig, error) + // GetComponents get all components in realm + GetComponents(ctx context.Context, token, realm string) ([]*Component, error) + // GetComponentsWithParams get all components in realm with query params + GetComponentsWithParams(ctx context.Context, token, realm string, params GetComponentsParams) ([]*Component, error) + // GetComponent get exactly one component by ID + GetComponent(ctx context.Context, token, realm string, componentID string) (*Component, error) + // UpdateComponent updates the given component + UpdateComponent(ctx context.Context, token, realm string, component Component) error + // GetDefaultGroups returns a list of default groups + GetDefaultGroups(ctx context.Context, token, realm string) ([]*Group, error) + // AddDefaultGroup adds group to the list of default groups + AddDefaultGroup(ctx context.Context, token, realm, groupID string) error + // RemoveDefaultGroup removes group from the list of default groups + RemoveDefaultGroup(ctx context.Context, token, realm, groupID string) error + // GetRoleMappingByGroupID gets the role mappings by group + GetRoleMappingByGroupID(ctx context.Context, token, realm, groupID string) (*MappingsRepresentation, error) + // GetRoleMappingByUserID gets the role mappings by user + GetRoleMappingByUserID(ctx context.Context, token, realm, userID string) (*MappingsRepresentation, error) + // GetGroup get group with id in realm + GetGroup(ctx context.Context, token, realm, groupID string) (*Group, error) + // GetGroupByPath get group with path in realm + GetGroupByPath(ctx context.Context, token, realm, groupPath string) (*Group, error) + // GetGroups get all groups in realm + GetGroups(ctx context.Context, token, realm string, params GetGroupsParams) ([]*Group, error) + // GetGroupManagementPermissions returns whether group Authorization permissions have been initialized or not and a reference + // to the managed permissions + GetGroupManagementPermissions(ctx context.Context, token, realm string, idOfGroup string) (*ManagementPermissionRepresentation, error) + // GetGroupsByRole gets groups assigned with a specific role of a realm + GetGroupsByRole(ctx context.Context, token, realm string, roleName string) ([]*Group, error) + // GetGroupsByClientRole gets groups with specified roles assigned of given client within a realm + GetGroupsByClientRole(ctx context.Context, token, realm string, roleName string, clientID string) ([]*Group, error) + // GetGroupsCount gets the groups count in the realm + GetGroupsCount(ctx context.Context, token, realm string, params GetGroupsParams) (int, error) + // GetGroupMembers get a list of users of group with id in realm + GetGroupMembers(ctx context.Context, token, realm, groupID string, params GetGroupsParams) ([]*User, error) + // GetClientRoles get all roles for the given client in realm + GetClientRoles(ctx context.Context, token, realm, idOfClient string, params GetRoleParams) ([]*Role, error) + // GetClientRoleByID gets role for the given client in realm using role ID + GetClientRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) + // GetClientRolesByUserID returns all client roles assigned to the given user + GetClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) + // GetClientRolesByGroupID returns all client roles assigned to the given group + GetClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) + // GetCompositeClientRolesByRoleID returns all client composite roles associated with the given client role + GetCompositeClientRolesByRoleID(ctx context.Context, token, realm, idOfClient, roleID string) ([]*Role, error) + // GetCompositeClientRolesByUserID returns all client roles and composite roles assigned to the given user + GetCompositeClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) + // GetAvailableClientRolesByUserID returns all available client roles to the given user + GetAvailableClientRolesByUserID(ctx context.Context, token, realm, idOfClient, userID string) ([]*Role, error) + // GetAvailableClientRolesByGroupID returns all available roles to the given group + GetAvailableClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) + // GetCompositeClientRolesByGroupID returns all client roles and composite roles assigned to the given group + GetCompositeClientRolesByGroupID(ctx context.Context, token, realm, idOfClient, groupID string) ([]*Role, error) + // GetClientRole get a role for the given client in a realm by role name + GetClientRole(ctx context.Context, token, realm, idOfClient, roleName string) (*Role, error) + // GetClients gets all clients in realm + GetClients(ctx context.Context, token, realm string, params GetClientsParams) ([]*Client, error) + // GetClientManagementPermissions returns whether client Authorization permissions have been initialized or not and a reference + // to the managed permissions + GetClientManagementPermissions(ctx context.Context, token, realm string, idOfClient string) (*ManagementPermissionRepresentation, error) + // CreateRealmRole creates a role in a realm + CreateRealmRole(ctx context.Context, token string, realm string, role Role) (string, error) + // GetRealmRole returns a role from a realm by role's name + GetRealmRole(ctx context.Context, token, realm, roleName string) (*Role, error) + // GetRealmRoleByID returns a role from a realm by role's ID + GetRealmRoleByID(ctx context.Context, token, realm, roleID string) (*Role, error) + // GetRealmRoles get all roles of the given realm. + GetRealmRoles(ctx context.Context, token, realm string, params GetRoleParams) ([]*Role, error) + // GetRealmRolesByUserID returns all roles assigned to the given user + GetRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) + // GetRealmRolesByGroupID returns all roles assigned to the given group + GetRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) + // UpdateRealmRole updates a role in a realm + UpdateRealmRole(ctx context.Context, token, realm, roleName string, role Role) error + // UpdateRealmRoleByID updates a role in a realm by role's ID + UpdateRealmRoleByID(ctx context.Context, token, realm, roleID string, role Role) error + // DeleteRealmRole deletes a role in a realm by role's name + DeleteRealmRole(ctx context.Context, token, realm, roleName string) error + // AddRealmRoleToUser adds realm-level role mappings + AddRealmRoleToUser(ctx context.Context, token, realm, userID string, roles []Role) error + // DeleteRealmRoleFromUser deletes realm-level role mappings + DeleteRealmRoleFromUser(ctx context.Context, token, realm, userID string, roles []Role) error + // AddRealmRoleToGroup adds realm-level role mappings + AddRealmRoleToGroup(ctx context.Context, token, realm, groupID string, roles []Role) error + // DeleteRealmRoleFromGroup deletes realm-level role mappings + DeleteRealmRoleFromGroup(ctx context.Context, token, realm, groupID string, roles []Role) error + // AddRealmRoleComposite adds a role to the composite. + AddRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error + // DeleteRealmRoleComposite deletes a role from the composite. + DeleteRealmRoleComposite(ctx context.Context, token, realm, roleName string, roles []Role) error + // GetCompositeRealmRoles returns all realm composite roles associated with the given realm role + GetCompositeRealmRoles(ctx context.Context, token, realm, roleName string) ([]*Role, error) + // GetCompositeRolesByRoleID returns all realm composite roles associated with the given client role + GetCompositeRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) + // GetCompositeRealmRolesByRoleID returns all realm composite roles associated with the given client role + GetCompositeRealmRolesByRoleID(ctx context.Context, token, realm, roleID string) ([]*Role, error) + // GetCompositeRealmRolesByUserID returns all realm roles and composite roles assigned to the given user + GetCompositeRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) + // GetCompositeRealmRolesByGroupID returns all realm roles and composite roles assigned to the given group + GetCompositeRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) + // GetAvailableRealmRolesByUserID returns all available realm roles to the given user + GetAvailableRealmRolesByUserID(ctx context.Context, token, realm, userID string) ([]*Role, error) + // GetAvailableRealmRolesByGroupID returns all available realm roles to the given group + GetAvailableRealmRolesByGroupID(ctx context.Context, token, realm, groupID string) ([]*Role, error) + // GetRealm returns top-level representation of the realm + GetRealm(ctx context.Context, token, realm string) (*RealmRepresentation, error) + // GetRealms returns top-level representation of all realms + GetRealms(ctx context.Context, token string) ([]*RealmRepresentation, error) + // CreateRealm creates a realm + CreateRealm(ctx context.Context, token string, realm RealmRepresentation) (string, error) + // UpdateRealm updates a given realm + UpdateRealm(ctx context.Context, token string, realm RealmRepresentation) error + // DeleteRealm removes a realm + DeleteRealm(ctx context.Context, token, realm string) error + // ClearRealmCache clears realm cache + ClearRealmCache(ctx context.Context, token, realm string) error + // ClearUserCache clears realm cache + ClearUserCache(ctx context.Context, token, realm string) error + // ClearKeysCache clears realm cache + ClearKeysCache(ctx context.Context, token, realm string) error + // GetAuthenticationFlows get all authentication flows from a realm + GetAuthenticationFlows(ctx context.Context, token, realm string) ([]*AuthenticationFlowRepresentation, error) + // GetAuthenticationFlow get an authentication flow with the given ID + GetAuthenticationFlow(ctx context.Context, token, realm string, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) + // CreateAuthenticationFlow creates a new Authentication flow in a realm + CreateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation) error + // UpdateAuthenticationFlow a given Authentication Flow + UpdateAuthenticationFlow(ctx context.Context, token, realm string, flow AuthenticationFlowRepresentation, authenticationFlowID string) (*AuthenticationFlowRepresentation, error) + // DeleteAuthenticationFlow deletes a flow in a realm with the given ID + DeleteAuthenticationFlow(ctx context.Context, token, realm, flowID string) error + // GetAuthenticationExecutions retrieves all executions of a given flow + GetAuthenticationExecutions(ctx context.Context, token, realm, flow string) ([]*ModifyAuthenticationExecutionRepresentation, error) + // CreateAuthenticationExecution creates a new execution for the given flow name in the given realm + CreateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution CreateAuthenticationExecutionRepresentation) error + // UpdateAuthenticationExecution updates an authentication execution for the given flow in the given realm + UpdateAuthenticationExecution(ctx context.Context, token, realm, flow string, execution ModifyAuthenticationExecutionRepresentation) error + // DeleteAuthenticationExecution delete a single execution with the given ID + DeleteAuthenticationExecution(ctx context.Context, token, realm, executionID string) error + // CreateAuthenticationExecutionFlow creates a new execution for the given flow name in the given realm + CreateAuthenticationExecutionFlow(ctx context.Context, token, realm, flow string, executionFlow CreateAuthenticationExecutionFlowRepresentation) error + // CreateUser creates the given user in the given realm and returns it's userID + // Note: Keycloak has not documented what members of the User object are actually being accepted, when creating a user. + // Things like RealmRoles must be attached using followup calls to the respective functions. + CreateUser(ctx context.Context, token, realm string, user User) (string, error) + // DeleteUser delete a given user + DeleteUser(ctx context.Context, token, realm, userID string) error + // GetUserByID fetches a user from the given realm with the given userID + GetUserByID(ctx context.Context, accessToken, realm, userID string) (*User, error) + // GetUserCount gets the user count in the realm + GetUserCount(ctx context.Context, token string, realm string, params GetUsersParams) (int, error) + // GetUserGroups get all groups for user + GetUserGroups(ctx context.Context, token, realm, userID string, params GetGroupsParams) ([]*Group, error) + // GetUsers get all users in realm + GetUsers(ctx context.Context, token, realm string, params GetUsersParams) ([]*User, error) + // GetUsersByRoleName returns all users have a given role + GetUsersByRoleName(ctx context.Context, token, realm, roleName string, params GetUsersByRoleParams) ([]*User, error) + // GetUsersByClientRoleName returns all users have a given client role + GetUsersByClientRoleName(ctx context.Context, token, realm, idOfClient, roleName string, params GetUsersByRoleParams) ([]*User, error) + // SetPassword sets a new password for the user with the given id. Needs elevated privileges + SetPassword(ctx context.Context, token, userID, realm, password string, temporary bool) error + // UpdateUser updates a given user + UpdateUser(ctx context.Context, token, realm string, user User) error + // AddUserToGroup puts given user to given group + AddUserToGroup(ctx context.Context, token, realm, userID, groupID string) error + // DeleteUserFromGroup deletes given user from given group + DeleteUserFromGroup(ctx context.Context, token, realm, userID, groupID string) error + // GetUserSessions returns user sessions associated with the user + GetUserSessions(ctx context.Context, token, realm, userID string) ([]*UserSessionRepresentation, error) + // GetUserOfflineSessionsForClient returns offline sessions associated with the user and client + GetUserOfflineSessionsForClient(ctx context.Context, token, realm, userID, idOfClient string) ([]*UserSessionRepresentation, error) + // AddClientRolesToUser adds client-level role mappings + AddClientRolesToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error + // AddClientRoleToUser adds client-level role mappings + // + // Deprecated: replaced by AddClientRolesToUser + AddClientRoleToUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error + // AddClientRolesToGroup adds a client role to the group + AddClientRolesToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error + // AddClientRoleToGroup adds a client role to the group + // + // Deprecated: replaced by AddClientRolesToGroup + AddClientRoleToGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error + // DeleteClientRolesFromUser adds client-level role mappings + DeleteClientRolesFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error + // DeleteClientRoleFromUser adds client-level role mappings + // + // Deprecated: replaced by DeleteClientRolesFrom + DeleteClientRoleFromUser(ctx context.Context, token, realm, idOfClient, userID string, roles []Role) error + // DeleteClientRoleFromGroup removes a client role from from the group + DeleteClientRoleFromGroup(ctx context.Context, token, realm, idOfClient, groupID string, roles []Role) error + // AddClientRoleComposite adds roles as composite + AddClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error + // DeleteClientRoleComposite deletes composites from a role + DeleteClientRoleComposite(ctx context.Context, token, realm, roleID string, roles []Role) error + // GetUserFederatedIdentities gets all user federated identities + GetUserFederatedIdentities(ctx context.Context, token, realm, userID string) ([]*FederatedIdentityRepresentation, error) + // CreateUserFederatedIdentity creates an user federated identity + CreateUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string, federatedIdentityRep FederatedIdentityRepresentation) error + // DeleteUserFederatedIdentity deletes an user federated identity + DeleteUserFederatedIdentity(ctx context.Context, token, realm, userID, providerID string) error + // GetUserBruteForceDetectionStatus fetches a user status regarding brute force protection + GetUserBruteForceDetectionStatus(ctx context.Context, accessToken, realm, userID string) (*BruteForceStatus, error) + // CreateIdentityProvider creates an identity provider in a realm + CreateIdentityProvider(ctx context.Context, token string, realm string, providerRep IdentityProviderRepresentation) (string, error) + // GetIdentityProviders returns list of identity providers in a realm + GetIdentityProviders(ctx context.Context, token, realm string) ([]*IdentityProviderRepresentation, error) + // GetIdentityProvider gets the identity provider in a realm + GetIdentityProvider(ctx context.Context, token, realm, alias string) (*IdentityProviderRepresentation, error) + // UpdateIdentityProvider updates the identity provider in a realm + UpdateIdentityProvider(ctx context.Context, token, realm, alias string, providerRep IdentityProviderRepresentation) error + // DeleteIdentityProvider deletes the identity provider in a realm + DeleteIdentityProvider(ctx context.Context, token, realm, alias string) error + // ExportIDPPublicBrokerConfig exports the broker config for a given alias + ExportIDPPublicBrokerConfig(ctx context.Context, token, realm, alias string) (*string, error) + // ImportIdentityProviderConfig parses and returns the identity provider config at a given URL + ImportIdentityProviderConfig(ctx context.Context, token, realm, fromURL, providerID string) (map[string]string, error) + // ImportIdentityProviderConfigFromFile parses and returns the identity provider config from a given file + ImportIdentityProviderConfigFromFile(ctx context.Context, token, realm, providerID, fileName string, fileBody io.Reader) (map[string]string, error) + // CreateIdentityProviderMapper creates an instance of an identity provider mapper associated with the given alias + CreateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) (string, error) + // GetIdentityProviderMapper gets the mapper by id for the given identity provider alias in a realm + GetIdentityProviderMapper(ctx context.Context, token string, realm string, alias string, mapperID string) (*IdentityProviderMapper, error) + // DeleteIdentityProviderMapper deletes an instance of an identity provider mapper associated with the given alias and mapper ID + DeleteIdentityProviderMapper(ctx context.Context, token, realm, alias, mapperID string) error + // GetIdentityProviderMappers returns list of mappers associated with an identity provider + GetIdentityProviderMappers(ctx context.Context, token, realm, alias string) ([]*IdentityProviderMapper, error) + // GetIdentityProviderMapperByID gets the mapper of an identity provider + GetIdentityProviderMapperByID(ctx context.Context, token, realm, alias, mapperID string) (*IdentityProviderMapper, error) + // UpdateIdentityProviderMapper updates mapper of an identity provider + UpdateIdentityProviderMapper(ctx context.Context, token, realm, alias string, mapper IdentityProviderMapper) error + // GetResource returns a client's resource with the given id, using access token from admin + GetResource(ctx context.Context, token, realm, idOfClient, resourceID string) (*ResourceRepresentation, error) + // GetResourceClient returns a client's resource with the given id, using access token from client + GetResourceClient(ctx context.Context, token, realm, resourceID string) (*ResourceRepresentation, error) + // GetResources returns resources associated with the client, using access token from admin + GetResources(ctx context.Context, token, realm, idOfClient string, params GetResourceParams) ([]*ResourceRepresentation, error) + // GetResourcesClient returns resources associated with the client, using access token from client + GetResourcesClient(ctx context.Context, token, realm string, params GetResourceParams) ([]*ResourceRepresentation, error) + // GetResourceServer returns resource server settings. + // The access token must have the realm view_clients role on its service + // account to be allowed to call this endpoint. + GetResourceServer(ctx context.Context, token, realm, idOfClient string) (*ResourceServerRepresentation, error) + // UpdateResource updates a resource associated with the client, using access token from admin + UpdateResource(ctx context.Context, token, realm, idOfClient string, resource ResourceRepresentation) error + // UpdateResourceClient updates a resource associated with the client, using access token from client + UpdateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) error + // CreateResource creates a resource associated with the client, using access token from admin + CreateResource(ctx context.Context, token, realm string, idOfClient string, resource ResourceRepresentation) (*ResourceRepresentation, error) + // CreateResourceClient creates a resource associated with the client, using access token from client + CreateResourceClient(ctx context.Context, token, realm string, resource ResourceRepresentation) (*ResourceRepresentation, error) + // DeleteResource deletes a resource associated with the client (using an admin token) + DeleteResource(ctx context.Context, token, realm, idOfClient, resourceID string) error + // DeleteResourceClient deletes a resource associated with the client (using a client token) + DeleteResourceClient(ctx context.Context, token, realm, resourceID string) error + // GetScope returns a client's scope with the given id + GetScope(ctx context.Context, token, realm, idOfClient, scopeID string) (*ScopeRepresentation, error) + // GetScopes returns scopes associated with the client + GetScopes(ctx context.Context, token, realm, idOfClient string, params GetScopeParams) ([]*ScopeRepresentation, error) + // CreateScope creates a scope associated with the client + CreateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) (*ScopeRepresentation, error) + // GetPermissionScope gets the permission scope associated with the client + GetPermissionScope(ctx context.Context, token, realm, idOfClient string, idOfScope string) (*PolicyRepresentation, error) + // UpdatePermissionScope updates a permission scope associated with the client + UpdatePermissionScope(ctx context.Context, token, realm, idOfClient string, idOfScope string, policy PolicyRepresentation) error + // UpdateScope updates a scope associated with the client + UpdateScope(ctx context.Context, token, realm, idOfClient string, scope ScopeRepresentation) error + // DeleteScope deletes a scope associated with the client + DeleteScope(ctx context.Context, token, realm, idOfClient, scopeID string) error + // GetPolicy returns a client's policy with the given id + GetPolicy(ctx context.Context, token, realm, idOfClient, policyID string) (*PolicyRepresentation, error) + // GetPolicies returns policies associated with the client + GetPolicies(ctx context.Context, token, realm, idOfClient string, params GetPolicyParams) ([]*PolicyRepresentation, error) + // CreatePolicy creates a policy associated with the client + CreatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) (*PolicyRepresentation, error) + // UpdatePolicy updates a policy associated with the client + UpdatePolicy(ctx context.Context, token, realm, idOfClient string, policy PolicyRepresentation) error + // DeletePolicy deletes a policy associated with the client + DeletePolicy(ctx context.Context, token, realm, idOfClient, policyID string) error + // GetAuthorizationPolicyAssociatedPolicies returns a client's associated policies of specific policy with the given policy id, using access token from admin + GetAuthorizationPolicyAssociatedPolicies(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyRepresentation, error) + // GetAuthorizationPolicyResources returns a client's resources of specific policy with the given policy id, using access token from admin + GetAuthorizationPolicyResources(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyResourceRepresentation, error) + // GetAuthorizationPolicyScopes returns a client's scopes of specific policy with the given policy id, using access token from admin + GetAuthorizationPolicyScopes(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PolicyScopeRepresentation, error) + // GetResourcePolicy updates a permission for a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange + GetResourcePolicy(ctx context.Context, token, realm, permissionID string) (*ResourcePolicyRepresentation, error) + // GetResourcePolicies returns resources associated with the client, using token obtained by Resource Owner Password Credentials Grant or Token exchange + GetResourcePolicies(ctx context.Context, token, realm string, params GetResourcePoliciesParams) ([]*ResourcePolicyRepresentation, error) + // CreateResourcePolicy associates a permission with a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange + CreateResourcePolicy(ctx context.Context, token, realm, resourceID string, policy ResourcePolicyRepresentation) (*ResourcePolicyRepresentation, error) + // UpdateResourcePolicy updates a permission for a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange + UpdateResourcePolicy(ctx context.Context, token, realm, permissionID string, policy ResourcePolicyRepresentation) error + // DeleteResourcePolicy deletes a permission for a specific resource, using token obtained by Resource Owner Password Credentials Grant or Token exchange + DeleteResourcePolicy(ctx context.Context, token, realm, permissionID string) error + // GetPermission returns a client's permission with the given id + GetPermission(ctx context.Context, token, realm, idOfClient, permissionID string) (*PermissionRepresentation, error) + // GetDependentPermissions returns a client's permission with the given policy id + GetDependentPermissions(ctx context.Context, token, realm, idOfClient, policyID string) ([]*PermissionRepresentation, error) + // GetPermissionResources returns a client's resource attached for the given permission id + GetPermissionResources(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionResource, error) + // GetPermissionScopes returns a client's scopes configured for the given permission id + GetPermissionScopes(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionScope, error) + // GetPermissions returns permissions associated with the client + GetPermissions(ctx context.Context, token, realm, idOfClient string, params GetPermissionParams) ([]*PermissionRepresentation, error) + // CreatePermissionTicket creates a permission ticket, using access token from client + CreatePermissionTicket(ctx context.Context, token, realm string, permissions []CreatePermissionTicketParams) (*PermissionTicketResponseRepresentation, error) + // GrantUserPermission lets resource owner grant permission for specific resource ID to specific user ID + GrantUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) + // UpdateUserPermission updates user permissions. + UpdateUserPermission(ctx context.Context, token, realm string, permission PermissionGrantParams) (*PermissionGrantResponseRepresentation, error) + // GetUserPermissions gets granted permissions according query parameters + GetUserPermissions(ctx context.Context, token, realm string, params GetUserPermissionParams) ([]*PermissionGrantResponseRepresentation, error) + // DeleteUserPermission revokes permissions according query parameters + DeleteUserPermission(ctx context.Context, token, realm, ticketID string) error + // CreatePermission creates a permission associated with the client + CreatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) (*PermissionRepresentation, error) + // UpdatePermission updates a permission associated with the client + UpdatePermission(ctx context.Context, token, realm, idOfClient string, permission PermissionRepresentation) error + // DeletePermission deletes a policy associated with the client + DeletePermission(ctx context.Context, token, realm, idOfClient, permissionID string) error + // GetCredentialRegistrators returns credentials registrators + GetCredentialRegistrators(ctx context.Context, token, realm string) ([]string, error) + // GetConfiguredUserStorageCredentialTypes returns credential types, which are provided by the user storage where user is stored + GetConfiguredUserStorageCredentialTypes(ctx context.Context, token, realm, userID string) ([]string, error) + // GetCredentials returns credentials available for a given user + GetCredentials(ctx context.Context, token, realm, userID string) ([]*CredentialRepresentation, error) + // DeleteCredentials deletes the given credential for a given user + DeleteCredentials(ctx context.Context, token, realm, userID, credentialID string) error + // UpdateCredentialUserLabel updates label for the given credential for the given user + UpdateCredentialUserLabel(ctx context.Context, token, realm, userID, credentialID, userLabel string) error + // DisableAllCredentialsByType disables all credentials for a user of a specific type + DisableAllCredentialsByType(ctx context.Context, token, realm, userID string, types []string) error + // MoveCredentialBehind move a credential to a position behind another credential + MoveCredentialBehind(ctx context.Context, token, realm, userID, credentialID, newPreviousCredentialID string) error + // MoveCredentialToFirst move a credential to a first position in the credentials list of the user + MoveCredentialToFirst(ctx context.Context, token, realm, userID, credentialID string) error + // GetEvents returns events + GetEvents(ctx context.Context, token string, realm string, params GetEventsParams) ([]*EventRepresentation, error) + // GetClientScopesScopeMappingsRealmRolesAvailable returns realm-level roles that are available to attach to this client scope + GetClientScopesScopeMappingsRealmRolesAvailable(ctx context.Context, token, realm, clientScopeID string) ([]*Role, error) + // GetClientScopesScopeMappingsRealmRoles returns roles associated with a client-scope + GetClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string) ([]*Role, error) + // DeleteClientScopesScopeMappingsRealmRoles deletes realm-level roles from the client-scope + DeleteClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error + // CreateClientScopesScopeMappingsRealmRoles creates realm-level roles to the client scope + CreateClientScopesScopeMappingsRealmRoles(ctx context.Context, token, realm, clientScopeID string, roles []Role) error + // RegisterRequiredAction creates a required action for a given realm + RegisterRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error + // GetRequiredActions gets a list of required actions for a given realm + GetRequiredActions(ctx context.Context, token string, realm string) ([]*RequiredActionProviderRepresentation, error) + // GetRequiredAction gets a required action for a given realm + GetRequiredAction(ctx context.Context, token string, realm string, alias string) (*RequiredActionProviderRepresentation, error) + // UpdateRequiredAction updates a required action for a given realm + UpdateRequiredAction(ctx context.Context, token string, realm string, requiredAction RequiredActionProviderRepresentation) error + // DeleteRequiredAction updates a required action for a given realm + DeleteRequiredAction(ctx context.Context, token string, realm string, alias string) error + // CreateClientScopesScopeMappingsClientRoles attaches a client role to a client scope (not client's scope) + CreateClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error + // GetClientScopesScopeMappingsClientRolesAvailable returns available (i.e. not attached via + // CreateClientScopesScopeMappingsClientRoles) client roles for a specific client, for a client scope + // (not client's scope). + GetClientScopesScopeMappingsClientRolesAvailable(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) + // GetClientScopesScopeMappingsClientRoles returns attached client roles for a specific client, for a client scope + // (not client's scope). + GetClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string) ([]*Role, error) + // DeleteClientScopesScopeMappingsClientRoles removes attachment of client roles from a client scope + // (not client's scope). + DeleteClientScopesScopeMappingsClientRoles(ctx context.Context, token, realm, idOfClientScope, idOfClient string, roles []Role) error + // RevokeToken revokes the passed token. The token can either be an access or refresh token. + RevokeToken(ctx context.Context, realm, clientID, clientSecret, refreshToken string) error + // UpdateUsersManagementPermissions updates the management permissions for users + UpdateUsersManagementPermissions(ctx context.Context, accessToken, realm string, managementPermissions ManagementPermissionRepresentation) (*ManagementPermissionRepresentation, error) + // GetUsersManagementPermissions returns the management permissions for users + GetUsersManagementPermissions(ctx context.Context, accessToken, realm string) (*ManagementPermissionRepresentation, error) +} diff --git a/model_test.go b/model_test.go index d14acf60..1a5affcc 100644 --- a/model_test.go +++ b/model_test.go @@ -339,6 +339,6 @@ func TestStringerOmitEmpty(t *testing.T) { } for _, custom := range customs { - assert.Equal(t, "{}", custom.(Stringable).String()) + assert.Equal(t, "{}", custom.String()) } } diff --git a/run-tests.sh b/run-tests.sh index 57875f8e..f762b3eb 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -1,7 +1,7 @@ #!/bin/sh -docker-compose down -docker-compose up -d +docker compose down +docker compose up -d keycloakServer=http://localhost:8080 url="${keycloakServer}/health" @@ -23,4 +23,4 @@ fi go test -failfast -race -cover -coverprofile=coverage.out -covermode=atomic -p 10 -cpu 1,2 -bench . -benchmem ${ARGS[@]} -docker-compose down +docker compose down From f311a599d0b9dd12f13868ccd4178ee8c47f143b Mon Sep 17 00:00:00 2001 From: Simon Fuhrer Date: Tue, 5 Nov 2024 10:35:31 +0100 Subject: [PATCH 2/8] add GetRealmRoleGroups function (#486) --- client.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/client.go b/client.go index e2f2dfef..96090c7f 100644 --- a/client.go +++ b/client.go @@ -1291,6 +1291,22 @@ func (g *GoCloak) GetClientScopeMappings(ctx context.Context, token, realm, idOf return result, nil } +// GetRealmRoleGroups returns groups associated with the realm role +func (g *GoCloak) GetRealmRoleGroups(ctx context.Context, token, roleName, realm string) ([]*Group, error) { + const errMessage = "could not get groups by realm roleName" + + var result []*Group + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "roles", roleName, "groups")) + + if err = checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + // GetClientScopeMappingsRealmRoles returns realm-level roles associated with the client’s scope func (g *GoCloak) GetClientScopeMappingsRealmRoles(ctx context.Context, token, realm, idOfClient string) ([]*Role, error) { const errMessage = "could not get realm-level roles with the client’s scope" From f432da505df858b7e39bdbe6e71d9546901a7b47 Mon Sep 17 00:00:00 2001 From: Srivastav Nanduri Date: Tue, 5 Nov 2024 15:08:21 +0530 Subject: [PATCH 3/8] Add azp to introspect token result (#480) --- models.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models.go b/models.go index a093b233..788702bd 100644 --- a/models.go +++ b/models.go @@ -193,6 +193,7 @@ type IntroSpectTokenResult struct { AuthTime *int `json:"auth_time,omitempty"` Jti *string `json:"jti,omitempty"` Type *string `json:"typ,omitempty"` + Azp *string `json:"azp,omitempty"` } // User represents the Keycloak User Structure From cd7eeb8e9e3b6be9f28a5caec1909f70b4510f0a Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 5 Nov 2024 10:39:45 +0100 Subject: [PATCH 4/8] go fmt --- models.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models.go b/models.go index 788702bd..eb42c137 100644 --- a/models.go +++ b/models.go @@ -193,7 +193,7 @@ type IntroSpectTokenResult struct { AuthTime *int `json:"auth_time,omitempty"` Jti *string `json:"jti,omitempty"` Type *string `json:"typ,omitempty"` - Azp *string `json:"azp,omitempty"` + Azp *string `json:"azp,omitempty"` } // User represents the Keycloak User Structure From f6f314e818ed54ef7c429757d720fa9cd8fc917a Mon Sep 17 00:00:00 2001 From: Tobias Theel Date: Tue, 5 Nov 2024 10:41:54 +0100 Subject: [PATCH 5/8] nolint --- pkg/jwx/jwx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/jwx/jwx.go b/pkg/jwx/jwx.go index 8eeefada..8bbae255 100644 --- a/pkg/jwx/jwx.go +++ b/pkg/jwx/jwx.go @@ -109,7 +109,7 @@ func decodeRSAPublicKey(e, n *string) (*rsa.PublicKey, error) { return nil, errors.Wrap(err, errMessage) } - pKey := rsa.PublicKey{N: nInt, E: int(eInt)} + pKey := rsa.PublicKey{N: nInt, E: int(eInt)} //nolint return &pKey, nil } From 8f8cdf1e9dc62bf9f4e805dfa2a81cd8018c570c Mon Sep 17 00:00:00 2001 From: "Michael \"Miguel\" Alves" <127232498+michael-picpay@users.noreply.github.com> Date: Tue, 5 Nov 2024 06:43:44 -0300 Subject: [PATCH 6/8] adding client template fields (#487) * adding CLient template fields * revert removing import --- models.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/models.go b/models.go index eb42c137..205d811e 100644 --- a/models.go +++ b/models.go @@ -464,6 +464,7 @@ type Client struct { BearerOnly *bool `json:"bearerOnly,omitempty"` ClientAuthenticatorType *string `json:"clientAuthenticatorType,omitempty"` ClientID *string `json:"clientId,omitempty"` + ClientTemplate *string `json:"clientTemplate,omitempty"` ConsentRequired *bool `json:"consentRequired,omitempty"` DefaultClientScopes *[]string `json:"defaultClientScopes,omitempty"` DefaultRoles *[]string `json:"defaultRoles,omitempty"` @@ -490,6 +491,9 @@ type Client struct { ServiceAccountsEnabled *bool `json:"serviceAccountsEnabled,omitempty"` StandardFlowEnabled *bool `json:"standardFlowEnabled,omitempty"` SurrogateAuthRequired *bool `json:"surrogateAuthRequired,omitempty"` + UseTemplateConfig *bool `json:"useTemplateConfig,omitempty"` + UseTemplateMappers *bool `json:"useTemplateMappers,omitempty"` + UseTemplateScope *bool `json:"useTemplateScope,omitempty"` WebOrigins *[]string `json:"webOrigins,omitempty"` } From d77c7889c3af9633a22eef7b8e2e87c585e07537 Mon Sep 17 00:00:00 2001 From: Nicholas Thompson Date: Tue, 5 Nov 2024 11:44:11 +0200 Subject: [PATCH 7/8] Add support for get client scope permissions (#490) Add the permissions request for a client scope --- client.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/client.go b/client.go index 96090c7f..42a593f2 100644 --- a/client.go +++ b/client.go @@ -3740,6 +3740,21 @@ func (g *GoCloak) GetPermissionResources(ctx context.Context, token, realm, idOf return result, nil } +// GetScopePermissions returns permissions associated with the client scope +func (g *GoCloak) GetScopePermissions(ctx context.Context, token, realm, idOfClient, idOfScope string) ([]*PolicyRepresentation, error) { + const errMessage = "could not get scope permissions" + + var result []*PolicyRepresentation + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "clients", idOfClient, "authz", "resource-server", "scope", idOfScope, "permissions")) + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + // GetPermissionScopes returns a client's scopes configured for the given permission id func (g *GoCloak) GetPermissionScopes(ctx context.Context, token, realm, idOfClient, permissionID string) ([]*PermissionScope, error) { const errMessage = "could not get permission scopes" From 8867dd15fd3fe9ba155548bc037bad1be78b6b7a Mon Sep 17 00:00:00 2001 From: Surasith Date: Tue, 5 Nov 2024 16:44:30 +0700 Subject: [PATCH 8/8] feat: get child groups and get unregistered required actions (#484) * chore: update keycloak image version and fix docker compose * feat: get child groups * docs: update readme * chore: update health check endpoint * chore: update docker compose * test: update tests to be compatible with KC 25 * feat: get unregisterd required actions * test: update test create and get required action * feat: get child group params * docs: update readme --------- Co-authored-by: Nerzal --- Dockerfile | 5 ++- README.md | 1 + client.go | 39 ++++++++++++++++++++ client_test.go | 91 ++++++++++++++++++++++++++++++++++------------ docker-compose.yml | 9 +++-- models.go | 14 +++++++ run-tests.sh | 6 +-- 7 files changed, 132 insertions(+), 33 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1590f824..6ae473d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/keycloak/keycloak:19.0 +FROM quay.io/keycloak/keycloak:25.0.1 COPY testdata data/import WORKDIR /opt/keycloak ENV KC_HOSTNAME=localhost @@ -6,6 +6,7 @@ ENV KEYCLOAK_USER=admin ENV KEYCLOAK_PASSWORD=secret ENV KEYCLOAK_ADMIN=admin ENV KEYCLOAK_ADMIN_PASSWORD=secret -ENV KC_FEATURES=account-api,account2,authorization,client-policies,impersonation,docker,scripts,upload_scripts,admin-fine-grained-authz +ENV KC_HEALTH_ENABLED=true +ENV KC_FEATURES=account-api,account3,authorization,client-policies,impersonation,docker,scripts,admin-fine-grained-authz RUN /opt/keycloak/bin/kc.sh import --file /data/import/gocloak-realm.json ENTRYPOINT ["/opt/keycloak/bin/kc.sh"] diff --git a/README.md b/README.md index 6eb6b687..0138cc78 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ To get the `clientId` from `id`, use `GetClients` method with `GetClientsParams{ [GoCloakIface](gocloak_iface.go) holds all methods a client should fulfil. + ## Configure gocloak to skip TLS Insecure Verification ```go diff --git a/client.go b/client.go index 42a593f2..b6d47efe 100644 --- a/client.go +++ b/client.go @@ -1719,6 +1719,28 @@ func (g *GoCloak) GetGroup(ctx context.Context, token, realm, groupID string) (* return &result, nil } +// GetChildGroups get child groups of group with id in realm +func (g *GoCloak) GetChildGroups(ctx context.Context, token, realm, groupID string, params GetChildGroupsParams) ([]*Group, error) { + const errMessage = "could not get child groups" + + var result []*Group + queryParams, err := GetQueryParams(params) + if err != nil { + return nil, errors.Wrap(err, errMessage) + } + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + SetQueryParams(queryParams). + Get(g.getAdminRealmURL(realm, "groups", groupID, "children")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + // GetGroupByPath get group with path in realm func (g *GoCloak) GetGroupByPath(ctx context.Context, token, realm, groupPath string) (*Group, error) { const errMessage = "could not get group" @@ -4194,6 +4216,23 @@ func (g *GoCloak) RegisterRequiredAction(ctx context.Context, token string, real return err } +// GetUnregisteredRequiredActions gets a list of unregistered required actions for a given realm +func (g *GoCloak) GetUnregisteredRequiredActions(ctx context.Context, token string, realm string) ([]*UnregisteredRequiredActionProviderRepresentation, error) { + const errMessage = "could not get unregistered required actions" + + var result []*UnregisteredRequiredActionProviderRepresentation + + resp, err := g.GetRequestWithBearerAuth(ctx, token). + SetResult(&result). + Get(g.getAdminRealmURL(realm, "authentication", "unregistered-required-actions")) + + if err := checkForError(resp, err, errMessage); err != nil { + return nil, err + } + + return result, nil +} + // GetRequiredActions gets a list of required actions for a given realm func (g *GoCloak) GetRequiredActions(ctx context.Context, token string, realm string) ([]*RequiredActionProviderRepresentation, error) { const errMessage = "could not get required actions" diff --git a/client_test.go b/client_test.go index 05f78718..cf50285a 100644 --- a/client_test.go +++ b/client_test.go @@ -820,7 +820,7 @@ func Test_LoginClient_UnknownRealm(t *testing.T) { cfg.GoCloak.ClientSecret, "ThisRealmDoesNotExist") require.Error(t, err, "Login shouldn't be successful") - require.EqualError(t, err, "404 Not Found: Realm does not exist") + require.EqualError(t, err, "404 Not Found: Realm does not exist: For more on this error consult the server log at the debug level.") } func Test_GetIssuer(t *testing.T) { @@ -1410,8 +1410,9 @@ func CreateClientScope(t *testing.T, client gocloak.GoCloakIface, scope *gocloak if scope == nil { scope = &gocloak.ClientScope{ - ID: GetRandomNameP("client-scope-id-"), - Name: GetRandomNameP("client-scope-name-"), + ID: GetRandomNameP("client-scope-id-"), + Name: GetRandomNameP("client-scope-name-"), + Protocol: gocloak.StringP("openid-connect"), } } @@ -1422,10 +1423,10 @@ func CreateClientScope(t *testing.T, client gocloak.GoCloakIface, scope *gocloak cfg.GoCloak.Realm, *scope, ) + require.NoError(t, err, "CreateClientScope failed") if !gocloak.NilOrEmpty(scope.ID) { require.Equal(t, clientScopeID, *scope.ID) } - require.NoError(t, err, "CreateClientScope failed") tearDown := func() { err := client.DeleteClientScope( context.Background(), @@ -2427,6 +2428,40 @@ func Test_GetGroupFull(t *testing.T) { require.True(t, ok, "UserAttributeContains") } +func Test_GetChildGroups(t *testing.T) { + t.Parallel() + cfg := GetConfig(t) + client := NewClientWithDebug(t) + token := GetAdminToken(t, client) + + tearDown, groupID := CreateGroup(t, client) + defer tearDown() + + childGroupIDs := []string{} + for i := 0; i < 3; i++ { + childGroupID, err := client.CreateChildGroup(context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + groupID, + gocloak.Group{ + Name: GetRandomNameP("Group"), + }, + ) + require.NoError(t, err, "CreateChildGroup failed") + childGroupIDs = append(childGroupIDs, childGroupID) + } + + childGroups, err := client.GetChildGroups( + context.Background(), + token.AccessToken, + cfg.GoCloak.Realm, + groupID, + gocloak.GetChildGroupsParams{}, + ) + require.NoError(t, err, "GetChildGroups failed") + require.Len(t, childGroups, len(childGroupIDs)) +} + func Test_GetGroupMembers(t *testing.T) { t.Parallel() cfg := GetConfig(t) @@ -2604,10 +2639,10 @@ func Test_SendVerifyEmail(t *testing.T) { cfg.GoCloak.Realm, params) if err != nil { - if err.Error() == "500 Internal Server Error: Failed to send execute actions email" { + if err.Error() == "500 Internal Server Error: Failed to send verify email" { return } - require.NoError(t, err, "ExecuteActionsEmail failed") + require.NoError(t, err, "SendVerifyEmail failed") } } @@ -4830,7 +4865,7 @@ func Test_CreateDeleteClientScopeWithMappers(t *testing.T) { cfg.GoCloak.Realm, id, ) - require.EqualError(t, err, "404 Not Found: Could not find client scope") + require.EqualError(t, err, "404 Not Found: Could not find client scope: For more on this error consult the server log at the debug level.") require.Nil(t, clientScopeActual, "client scope has not been deleted") } @@ -5749,8 +5784,8 @@ func Test_GetAuthorizationPolicyScopes(t *testing.T) { require.Equal(t, *scopes[0].ID, scopeID) defer func() { - scope() policy() + scope() }() } @@ -6421,7 +6456,7 @@ func Test_CheckError(t *testing.T) { expectedError := &gocloak.APIError{ Code: http.StatusNotFound, - Message: "404 Not Found: Could not find client", + Message: "404 Not Found: Could not find client: For more on this error consult the server log at the debug level.", Type: gocloak.APIErrTypeUnknown, } @@ -6606,13 +6641,14 @@ func Test_ImportIdentityProviderConfig(t *testing.T) { require.NoError(t, err, "ImportIdentityProviderConfig failed") expected := map[string]string{ - "userInfoUrl": "https://openidconnect.googleapis.com/v1/userinfo", - "validateSignature": "true", - "tokenUrl": "https://oauth2.googleapis.com/token", - "authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth", - "jwksUrl": "https://www.googleapis.com/oauth2/v3/certs", - "issuer": "https://accounts.google.com", - "useJwksUrl": "true", + "userInfoUrl": "https://openidconnect.googleapis.com/v1/userinfo", + "validateSignature": "true", + "tokenUrl": "https://oauth2.googleapis.com/token", + "authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth", + "jwksUrl": "https://www.googleapis.com/oauth2/v3/certs", + "issuer": "https://accounts.google.com", + "useJwksUrl": "true", + "metadataDescriptorUrl": "https://accounts.google.com/.well-known/openid-configuration", } require.Len( @@ -6687,6 +6723,7 @@ E8go1LcvbfHNyknHu2sptnRq55fHZSHr18vVsQRfDYMG "loginHint": "false", "enabledFromMetadata": "true", "idpEntityId": "https://accounts.google.com/o/saml2?idpid=C01unc9st", + "syncMode": "LEGACY", } require.Len( @@ -6871,16 +6908,22 @@ func TestGocloak_CreateAndGetRequiredAction(t *testing.T) { cfg := GetConfig(t) client := NewClientWithDebug(t) token := GetAdminToken(t, client) + + // need to get unregistered required actions first + // refer to test suit of Keycloak for more details + // https://github.com/keycloak/keycloak/blob/main/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/RequiredActionsTest.java#L93 + unregisteredRequiredActions, err := client.GetUnregisteredRequiredActions(context.Background(), token.AccessToken, cfg.GoCloak.Realm) + require.NoError(t, err, "Failed to get required actions") + require.NotEmpty(t, unregisteredRequiredActions, "Required actions must not be empty") + require.NotNil(t, unregisteredRequiredActions[0].Name, "Required action name must not be nil") + require.NotNil(t, unregisteredRequiredActions[0].ProviderID, "Required action alias must not be nil") + requiredAction := gocloak.RequiredActionProviderRepresentation{ - Alias: gocloak.StringP("VERIFY_EMAIL_NEW"), - Config: nil, - DefaultAction: gocloak.BoolP(false), - Enabled: gocloak.BoolP(true), - Name: gocloak.StringP("Verify Email new"), - Priority: gocloak.Int32P(50), - ProviderID: gocloak.StringP("VERIFY_EMAIL_NEW"), + Alias: unregisteredRequiredActions[0].ProviderID, + Name: unregisteredRequiredActions[0].Name, + ProviderID: unregisteredRequiredActions[0].ProviderID, } - err := client.RegisterRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, requiredAction) + err = client.RegisterRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, requiredAction) require.NoError(t, err, "Failed to register required action") ra, err := client.GetRequiredAction(context.Background(), token.AccessToken, cfg.GoCloak.Realm, *requiredAction.Alias) diff --git a/docker-compose.yml b/docker-compose.yml index 01bdf32d..c467aad6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,4 @@ +version: "3" services: keycloak: build: . @@ -10,12 +11,12 @@ services: KC_HEALTH_ENABLED: "true" ports: - "8080:8080" + - "9000:9000" healthcheck: - test: curl --fail --silent http://localhost:8080/health/ready 2>&1 || exit 1 + test: curl --fail --silent http://localhost:9000/health/ready 2>&1 || exit 1 interval: 10s timeout: 10s retries: 5 volumes: - - ./testdata/gocloak-realm.json:/opt/keycloak/data/import/gocloak-realm.json - entrypoint: ["/opt/keycloak/bin/kc.sh", "start-dev --features=preview --import-realm"] - \ No newline at end of file + - ./testdata/gocloak-realm.json:/opt/keycloak/data/import/gocloak-realm.json + entrypoint: ["/opt/keycloak/bin/kc.sh", "start-dev", "--features=preview", "--import-realm"] diff --git a/models.go b/models.go index 205d811e..ccab7ad8 100644 --- a/models.go +++ b/models.go @@ -352,6 +352,15 @@ type GetGroupsParams struct { Search *string `json:"search,omitempty"` } +// GetChildGroupsParams represents the optional parameters for getting child groups +type GetChildGroupsParams struct { + BriefRepresentation *bool `json:"briefRepresentation,string,omitempty"` + Exact *bool `json:"exact,string,omitempty"` + First *int `json:"first,string,omitempty"` + Max *int `json:"max,string,omitempty"` + Search *string `json:"search,omitempty"` +} + // MarshalJSON is a custom json marshaling function to automatically set the Full and BriefRepresentation properties // for backward compatibility func (obj GetGroupsParams) MarshalJSON() ([]byte, error) { @@ -1416,6 +1425,11 @@ type RequiredActionProviderRepresentation struct { ProviderID *string `json:"providerId,omitempty"` } +type UnregisteredRequiredActionProviderRepresentation struct { + Name *string `json:"name,omitempty"` + ProviderID *string `json:"providerId,omitempty"` +} + // ManagementPermissionRepresentation is a representation of management permissions // v18: https://www.keycloak.org/docs-api/18.0/rest-api/#_managementpermissionreference type ManagementPermissionRepresentation struct { diff --git a/run-tests.sh b/run-tests.sh index f762b3eb..2ae0632e 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -3,8 +3,8 @@ docker compose down docker compose up -d -keycloakServer=http://localhost:8080 -url="${keycloakServer}/health" +keycloakServer=http://localhost +url="${keycloakServer}:9000/health" echo "Checking service availability at $url (CTRL+C to exit)" while true; do response=$(curl -s -o /dev/null -w "%{http_code}" $url) @@ -13,7 +13,7 @@ while true; do fi sleep 1 done -echo "Service is now available at ${keycloakServer}" +echo "Service is now available at ${keycloakServer}:8080" ARGS=() if [ $# -gt 0 ]; then