Repository: Nerzal/gocloak
Pull request #480 (2024-08-05 10:49:01)

Add azp to introspect token result
This adds the `azp` claim into the introspection result so clients can use this to get the requestor client ID to be used further down in the code


Patch:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 4ad47cb..0131c2d 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 9dc4aac..e838335 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 d59a6c3..d5d49ce 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 0409e81..b32a0b5 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 6f4d7c0..6eb6b68 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 ccff45f..96090c7 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 = "/"
@@ -1288,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"
diff --git a/docker-compose.yml b/docker-compose.yml
index b422ddb..01bdf32 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 cde0112..7af6422 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 86853e2..d9d6167 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 0000000..be49353
--- /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/models.go b/models.go
index a093b23..788702b 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


Test patch:
diff --git a/client_test.go b/client_test.go
index 0cda97c..05f7871 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/model_test.go b/model_test.go
index d14acf6..1a5affc 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 57875f8..f762b3e 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