diff --git a/Keycloak.Net.Core.sln b/Keycloak.Net.Core.sln index d47406a0..016f7f4b 100644 --- a/Keycloak.Net.Core.sln +++ b/Keycloak.Net.Core.sln @@ -7,11 +7,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A56F65F6 ProjectSection(SolutionItems) = preProject build\build.ps1 = build\build.ps1 build\test.ps1 = build\test.ps1 + build\start-keycloak.sh = build\start-keycloak.sh EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{04ECC844-41D5-4A2B-85F1-DA1E3B3C58B3}" ProjectSection(SolutionItems) = preProject - test\insurance-realm-export.json = test\insurance-realm-export.json + test\keycloak-net-fixture-realm-export.json = test\keycloak-net-fixture-realm-export.json EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{46B1B298-8884-4FE7-831D-FBCA62E10A72}" diff --git a/README.md b/README.md index c919b473..6910c342 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ * changed ClientConfig to Dictionary * removed signing * .NET 8 and .NET 10 support only - * updated for keycloak version 25+ + * updated for keycloak version 26+ * added support for changing default `AdminClientId` which has default `admin-cli` value * added support for System.Text.Json in replacement of NewtonsoftJson. @@ -34,9 +34,9 @@ ); ``` -C# client for [Keycloak](https://www.keycloak.org/) 6.x +C# client for [Keycloak](https://www.keycloak.org/) 26.x -See documentation at [https://www.keycloak.org/docs-api/6.0/rest-api/](https://www.keycloak.org/docs-api/6.0/rest-api/) +See documentation at [https://www.keycloak.org/docs-api/latest/rest-api/](https://www.keycloak.org/docs-api/latest/rest-api/) ## Features * [X] Attack Detection @@ -63,8 +63,20 @@ See documentation at [https://www.keycloak.org/docs-api/6.0/rest-api/](https://w ## Testing -In order to run the tests, all it's needed is to have a running instance of Keycloak with (preferably) the `master` realm credentials admin/admin (as it's currently configured in the `/test/Keycloak.Net.Core.Tests/appsettings.json`) and create a new realm `Insurance` by importing the file in `/test/insurance-real-export.json`, which also has its admin user with the same credentials as mentioned before. +The easiest way to run the tests is to use the fixture launcher: -Then it's just as easy as running the tests. +```bash +./build/start-keycloak.sh --test --auto-cleanup +``` -If for some reason you want to change the credentials, you need to make sure both realms have the same user and password as the tests use the same credentials for both `master` and `Insurance` realms. \ No newline at end of file +This starts Keycloak 26.7.0 in Docker, imports `/test/keycloak-net-fixture-realm-export.json`, runs the tests, and removes the container when the run completes. + +To start the fixture server without running tests: + +```bash +./build/start-keycloak.sh +``` + +The fixture realm is `keycloak-net-fixture`. The tests use the credentials in `/test/Keycloak.Net.Core.Tests/appsettings.json`; the fixture export includes the matching realm admin user. + +If you prefer to run Keycloak manually, import `/test/keycloak-net-fixture-realm-export.json` into a Keycloak 26.7.0 instance before running the tests. The imported realm must be available at `keycloak-net-fixture`, and the credentials in `/test/Keycloak.Net.Core.Tests/appsettings.json` must match the realm admin user included in the export. diff --git a/build/start-keycloak.sh b/build/start-keycloak.sh new file mode 100755 index 00000000..842e0a54 --- /dev/null +++ b/build/start-keycloak.sh @@ -0,0 +1,172 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +CONTAINER_NAME="${KEYCLOAK_CONTAINER_NAME:-keycloak-net-tests}" +KEYCLOAK_VERSION="${KEYCLOAK_VERSION:-26.7.0}" +KEYCLOAK_IMAGE="${KEYCLOAK_IMAGE:-quay.io/keycloak/keycloak:${KEYCLOAK_VERSION}}" +KEYCLOAK_PORT="${KEYCLOAK_PORT:-8080}" +KEYCLOAK_ADMIN="${KEYCLOAK_ADMIN:-admin}" +KEYCLOAK_ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD:-admin}" +REALM_EXPORT="${REALM_EXPORT:-${ROOT_DIR}/test/keycloak-net-fixture-realm-export.json}" +TEST_TARGET="${TEST_TARGET:-${ROOT_DIR}/Keycloak.Net.Core.sln}" +AUTO_CLEANUP=0 +RUN_TESTS=0 +DOTNET_TEST_ARGS=() + +usage() { + cat </dev/null 2>&1; then + echo "Docker is required to run the Keycloak integration tests." >&2 + exit 1 +fi + +if [[ "$RUN_TESTS" -eq 1 ]] && ! command -v dotnet >/dev/null 2>&1; then + echo ".NET SDK is required to run the test project." >&2 + exit 1 +fi + +if [[ "$RUN_TESTS" -eq 0 && "${#DOTNET_TEST_ARGS[@]}" -gt 0 ]]; then + echo "dotnet test arguments were provided, but --test was not specified." >&2 + echo "Use: build/start-keycloak.sh --test -- ${DOTNET_TEST_ARGS[*]}" >&2 + exit 1 +fi + +if [[ ! -f "$REALM_EXPORT" ]]; then + echo "Realm export not found: $REALM_EXPORT" >&2 + exit 1 +fi + +cleanup() { + local exit_code=$? + + docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true + exit "$exit_code" +} + +wait_for_interrupt() { + echo "Press Ctrl-C to stop Keycloak and remove the container." + + while true; do + sleep 1 + done +} + +wait_for_keycloak() { + local url="http://localhost:${KEYCLOAK_PORT}/realms/master" + local retries=120 + + echo "Waiting for Keycloak at $url" + + for ((attempt = 1; attempt <= retries; attempt++)); do + if curl --fail --silent --output /dev/null "$url"; then + echo "Keycloak is ready." + return 0 + fi + + sleep 1 + done + + echo "Keycloak did not become ready within ${retries}s." >&2 + docker logs "$CONTAINER_NAME" >&2 || true + return 1 +} + +trap cleanup EXIT +trap 'exit 130' INT +trap 'exit 143' TERM + +docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true + +echo "Starting Keycloak ${KEYCLOAK_IMAGE} on port ${KEYCLOAK_PORT}" + +docker run \ + --detach \ + --name "$CONTAINER_NAME" \ + --publish "${KEYCLOAK_PORT}:8080" \ + --env KEYCLOAK_ADMIN="$KEYCLOAK_ADMIN" \ + --env KEYCLOAK_ADMIN_PASSWORD="$KEYCLOAK_ADMIN_PASSWORD" \ + --volume "${REALM_EXPORT}:/opt/keycloak/data/import/keycloak-net-fixture-realm-export.json:ro" \ + "$KEYCLOAK_IMAGE" \ + start-dev --features=admin-fine-grained-authz:v1 --import-realm >/dev/null + +wait_for_keycloak + +echo "Keycloak is running at http://localhost:${KEYCLOAK_PORT}" + +if [[ "$RUN_TESTS" -eq 1 ]]; then + test_exit_code=0 + + if ((${#DOTNET_TEST_ARGS[@]})); then + echo "Running tests: dotnet test ${TEST_TARGET} ${DOTNET_TEST_ARGS[*]}" + dotnet test "$TEST_TARGET" "${DOTNET_TEST_ARGS[@]}" || test_exit_code=$? + else + echo "Running tests: dotnet test ${TEST_TARGET}" + dotnet test "$TEST_TARGET" || test_exit_code=$? + fi + + if [[ "$AUTO_CLEANUP" -eq 0 ]]; then + wait_for_interrupt + fi + + exit "$test_exit_code" +else + if [[ "$AUTO_CLEANUP" -eq 0 ]]; then + wait_for_interrupt + fi +fi diff --git a/src/Keycloak.Net.Core/Models/Root/Category.cs b/src/Keycloak.Net.Core/Models/Root/Category.cs index 5f8118ac..caa295cd 100644 --- a/src/Keycloak.Net.Core/Models/Root/Category.cs +++ b/src/Keycloak.Net.Core/Models/Root/Category.cs @@ -20,4 +20,6 @@ public enum Category NameIdMapper, [EnumMember(Value = "Audience mapper")] AudienceMapper, -} \ No newline at end of file + [EnumMember(Value = "AuthnContextClassRef mapper")] + AuthnContextClassRefMapper, +} diff --git a/src/Keycloak.Net.Core/Models/Root/Locale.cs b/src/Keycloak.Net.Core/Models/Root/Locale.cs index 124934cf..a3235463 100644 --- a/src/Keycloak.Net.Core/Models/Root/Locale.cs +++ b/src/Keycloak.Net.Core/Models/Root/Locale.cs @@ -21,6 +21,8 @@ public enum Locale Fi, Hr, Hu, + Hy, + Id, It, Ja, Kk, @@ -42,6 +44,7 @@ public enum Locale Th, Tr, Uk, + Vi, [EnumMember(Value = "zh-CN")] ZhCn, [EnumMember(Value = "zh-TW")] diff --git a/src/Keycloak.Net.Core/RealmsAdmin/KeycloakClient.cs b/src/Keycloak.Net.Core/RealmsAdmin/KeycloakClient.cs index ecf0666a..0bd9723f 100644 --- a/src/Keycloak.Net.Core/RealmsAdmin/KeycloakClient.cs +++ b/src/Keycloak.Net.Core/RealmsAdmin/KeycloakClient.cs @@ -265,7 +265,7 @@ public async Task UpdateRealmEventsProviderConfigurationAsync(string realm public async Task GetRealmGroupByPathAsync(string realm, string path, CancellationToken cancellationToken = default) => - await GetBaseUrl(realm).AppendPathSegment($"/admin/realms/{realm}/group-by-path/{path}") + await GetBaseUrl(realm).AppendPathSegment($"/admin/realms/{realm}/group-by-path/{path.TrimStart('/')}") .GetJsonAsync(cancellationToken: cancellationToken) .ConfigureAwait(false); @@ -371,4 +371,4 @@ await GetBaseUrl(realm).AppendPathSegment($"/admin/realms/{realm}/users-manageme .PutJsonAsync(managementPermission, cancellationToken: cancellationToken) .ReceiveJson() .ConfigureAwait(false); -} \ No newline at end of file +} diff --git a/test/Keycloak.Net.Core.Tests/AttackDetection/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/AttackDetection/KeycloakClientShould.cs index 336275c2..4c505e52 100644 --- a/test/Keycloak.Net.Core.Tests/AttackDetection/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/AttackDetection/KeycloakClientShould.cs @@ -6,17 +6,18 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("Insurance", "vermeulen")] - public async Task GetUserNameStatusInBruteForceDetectionAsync(string realm, string search) + [Fact] + public async Task GetUserNameStatusInBruteForceDetectionAsync() { - var users = await _client.GetUsersAsync(realm, search: search).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetUserNameStatusInBruteForceDetectionAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUserNameStatusInBruteForceDetectionAsync(realm, userId); + + Assert.Equal(0, result.NumFailures); + Assert.False(result.Disabled); + Assert.Equal(0, result.LastFailure); + Assert.Equal("n/a", result.LastIpFailure); } } } diff --git a/test/Keycloak.Net.Core.Tests/AuthenticationManagement/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/AuthenticationManagement/KeycloakClientShould.cs index f635cc30..d8054fab 100644 --- a/test/Keycloak.Net.Core.Tests/AuthenticationManagement/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/AuthenticationManagement/KeycloakClientShould.cs @@ -6,150 +6,169 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetAuthenticatorProvidersAsync(string realm) + [Fact] + public async Task GetAuthenticatorProvidersAsync() { - var result = await _client.GetAuthenticatorProvidersAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetAuthenticatorProvidersAsync(realm); + var providerIds = result.Select(x => x["id"].ToString()).ToArray(); + + Assert.Contains("auth-cookie", providerIds); + Assert.Contains("auth-password-form", providerIds); } - [Theory] - [InlineData("master")] - public async Task GetClientAuthenticatorProvidersAsync(string realm) + [Fact] + public async Task GetClientAuthenticatorProvidersAsync() { - var result = await _client.GetClientAuthenticatorProvidersAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetClientAuthenticatorProvidersAsync(realm); + var providerIds = result.Select(x => x["id"].ToString()).ToArray(); + + Assert.Contains("client-secret", providerIds); + Assert.Contains("client-jwt", providerIds); } - [Theory] - [InlineData("master")] - public async Task GetAuthenticatorProviderConfigurationDescriptionAsync(string realm) + [Fact] + public async Task GetAuthenticatorProviderConfigurationDescriptionAsync() { - var providers = await _client.GetAuthenticatorProvidersAsync(realm).ConfigureAwait(false); - string providerId = providers.FirstOrDefault()?.FirstOrDefault(x => x.Key == "id").Value.ToString(); - if (providerId != null) - { - var result = await _client.GetAuthenticatorProviderConfigurationDescriptionAsync(realm, providerId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetAuthenticatorProviderConfigurationDescriptionAsync(realm, "auth-cookie"); + + Assert.Equal("auth-cookie", result.ProviderId); + Assert.Equal("Cookie", result.Name); } - [Theory(Skip = "Not working yet")] - [InlineData("master")] - public async Task GetAuthenticatorConfigurationAsync(string realm) + [Fact(Skip = "Requires a configured authenticator configuration ID to be meaningfully tested.")] + public async Task GetAuthenticatorConfigurationAsync() { + var realm = KeycloakTestFixture.Realm; string configurationId = ""; //TODO if (configurationId != null) { - var result = await _client.GetAuthenticatorConfigurationAsync(realm, configurationId).ConfigureAwait(false); + var result = await _client.GetAuthenticatorConfigurationAsync(realm, configurationId); Assert.NotNull(result); } } - [Theory] - [InlineData("master")] - public async Task GetAuthenticationExecutionAsync(string realm) + [Fact] + public async Task GetAuthenticationExecutionAsync() { - var flows = await _client.GetAuthenticationFlowsAsync(realm).ConfigureAwait(false); - string flowAlias = flows.FirstOrDefault()?.Alias; - if (flowAlias != null) - { - var executions = await _client.GetAuthenticationFlowExecutionsAsync(realm, flowAlias).ConfigureAwait(false); - string executionId = executions.FirstOrDefault()?.Id; - if (executionId != null) - { - var result = await _client.GetAuthenticationExecutionAsync(realm, executionId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var executions = await _client.GetAuthenticationFlowExecutionsAsync(realm, "browser"); + var executionId = executions.Single(x => x.ProviderId == "auth-cookie").Id; + + var result = await _client.GetAuthenticationExecutionAsync(realm, executionId); + + Assert.Equal(executionId, result.Id); + Assert.Equal("auth-cookie", result.Authenticator); + Assert.Equal("ALTERNATIVE", result.Requirement); } - [Theory] - [InlineData("master")] - public async Task GetAuthenticationFlowsAsync(string realm) + [Fact] + public async Task GetAuthenticationFlowsAsync() { - var result = await _client.GetAuthenticationFlowsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetAuthenticationFlowsAsync(realm); + var aliases = result.Select(x => x.Alias).ToArray(); + + Assert.Contains("browser", aliases); + Assert.Contains("direct grant", aliases); } - [Theory] - [InlineData("master")] - public async Task GetAuthenticationFlowExecutionsAsync(string realm) + [Fact] + public async Task GetAuthenticationFlowExecutionsAsync() { - var flows = await _client.GetAuthenticationFlowsAsync(realm).ConfigureAwait(false); - string flowAlias = flows.FirstOrDefault()?.Alias; - if (flowAlias != null) - { - var result = await _client.GetAuthenticationFlowExecutionsAsync(realm, flowAlias).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetAuthenticationFlowExecutionsAsync(realm, "browser"); + var providerIds = result.Select(x => x.ProviderId).ToArray(); + + Assert.Contains("auth-cookie", providerIds); + Assert.Contains("auth-username-password-form", providerIds); } - [Theory] - [InlineData("master")] - public async Task GetAuthenticationFlowByIdAsync(string realm) + [Fact] + public async Task GetAuthenticationFlowByIdAsync() { - var flows = await _client.GetAuthenticationFlowsAsync(realm).ConfigureAwait(false); - string flowId = flows.FirstOrDefault()?.Id; - if (flowId != null) - { - var result = await _client.GetAuthenticationFlowByIdAsync(realm, flowId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var flows = await _client.GetAuthenticationFlowsAsync(realm); + var flowId = flows.Single(x => x.Alias == "browser").Id; + + var result = await _client.GetAuthenticationFlowByIdAsync(realm, flowId); + + Assert.Equal(flowId, result.Id); + Assert.Equal("browser", result.Alias); + Assert.Equal("basic-flow", result.ProviderId); } - [Theory] - [InlineData("master")] - public async Task GetFormActionProvidersAsync(string realm) + [Fact] + public async Task GetFormActionProvidersAsync() { - var result = await _client.GetFormActionProvidersAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetFormActionProvidersAsync(realm); + var providerIds = result.Select(x => x["id"].ToString()).ToArray(); + + Assert.Contains("registration-user-creation", providerIds); } - [Theory] - [InlineData("master")] - public async Task GetFormProvidersAsync(string realm) + [Fact] + public async Task GetFormProvidersAsync() { - var result = await _client.GetFormProvidersAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetFormProvidersAsync(realm); + var providerIds = result.Select(x => x["id"].ToString()).ToArray(); + + Assert.Contains("registration-page-form", providerIds); } - [Theory] - [InlineData("master")] - public async Task GetConfigurationDescriptionsForAllClientsAsync(string realm) + [Fact] + public async Task GetConfigurationDescriptionsForAllClientsAsync() { - var result = await _client.GetConfigurationDescriptionsForAllClientsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetConfigurationDescriptionsForAllClientsAsync(realm); + + Assert.Contains("client-secret", result.Keys); + Assert.Contains("client-jwt", result.Keys); } - [Theory] - [InlineData("master")] - public async Task GetRequiredActionsAsync(string realm) + [Fact] + public async Task GetRequiredActionsAsync() { - var result = await _client.GetRequiredActionsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRequiredActionsAsync(realm); + var aliases = result.Select(x => x.Alias).ToArray(); + + Assert.Contains("UPDATE_PASSWORD", aliases); + Assert.Contains("VERIFY_EMAIL", aliases); } - [Theory] - [InlineData("master")] - public async Task GetRequiredActionByAliasAsync(string realm) + [Fact] + public async Task GetRequiredActionByAliasAsync() { - var requiredActions = await _client.GetRequiredActionsAsync(realm).ConfigureAwait(false); - string requiredActionAlias = requiredActions.FirstOrDefault()?.Alias; - if (requiredActionAlias != null) - { - var result = await _client.GetRequiredActionByAliasAsync(realm, requiredActionAlias).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRequiredActionByAliasAsync(realm, "UPDATE_PASSWORD"); + + Assert.Equal("UPDATE_PASSWORD", result.Alias); + Assert.True(result.Enabled); } - [Theory] - [InlineData("master")] - public async Task GetUnregisteredRequiredActionsAsync(string realm) + [Fact] + public async Task GetUnregisteredRequiredActionsAsync() { - var result = await _client.GetUnregisteredRequiredActionsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetUnregisteredRequiredActionsAsync(realm); + + Assert.Empty(result); } } } diff --git a/test/Keycloak.Net.Core.Tests/ClientAttributeCertificate/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/ClientAttributeCertificate/KeycloakClientShould.cs index 5d069a46..8ffd8838 100644 --- a/test/Keycloak.Net.Core.Tests/ClientAttributeCertificate/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/ClientAttributeCertificate/KeycloakClientShould.cs @@ -6,20 +6,16 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetKeyInfoAsync(string realm) + [Fact] + public async Task GetKeyInfoAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - (string clientId, string attribute) = clients - .Where(x => x.Attributes.Any()) - .Select(client => (client.Id, client.Attributes.FirstOrDefault().Key)) - .FirstOrDefault(); - if (clientId != null) - { - var result = await _client.GetKeyInfoAsync(realm, clientId, attribute).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetKeyInfoAsync(realm, clientUuid, "jwt.credential"); + + Assert.Null(result.Kid); + Assert.Null(result._Certificate); } } } diff --git a/test/Keycloak.Net.Core.Tests/ClientInitialAccess/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/ClientInitialAccess/KeycloakClientShould.cs index f8ecf49b..224fe9b2 100644 --- a/test/Keycloak.Net.Core.Tests/ClientInitialAccess/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/ClientInitialAccess/KeycloakClientShould.cs @@ -5,12 +5,14 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetClientInitialAccessAsync(string realm) + [Fact] + public async Task GetClientInitialAccessAsync() { - var result = await _client.GetClientInitialAccessAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetClientInitialAccessAsync(realm); + + Assert.Empty(result); } } } diff --git a/test/Keycloak.Net.Core.Tests/ClientRegistrationPolicy/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/ClientRegistrationPolicy/KeycloakClientShould.cs index f5515a3b..00b833c7 100644 --- a/test/Keycloak.Net.Core.Tests/ClientRegistrationPolicy/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/ClientRegistrationPolicy/KeycloakClientShould.cs @@ -1,16 +1,21 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using Xunit; namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetRetrieveProvidersBasePathAsync(string realm) + [Fact] + public async Task GetRetrieveProvidersBasePathAsync() { - var result = await _client.GetRetrieveProvidersBasePathAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRetrieveProvidersBasePathAsync(realm); + var providerIds = result.Select(x => x.Id).ToArray(); + + Assert.Contains("allowed-client-templates", providerIds); + Assert.Contains("max-clients", providerIds); } } } diff --git a/test/Keycloak.Net.Core.Tests/ClientRoleMappings/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/ClientRoleMappings/KeycloakClientShould.cs index 341a0588..575d71d9 100644 --- a/test/Keycloak.Net.Core.Tests/ClientRoleMappings/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/ClientRoleMappings/KeycloakClientShould.cs @@ -6,112 +6,82 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientRoleMappingsForGroupAsync(string realm, string clientId) + [Fact] + public async Task GetClientRoleMappingsForGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientId != null) - { - var result = await _client.GetClientRoleMappingsForGroupAsync(realm, groupId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetClientRoleMappingsForGroupAsync(realm, groupId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-group-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetAvailableClientRoleMappingsForGroupAsync(string realm, string clientId) + [Fact] + public async Task GetAvailableClientRoleMappingsForGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientId != null) - { - var result = await _client.GetAvailableClientRoleMappingsForGroupAsync(realm, groupId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetAvailableClientRoleMappingsForGroupAsync(realm, groupId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-group-available"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetEffectiveClientRoleMappingsForGroupAsync(string realm, string clientId) + [Fact] + public async Task GetEffectiveClientRoleMappingsForGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientId != null) - { - var result = await _client.GetEffectiveClientRoleMappingsForGroupAsync(realm, groupId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetEffectiveClientRoleMappingsForGroupAsync(realm, groupId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-group-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientRoleMappingsForUserAsync(string realm, string clientId) + [Fact] + public async Task GetClientRoleMappingsForUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientId != null) - { - var result = await _client.GetClientRoleMappingsForUserAsync(realm, userId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + var clientUuid = await _fixture.UserClientUuidAsync(); + + var result = await _client.GetClientRoleMappingsForUserAsync(realm, userId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-user-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetAvailableClientRoleMappingsForUserAsync(string realm, string clientId) + [Fact] + public async Task GetAvailableClientRoleMappingsForUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientId != null) - { - var result = await _client.GetAvailableClientRoleMappingsForUserAsync(realm, userId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + var clientUuid = await _fixture.UserClientUuidAsync(); + + var result = await _client.GetAvailableClientRoleMappingsForUserAsync(realm, userId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-user-available"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetEffectiveClientRoleMappingsForUserAsync(string realm, string clientId) + [Fact] + public async Task GetEffectiveClientRoleMappingsForUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientId != null) - { - var result = await _client.GetEffectiveClientRoleMappingsForUserAsync(realm, userId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + var clientUuid = await _fixture.UserClientUuidAsync(); + + var result = await _client.GetEffectiveClientRoleMappingsForUserAsync(realm, userId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-user-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } } } diff --git a/test/Keycloak.Net.Core.Tests/ClientScopes/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/ClientScopes/KeycloakClientShould.cs index 3f133d26..349f6ba4 100644 --- a/test/Keycloak.Net.Core.Tests/ClientScopes/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/ClientScopes/KeycloakClientShould.cs @@ -6,25 +6,30 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetClientScopesAsync(string realm) + [Fact] + public async Task GetClientScopesAsync() { - var result = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + + var result = await _client.GetClientScopesAsync(realm); + var clientScope = result.Single(x => x.Name == KeycloakTestFixture.ClientScopeName); + + Assert.Equal(clientScopeId, clientScope.Id); } - [Theory] - [InlineData("master")] - public async Task GetClientScopeAsync(string realm) + [Fact] + public async Task GetClientScopeAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var result = await _client.GetClientScopeAsync(realm, clientScopeId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + + var result = await _client.GetClientScopeAsync(realm, clientScopeId); + + Assert.Equal(clientScopeId, result.Id); + Assert.Equal("keycloak-net-fixture-client-scope", result.Name); + Assert.Equal("Fixture client scope for Keycloak.Net tests.", result.Description); + Assert.Equal("openid-connect", result.Protocol); } } } diff --git a/test/Keycloak.Net.Core.Tests/Clients/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/Clients/KeycloakClientShould.cs index ae904829..ee9cdbba 100644 --- a/test/Keycloak.Net.Core.Tests/Clients/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/Clients/KeycloakClientShould.cs @@ -6,263 +6,248 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetClientsAsync(string realm) + [Fact] + public async Task GetClientsAsync() { - var result = await _client.GetClientsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + var fixtureClientUuid = await _fixture.FixtureClientUuidAsync(); + var groupClientUuid = await _fixture.GroupClientUuidAsync(); + var userClientUuid = await _fixture.UserClientUuidAsync(); + + var result = await _client.GetClientsAsync(realm); + + Assert.Equal(fixtureClientUuid, result.Single(x => x.ClientId == KeycloakTestFixture.FixtureClientId).Id); + Assert.Equal(groupClientUuid, result.Single(x => x.ClientId == KeycloakTestFixture.GroupClientId).Id); + Assert.Equal(userClientUuid, result.Single(x => x.ClientId == KeycloakTestFixture.UserClientId).Id); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientAsync(string realm, string clientId) + [Fact] + public async Task GetClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetClientAsync(realm, clientUuid); + + Assert.Equal(clientUuid, result.Id); + Assert.Equal("keycloak-net-fixture-client", result.ClientId); + Assert.True(result.Enabled); + Assert.Equal("openid-connect", result.Protocol); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GenerateClientSecretAsync(string realm, string clientId) + [Fact] + public async Task GenerateClientSecretAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GenerateClientSecretAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GenerateClientSecretAsync(realm, clientUuid); + + Assert.Equal("secret", result.Type); + Assert.False(string.IsNullOrWhiteSpace(result.Value)); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientSecretAsync(string realm, string clientId) + [Fact] + public async Task GetClientSecretAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientSecretAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetClientSecretAsync(realm, clientUuid); + + Assert.Equal("secret", result.Type); + Assert.False(string.IsNullOrWhiteSpace(result.Value)); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetDefaultClientScopesAsync(string realm, string clientId) + [Fact] + public async Task GetDefaultClientScopesAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetDefaultClientScopesAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetDefaultClientScopesAsync(realm, clientUuid); + string[] expectedScopeNames = ["web-origins", "service_account", "acr", "profile", "roles", "basic", "email"]; + + Assert.Equivalent(expectedScopeNames, result.Select(x => x.Name), strict: true); } - [Theory(Skip = "Not working yet")] - [InlineData("Insurance", "insurance-product")] - public async Task GenerateClientExampleAccessTokenAsync(string realm, string clientId) + [Fact(Skip = "Not working yet")] + public async Task GenerateClientExampleAccessTokenAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GenerateClientExampleAccessTokenAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GenerateClientExampleAccessTokenAsync(realm, clientUuid); + + Assert.NotNull(result); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetProtocolMappersInTokenGenerationAsync(string realm, string clientId) + [Fact] + public async Task GetProtocolMappersInTokenGenerationAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetProtocolMappersInTokenGenerationAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetProtocolMappersInTokenGenerationAsync(realm, clientUuid); + var mapperNames = result.Select(x => x.MapperName).ToArray(); + + Assert.Contains("Client IP Address", mapperNames); + Assert.Contains("Client Host", mapperNames); + Assert.Contains("Client ID", mapperNames); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientGrantedScopeMappingsAsync(string realm, string clientId) + [Fact] + public async Task GetClientGrantedScopeMappingsAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientGrantedScopeMappingsAsync(realm, clientsId, realm).ConfigureAwait(false); - Assert.NotNull(result); - result = await _client.GetClientGrantedScopeMappingsAsync(realm, clientsId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var realmRoles = await _client.GetClientGrantedScopeMappingsAsync(realm, clientUuid, realm); + var clientRoles = await _client.GetClientGrantedScopeMappingsAsync(realm, clientUuid, clientUuid); + + Assert.Contains(realmRoles, x => x.Name == "default-roles-keycloak-net-fixture"); + Assert.Contains(realmRoles, x => x.Name == "offline_access"); + Assert.Empty(clientRoles); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientNotGrantedScopeMappingsAsync(string realm, string clientId) + [Fact] + public async Task GetClientNotGrantedScopeMappingsAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientNotGrantedScopeMappingsAsync(realm, clientsId, realm).ConfigureAwait(false); - Assert.NotNull(result); - result = await _client.GetClientNotGrantedScopeMappingsAsync(realm, clientsId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var realmRoles = await _client.GetClientNotGrantedScopeMappingsAsync(realm, clientUuid, realm); + var clientRoles = await _client.GetClientNotGrantedScopeMappingsAsync(realm, clientUuid, clientUuid); + + Assert.Empty(realmRoles); + Assert.Empty(clientRoles); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientProviderAsync(string realm, string clientId) + [Fact] + public async Task GetClientProviderAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var providerInstances = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - string providerInstanceId = providerInstances.FirstOrDefault()?.ProviderId; - if (providerInstanceId != null) - { - string result = await _client.GetClientProviderAsync(realm, clientsId, providerInstanceId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetClientProviderAsync(realm, clientUuid, "keycloak-oidc-keycloak-json"); + + Assert.Contains("\"realm\" : \"keycloak-net-fixture\"", result); + Assert.Contains("\"resource\" : \"keycloak-net-fixture-client\"", result); + Assert.Contains("\"credentials\"", result); } - [SkippableTheory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientAuthorizationPermissionsInitializedAsync(string realm, string clientId) + [SkippableFact] + public async Task GetClientAuthorizationPermissionsInitializedAsync() { Skip.IfNot(IsServerFeatureEnabled("ADMIN_FINE_GRAINED_AUTHZ"), "Requires Keycloak feature ADMIN_FINE_GRAINED_AUTHZ (v1) to be enabled."); - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientAuthorizationPermissionsInitializedAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetClientAuthorizationPermissionsInitializedAsync(realm, clientUuid); + + Assert.False(result.Enabled); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientOfflineSessionCountAsync(string realm, string clientId) + [Fact] + public async Task GetClientOfflineSessionCountAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - int? result = await _client.GetClientOfflineSessionCountAsync(realm, clientsId); - Assert.True(result >= 0); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetClientOfflineSessionCountAsync(realm, clientUuid); + + Assert.Equal(0, result); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientOfflineSessionsAsync(string realm, string clientId) + [Fact] + public async Task GetClientOfflineSessionsAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientOfflineSessionsAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetClientOfflineSessionsAsync(realm, clientUuid); + + Assert.Empty(result); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetOptionalClientScopesAsync(string realm, string clientId) + [Fact] + public async Task GetOptionalClientScopesAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetOptionalClientScopesAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetOptionalClientScopesAsync(realm, clientUuid); + string[] expectedScopeNames = ["address", "phone", "offline_access", "organization", "microprofile-jwt"]; + + Assert.Equivalent(expectedScopeNames, result.Select(x => x.Name), strict: true); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GenerateClientRegistrationAccessTokenAsync(string realm, string clientId) + [Fact] + public async Task GenerateClientRegistrationAccessTokenAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GenerateClientRegistrationAccessTokenAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GenerateClientRegistrationAccessTokenAsync(realm, clientUuid); + + Assert.Equal(clientUuid, result.Id); + Assert.Equal("keycloak-net-fixture-client", result.ClientId); + Assert.False(string.IsNullOrWhiteSpace(result.Secret)); } - [Theory()] - [InlineData("Insurance", "insurance-product")] - public async Task GetUserForServiceAccountAsync(string realm, string clientId) + [Fact] + public async Task GetUserForServiceAccountAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetUserForServiceAccountAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetUserForServiceAccountAsync(realm, clientUuid); + + Assert.Equal("service-account-keycloak-net-fixture-client", result.UserName); + Assert.True(result.Enabled); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientSessionCountAsync(string realm, string clientId) + [Fact] + public async Task GetClientSessionCountAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - int? result = await _client.GetClientSessionCountAsync(realm, clientsId); - Assert.True(result >= 0); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetClientSessionCountAsync(realm, clientUuid); + + Assert.Equal(0, result); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task TestClientClusterNodesAvailableAsync(string realm, string clientId) + [Fact] + public async Task TestClientClusterNodesAvailableAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.TestClientClusterNodesAvailableAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.TestClientClusterNodesAvailableAsync(realm, clientUuid); + + Assert.Null(result.FailedRequests); + Assert.Null(result.SuccessRequests); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientUserSessionsAsync(string realm, string clientId) + [Fact] + public async Task GetClientUserSessionsAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientUserSessionsAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.FixtureClientUuidAsync(); + + var result = await _client.GetClientUserSessionsAsync(realm, clientUuid); + + Assert.Empty(result); } - [Theory(Skip = "Pending to figure out test configuration")] - [InlineData("Insurance", "insurance-product")] - public async Task GetResourcesOwnedByClientAsync(string realm, string clientId) + [Fact(Skip = "Pending to figure out test configuration")] + public async Task GetResourcesOwnedByClientAsync() { - var result = await _client.GetResourcesOwnedByClientAsync(realm, clientId).ConfigureAwait(false); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetResourcesOwnedByClientAsync(realm, KeycloakTestFixture.FixtureClientId); + Assert.NotNull(result); } } diff --git a/test/Keycloak.Net.Core.Tests/Components/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/Components/KeycloakClientShould.cs index 91543887..58a3cd63 100644 --- a/test/Keycloak.Net.Core.Tests/Components/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/Components/KeycloakClientShould.cs @@ -6,25 +6,30 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetComponentsAsync(string realm) + [Fact] + public async Task GetComponentsAsync() { - var result = await _client.GetComponentsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetComponentsAsync(realm); + var componentNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("Allowed Client Scopes", componentNames); + Assert.Contains("rsa-generated", componentNames); } - [Theory] - [InlineData("master")] - public async Task GetComponentAsync(string realm) + [Fact] + public async Task GetComponentAsync() { - var components = await _client.GetComponentsAsync(realm).ConfigureAwait(false); - string componentId = components.FirstOrDefault()?.Id; - if (componentId != null) - { - var result = await _client.GetComponentAsync(realm, componentId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var components = await _client.GetComponentsAsync(realm); + var component = components.First(x => x.ProviderId == "rsa-generated"); + + var result = await _client.GetComponentAsync(realm, component.Id); + + Assert.Equal(component.Id, result.Id); + Assert.Equal("rsa-generated", result.Name); + Assert.Equal("org.keycloak.keys.KeyProvider", result.ProviderType); } } } diff --git a/test/Keycloak.Net.Core.Tests/Groups/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/Groups/KeycloakClientShould.cs index dd4d09ad..a9204cc8 100644 --- a/test/Keycloak.Net.Core.Tests/Groups/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/Groups/KeycloakClientShould.cs @@ -6,59 +6,65 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetGroupHierarchyAsync(string realm) + [Fact] + public async Task GetGroupHierarchyAsync() { - var result = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetGroupHierarchyAsync(realm, search: KeycloakTestFixture.GroupName); + string[] expectedGroupNames = ["keycloak-net-fixture-group"]; + + Assert.Equivalent(expectedGroupNames, result.Select(x => x.Name), strict: true); + Assert.Equal(groupId, result.Single().Id); } - [Theory] - [InlineData("master")] - public async Task GetGroupsCountAsync(string realm) + [Fact] + public async Task GetGroupsCountAsync() { - int? result = await _client.GetGroupsCountAsync(realm); - Assert.True(result >= 0); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetGroupsCountAsync(realm, search: KeycloakTestFixture.GroupName); + + Assert.Equal(1, result); } - [Theory] - [InlineData("master")] - public async Task GetGroupAsync(string realm) + [Fact] + public async Task GetGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var result = await _client.GetGroupAsync(realm, groupId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetGroupAsync(realm, groupId); + + Assert.Equal(groupId, result.Id); + Assert.Equal("keycloak-net-fixture-group", result.Name); + Assert.Equal("/keycloak-net-fixture-group", result.Path); } - [Theory] - [InlineData("master")] - public async Task GetGroupClientAuthorizationPermissionsInitializedAsync(string realm) + [Fact] + public async Task GetGroupClientAuthorizationPermissionsInitializedAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var result = await _client.GetGroupClientAuthorizationPermissionsInitializedAsync(realm, groupId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetGroupClientAuthorizationPermissionsInitializedAsync(realm, groupId); + + Assert.False(result.Enabled); } - [Theory] - [InlineData("master")] - public async Task GetGroupUsersAsync(string realm) + [Fact] + public async Task GetGroupUsersAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var result = await _client.GetGroupUsersAsync(realm, groupId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetGroupUsersAsync(realm, groupId); + string[] expectedUserNames = ["keycloak-net-fixture-user"]; + + Assert.Equivalent(expectedUserNames, result.Select(x => x.UserName), strict: true); + Assert.Equal(userId, result.Single().Id); } } } diff --git a/test/Keycloak.Net.Core.Tests/IdentityProviders/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/IdentityProviders/KeycloakClientShould.cs index 44720240..18969ccd 100644 --- a/test/Keycloak.Net.Core.Tests/IdentityProviders/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/IdentityProviders/KeycloakClientShould.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Xunit; @@ -6,103 +7,101 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetIdentityProviderInstancesAsync(string realm) + [Fact] + public async Task GetIdentityProviderInstancesAsync() { - var result = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetIdentityProviderInstancesAsync(realm); + string[] expectedAliases = ["keycloak-net-fixture-oidc"]; + + Assert.Equivalent(expectedAliases, result.Select(x => x.Alias), strict: true); } - [Theory] - [InlineData("master")] - public async Task GetIdentityProviderAsync(string realm) + [Fact] + public async Task GetIdentityProviderAsync() { - var identityProviderInstances = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - string identityProviderAlias = identityProviderInstances.FirstOrDefault()?.Alias; - if (identityProviderAlias != null) - { - var result = await _client.GetIdentityProviderAsync(realm, identityProviderAlias).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var identityProviderAlias = KeycloakTestFixture.IdentityProviderAlias; + + var result = await _client.GetIdentityProviderAsync(realm, identityProviderAlias); + + Assert.Equal(identityProviderAlias, result.Alias); + Assert.Equal("oidc", result.ProviderId); + Assert.True(result.Enabled); + Assert.True(result.LinkOnly); } //[Theory] - //[InlineData("Insurance")] + //[InlineData("keycloak-net-fixture")] //public async Task GetIdentityProviderTokenAsync(string realm) //{ // var token = await _client.GetIdentityProviderTokenAsync(realm).ConfigureAwait(false); // Assert.NotNull(token); //} - [Theory] - [InlineData("master")] - public async Task GetIdentityProviderAuthorizationPermissionsInitializedAsync(string realm) + [SkippableFact] + public async Task GetIdentityProviderAuthorizationPermissionsInitializedAsync() { - var identityProviderInstances = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - string identityProviderAlias = identityProviderInstances.FirstOrDefault()?.Alias; - if (identityProviderAlias != null) - { - var result = await _client.GetIdentityProviderAuthorizationPermissionsInitializedAsync(realm, identityProviderAlias).ConfigureAwait(false); - Assert.NotNull(result); - } + Skip.IfNot(IsServerFeatureEnabled("ADMIN_FINE_GRAINED_AUTHZ"), "Requires Keycloak feature ADMIN_FINE_GRAINED_AUTHZ (v1) to be enabled."); + var realm = KeycloakTestFixture.Realm; + var identityProviderAlias = KeycloakTestFixture.IdentityProviderAlias; + + var result = await _client.GetIdentityProviderAuthorizationPermissionsInitializedAsync(realm, identityProviderAlias); + + Assert.False(result.Enabled); } - [Theory] - [InlineData("master")] - public async Task GetIdentityProviderMapperTypesAsync(string realm) + [Fact] + public async Task GetIdentityProviderMapperTypesAsync() { - var identityProviderInstances = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - string identityProviderAlias = identityProviderInstances.FirstOrDefault()?.Alias; - if (identityProviderAlias != null) - { - var result = await _client.GetIdentityProviderMapperTypesAsync(realm, identityProviderAlias).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var identityProviderAlias = KeycloakTestFixture.IdentityProviderAlias; + + var result = await _client.GetIdentityProviderMapperTypesAsync(realm, identityProviderAlias); + + Assert.Contains("oidc-user-attribute-idp-mapper", result.Keys); } - [Theory] - [InlineData("master")] - public async Task GetIdentityProviderMappersAsync(string realm) + [Fact] + public async Task GetIdentityProviderMappersAsync() { - var identityProviderInstances = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - string identityProviderAlias = identityProviderInstances.FirstOrDefault()?.Alias; - if (identityProviderAlias != null) - { - var result = await _client.GetIdentityProviderMappersAsync(realm, identityProviderAlias).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var identityProviderAlias = KeycloakTestFixture.IdentityProviderAlias; + var mapperId = await _fixture.IdentityProviderMapperIdAsync(); + + var result = await _client.GetIdentityProviderMappersAsync(realm, identityProviderAlias); + string[] expectedMapperNames = ["keycloak-net-fixture-idp-mapper"]; + + Assert.Equivalent(expectedMapperNames, result.Select(x => x.Name), strict: true); + Assert.Equal(mapperId, result.Single().Id); } - [Theory] - [InlineData("master")] - public async Task GetIdentityProviderMapperByIdAsync(string realm) + [Fact] + public async Task GetIdentityProviderMapperByIdAsync() { - var identityProviderInstances = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - string identityProviderAlias = identityProviderInstances.FirstOrDefault()?.Alias; - if (identityProviderAlias != null) - { - var mappers = await _client.GetIdentityProviderMappersAsync(realm, identityProviderAlias).ConfigureAwait(false); - string mapperId = mappers.FirstOrDefault()?.Id; - if (mapperId != null) - { - var result = await _client.GetIdentityProviderMapperByIdAsync(realm, identityProviderAlias, mapperId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var identityProviderAlias = KeycloakTestFixture.IdentityProviderAlias; + var mapperId = await _fixture.IdentityProviderMapperIdAsync(); + + var result = await _client.GetIdentityProviderMapperByIdAsync(realm, identityProviderAlias, mapperId); + + Assert.Equal(mapperId, result.Id); + Assert.Equal("keycloak-net-fixture-idp-mapper", result.Name); + Assert.Equal("oidc-user-attribute-idp-mapper", result._IdentityProviderMapper); + Assert.Equal("fixture_claim", ((JsonElement)result.Config["claim"]).GetString()); + Assert.Equal("fixtureAttribute", ((JsonElement)result.Config["user.attribute"]).GetString()); } - [Theory] - [InlineData("master")] - public async Task GetIdentityProviderByProviderIdAsync(string realm) + [Fact] + public async Task GetIdentityProviderByProviderIdAsync() { - var identityProviderInstances = await _client.GetIdentityProviderInstancesAsync(realm).ConfigureAwait(false); - string identityProviderId = identityProviderInstances.FirstOrDefault()?.ProviderId; - if (identityProviderId != null) - { - var result = await _client.GetIdentityProviderByProviderIdAsync(realm, identityProviderId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetIdentityProviderByProviderIdAsync(realm, "oidc"); + + Assert.Equal("oidc", result.Id); + Assert.Equal("OpenID Connect v1.0", result.Name); } } } diff --git a/test/Keycloak.Net.Core.Tests/Key/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/Key/KeycloakClientShould.cs index d8b14480..989f9561 100644 --- a/test/Keycloak.Net.Core.Tests/Key/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/Key/KeycloakClientShould.cs @@ -1,16 +1,22 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using Xunit; namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetKeysAsync(string realm) + [Fact] + public async Task GetKeysAsync() { - var result = await _client.GetKeysAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetKeysAsync(realm); + var algorithms = result.Keys.Select(x => x.Algorithm).ToArray(); + + Assert.NotNull(result.Active.Rs256); + Assert.Contains("RS256", algorithms); + Assert.Contains("AES", algorithms); } } } diff --git a/test/Keycloak.Net.Core.Tests/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/KeycloakClientShould.cs index b4a09839..71c9beee 100644 --- a/test/Keycloak.Net.Core.Tests/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/KeycloakClientShould.cs @@ -6,11 +6,12 @@ namespace Keycloak.Net.Tests { - public partial class KeycloakClientShould + public partial class KeycloakClientShould { - private readonly KeycloakClient _client; + private static readonly KeycloakClient _client = CreateKeycloakClient(); + private static readonly KeycloakTestFixture _fixture = new(_client); - public KeycloakClientShould() + private static KeycloakClient CreateKeycloakClient() { var configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", @@ -22,16 +23,12 @@ public KeycloakClientShould() var userName = configuration["userName"]!; var password = configuration["password"]!; - _client = new(url, userName, password); + return new(url, userName, password); } private static readonly Lazy> _enabledFeatures = new(() => { - var configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false) - .Build(); - var client = new KeycloakClient(configuration["url"]!, configuration["userName"]!, configuration["password"]!); - var info = client.GetServerInfoAsync("master").GetAwaiter().GetResult(); + var info = _client.GetServerInfoAsync("master").GetAwaiter().GetResult(); return new HashSet( info.Features?.Where(f => f.Enabled).Select(f => f.Name) ?? Enumerable.Empty(), StringComparer.OrdinalIgnoreCase); diff --git a/test/Keycloak.Net.Core.Tests/KeycloakTestFixture.cs b/test/Keycloak.Net.Core.Tests/KeycloakTestFixture.cs new file mode 100644 index 00000000..6f60f10d --- /dev/null +++ b/test/Keycloak.Net.Core.Tests/KeycloakTestFixture.cs @@ -0,0 +1,151 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace Keycloak.Net.Tests; + +internal sealed class KeycloakTestFixture +{ + private const string GroupClientIdValue = "keycloak-net-fixture-group-client"; + private const string UserClientIdValue = "keycloak-net-fixture-user-client"; + private const string FixtureClientIdValue = "keycloak-net-fixture-client"; + private const string GroupNameValue = "keycloak-net-fixture-group"; + private const string DefaultGroupNameValue = "keycloak-net-fixture-default-group"; + private const string UserNameValue = "keycloak-net-fixture-user"; + private const string ClientScopeNameValue = "keycloak-net-fixture-client-scope"; + private const string ProtocolMapperName = "keycloak-net-fixture-protocol-mapper"; + private const string IdentityProviderAliasValue = "keycloak-net-fixture-oidc"; + private const string IdentityProviderMapperName = "keycloak-net-fixture-idp-mapper"; + private const string RealmRoleNameValue = "keycloak-net-realm-available"; + private const string GroupClientRoleNameValue = "keycloak-net-group-mapped"; + private const string UserClientRoleNameValue = "keycloak-net-user-mapped"; + private const string GroupRealmRoleNameValue = "keycloak-net-group-realm-mapped"; + private const string UserRealmRoleNameValue = "keycloak-net-user-realm-mapped"; + + private readonly KeycloakClient _client; + private readonly Lazy> _groupClientUuid; + private readonly Lazy> _userClientUuid; + private readonly Lazy> _fixtureClientUuid; + private readonly Lazy> _groupId; + private readonly Lazy> _defaultGroupId; + private readonly Lazy> _userId; + private readonly Lazy> _clientScopeId; + private readonly Lazy> _protocolMapperId; + private readonly Lazy> _identityProviderMapperId; + private readonly Lazy> _realmRoleId; + + public static string Realm => "keycloak-net-fixture"; + public static string IdentityProviderAlias => IdentityProviderAliasValue; + public static string FixtureClientId => FixtureClientIdValue; + public static string GroupClientId => GroupClientIdValue; + public static string UserClientId => UserClientIdValue; + public static string GroupName => GroupNameValue; + public static string DefaultGroupPath => $"/{DefaultGroupNameValue}"; + public static string UserName => UserNameValue; + public static string ClientScopeName => ClientScopeNameValue; + public static string RealmRoleName => RealmRoleNameValue; + public static string GroupClientRoleName => GroupClientRoleNameValue; + public static string UserClientRoleName => UserClientRoleNameValue; + public static string GroupRealmRoleName => GroupRealmRoleNameValue; + public static string UserRealmRoleName => UserRealmRoleNameValue; + + public KeycloakTestFixture(KeycloakClient client) + { + _client = client; + _groupClientUuid = new(() => ResolveClientUuidAsync(GroupClientIdValue)); + _userClientUuid = new(() => ResolveClientUuidAsync(UserClientIdValue)); + _fixtureClientUuid = new(() => ResolveClientUuidAsync(FixtureClientIdValue)); + _groupId = new(() => ResolveGroupIdAsync(GroupNameValue)); + _defaultGroupId = new(() => ResolveGroupIdAsync(DefaultGroupNameValue)); + _userId = new(() => ResolveUserIdAsync(UserNameValue)); + _clientScopeId = new(() => ResolveClientScopeIdAsync(ClientScopeNameValue)); + _protocolMapperId = new(() => ResolveProtocolMapperIdAsync()); + _identityProviderMapperId = new(() => ResolveIdentityProviderMapperIdAsync()); + _realmRoleId = new(() => ResolveRealmRoleIdAsync()); + } + + public Task GroupClientUuidAsync() => _groupClientUuid.Value; + + public Task UserClientUuidAsync() => _userClientUuid.Value; + + public Task FixtureClientUuidAsync() => _fixtureClientUuid.Value; + + public Task GroupIdAsync() => _groupId.Value; + + public Task DefaultGroupIdAsync() => _defaultGroupId.Value; + + public Task UserIdAsync() => _userId.Value; + + public Task ClientScopeIdAsync() => _clientScopeId.Value; + + public Task ProtocolMapperIdAsync() => _protocolMapperId.Value; + + public Task IdentityProviderMapperIdAsync() => _identityProviderMapperId.Value; + + public Task RealmRoleIdAsync() => _realmRoleId.Value; + + private async Task ResolveClientUuidAsync(string clientId) + { + var clients = await _client.GetClientsAsync(Realm); + var id = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; + + Assert.NotNull(id); + return id; + } + + private async Task ResolveGroupIdAsync(string groupName) + { + var groups = await _client.GetGroupHierarchyAsync(Realm, search: groupName); + var id = groups.FirstOrDefault(x => x.Name == groupName)?.Id; + + Assert.NotNull(id); + return id; + } + + private async Task ResolveUserIdAsync(string username) + { + var users = await _client.GetUsersAsync(Realm, username: username, exact: true); + var id = users.FirstOrDefault(x => x.UserName == username)?.Id; + + Assert.NotNull(id); + return id; + } + + private async Task ResolveClientScopeIdAsync(string clientScopeName) + { + var clientScopes = await _client.GetClientScopesAsync(Realm); + var id = clientScopes.FirstOrDefault(x => x.Name == clientScopeName)?.Id; + + Assert.NotNull(id); + return id; + } + + private async Task ResolveProtocolMapperIdAsync() + { + var clientScopeId = await ClientScopeIdAsync(); + var protocolMappers = await _client.GetProtocolMappersAsync(Realm, clientScopeId); + var id = protocolMappers.FirstOrDefault(x => x.Name == ProtocolMapperName)?.Id; + + Assert.NotNull(id); + return id; + } + + private async Task ResolveRealmRoleIdAsync() + { + var roles = await _client.GetRolesAsync(Realm); + var id = roles.FirstOrDefault(x => x.Name == RealmRoleNameValue)?.Id; + + Assert.NotNull(id); + return id; + } + + private async Task ResolveIdentityProviderMapperIdAsync() + { + var mappers = await _client.GetIdentityProviderMappersAsync(Realm, IdentityProviderAliasValue); + var id = mappers.FirstOrDefault(x => x.Name == IdentityProviderMapperName)?.Id; + + Assert.NotNull(id); + return id; + } +} diff --git a/test/Keycloak.Net.Core.Tests/ProtocolMappers/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/ProtocolMappers/KeycloakClientShould.cs index d7d27595..de3aefc6 100644 --- a/test/Keycloak.Net.Core.Tests/ProtocolMappers/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/ProtocolMappers/KeycloakClientShould.cs @@ -6,53 +6,53 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetProtocolMappersAsync(string realm) + [Fact] + public async Task GetProtocolMappersAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault(x => x.ProtocolMappers != null && x.ProtocolMappers.Any())?.Id; - if (clientScopeId != null) - { - var result = await _client.GetProtocolMappersAsync(realm, clientScopeId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + var protocolMapperId = await _fixture.ProtocolMapperIdAsync(); + + var result = await _client.GetProtocolMappersAsync(realm, clientScopeId); + + var protocolMapper = Assert.Single(result); + Assert.Equal(protocolMapperId, protocolMapper.Id); + Assert.Equal("keycloak-net-fixture-protocol-mapper", protocolMapper.Name); + Assert.Equal("openid-connect", protocolMapper.Protocol); + Assert.Equal("oidc-hardcoded-claim-mapper", protocolMapper._ProtocolMapper); } - [Theory] - [InlineData("master")] - public async Task GetProtocolMapperAsync(string realm) + [Fact] + public async Task GetProtocolMapperAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault(x => x.ProtocolMappers != null && x.ProtocolMappers.Any())?.Id; - if (clientScopeId != null) - { - var protocolMappers = await _client.GetProtocolMappersAsync(realm, clientScopeId).ConfigureAwait(false); - string protocolMapperId = protocolMappers.FirstOrDefault()?.Id; - if (protocolMapperId != null) - { - var result = await _client.GetProtocolMapperAsync(realm, clientScopeId, protocolMapperId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + var protocolMapperId = await _fixture.ProtocolMapperIdAsync(); + + var result = await _client.GetProtocolMapperAsync(realm, clientScopeId, protocolMapperId); + + Assert.Equal(protocolMapperId, result.Id); + Assert.Equal("keycloak-net-fixture-protocol-mapper", result.Name); + Assert.Equal("openid-connect", result.Protocol); + Assert.Equal("oidc-hardcoded-claim-mapper", result._ProtocolMapper); + Assert.Equal("keycloak_net_fixture", result.Config["claim.name"]); + Assert.Equal("phase1", result.Config["claim.value"]); } - [Theory] - [InlineData("master")] - public async Task GetProtocolMappersByNameAsync(string realm) + [Fact] + public async Task GetProtocolMappersByNameAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault(x => x.ProtocolMappers != null && x.ProtocolMappers.Any())?.Id; - if (clientScopeId != null) - { - var protocolMappers = await _client.GetProtocolMappersAsync(realm, clientScopeId).ConfigureAwait(false); - string protocol = protocolMappers.FirstOrDefault()?.Name; - if (protocol != null) - { - var result = await _client.GetProtocolMappersByNameAsync(realm, clientScopeId, protocol).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + var protocolMapperId = await _fixture.ProtocolMapperIdAsync(); + + var result = await _client.GetProtocolMappersByNameAsync(realm, clientScopeId, "openid-connect"); + + var protocolMapper = Assert.Single(result); + Assert.Equal(protocolMapperId, protocolMapper.Id); + Assert.Equal("keycloak-net-fixture-protocol-mapper", protocolMapper.Name); + Assert.Equal("openid-connect", protocolMapper.Protocol); + Assert.Equal("oidc-hardcoded-claim-mapper", protocolMapper._ProtocolMapper); } } } diff --git a/test/Keycloak.Net.Core.Tests/RealmsAdmin/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/RealmsAdmin/KeycloakClientShould.cs index 887fad7a..a6a09e56 100644 --- a/test/Keycloak.Net.Core.Tests/RealmsAdmin/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/RealmsAdmin/KeycloakClientShould.cs @@ -6,98 +6,133 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetRealmsAsync(string realm) + [Fact] + public async Task GetRealmsAsync() { - var result = await _client.GetRealmsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRealmsAsync(realm); + + Assert.Contains(result, x => x._Realm == realm); } - [Theory] - [InlineData("master")] - public async Task GetRealmAsync(string realm) + [Fact] + public async Task GetRealmAsync() { - var result = await _client.GetRealmAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRealmAsync(realm); + + Assert.Equal(realm, result._Realm); + Assert.True(result.Enabled); + Assert.False(result.RegistrationAllowed); } - [Theory] - [InlineData("master")] - public async Task GetAdminEventsAsync(string realm) + [Fact] + public async Task GetAdminEventsAsync() { - var result = await _client.GetAdminEventsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetAdminEventsAsync(realm); + + Assert.Empty(result); } - [Theory] - [InlineData("master")] - public async Task GetClientSessionStatsAsync(string realm) + [Fact] + public async Task GetClientSessionStatsAsync() { - var result = await _client.GetClientSessionStatsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetClientSessionStatsAsync(realm); + + var stats = Assert.Single(result); + Assert.Equal("admin-cli", stats["clientId"]?.ToString()); + Assert.True(int.Parse(stats["active"]!.ToString()!) >= 0); + Assert.True(int.Parse(stats["offline"]!.ToString()!) >= 0); } - [Theory] - [InlineData("master")] - public async Task GetRealmDefaultClientScopesAsync(string realm) + [Fact] + public async Task GetRealmDefaultClientScopesAsync() { - var result = await _client.GetRealmDefaultClientScopesAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRealmDefaultClientScopesAsync(realm); + string[] expectedScopeNames = ["role_list", "saml_organization", "AuthnContextClassRef", "profile", "email", "roles", "web-origins", "acr", "basic"]; + + Assert.Equivalent(expectedScopeNames, result.Select(x => x.Name), strict: true); } - [Theory] - [InlineData("master")] - public async Task GetRealmGroupHierarchyAsync(string realm) + [Fact] + public async Task GetRealmGroupHierarchyAsync() { - var result = await _client.GetRealmGroupHierarchyAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + var defaultGroupId = await _fixture.DefaultGroupIdAsync(); + + var result = await _client.GetRealmGroupHierarchyAsync(realm); + + var group = Assert.Single(result); + Assert.Equal(defaultGroupId, group.Id); + Assert.Equal("keycloak-net-fixture-default-group", group.Name); + Assert.Equal("/keycloak-net-fixture-default-group", group.Path); } - [Theory] - [InlineData("master")] - public async Task GetRealmOptionalClientScopesAsync(string realm) + [Fact] + public async Task GetRealmOptionalClientScopesAsync() { - var result = await _client.GetRealmOptionalClientScopesAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRealmOptionalClientScopesAsync(realm); + string[] expectedScopeNames = ["offline_access", "address", "phone", "microprofile-jwt", "organization"]; + + Assert.Equivalent(expectedScopeNames, result.Select(x => x.Name), strict: true); } - [Theory] - [InlineData("master")] - public async Task GetEventsAsync(string realm) + [Fact] + public async Task GetEventsAsync() { - var result = await _client.GetEventsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetEventsAsync(realm); + + Assert.Empty(result); } - [Theory] - [InlineData("master")] - public async Task GetRealmEventsProviderConfigurationAsync(string realm) + [Fact] + public async Task GetRealmEventsProviderConfigurationAsync() { - var result = await _client.GetRealmEventsProviderConfigurationAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRealmEventsProviderConfigurationAsync(realm); + + Assert.False(result.EventsEnabled); + Assert.False(result.AdminEventsEnabled); + Assert.False(result.AdminEventsDetailsEnabled); + Assert.Contains("jboss-logging", result.EventsListeners); + Assert.Contains("LOGIN", result.EnabledEventTypes); } - [Theory] - [InlineData("master")] - public async Task GetRealmGroupByPathAsync(string realm) + [Fact] + public async Task GetRealmGroupByPathAsync() { - var groups = await _client.GetRealmGroupHierarchyAsync(realm).ConfigureAwait(false); - string path = groups.FirstOrDefault()?.Path; - if (path != null) - { - var result = await _client.GetRealmGroupByPathAsync(realm, path).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var defaultGroupId = await _fixture.DefaultGroupIdAsync(); + + var result = await _client.GetRealmGroupByPathAsync(realm, KeycloakTestFixture.DefaultGroupPath); + + Assert.Equal(defaultGroupId, result.Id); + Assert.Equal("keycloak-net-fixture-default-group", result.Name); + Assert.Equal("/keycloak-net-fixture-default-group", result.Path); } - [SkippableTheory] - [InlineData("master")] - public async Task GetRealmUsersManagementPermissionsAsync(string realm) + [SkippableFact] + public async Task GetRealmUsersManagementPermissionsAsync() { Skip.IfNot(IsServerFeatureEnabled("ADMIN_FINE_GRAINED_AUTHZ"), "Requires Keycloak feature ADMIN_FINE_GRAINED_AUTHZ (v1) to be enabled."); - var result = await _client.GetRealmUsersManagementPermissionsAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRealmUsersManagementPermissionsAsync(realm); + + Assert.False(result.Enabled); } } } diff --git a/test/Keycloak.Net.Core.Tests/RoleMapper/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/RoleMapper/KeycloakClientShould.cs index cba7df58..b0ab3316 100644 --- a/test/Keycloak.Net.Core.Tests/RoleMapper/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/RoleMapper/KeycloakClientShould.cs @@ -6,108 +6,106 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetRoleMappingsForGroupAsync(string realm) + [Fact] + public async Task GetRoleMappingsForGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var result = await _client.GetRoleMappingsForGroupAsync(realm, groupId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetRoleMappingsForGroupAsync(realm, groupId); + string[] expectedRealmRoleNames = ["keycloak-net-group-realm-mapped"]; + string[] expectedClientRoleNames = ["keycloak-net-group-mapped"]; + + Assert.Equivalent(expectedRealmRoleNames, result.RealmMappings.Select(x => x.Name)); + Assert.True(result.ClientMappings.TryGetValue("keycloak-net-fixture-group-client", out var clientMapping)); + Assert.Equivalent(expectedClientRoleNames, clientMapping.Mappings.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetRealmRoleMappingsForGroupAsync(string realm) + [Fact] + public async Task GetRealmRoleMappingsForGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var result = await _client.GetRealmRoleMappingsForGroupAsync(realm, groupId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetRealmRoleMappingsForGroupAsync(realm, groupId); + string[] expectedRoleNames = ["keycloak-net-group-realm-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetAvailableRealmRoleMappingsForGroupAsync(string realm) + [Fact] + public async Task GetAvailableRealmRoleMappingsForGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var result = await _client.GetAvailableRealmRoleMappingsForGroupAsync(realm, groupId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetAvailableRealmRoleMappingsForGroupAsync(realm, groupId); + var roleNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("keycloak-net-realm-available", roleNames); + Assert.DoesNotContain("keycloak-net-group-realm-mapped", roleNames); } - [Theory] - [InlineData("master")] - public async Task GetEffectiveRealmRoleMappingsForGroupAsync(string realm) + [Fact] + public async Task GetEffectiveRealmRoleMappingsForGroupAsync() { - var groups = await _client.GetGroupHierarchyAsync(realm).ConfigureAwait(false); - string groupId = groups.FirstOrDefault()?.Id; - if (groupId != null) - { - var result = await _client.GetEffectiveRealmRoleMappingsForGroupAsync(realm, groupId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetEffectiveRealmRoleMappingsForGroupAsync(realm, groupId); + + Assert.Contains(result, x => x.Name == "keycloak-net-group-realm-mapped"); } - [Theory] - [InlineData("master")] - public async Task GetRoleMappingsForUserAsync(string realm) + [Fact] + public async Task GetRoleMappingsForUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetRoleMappingsForUserAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetRoleMappingsForUserAsync(realm, userId); + string[] expectedRoleNames = ["keycloak-net-user-realm-mapped"]; + string[] expectedClientRoleNames = ["keycloak-net-user-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.RealmMappings.Select(x => x.Name)); + Assert.True(result.ClientMappings.TryGetValue("keycloak-net-fixture-user-client", out var clientMapping)); + Assert.Equivalent(expectedClientRoleNames, clientMapping.Mappings.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetRealmRoleMappingsForUserAsync(string realm) + [Fact] + public async Task GetRealmRoleMappingsForUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetRealmRoleMappingsForUserAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetRealmRoleMappingsForUserAsync(realm, userId); + string[] expectedRoleNames = ["keycloak-net-user-realm-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetAvailableRealmRoleMappingsForUserAsync(string realm) + [Fact] + public async Task GetAvailableRealmRoleMappingsForUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetAvailableRealmRoleMappingsForUserAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetAvailableRealmRoleMappingsForUserAsync(realm, userId); + var roleNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("keycloak-net-realm-available", roleNames); + Assert.DoesNotContain("keycloak-net-user-realm-mapped", roleNames); } - [Theory] - [InlineData("master")] - public async Task GetEffectiveRealmRoleMappingsForUserAsync(string realm) + [Fact] + public async Task GetEffectiveRealmRoleMappingsForUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetEffectiveRealmRoleMappingsForUserAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetEffectiveRealmRoleMappingsForUserAsync(realm, userId); + + Assert.Contains(result, x => x.Name == "keycloak-net-user-realm-mapped"); } } } diff --git a/test/Keycloak.Net.Core.Tests/Roles/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/Roles/KeycloakClientShould.cs index ff86c8d7..dd797580 100644 --- a/test/Keycloak.Net.Core.Tests/Roles/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/Roles/KeycloakClientShould.cs @@ -6,248 +6,200 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetRolesForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetRoleByNameForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRoleByNameAsync(realm, clientsId, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetRoleCompositesForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRoleCompositesAsync(realm, clientsId, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetApplicationRolesForCompositeForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetApplicationRolesForCompositeAsync(realm, clientsId, roleName, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetRealmRolesForCompositeForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRealmRolesForCompositeAsync(realm, clientsId, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetGroupsWithRoleNameForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetGroupsWithRoleNameAsync(realm, clientsId, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetRoleAuthorizationPermissionsInitializedForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRoleAuthorizationPermissionsInitializedAsync(realm, clientsId, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetUsersWithRoleNameForClientAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm, clientsId).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetUsersWithRoleNameAsync(realm, clientsId, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("master")] - public async Task GetRolesForRealmAsync(string realm) - { - var result = await _client.GetRolesAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); - } - - [Theory] - [InlineData("master")] - public async Task GetRoleByNameForRealmAsync(string realm) - { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRoleByNameAsync(realm, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - - [Theory] - [InlineData("master")] - public async Task GetRoleCompositesForRealmAsync(string realm) - { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRoleCompositesAsync(realm, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetApplicationRolesForCompositeForRealmAsync(string realm, string clientId) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetApplicationRolesForCompositeAsync(realm, roleName, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } - } - - [Theory] - [InlineData("master")] - public async Task GetRealmRolesForCompositeForRealmAsync(string realm) - { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRealmRolesForCompositeAsync(realm, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - - [Theory] - [InlineData("master")] - public async Task GetGroupsWithRoleNameForRealmAsync(string realm) - { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetGroupsWithRoleNameAsync(realm, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - - [SkippableTheory] - [InlineData("master")] - public async Task GetRoleAuthorizationPermissionsInitializedForRealmAsync(string realm) + [Fact] + public async Task GetRolesForClientAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetRolesAsync(realm, clientUuid); + string[] expectedRoleNames = ["keycloak-net-group-mapped", "keycloak-net-group-available"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name), strict: true); + Assert.All(result, x => Assert.Equal(clientUuid, x.ContainerId)); + } + + [Fact] + public async Task GetRoleByNameForClientAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetRoleByNameAsync(realm, clientUuid, KeycloakTestFixture.GroupClientRoleName); + + Assert.Equal("keycloak-net-group-mapped", result.Name); + Assert.Equal(clientUuid, result.ContainerId); + Assert.True(result.ClientRole); + } + + [Fact] + public async Task GetRoleCompositesForClientAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetRoleCompositesAsync(realm, clientUuid, KeycloakTestFixture.GroupClientRoleName); + + Assert.Empty(result); + } + + [Fact] + public async Task GetApplicationRolesForCompositeForClientAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetApplicationRolesForCompositeAsync(realm, clientUuid, KeycloakTestFixture.GroupClientRoleName, clientUuid); + + Assert.Empty(result); + } + + [Fact] + public async Task GetRealmRolesForCompositeForClientAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetRealmRolesForCompositeAsync(realm, clientUuid, KeycloakTestFixture.GroupClientRoleName); + + Assert.Empty(result); + } + + [Fact] + public async Task GetGroupsWithRoleNameForClientAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetGroupsWithRoleNameAsync(realm, clientUuid, KeycloakTestFixture.GroupClientRoleName); + string[] expectedGroupNames = ["keycloak-net-fixture-group"]; + + Assert.Equivalent(expectedGroupNames, result.Select(x => x.Name), strict: true); + Assert.Equal(groupId, result.Single().Id); + } + + [SkippableFact] + public async Task GetRoleAuthorizationPermissionsInitializedForClientAsync() + { + Skip.IfNot(IsServerFeatureEnabled("ADMIN_FINE_GRAINED_AUTHZ"), "Requires Keycloak feature ADMIN_FINE_GRAINED_AUTHZ (v1) to be enabled."); + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetRoleAuthorizationPermissionsInitializedAsync(realm, clientUuid, KeycloakTestFixture.GroupClientRoleName); + + Assert.False(result.Enabled); + } + + [Fact] + public async Task GetUsersWithRoleNameForClientAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.UserClientUuidAsync(); + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUsersWithRoleNameAsync(realm, clientUuid, KeycloakTestFixture.UserClientRoleName); + string[] expectedUserNames = ["keycloak-net-fixture-user"]; + + Assert.Equivalent(expectedUserNames, result.Select(x => x.UserName), strict: true); + Assert.Equal(userId, result.Single().Id); + } + + [Fact] + public async Task GetRolesForRealmAsync() + { + var realm = KeycloakTestFixture.Realm; + var roleId = await _fixture.RealmRoleIdAsync(); + + var result = await _client.GetRolesAsync(realm, search: "keycloak-net-"); + var roleNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("keycloak-net-group-realm-mapped", roleNames); + Assert.Contains("keycloak-net-user-realm-mapped", roleNames); + Assert.Contains("keycloak-net-realm-available", roleNames); + Assert.Equal(roleId, result.Single(x => x.Name == KeycloakTestFixture.RealmRoleName).Id); + } + + [Fact] + public async Task GetRoleByNameForRealmAsync() + { + var realm = KeycloakTestFixture.Realm; + var roleId = await _fixture.RealmRoleIdAsync(); + + var result = await _client.GetRoleByNameAsync(realm, KeycloakTestFixture.RealmRoleName); + + Assert.Equal(roleId, result.Id); + Assert.Equal("keycloak-net-realm-available", result.Name); + Assert.False(result.ClientRole); + } + + [Fact] + public async Task GetRoleCompositesForRealmAsync() + { + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRoleCompositesAsync(realm, KeycloakTestFixture.RealmRoleName); + + Assert.Empty(result); + } + + [Fact] + public async Task GetApplicationRolesForCompositeForRealmAsync() + { + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetApplicationRolesForCompositeAsync(realm, KeycloakTestFixture.RealmRoleName, clientUuid); + + Assert.Empty(result); + } + + [Fact] + public async Task GetRealmRolesForCompositeForRealmAsync() + { + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetRealmRolesForCompositeAsync(realm, KeycloakTestFixture.RealmRoleName); + + Assert.Empty(result); + } + + [Fact] + public async Task GetGroupsWithRoleNameForRealmAsync() + { + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + + var result = await _client.GetGroupsWithRoleNameAsync(realm, KeycloakTestFixture.GroupRealmRoleName); + string[] expectedGroupNames = ["keycloak-net-fixture-group"]; + + Assert.Equivalent(expectedGroupNames, result.Select(x => x.Name), strict: true); + Assert.Equal(groupId, result.Single().Id); + } + + [SkippableFact] + public async Task GetRoleAuthorizationPermissionsInitializedForRealmAsync() { Skip.IfNot(IsServerFeatureEnabled("ADMIN_FINE_GRAINED_AUTHZ"), "Requires Keycloak feature ADMIN_FINE_GRAINED_AUTHZ (v1) to be enabled."); - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetRoleAuthorizationPermissionsInitializedAsync(realm, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } - } - - [Theory] - [InlineData("master")] - public async Task GetUsersWithRoleNameForRealmAsync(string realm) - { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleName = roles.FirstOrDefault()?.Name; - if (roleName != null) - { - var result = await _client.GetUsersWithRoleNameAsync(realm, roleName).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var roleName = KeycloakTestFixture.RealmRoleName; + + var result = await _client.GetRoleAuthorizationPermissionsInitializedAsync(realm, roleName); + + Assert.False(result.Enabled); + } + + [Fact] + public async Task GetUsersWithRoleNameForRealmAsync() + { + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUsersWithRoleNameAsync(realm, KeycloakTestFixture.UserRealmRoleName); + string[] expectedUserNames = ["keycloak-net-fixture-user"]; + + Assert.Equivalent(expectedUserNames, result.Select(x => x.UserName), strict: true); + Assert.Equal(userId, result.Single().Id); } } } diff --git a/test/Keycloak.Net.Core.Tests/RolesById/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/RolesById/KeycloakClientShould.cs index db41bdf5..6808afac 100644 --- a/test/Keycloak.Net.Core.Tests/RolesById/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/RolesById/KeycloakClientShould.cs @@ -6,75 +6,62 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetRoleByIdAsync(string realm) + [Fact] + public async Task GetRoleByIdAsync() { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleId = roles.FirstOrDefault()?.Id; - if (roleId != null) - { - var result = await _client.GetRoleByIdAsync(realm, roleId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var roleId = await _fixture.RealmRoleIdAsync(); + + var result = await _client.GetRoleByIdAsync(realm, roleId); + + Assert.Equal(roleId, result.Id); + Assert.Equal("keycloak-net-realm-available", result.Name); } - [Theory] - [InlineData("master")] - public async Task GetRoleChildrenAsync(string realm) + [Fact] + public async Task GetRoleChildrenAsync() { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleId = roles.FirstOrDefault()?.Id; - if (roleId != null) - { - var result = await _client.GetRoleChildrenAsync(realm, roleId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var roleId = await _fixture.RealmRoleIdAsync(); + + var result = await _client.GetRoleChildrenAsync(realm, roleId); + + Assert.Empty(result); } - [Theory] - [InlineData("Insurance", "insurance-product")] - public async Task GetClientRolesForCompositeByIdAsync(string realm, string clientId) + [Fact] + public async Task GetClientRolesForCompositeByIdAsync() { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleId = roles.FirstOrDefault()?.Id; - if (roleId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientsId = clients.FirstOrDefault(x => x.ClientId == clientId)?.Id; - if (clientsId != null) - { - var result = await _client.GetClientRolesForCompositeByIdAsync(realm, roleId, clientsId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var roleId = await _fixture.RealmRoleIdAsync(); + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetClientRolesForCompositeByIdAsync(realm, roleId, clientUuid); + + Assert.Empty(result); } - [Theory] - [InlineData("master")] - public async Task GetRealmRolesForCompositeByIdAsync(string realm) + [Fact] + public async Task GetRealmRolesForCompositeByIdAsync() { - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleId = roles.FirstOrDefault()?.Id; - if (roleId != null) - { - var result = await _client.GetRealmRolesForCompositeByIdAsync(realm, roleId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var roleId = await _fixture.RealmRoleIdAsync(); + + var result = await _client.GetRealmRolesForCompositeByIdAsync(realm, roleId); + + Assert.Empty(result); } - [SkippableTheory] - [InlineData("master")] - public async Task GetRoleByIdAuthorizationPermissionsInitializedAsync(string realm) + [SkippableFact] + public async Task GetRoleByIdAuthorizationPermissionsInitializedAsync() { Skip.IfNot(IsServerFeatureEnabled("ADMIN_FINE_GRAINED_AUTHZ"), "Requires Keycloak feature ADMIN_FINE_GRAINED_AUTHZ (v1) to be enabled."); - var roles = await _client.GetRolesAsync(realm).ConfigureAwait(false); - string roleId = roles.FirstOrDefault()?.Id; - if (roleId != null) - { - var result = await _client.GetRoleByIdAuthorizationPermissionsInitializedAsync(realm, roleId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var roleId = await _fixture.RealmRoleIdAsync(); + + var result = await _client.GetRoleByIdAuthorizationPermissionsInitializedAsync(realm, roleId); + + Assert.False(result.Enabled); } } } diff --git a/test/Keycloak.Net.Core.Tests/Root/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/Root/KeycloakClientShould.cs index 57462676..8a2a232a 100644 --- a/test/Keycloak.Net.Core.Tests/Root/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/Root/KeycloakClientShould.cs @@ -1,23 +1,30 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using Xunit; namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetServerInfoAsync(string realm) + [Fact] + public async Task GetServerInfoAsync() { - var result = await _client.GetServerInfoAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetServerInfoAsync(realm); + var enabledFeatures = result.Features.Where(x => x.Enabled).Select(x => x.Name).ToArray(); + + Assert.Contains("ADMIN_FINE_GRAINED_AUTHZ", enabledFeatures); + Assert.NotNull(result.SystemInfo); } - [Theory] - [InlineData("master")] - public async Task CorsPreflightAsync(string realm) + [Fact] + public async Task CorsPreflightAsync() { + var realm = KeycloakTestFixture.Realm; + bool? result = await _client.CorsPreflightAsync(realm); + Assert.True(result); } } diff --git a/test/Keycloak.Net.Core.Tests/ScopeMappings/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/ScopeMappings/KeycloakClientShould.cs index e2c7baa2..7206b998 100644 --- a/test/Keycloak.Net.Core.Tests/ScopeMappings/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/ScopeMappings/KeycloakClientShould.cs @@ -6,201 +6,188 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetScopeMappingsAsync(string realm) + [Fact] + public async Task GetScopeMappingsAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var result = await _client.GetScopeMappingsAsync(realm, clientScopeId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + + var result = await _client.GetScopeMappingsAsync(realm, clientScopeId); + string[] expectedRealmRoleNames = ["keycloak-net-group-realm-mapped"]; + string[] expectedClientRoleNames = ["keycloak-net-group-mapped"]; + + Assert.Equivalent(expectedRealmRoleNames, result.RealmMappings.Select(x => x.Name)); + Assert.True(result.ClientMappings.TryGetValue("keycloak-net-fixture-group-client", out var clientMapping)); + Assert.Equivalent(expectedClientRoleNames, clientMapping.Mappings.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetClientRolesForClientScopeAsync(string realm) + [Fact] + public async Task GetClientRolesForClientScopeAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetClientRolesForClientScopeAsync(realm, clientScopeId, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetClientRolesForClientScopeAsync(realm, clientScopeId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-group-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetAvailableClientRolesForClientScopeAsync(string realm) + [Fact] + public async Task GetAvailableClientRolesForClientScopeAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetAvailableClientRolesForClientScopeAsync(realm, clientScopeId, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetAvailableClientRolesForClientScopeAsync(realm, clientScopeId, clientUuid); + var roleNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("keycloak-net-group-available", roleNames); + Assert.DoesNotContain("keycloak-net-group-mapped", roleNames); } - [Theory] - [InlineData("master")] - public async Task GetEffectiveClientRolesForClientScopeAsync(string realm) + [Fact] + public async Task GetEffectiveClientRolesForClientScopeAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetEffectiveClientRolesForClientScopeAsync(realm, clientScopeId, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetEffectiveClientRolesForClientScopeAsync(realm, clientScopeId, clientUuid); + string[] expectedRoleNames = ["keycloak-net-group-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetRealmRolesForClientScopeAsync(string realm) + [Fact] + public async Task GetRealmRolesForClientScopeAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var result = await _client.GetRealmRolesForClientScopeAsync(realm, clientScopeId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + + var result = await _client.GetRealmRolesForClientScopeAsync(realm, clientScopeId); + string[] expectedRoleNames = ["keycloak-net-group-realm-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetAvailableRealmRolesForClientScopeAsync(string realm) + [Fact] + public async Task GetAvailableRealmRolesForClientScopeAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var result = await _client.GetAvailableRealmRolesForClientScopeAsync(realm, clientScopeId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + + var result = await _client.GetAvailableRealmRolesForClientScopeAsync(realm, clientScopeId); + var roleNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("keycloak-net-realm-available", roleNames); + Assert.DoesNotContain("keycloak-net-group-realm-mapped", roleNames); } - [Theory] - [InlineData("master")] - public async Task GetEffectiveRealmRolesForClientScopeAsync(string realm) + [Fact] + public async Task GetEffectiveRealmRolesForClientScopeAsync() { - var clientScopes = await _client.GetClientScopesAsync(realm).ConfigureAwait(false); - string clientScopeId = clientScopes.FirstOrDefault()?.Id; - if (clientScopeId != null) - { - var result = await _client.GetEffectiveRealmRolesForClientScopeAsync(realm, clientScopeId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientScopeId = await _fixture.ClientScopeIdAsync(); + + var result = await _client.GetEffectiveRealmRolesForClientScopeAsync(realm, clientScopeId); + string[] expectedRoleNames = ["keycloak-net-group-realm-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetScopeMappingsForClientAsync(string realm) + [Fact] + public async Task GetScopeMappingsForClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetScopeMappingsForClientAsync(realm, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetScopeMappingsForClientAsync(realm, clientUuid); + string[] expectedRealmRoleNames = ["keycloak-net-user-realm-mapped"]; + string[] expectedClientRoleNames = ["keycloak-net-user-mapped"]; + + Assert.Equivalent(expectedRealmRoleNames, result.RealmMappings.Select(x => x.Name)); + Assert.True(result.ClientMappings.TryGetValue("keycloak-net-fixture-user-client", out var clientMapping)); + Assert.Equivalent(expectedClientRoleNames, clientMapping.Mappings.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetClientRolesScopeMappingsForClientAsync(string realm) + [Fact] + public async Task GetClientRolesScopeMappingsForClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetClientRolesScopeMappingsForClientAsync(realm, clientId, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + var scopeClientUuid = await _fixture.UserClientUuidAsync(); + + var result = await _client.GetClientRolesScopeMappingsForClientAsync(realm, clientUuid, scopeClientUuid); + string[] expectedRoleNames = ["keycloak-net-user-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetAvailableClientRolesForClientScopeForClientAsync(string realm) + [Fact] + public async Task GetAvailableClientRolesForClientScopeForClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetAvailableClientRolesForClientScopeForClientAsync(realm, clientId, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + var scopeClientUuid = await _fixture.UserClientUuidAsync(); + + var result = await _client.GetAvailableClientRolesForClientScopeForClientAsync(realm, clientUuid, scopeClientUuid); + var roleNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("keycloak-net-user-available", roleNames); + Assert.DoesNotContain("keycloak-net-user-mapped", roleNames); } - [Theory] - [InlineData("master")] - public async Task GetEffectiveClientRolesForClientScopeForClientAsync(string realm) + [Fact] + public async Task GetEffectiveClientRolesForClientScopeForClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetEffectiveClientRolesForClientScopeForClientAsync(realm, clientId, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + var scopeClientUuid = await _fixture.UserClientUuidAsync(); + + var result = await _client.GetEffectiveClientRolesForClientScopeForClientAsync(realm, clientUuid, scopeClientUuid); + string[] expectedRoleNames = ["keycloak-net-user-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetRealmRolesScopeMappingsForClientAsync(string realm) + [Fact] + public async Task GetRealmRolesScopeMappingsForClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetRealmRolesScopeMappingsForClientAsync(realm, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetRealmRolesScopeMappingsForClientAsync(realm, clientUuid); + string[] expectedRoleNames = ["keycloak-net-user-realm-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } - [Theory] - [InlineData("master")] - public async Task GetAvailableRealmRolesForClientScopeForClientAsync(string realm) + [Fact] + public async Task GetAvailableRealmRolesForClientScopeForClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetAvailableRealmRolesForClientScopeForClientAsync(realm, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetAvailableRealmRolesForClientScopeForClientAsync(realm, clientUuid); + var roleNames = result.Select(x => x.Name).ToArray(); + + Assert.Contains("keycloak-net-realm-available", roleNames); + Assert.DoesNotContain("keycloak-net-user-realm-mapped", roleNames); } - [Theory] - [InlineData("master")] - public async Task GetEffectiveRealmRolesForClientScopeForClientAsync(string realm) + [Fact] + public async Task GetEffectiveRealmRolesForClientScopeForClientAsync() { - var clients = await _client.GetClientsAsync(realm).ConfigureAwait(false); - string clientId = clients.FirstOrDefault()?.Id; - if (clientId != null) - { - var result = await _client.GetEffectiveRealmRolesForClientScopeForClientAsync(realm, clientId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var clientUuid = await _fixture.GroupClientUuidAsync(); + + var result = await _client.GetEffectiveRealmRolesForClientScopeForClientAsync(realm, clientUuid); + string[] expectedRoleNames = ["keycloak-net-user-realm-mapped"]; + + Assert.Equivalent(expectedRoleNames, result.Select(x => x.Name)); } } } diff --git a/test/Keycloak.Net.Core.Tests/UserStorageProvider/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/UserStorageProvider/KeycloakClientShould.cs index b730bb98..e7546004 100644 --- a/test/Keycloak.Net.Core.Tests/UserStorageProvider/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/UserStorageProvider/KeycloakClientShould.cs @@ -5,22 +5,22 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory(Skip = "Not working yet")] - [InlineData("master")] - public async Task TriggerUserSynchronizationAsync(string realm) + [Fact(Skip = "Requires an LDAP/user-storage provider test server to be meaningfully tested.")] + public async Task TriggerUserSynchronizationAsync() { + var realm = KeycloakTestFixture.Realm; string storageProviderId = ""; - var result = await _client.TriggerUserSynchronizationAsync(realm, storageProviderId, UserSyncActions.Full).ConfigureAwait(false); + var result = await _client.TriggerUserSynchronizationAsync(realm, storageProviderId, UserSyncActions.Full); Assert.NotNull(result); } - [Theory(Skip = "Not working yet")] - [InlineData("master")] - public async Task TriggerLdapMapperSynchronizationAsync(string realm) + [Fact(Skip = "Requires an LDAP/user-storage provider test server to be meaningfully tested.")] + public async Task TriggerLdapMapperSynchronizationAsync() { + var realm = KeycloakTestFixture.Realm; string storageProviderId = ""; string mapperId = ""; - var result = await _client.TriggerLdapMapperSynchronizationAsync(realm, storageProviderId, mapperId, LdapMapperSyncActions.KeycloakToFed).ConfigureAwait(false); + var result = await _client.TriggerLdapMapperSynchronizationAsync(realm, storageProviderId, mapperId, LdapMapperSyncActions.KeycloakToFed); Assert.NotNull(result); } } diff --git a/test/Keycloak.Net.Core.Tests/Users/KeycloakClientShould.cs b/test/Keycloak.Net.Core.Tests/Users/KeycloakClientShould.cs index 584ba506..57ab0e3b 100644 --- a/test/Keycloak.Net.Core.Tests/Users/KeycloakClientShould.cs +++ b/test/Keycloak.Net.Core.Tests/Users/KeycloakClientShould.cs @@ -6,86 +6,87 @@ namespace Keycloak.Net.Tests { public partial class KeycloakClientShould { - [Theory] - [InlineData("master")] - public async Task GetUsersAsync(string realm) + [Fact] + public async Task GetUsersAsync() { - var result = await _client.GetUsersAsync(realm).ConfigureAwait(false); - Assert.NotNull(result); + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUsersAsync(realm, username: KeycloakTestFixture.UserName, exact: true); + string[] expectedUserNames = ["keycloak-net-fixture-user"]; + + Assert.Equivalent(expectedUserNames, result.Select(x => x.UserName), strict: true); + Assert.Equal(userId, result.Single().Id); } - [Theory] - [InlineData("master")] - public async Task GetUsersCountAsync(string realm) + [Fact] + public async Task GetUsersCountAsync() { - int? result = await _client.GetUsersCountAsync(realm); - Assert.True(result >= 0); + var realm = KeycloakTestFixture.Realm; + + var result = await _client.GetUsersCountAsync(realm, username: KeycloakTestFixture.UserName); + + Assert.Equal(1, result); } - [Theory] - [InlineData("master")] - public async Task GetUserAsync(string realm) + [Fact] + public async Task GetUserAsync() { - var users = await _client.GetUsersAsync(realm).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetUserAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - Assert.Equal(userId, result.Id); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUserAsync(realm, userId); + + Assert.Equal(userId, result.Id); + Assert.Equal("keycloak-net-fixture-user", result.UserName); + Assert.True(result.Enabled); } - [Theory] - [InlineData("Insurance", "vermeulen")] - public async Task GetUserSocialLoginsAsync(string realm, string search) + [Fact] + public async Task GetUserSocialLoginsAsync() { - var users = await _client.GetUsersAsync(realm, search: search).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetUserSocialLoginsAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUserSocialLoginsAsync(realm, userId); + + Assert.Empty(result); } - [Theory] - [InlineData("Insurance", "vermeulen")] - public async Task GetUserGroupsAsync(string realm, string search) + [Fact] + public async Task GetUserGroupsAsync() { - var users = await _client.GetUsersAsync(realm, search: search).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetUserGroupsAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var groupId = await _fixture.GroupIdAsync(); + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUserGroupsAsync(realm, userId); + string[] expectedGroupNames = ["keycloak-net-fixture-group"]; + + Assert.Equivalent(expectedGroupNames, result.Select(x => x.Name), strict: true); + Assert.Equal(groupId, result.Single().Id); } - [Theory] - [InlineData("Insurance", "vermeulen")] - public async Task GetUserGroupsCountAsync(string realm, string search) + [Fact] + public async Task GetUserGroupsCountAsync() { - var users = await _client.GetUsersAsync(realm, search: search).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - int? result = await _client.GetUserGroupsCountAsync(realm, userId); - Assert.True(result >= 0); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUserGroupsCountAsync(realm, userId); + + Assert.Equal(1, result); } - [Theory] - [InlineData("Insurance", "vermeulen")] - public async Task GetUserSessionsAsync(string realm, string search) + [Fact] + public async Task GetUserSessionsAsync() { - var users = await _client.GetUsersAsync(realm, search: search).ConfigureAwait(false); - string userId = users.FirstOrDefault()?.Id; - if (userId != null) - { - var result = await _client.GetUserSessionsAsync(realm, userId).ConfigureAwait(false); - Assert.NotNull(result); - } + var realm = KeycloakTestFixture.Realm; + var userId = await _fixture.UserIdAsync(); + + var result = await _client.GetUserSessionsAsync(realm, userId); + + Assert.Empty(result); } } } diff --git a/test/insurance-realm-export.json b/test/keycloak-net-fixture-realm-export.json similarity index 59% rename from test/insurance-realm-export.json rename to test/keycloak-net-fixture-realm-export.json index a7c53059..c842d0db 100644 --- a/test/insurance-realm-export.json +++ b/test/keycloak-net-fixture-realm-export.json @@ -1,6 +1,6 @@ { - "id" : "9c4a14df-5f46-4a3f-9e0f-ab0427950e15", - "realm" : "Insurance", + "id" : "b304600c-8086-4cd7-8f8c-2be813717f13", + "realm" : "keycloak-net-fixture", "notBefore" : 0, "defaultSignatureAlgorithm" : "RS256", "revokeRefreshToken" : false, @@ -38,24 +38,42 @@ "bruteForceProtected" : false, "permanentLockout" : false, "maxTemporaryLockouts" : 0, + "bruteForceStrategy" : "MULTIPLE", "maxFailureWaitSeconds" : 900, "minimumQuickLoginWaitSeconds" : 60, "waitIncrementSeconds" : 60, "quickLoginCheckMilliSeconds" : 1000, "maxDeltaTimeSeconds" : 43200, "failureFactor" : 30, + "maxSecondaryAuthFailures" : 0, "roles" : { "realm" : [ { - "id" : "dfb6f076-b7a6-468b-a568-01a150eda2da", + "id" : "3c3b518c-73bb-440e-90aa-36ba703eb80c", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "b304600c-8086-4cd7-8f8c-2be813717f13", + "attributes" : { } + }, { + "id" : "f0ad146f-09ef-4c37-8126-720faf9947ff", "name" : "uma_authorization", "description" : "${role_uma_authorization}", "composite" : false, "clientRole" : false, - "containerId" : "9c4a14df-5f46-4a3f-9e0f-ab0427950e15", + "containerId" : "b304600c-8086-4cd7-8f8c-2be813717f13", + "attributes" : { } + }, { + "id" : "d7ee7540-cefa-4274-bd1a-a0021c94b03d", + "name" : "keycloak-net-group-realm-mapped", + "description" : "Direct group realm mapping fixture role.", + "composite" : false, + "clientRole" : false, + "containerId" : "b304600c-8086-4cd7-8f8c-2be813717f13", "attributes" : { } }, { - "id" : "f1734292-945d-436b-88a5-f961e129676d", - "name" : "default-roles-insurance", + "id" : "7afb4507-b96e-4298-9db5-3fe01a02d3b6", + "name" : "default-roles-keycloak-net-fixture", "description" : "${role_default-roles}", "composite" : true, "composites" : { @@ -65,74 +83,77 @@ } }, "clientRole" : false, - "containerId" : "9c4a14df-5f46-4a3f-9e0f-ab0427950e15", + "containerId" : "b304600c-8086-4cd7-8f8c-2be813717f13", "attributes" : { } }, { - "id" : "53e45aca-11c9-4986-98ed-2e98e0b4df21", - "name" : "offline_access", - "description" : "${role_offline-access}", + "id" : "4731e4cb-23d9-45bf-bed5-87c5f8d15422", + "name" : "keycloak-net-realm-available", + "description" : "Unmapped realm fixture role for available-role assertions.", + "composite" : false, + "clientRole" : false, + "containerId" : "b304600c-8086-4cd7-8f8c-2be813717f13", + "attributes" : { } + }, { + "id" : "0787953f-c63d-4cff-b3d5-2496336b14ab", + "name" : "keycloak-net-user-realm-mapped", + "description" : "Direct user realm mapping fixture role.", "composite" : false, "clientRole" : false, - "containerId" : "9c4a14df-5f46-4a3f-9e0f-ab0427950e15", + "containerId" : "b304600c-8086-4cd7-8f8c-2be813717f13", "attributes" : { } } ], "client" : { - "insurance-product" : [ ], - "realm-management" : [ { - "id" : "a06409d0-35ef-4fae-a909-d88d802b83cd", - "name" : "query-realms", - "description" : "${role_query-realms}", + "keycloak-net-fixture-group-client" : [ { + "id" : "2592a100-02f6-4e5d-9195-85c2d658affa", + "name" : "keycloak-net-group-available", + "description" : "Unmapped group fixture role for available-role assertions.", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "cc783ea2-1c13-4ea5-9054-f6c6d2974f31", "attributes" : { } }, { - "id" : "7ad42582-0c55-41cd-bd01-152b659444e5", - "name" : "query-groups", - "description" : "${role_query-groups}", + "id" : "f8fe7bab-4b27-4165-bb06-76abd37e2816", + "name" : "keycloak-net-group-mapped", + "description" : "Direct group mapping fixture role.", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "cc783ea2-1c13-4ea5-9054-f6c6d2974f31", "attributes" : { } - }, { - "id" : "284beb7f-7eaa-441b-a8f6-ed52153b4087", - "name" : "manage-events", - "description" : "${role_manage-events}", + } ], + "realm-management" : [ { + "id" : "fa7e9249-e3af-4ca1-aea7-5b846857e9e5", + "name" : "view-authorization", + "description" : "${role_view-authorization}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "db530b3e-0b1e-43a9-81c7-f226e501ded5", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "realm-management" : [ "query-groups", "query-users" ] - } - }, + "id" : "ccaf7dba-0ec1-47d8-8d11-737a1a7b8f3b", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "5ea80ce1-f543-4afc-9fbe-2bc3fd0436cf", - "name" : "view-authorization", - "description" : "${role_view-authorization}", + "id" : "2d41fddb-3fe6-4e7c-aaac-cabbc08d6867", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "4c0efd7c-de6e-4bca-81ae-fc5649803b2c", - "name" : "manage-clients", - "description" : "${role_manage-clients}", + "id" : "d782e23e-145f-4baf-a332-1ea2fd6b27a8", + "name" : "query-realms", + "description" : "${role_query-realms}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "aa69b69d-ef3a-4a10-a373-1154a6de3550", + "id" : "30986c3b-2cb7-4830-a15a-d7ee77ccb875", "name" : "view-clients", "description" : "${role_view-clients}", "composite" : true, @@ -142,124 +163,216 @@ } }, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "e46d4691-8267-4522-9512-7484e9e5d995", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, + "id" : "047033b9-1f66-48e2-8ecb-85d340ae9a4c", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-users", "query-groups" ] + } + }, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "caabb3ce-992c-494b-9985-5cfd914d5c0f", - "name" : "view-events", - "description" : "${role_view-events}", + "id" : "f16237bb-3748-474e-a4a7-ec2d152f896c", + "name" : "query-users", + "description" : "${role_query-users}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "141e7709-c261-4ba2-8d11-ecba072219a4", - "name" : "view-realm", - "description" : "${role_view-realm}", + "id" : "8751528a-9385-4ea5-9d48-f18a2d74a813", + "name" : "view-events", + "description" : "${role_view-events}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "0192fe88-a34d-4170-8853-bc12bd882861", - "name" : "impersonation", - "description" : "${role_impersonation}", + "id" : "76d52226-7c15-42df-aa27-8b9854e401fc", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "b2b807df-c726-4dc6-93aa-4d17dfff4ff7", - "name" : "query-users", - "description" : "${role_query-users}", + "id" : "9c128cb7-8540-47c9-80f9-af423354277f", + "name" : "manage-events", + "description" : "${role_manage-events}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "34146c2a-6ba4-431f-9715-b74e536c16bd", - "name" : "query-clients", - "description" : "${role_query-clients}", + "id" : "1cf5607f-89c9-480f-b0d9-e195df7c6f7c", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "a8bb3f57-8bcb-464b-947e-9b5729fc48f2", - "name" : "manage-users", - "description" : "${role_manage-users}", + "id" : "ae779547-8b73-4fbd-acbc-b4a6460ba8c3", + "name" : "query-groups", + "description" : "${role_query-groups}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "5e872cce-062c-436e-ac54-8bbae2820c31", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", + "id" : "17c8a03a-f134-4e72-b9b2-fc397f8e060e", + "name" : "create-client", + "description" : "${role_create-client}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "9eea7e32-85cc-4120-8446-36dbe676dc9f", + "id" : "578fe056-0604-4eff-a4db-9d97307d1cd3", "name" : "realm-admin", "description" : "${role_realm-admin}", "composite" : true, "composites" : { "client" : { - "realm-management" : [ "query-realms", "query-groups", "manage-events", "view-users", "view-authorization", "manage-clients", "view-clients", "view-events", "manage-identity-providers", "view-realm", "impersonation", "query-users", "query-clients", "view-identity-providers", "manage-users", "create-client", "manage-realm", "manage-authorization" ] + "realm-management" : [ "view-authorization", "manage-users", "manage-authorization", "query-realms", "view-users", "view-clients", "query-users", "view-identity-providers", "view-events", "manage-events", "manage-identity-providers", "query-groups", "create-client", "view-organizations", "view-realm", "manage-realm", "manage-organizations", "impersonation", "query-clients", "manage-clients", "query-organizations" ] } }, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "7923dd55-38a9-4ae1-a54e-cb3f1c980362", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, + "id" : "d1aa8d0e-6b4f-404a-bac8-7f2c75b88ba7", + "name" : "view-organizations", + "description" : "${role_view-organizations}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-organizations" ] + } + }, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "98c72a76-8707-4aa6-8b95-dae77806e01d", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", + "id" : "ce6cafef-3370-480b-8690-eed5f5140dec", + "name" : "view-realm", + "description" : "${role_view-realm}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", "attributes" : { } }, { - "id" : "55c7da78-0a22-4f37-a525-a627694b36f4", + "id" : "21c218e5-1dab-433c-a441-8f1fb47f6641", "name" : "manage-realm", "description" : "${role_manage-realm}", "composite" : false, "clientRole" : true, - "containerId" : "2d6f788a-ff44-4acf-95a8-18426a88310a", + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", + "attributes" : { } + }, { + "id" : "8067b6c7-8e28-49ad-a88f-5c7992e09317", + "name" : "manage-organizations", + "description" : "${role_manage-organizations}", + "composite" : false, + "clientRole" : true, + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", + "attributes" : { } + }, { + "id" : "7630ea19-21ad-4baa-8e46-35391b917be8", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", + "attributes" : { } + }, { + "id" : "d52fe21e-459a-4a94-80b5-12d273b3ea3c", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", + "attributes" : { } + }, { + "id" : "71925076-53bf-4045-8c15-9c022e01674f", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", + "attributes" : { } + }, { + "id" : "366261d2-b7ad-403d-b3df-6b23f598dd9d", + "name" : "query-organizations", + "description" : "${role_query-organizations}", + "composite" : false, + "clientRole" : true, + "containerId" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", + "attributes" : { } + } ], + "keycloak-net-fixture-user-client" : [ { + "id" : "b92b26a2-a2d9-4f89-ae4f-384d77a73882", + "name" : "keycloak-net-user-mapped", + "description" : "Direct user mapping fixture role.", + "composite" : false, + "clientRole" : true, + "containerId" : "6c746edb-79c6-4a26-abea-e261f4dc2fb5", + "attributes" : { } + }, { + "id" : "dea21c2f-c126-4b94-8c31-c9a280f171a8", + "name" : "keycloak-net-user-available", + "description" : "Unmapped user fixture role for available-role assertions.", + "composite" : false, + "clientRole" : true, + "containerId" : "6c746edb-79c6-4a26-abea-e261f4dc2fb5", "attributes" : { } } ], "security-admin-console" : [ ], "admin-cli" : [ ], "account-console" : [ ], + "keycloak-net-fixture-client" : [ ], "broker" : [ { - "id" : "7ed30889-ce1c-4991-8afa-fcfa613ae78d", + "id" : "6c47f0b4-2b65-4c63-8b82-66886062f0f1", "name" : "read-token", "description" : "${role_read-token}", "composite" : false, "clientRole" : true, - "containerId" : "039323d3-a404-440e-8c6a-ac153d49a389", + "containerId" : "9fa91e34-0323-4bea-81fe-9bf39d58eec0", "attributes" : { } } ], "account" : [ { - "id" : "bbbf12d8-cba2-4042-86d4-b8790c54ba65", + "id" : "74b5d313-7ea2-4597-b8bf-413de9d7e2fd", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", + "attributes" : { } + }, { + "id" : "ca60a242-a78e-4ec2-81de-7d15fb1da33a", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", + "attributes" : { } + }, { + "id" : "114d19f7-54f7-466d-8edd-881d9572457e", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", + "attributes" : { } + }, { + "id" : "4cf65fcb-8a4c-4ba7-8694-27a925f90f64", "name" : "manage-consent", "description" : "${role_manage-consent}", "composite" : true, @@ -269,18 +382,10 @@ } }, "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", - "attributes" : { } - }, { - "id" : "85e508a6-081b-470e-8252-6fd0e0fb96ce", - "name" : "view-groups", - "description" : "${role_view-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", "attributes" : { } }, { - "id" : "62534f01-c2c5-406a-a950-d40cf5907439", + "id" : "3ff969b9-6716-4ca8-886f-2738d68745f5", "name" : "manage-account", "description" : "${role_manage-account}", "composite" : true, @@ -290,60 +395,63 @@ } }, "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", "attributes" : { } }, { - "id" : "544ea9b3-afbf-4bf5-a394-de48ae339848", - "name" : "view-applications", - "description" : "${role_view-applications}", + "id" : "cff41101-5b16-4da9-ada2-dcbb8b72280c", + "name" : "view-consent", + "description" : "${role_view-consent}", "composite" : false, "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", "attributes" : { } }, { - "id" : "8165b98e-6947-47f8-aa4e-6b94bb84bdb7", + "id" : "8d35f06e-caa8-48c7-b9df-c618f956649f", "name" : "view-profile", "description" : "${role_view-profile}", "composite" : false, "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", - "attributes" : { } - }, { - "id" : "da21be05-2967-4672-a03e-ad532b93e28e", - "name" : "manage-account-links", - "description" : "${role_manage-account-links}", - "composite" : false, - "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", - "attributes" : { } - }, { - "id" : "6fec1ddd-4e2e-4085-8e00-f1d6bb304feb", - "name" : "delete-account", - "description" : "${role_delete-account}", - "composite" : false, - "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", "attributes" : { } }, { - "id" : "9fa7ed0b-7a27-4602-8fe0-756f88a708b8", - "name" : "view-consent", - "description" : "${role_view-consent}", + "id" : "4933ee5a-9b71-45e7-80b9-b6e375e67833", + "name" : "view-groups", + "description" : "${role_view-groups}", "composite" : false, "clientRole" : true, - "containerId" : "26293ab2-81a5-4944-9d28-4518be763dd5", + "containerId" : "7738f1ae-bc6a-4975-8d46-aaf268816548", "attributes" : { } } ] } }, - "groups" : [ ], + "groups" : [ { + "id" : "960d4367-2574-460d-9dc4-08786bd3d891", + "name" : "keycloak-net-fixture-default-group", + "path" : "/keycloak-net-fixture-default-group", + "subGroups" : [ ], + "attributes" : { }, + "realmRoles" : [ ], + "clientRoles" : { } + }, { + "id" : "55060ae4-3526-426e-8864-6f75b863b6e2", + "name" : "keycloak-net-fixture-group", + "path" : "/keycloak-net-fixture-group", + "subGroups" : [ ], + "attributes" : { }, + "realmRoles" : [ "keycloak-net-group-realm-mapped" ], + "clientRoles" : { + "keycloak-net-fixture-group-client" : [ "keycloak-net-group-mapped" ] + } + } ], "defaultRole" : { - "id" : "f1734292-945d-436b-88a5-f961e129676d", - "name" : "default-roles-insurance", + "id" : "7afb4507-b96e-4298-9db5-3fe01a02d3b6", + "name" : "default-roles-keycloak-net-fixture", "description" : "${role_default-roles}", "composite" : true, "clientRole" : false, - "containerId" : "9c4a14df-5f46-4a3f-9e0f-ab0427950e15" + "containerId" : "b304600c-8086-4cd7-8f8c-2be813717f13" }, + "defaultGroups" : [ "/keycloak-net-fixture-default-group" ], "requiredCredentials" : [ "password" ], "otpPolicyType" : "totp", "otpPolicyAlgorithm" : "HmacSHA1", @@ -355,89 +463,123 @@ "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], "localizationTexts" : { }, "webAuthnPolicyRpEntityName" : "keycloak", - "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicySignatureAlgorithms" : [ "ES256", "RS256" ], "webAuthnPolicyRpId" : "", "webAuthnPolicyAttestationConveyancePreference" : "not specified", "webAuthnPolicyAuthenticatorAttachment" : "not specified", "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyResidentKey" : "not specified", "webAuthnPolicyUserVerificationRequirement" : "not specified", "webAuthnPolicyCreateTimeout" : 0, "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, "webAuthnPolicyAcceptableAaguids" : [ ], "webAuthnPolicyExtraOrigins" : [ ], "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256", "RS256" ], "webAuthnPolicyPasswordlessRpId" : "", "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessResidentKey" : "required", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "required", "webAuthnPolicyPasswordlessCreateTimeout" : 0, "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], "webAuthnPolicyPasswordlessExtraOrigins" : [ ], "users" : [ { - "id" : "c0a9af86-8378-4adc-b507-2d66caf52b17", + "id" : "d1c4e271-783f-496a-ad30-c10b71813615", "username" : "admin", "firstName" : "Admin", - "lastName" : "Admin", - "email" : "admin@admin.com", + "lastName" : "Fixture", + "email" : "admin@example.test", "emailVerified" : true, - "createdTimestamp" : 1727116269831, "enabled" : true, + "createdTimestamp" : 1783698883351, "totp" : false, "credentials" : [ { - "id" : "237e878d-59e3-4824-bc8e-65c8f76c43e8", + "id" : "a575d33d-e5ad-4e7f-ba38-77b5e6222165", "type" : "password", - "userLabel" : "My password", - "createdDate" : 1727116284494, - "secretData" : "{\"value\":\"FSaK1mAlI+2nqyWdC2GF5C7iTQy0S1tabralsLEQTpo=\",\"salt\":\"oQ7ZZENCxcW35+px/TnhTw==\",\"additionalParameters\":{}}", + "createdDate" : 1783698883435, + "secretData" : "{\"value\":\"ihwkCduxiH+1jqbOeG1BD8msIhauqbu68sj3L2IzrjE=\",\"salt\":\"baaK3EZzeAsyOV4BMyQYaA==\",\"additionalParameters\":{}}", "credentialData" : "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}" } ], "disableableCredentialTypes" : [ ], "requiredActions" : [ ], - "realmRoles" : [ "default-roles-insurance" ], + "realmRoles" : [ "default-roles-keycloak-net-fixture" ], "clientRoles" : { "realm-management" : [ "realm-admin" ] }, "notBefore" : 0, "groups" : [ ] }, { - "id" : "4a705340-17a6-4f62-b4d9-019afd1bf5af", - "username" : "service-account-insurance-product", + "id" : "554c73b2-2f37-498a-b0e4-8fc8bb62cbd4", + "username" : "keycloak-net-fixture-user", + "firstName" : "Keycloak.Net", + "lastName" : "Fixture", + "email" : "keycloak-net-fixture-user@example.test", + "emailVerified" : false, + "enabled" : true, + "createdTimestamp" : 1783698883944, + "totp" : false, + "credentials" : [ ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-keycloak-net-fixture", "keycloak-net-user-realm-mapped" ], + "clientRoles" : { + "keycloak-net-fixture-user-client" : [ "keycloak-net-user-mapped" ] + }, + "notBefore" : 0, + "groups" : [ "/keycloak-net-fixture-group" ] + }, { + "id" : "aa7c15d6-25c3-4aa6-9381-99e611599e3f", + "username" : "service-account-keycloak-net-fixture-client", "emailVerified" : false, - "createdTimestamp" : 1727117601381, "enabled" : true, + "createdTimestamp" : 1783698883600, "totp" : false, - "serviceAccountClientId" : "insurance-product", + "serviceAccountClientId" : "keycloak-net-fixture-client", "credentials" : [ ], "disableableCredentialTypes" : [ ], "requiredActions" : [ ], - "realmRoles" : [ "default-roles-insurance" ], + "realmRoles" : [ "default-roles-keycloak-net-fixture" ], "notBefore" : 0, "groups" : [ ] } ], "scopeMappings" : [ { + "client" : "keycloak-net-fixture-group-client", + "roles" : [ "keycloak-net-user-realm-mapped" ] + }, { + "clientScope" : "keycloak-net-fixture-client-scope", + "roles" : [ "keycloak-net-group-realm-mapped" ] + }, { "clientScope" : "offline_access", "roles" : [ "offline_access" ] } ], "clientScopeMappings" : { + "keycloak-net-fixture-group-client" : [ { + "clientScope" : "keycloak-net-fixture-client-scope", + "roles" : [ "keycloak-net-group-mapped" ] + } ], + "keycloak-net-fixture-user-client" : [ { + "client" : "keycloak-net-fixture-group-client", + "roles" : [ "keycloak-net-user-mapped" ] + } ], "account" : [ { "client" : "account-console", "roles" : [ "manage-account", "view-groups" ] } ] }, "clients" : [ { - "id" : "26293ab2-81a5-4944-9d28-4518be763dd5", + "id" : "7738f1ae-bc6a-4975-8d46-aaf268816548", "clientId" : "account", "name" : "${client_account}", "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/Insurance/account/", + "baseUrl" : "/realms/keycloak-net-fixture/account/", "surrogateAuthRequired" : false, "enabled" : true, "alwaysDisplayInConsole" : false, "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/Insurance/account/*" ], + "redirectUris" : [ "/realms/keycloak-net-fixture/account/*" ], "webOrigins" : [ ], "notBefore" : 0, "bearerOnly" : false, @@ -450,24 +592,25 @@ "frontchannelLogout" : false, "protocol" : "openid-connect", "attributes" : { + "realm_client" : "false", "post.logout.redirect.uris" : "+" }, "authenticationFlowBindingOverrides" : { }, "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] }, { - "id" : "fe6fd41f-68ab-42b6-a5be-39a65f54d680", + "id" : "6fccc381-8a11-4450-a310-c3bc15d4f022", "clientId" : "account-console", "name" : "${client_account-console}", "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/Insurance/account/", + "baseUrl" : "/realms/keycloak-net-fixture/account/", "surrogateAuthRequired" : false, "enabled" : true, "alwaysDisplayInConsole" : false, "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/Insurance/account/*" ], + "redirectUris" : [ "/realms/keycloak-net-fixture/account/*" ], "webOrigins" : [ ], "notBefore" : 0, "bearerOnly" : false, @@ -480,6 +623,7 @@ "frontchannelLogout" : false, "protocol" : "openid-connect", "attributes" : { + "realm_client" : "false", "post.logout.redirect.uris" : "+", "pkce.code.challenge.method" : "S256" }, @@ -487,17 +631,17 @@ "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, "protocolMappers" : [ { - "id" : "3ad759e6-d488-4958-8cbd-214cc74c1ff3", + "id" : "c5d57ff9-f939-49b2-b683-a374f47551fd", "name" : "audience resolve", "protocol" : "openid-connect", "protocolMapper" : "oidc-audience-resolve-mapper", "consentRequired" : false, "config" : { } } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] }, { - "id" : "2757cade-ceef-4b8e-8770-382a9cbcc2d5", + "id" : "3e9d780b-fad1-491a-9a4b-5a7f1e359a85", "clientId" : "admin-cli", "name" : "${client_admin-cli}", "surrogateAuthRequired" : false, @@ -516,14 +660,17 @@ "publicClient" : true, "frontchannelLogout" : false, "protocol" : "openid-connect", - "attributes" : { }, + "attributes" : { + "realm_client" : "false", + "client.use.lightweight.access.token.enabled" : "true" + }, "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, + "fullScopeAllowed" : true, "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] }, { - "id" : "039323d3-a404-440e-8c6a-ac153d49a389", + "id" : "9fa91e34-0323-4bea-81fe-9bf39d58eec0", "clientId" : "broker", "name" : "${client_broker}", "surrogateAuthRequired" : false, @@ -542,25 +689,22 @@ "publicClient" : false, "frontchannelLogout" : false, "protocol" : "openid-connect", - "attributes" : { }, + "attributes" : { + "realm_client" : "true" + }, "authenticationFlowBindingOverrides" : { }, "fullScopeAllowed" : false, "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "36683383-416b-4741-abe1-4dc87a258360", - "clientId" : "insurance-product", - "name" : "", - "description" : "", - "rootUrl" : "", - "adminUrl" : "", - "baseUrl" : "", + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "89f1b73e-aa5a-44c5-afe3-1a95c2ad7c90", + "clientId" : "keycloak-net-fixture-client", "surrogateAuthRequired" : false, "enabled" : true, "alwaysDisplayInConsole" : false, "clientAuthenticatorType" : "client-secret", - "secret" : "Y6Rf8ws2JUBuKbgJ0e0daJxMAZhDtIHv", + "secret" : "9iQX2Jwffk7FCAp624Kg6deUcd5Yoxfz28tX3h8AgCPOHAZKl8QY3ymrrYZLvzj2qIuy7UTWArkjsCayVJwm68", "redirectUris" : [ "/*" ], "webOrigins" : [ "/*" ], "notBefore" : 0, @@ -571,68 +715,22 @@ "directAccessGrantsEnabled" : true, "serviceAccountsEnabled" : true, "publicClient" : false, - "frontchannelLogout" : true, + "frontchannelLogout" : false, "protocol" : "openid-connect", "attributes" : { - "oidc.ciba.grant.enabled" : "false", - "client.secret.creation.time" : "1727119527", + "realm_client" : "false", + "client.secret.creation.time" : "1783698979", "backchannel.logout.session.required" : "true", - "oauth2.device.authorization.grant.enabled" : "false", - "display.on.consent.screen" : "false", "backchannel.logout.revoke.offline.tokens" : "false" }, "authenticationFlowBindingOverrides" : { }, "fullScopeAllowed" : true, "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "29a0ed31-9c7f-4d9b-be88-663008069fc8", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "id.token.claim" : "true", - "introspection.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" - } - }, { - "id" : "4ac8cf45-a9ca-4491-a72e-5d19f4a8a93d", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "id.token.claim" : "true", - "introspection.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" - } - }, { - "id" : "21d9273f-4777-49a1-a672-aa1a915e8155", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "client_id", - "id.token.claim" : "true", - "introspection.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "client_id", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + "defaultClientScopes" : [ "web-origins", "service_account", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] }, { - "id" : "2d6f788a-ff44-4acf-95a8-18426a88310a", - "clientId" : "realm-management", - "name" : "${client_realm-management}", + "id" : "cc783ea2-1c13-4ea5-9054-f6c6d2974f31", + "clientId" : "keycloak-net-fixture-group-client", "surrogateAuthRequired" : false, "enabled" : true, "alwaysDisplayInConsole" : false, @@ -640,32 +738,102 @@ "redirectUris" : [ ], "webOrigins" : [ ], "notBefore" : 0, - "bearerOnly" : true, + "bearerOnly" : false, "consentRequired" : false, - "standardFlowEnabled" : true, + "standardFlowEnabled" : false, "implicitFlowEnabled" : false, "directAccessGrantsEnabled" : false, "serviceAccountsEnabled" : false, - "publicClient" : false, + "publicClient" : true, "frontchannelLogout" : false, "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + "attributes" : { + "realm_client" : "false", + "backchannel.logout.session.required" : "true", + "backchannel.logout.revoke.offline.tokens" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "6c746edb-79c6-4a26-abea-e261f4dc2fb5", + "clientId" : "keycloak-net-fixture-user-client", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "false", + "backchannel.logout.session.required" : "true", + "backchannel.logout.revoke.offline.tokens" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] + }, { + "id" : "f81e9552-1b70-454f-a218-abcb1be7aeb2", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "authorizationServicesEnabled" : true, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "realm_client" : "true" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ], + "authorizationSettings" : { + "allowRemoteResourceManagement" : false, + "policyEnforcementMode" : "ENFORCING", + "resources" : [ ], + "policies" : [ ], + "scopes" : [ ], + "decisionStrategy" : "UNANIMOUS" + } }, { - "id" : "c31886d0-789f-4c12-89be-0bc38eee9955", + "id" : "24da2a20-7517-4d67-a653-fdaea1118b2a", "clientId" : "security-admin-console", "name" : "${client_security-admin-console}", "rootUrl" : "${authAdminUrl}", - "baseUrl" : "/admin/Insurance/console/", + "baseUrl" : "/admin/keycloak-net-fixture/console/", "surrogateAuthRequired" : false, "enabled" : true, "alwaysDisplayInConsole" : false, "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/admin/Insurance/console/*" ], + "redirectUris" : [ "/admin/keycloak-net-fixture/console/*" ], "webOrigins" : [ "+" ], "notBefore" : 0, "bearerOnly" : false, @@ -678,14 +846,16 @@ "frontchannelLogout" : false, "protocol" : "openid-connect", "attributes" : { + "realm_client" : "false", + "client.use.lightweight.access.token.enabled" : "true", "post.logout.redirect.uris" : "+", "pkce.code.challenge.method" : "S256" }, "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, + "fullScopeAllowed" : true, "nodeReRegistrationTimeout" : 0, "protocolMappers" : [ { - "id" : "26982867-c69f-460b-8221-7a16d45ae5cf", + "id" : "f54e0862-7dc4-4bd7-bd84-169cb542eb4c", "name" : "locale", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", @@ -700,92 +870,238 @@ "jsonType.label" : "String" } } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "basic", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ] } ], "clientScopes" : [ { - "id" : "86525215-0dd9-4463-8996-449283c3ed1c", - "name" : "microprofile-jwt", - "description" : "Microprofile - JWT built-in scope", + "id" : "2618dc13-1313-4416-a4f3-0fe68e33f33e", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "true", - "display.on.consent.screen" : "false" + "consent.screen.text" : "${emailScopeConsentText}", + "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "36b91802-e07b-4c6f-bb5c-a831c5a108a7", - "name" : "groups", + "id" : "40d6ab0d-aa2a-4afb-8fa0-525385fa8d69", + "name" : "email verified", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "protocolMapper" : "oidc-usermodel-property-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", - "multivalued" : "true", - "user.attribute" : "foo", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "groups", - "jsonType.label" : "String" + "claim.name" : "email_verified", + "jsonType.label" : "boolean" } }, { - "id" : "0400a008-2e2f-49e3-9369-80cab105ae28", - "name" : "upn", + "id" : "341567d0-ec96-41bc-a26f-fe744371bd92", + "name" : "email", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "username", + "user.attribute" : "email", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "upn", + "claim.name" : "email", "jsonType.label" : "String" } } ] }, { - "id" : "51a97751-f8a0-4cce-99eb-18c98e69d402", - "name" : "phone", - "description" : "OpenID Connect built-in scope: phone", + "id" : "3fd23c9e-ed70-43ae-8dd0-8f3806351f7e", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "true", - "consent.screen.text" : "${phoneScopeConsentText}", + "consent.screen.text" : "${addressScopeConsentText}", "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "cedcae82-652e-45b9-9a4b-e63bb2b09478", - "name" : "phone number verified", + "id" : "22237a25-6451-4f8e-8863-6ceda2f76366", + "name" : "address", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", + "protocolMapper" : "oidc-address-mapper", "consentRequired" : false, "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumberVerified", + "user.attribute.street" : "street", "id.token.claim" : "true", + "user.attribute.region" : "region", "access.token.claim" : "true", - "claim.name" : "phone_number_verified", - "jsonType.label" : "boolean" + "user.attribute.locality" : "locality" } - }, { - "id" : "fedc99cf-54ec-491c-9b16-d3f5ababf36a", - "name" : "phone number", + } ] + }, { + "id" : "1880bc3a-4c25-4e62-b294-7b3cc913be57", + "name" : "organization", + "description" : "Additional claims about the organization a subject belongs to", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "consent.screen.text" : "${organizationScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "107dac77-8fbf-43e0-b47c-69262cb0a28e", + "name" : "organization", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-organization-membership-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "organization", + "jsonType.label" : "String", + "multivalued" : "true" + } + } ] + }, { + "id" : "d7e4f8ba-5b14-4e6a-b8a6-e4dfd7b63557", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "18594889-2591-4c1c-b226-75a7de47344a", + "name" : "upn", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumber", + "user.attribute" : "username", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "phone_number", + "claim.name" : "upn", + "jsonType.label" : "String" + } + }, { + "id" : "27f49184-1830-418e-8e15-87f946ff8539", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "cd4bb41a-f7e6-4b63-8cbe-020e782a539e", + "name" : "saml_organization", + "description" : "Organization Membership", + "protocol" : "saml", + "attributes" : { + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "7fa89535-7a56-4a49-bb9e-e0282af5eda3", + "name" : "organization", + "protocol" : "saml", + "protocolMapper" : "saml-organization-membership-mapper", + "consentRequired" : false, + "config" : { } + } ] + }, { + "id" : "214f7d47-eb02-4cbb-b31f-cec62578330d", + "name" : "service_account", + "description" : "Specific scope for a client enabled for service accounts", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "0e19f282-ae59-4666-a297-5fbd8a25421e", + "name" : "Client Host", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientHost", + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientHost", + "jsonType.label" : "String" + } + }, { + "id" : "9304bdfd-a140-4186-9901-85801f4f0457", + "name" : "Client ID", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "client_id", + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "client_id", + "jsonType.label" : "String" + } + }, { + "id" : "aaedccfa-4189-4959-9d9a-214fc12be859", + "name" : "Client IP Address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientAddress", + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientAddress", "jsonType.label" : "String" } } ] }, { - "id" : "72f4c14a-6563-45ea-afd1-be6fc94132ee", + "id" : "c6c8eb0f-9b9e-4211-be16-8aa25c09d037", + "name" : "keycloak-net-fixture-client-scope", + "description" : "Fixture client scope for Keycloak.Net tests.", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "335dc099-0c97-41ee-b444-9ca3fe10c343", + "name" : "keycloak-net-fixture-protocol-mapper", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-hardcoded-claim-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "false", + "access.token.claim" : "true", + "claim.name" : "keycloak_net_fixture", + "jsonType.label" : "String", + "claim.value" : "phase1", + "userinfo.token.claim" : "false" + } + } ] + }, { + "id" : "aa8e2cbf-33c3-45d0-9b65-6e5d64a114dd", "name" : "profile", "description" : "OpenID Connect built-in scope: profile", "protocol" : "openid-connect", @@ -795,52 +1111,49 @@ "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "cb8c53e2-2c33-4ac1-bef4-2408716667e5", - "name" : "updated at", + "id" : "69d4f459-61ad-42ad-8ab1-9094f2df6f47", + "name" : "full name", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", + "protocolMapper" : "oidc-full-name-mapper", "consentRequired" : false, "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "updatedAt", "id.token.claim" : "true", + "introspection.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "updated_at", - "jsonType.label" : "long" + "userinfo.token.claim" : "true" } }, { - "id" : "5cd0f5b6-615b-44bc-999b-707eda41c81b", - "name" : "profile", + "id" : "190698fc-c7cf-4a1c-9974-15d0d02e0a36", + "name" : "username", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "profile", + "user.attribute" : "username", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "profile", + "claim.name" : "preferred_username", "jsonType.label" : "String" } }, { - "id" : "ca337257-5c60-4f66-887e-e91a89a4b87a", - "name" : "family name", + "id" : "043aee78-f563-4700-8e56-4b992071b096", + "name" : "nickname", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "lastName", + "user.attribute" : "nickname", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "family_name", + "claim.name" : "nickname", "jsonType.label" : "String" } }, { - "id" : "0b0ddffd-e3ba-4df9-8167-7b45a80d5202", + "id" : "f187ba97-1c96-4cfc-afe5-8f9657a8ec11", "name" : "website", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", @@ -855,176 +1168,216 @@ "jsonType.label" : "String" } }, { - "id" : "1793fcaf-a699-4e72-8663-7067cc4ea5b0", - "name" : "full name", + "id" : "5091da0e-6553-4b76-a0c8-72a9ff81daa0", + "name" : "given name", "protocol" : "openid-connect", - "protocolMapper" : "oidc-full-name-mapper", + "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { - "id.token.claim" : "true", "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", "access.token.claim" : "true", - "userinfo.token.claim" : "true" + "claim.name" : "given_name", + "jsonType.label" : "String" } }, { - "id" : "508c4f1e-650f-4e5d-ad98-94c4de30cf1f", - "name" : "nickname", + "id" : "6ba737c7-b31b-4123-9967-0b2a7ae8331c", + "name" : "middle name", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "nickname", + "user.attribute" : "middleName", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "nickname", + "claim.name" : "middle_name", "jsonType.label" : "String" } }, { - "id" : "53668a88-864c-4b81-9d0f-c3eeee1e5181", - "name" : "birthdate", + "id" : "1c26f98a-8d70-42f2-9fe3-a72848e2cd81", + "name" : "profile", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "birthdate", + "user.attribute" : "profile", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "birthdate", + "claim.name" : "profile", "jsonType.label" : "String" } }, { - "id" : "ed84c35a-bcca-418b-908e-7b922ea96042", - "name" : "username", + "id" : "2e8824dc-e996-4837-a45a-615112710261", + "name" : "zoneinfo", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "username", + "user.attribute" : "zoneinfo", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "preferred_username", + "claim.name" : "zoneinfo", "jsonType.label" : "String" } }, { - "id" : "09a0cd0a-48f7-427e-88b6-5abb5821b483", - "name" : "gender", + "id" : "6471df6a-d772-421f-9572-fec0a5866d47", + "name" : "birthdate", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "gender", + "user.attribute" : "birthdate", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "gender", + "claim.name" : "birthdate", "jsonType.label" : "String" } }, { - "id" : "54d41d70-9c74-48fc-b88c-77dddfbb193c", - "name" : "zoneinfo", + "id" : "40b06788-5b31-47a1-a190-ae4c4f54579c", + "name" : "updated at", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "zoneinfo", + "user.attribute" : "updatedAt", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "zoneinfo", - "jsonType.label" : "String" + "claim.name" : "updated_at", + "jsonType.label" : "long" } }, { - "id" : "f1c6a700-a25b-4b84-8c84-1851b20195fe", - "name" : "middle name", + "id" : "67bea96a-afd7-4b7a-b901-98e2d91c52b0", + "name" : "locale", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "middleName", + "user.attribute" : "locale", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "middle_name", + "claim.name" : "locale", "jsonType.label" : "String" } }, { - "id" : "46c31adf-b9c8-4842-9850-0f6a8106664d", - "name" : "picture", + "id" : "c3d199dc-2941-485d-8516-362b6e04c459", + "name" : "family name", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "picture", + "user.attribute" : "lastName", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "picture", + "claim.name" : "family_name", "jsonType.label" : "String" } }, { - "id" : "9535fcac-c5cf-43eb-9664-0aadc4101a41", - "name" : "given name", + "id" : "19306e0c-10d0-4f49-934c-9f0298b4751a", + "name" : "picture", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "firstName", + "user.attribute" : "picture", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "given_name", + "claim.name" : "picture", "jsonType.label" : "String" } }, { - "id" : "e055beff-8c2b-436a-9c56-eb2a57a6bf00", - "name" : "locale", + "id" : "6f1fe5a9-0725-4d7e-974b-c7e0295b78cf", + "name" : "gender", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "locale", + "user.attribute" : "gender", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "locale", + "claim.name" : "gender", "jsonType.label" : "String" } } ] }, { - "id" : "c0446948-7f87-4236-a8f1-f43c48ba0475", - "name" : "web-origins", - "description" : "OpenID Connect scope for add allowed web origins to the access token", + "id" : "7ff1179d-a152-4a2a-b4fb-c9e06ecfca46", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "false", - "consent.screen.text" : "", - "display.on.consent.screen" : "false" + "consent.screen.text" : "${rolesScopeConsentText}", + "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "365b868f-ee02-4171-b6c8-f11591517f4e", - "name" : "allowed web origins", + "id" : "fd8d3616-c9c7-4cfe-af1a-40ea675521b9", + "name" : "realm roles", "protocol" : "openid-connect", - "protocolMapper" : "oidc-allowed-origins-mapper", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "9adadedd-2c62-43af-bc1a-92d8bf619cb2", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "access.token.claim" : "true" } + }, { + "id" : "81babb2c-6ca2-442e-95b4-9377d83f859b", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } } ] }, { - "id" : "dc340fa5-1034-4398-8c19-823ebe156936", + "id" : "42e4a0b3-a193-4fd8-bab6-2a3901b758d5", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "ae65b034-751c-4aa5-99f2-45278f94c386", "name" : "role_list", "description" : "SAML role list", "protocol" : "saml", @@ -1033,7 +1386,7 @@ "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "cb5a696c-ab11-46d4-a6f2-8016828cd185", + "id" : "22ae630b-20db-4253-82e7-71471d153c52", "name" : "role list", "protocol" : "saml", "protocolMapper" : "saml-role-list-mapper", @@ -1045,191 +1398,139 @@ } } ] }, { - "id" : "a0da6176-8114-4bc5-b24a-c9d33aa6aeed", - "name" : "email", - "description" : "OpenID Connect built-in scope: email", + "id" : "311ea07d-9fc2-473e-9e87-88ef52e3a729", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "true", - "consent.screen.text" : "${emailScopeConsentText}", + "consent.screen.text" : "${phoneScopeConsentText}", "display.on.consent.screen" : "true" }, "protocolMappers" : [ { - "id" : "833966b9-7f0d-4188-9c12-1d987887140a", - "name" : "email verified", + "id" : "7528bed7-fc88-4b79-ab9f-d64d6f9d09d4", + "name" : "phone number verified", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", + "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "emailVerified", + "user.attribute" : "phoneNumberVerified", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "email_verified", + "claim.name" : "phone_number_verified", "jsonType.label" : "boolean" } }, { - "id" : "b841f839-7141-4eaf-a166-cecc9d49eb15", - "name" : "email", + "id" : "57d621dc-3156-442e-8c70-816c04dcaf22", + "name" : "phone number", "protocol" : "openid-connect", "protocolMapper" : "oidc-usermodel-attribute-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "userinfo.token.claim" : "true", - "user.attribute" : "email", + "user.attribute" : "phoneNumber", "id.token.claim" : "true", "access.token.claim" : "true", - "claim.name" : "email", + "claim.name" : "phone_number", "jsonType.label" : "String" } } ] }, { - "id" : "63c2c1ff-6e89-4e9f-a414-85085ff4d2ec", - "name" : "address", - "description" : "OpenID Connect built-in scope: address", + "id" : "bca36b95-d501-41fc-bd18-8d82823cde6c", + "name" : "basic", + "description" : "OpenID Connect scope for add all basic claims to the token", "protocol" : "openid-connect", "attributes" : { - "include.in.token.scope" : "true", - "consent.screen.text" : "${addressScopeConsentText}", - "display.on.consent.screen" : "true" + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" }, "protocolMappers" : [ { - "id" : "438122c8-eae4-40f4-9a43-8da71766e607", - "name" : "address", + "id" : "f272c0e9-3861-4ce4-a308-776926e4bc6c", + "name" : "sub", "protocol" : "openid-connect", - "protocolMapper" : "oidc-address-mapper", + "protocolMapper" : "oidc-sub-mapper", "consentRequired" : false, "config" : { - "user.attribute.formatted" : "formatted", - "user.attribute.country" : "country", "introspection.token.claim" : "true", - "user.attribute.postal_code" : "postal_code", - "userinfo.token.claim" : "true", - "user.attribute.street" : "street", - "id.token.claim" : "true", - "user.attribute.region" : "region", - "access.token.claim" : "true", - "user.attribute.locality" : "locality" + "access.token.claim" : "true" } - } ] - }, { - "id" : "9dbf391f-e23d-4e11-9c96-57357ee1c0a3", - "name" : "acr", - "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "f74840ec-d857-42f0-a9c7-ea85575a8578", - "name" : "acr loa level", + }, { + "id" : "3913019f-1341-4e46-946a-ee9f24f4b770", + "name" : "auth_time", "protocol" : "openid-connect", - "protocolMapper" : "oidc-acr-mapper", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", "consentRequired" : false, "config" : { + "user.session.note" : "AUTH_TIME", "id.token.claim" : "true", "introspection.token.claim" : "true", - "access.token.claim" : "true" + "access.token.claim" : "true", + "claim.name" : "auth_time", + "jsonType.label" : "long" } } ] }, { - "id" : "101a6d3e-0dff-4689-84d7-51ffeacea592", - "name" : "offline_access", - "description" : "OpenID Connect built-in scope: offline_access", - "protocol" : "openid-connect", - "attributes" : { - "consent.screen.text" : "${offlineAccessScopeConsentText}", - "display.on.consent.screen" : "true" - } + "id" : "dd0b0401-3c06-40cb-ba5f-7ea99bd4a147", + "name" : "AuthnContextClassRef", + "description" : "AuthnContextClassRef Level of Authentiation", + "protocol" : "saml", + "attributes" : { }, + "protocolMappers" : [ { + "id" : "dcf2556b-a8ca-4656-b1a9-53a58dfa947a", + "name" : "AuthnContextClassRef", + "protocol" : "saml", + "protocolMapper" : "saml-authn-context-class-ref-mapper", + "consentRequired" : false, + "config" : { } + } ] }, { - "id" : "c13df977-56af-4407-a4cd-f2c9343be370", - "name" : "roles", - "description" : "OpenID Connect scope for add user roles to the access token", + "id" : "6db2f38d-e4dd-4054-80d8-c848e4731ebe", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "false", - "consent.screen.text" : "${rolesScopeConsentText}", - "display.on.consent.screen" : "true" + "consent.screen.text" : "", + "display.on.consent.screen" : "false" }, "protocolMappers" : [ { - "id" : "2f281641-0058-496e-a797-377b8a79802f", - "name" : "client roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-client-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "introspection.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "resource_access.${client_id}.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "0c16fd05-3950-4338-bd3b-a82a31ac5435", - "name" : "audience resolve", + "id" : "4610a64f-5b49-4c62-b775-14786b9ae7f5", + "name" : "allowed web origins", "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", + "protocolMapper" : "oidc-allowed-origins-mapper", "consentRequired" : false, "config" : { "introspection.token.claim" : "true", "access.token.claim" : "true" } - }, { - "id" : "87963b59-193d-4122-84c6-b529a5f7fbcb", - "name" : "realm roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "introspection.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "realm_access.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } } ] - }, { - "id" : "b9b1e633-45bf-4602-a9b9-9e5573da2caa", - "name" : "basic", - "description" : "OpenID Connect scope for add all basic claims to the token", + }, { + "id" : "b23adac4-2425-4a7e-8ac8-8c497a124899", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", "protocol" : "openid-connect", "attributes" : { "include.in.token.scope" : "false", "display.on.consent.screen" : "false" }, "protocolMappers" : [ { - "id" : "5927c623-eb83-42be-a336-7383039e8353", - "name" : "sub", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-sub-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "access.token.claim" : "true" - } - }, { - "id" : "5999c07f-831a-4e8d-b4e8-6e17f6d3b061", - "name" : "auth_time", + "id" : "8e745ba7-b711-4717-b9a6-9a238b152075", + "name" : "acr loa level", "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "protocolMapper" : "oidc-acr-mapper", "consentRequired" : false, "config" : { - "user.session.note" : "AUTH_TIME", "id.token.claim" : "true", "introspection.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "auth_time", - "jsonType.label" : "long" + "access.token.claim" : "true" } } ] } ], - "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr", "basic" ], - "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "defaultDefaultClientScopes" : [ "role_list", "saml_organization", "AuthnContextClassRef", "profile", "email", "roles", "web-origins", "acr", "basic" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt", "organization" ], "browserSecurityHeaders" : { "contentSecurityPolicyReportOnly" : "", "xContentTypeOptions" : "nosniff", @@ -1237,7 +1538,6 @@ "xRobotsTag" : "none", "xFrameOptions" : "SAMEORIGIN", "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection" : "1; mode=block", "strictTransportSecurity" : "max-age=31536000; includeSubDomains" }, "smtpServer" : { }, @@ -1246,11 +1546,62 @@ "enabledEventTypes" : [ ], "adminEventsEnabled" : false, "adminEventsDetailsEnabled" : false, - "identityProviders" : [ ], - "identityProviderMappers" : [ ], + "identityProviders" : [ { + "alias" : "keycloak-net-fixture-oidc", + "internalId" : "c7250f3d-1289-469c-97f6-1cf038dbd28d", + "providerId" : "oidc", + "enabled" : true, + "trustEmail" : false, + "storeToken" : false, + "addReadTokenRoleOnCreate" : false, + "authenticateByDefault" : false, + "linkOnly" : true, + "hideOnLogin" : true, + "firstBrokerLoginFlowAlias" : "first broker login", + "config" : { + "userInfoUrl" : "https://fixture.example.test/userinfo", + "validateSignature" : "true", + "clientId" : "keycloak-net-fixture-idp-client", + "tokenUrl" : "https://fixture.example.test/token", + "authorizationUrl" : "https://fixture.example.test/auth", + "jwksUrl" : "https://fixture.example.test/jwks", + "logoutUrl" : "https://fixture.example.test/logout", + "clientSecret" : "fixture-secret", + "useJwksUrl" : "true" + }, + "types" : [ "USER_AUTHENTICATION", "CLIENT_ASSERTION", "TRUST_MATERIAL", "EXCHANGE_EXTERNAL_TOKEN", "JWT_AUTHORIZATION_GRANT" ] + } ], + "identityProviderMappers" : [ { + "id" : "e84b2b34-ddea-42b8-a7e2-58695ed35cac", + "name" : "keycloak-net-fixture-idp-mapper", + "identityProviderAlias" : "keycloak-net-fixture-oidc", + "identityProviderMapper" : "oidc-user-attribute-idp-mapper", + "config" : { + "syncMode" : "INHERIT", + "claim" : "fixture_claim", + "user.attribute" : "fixtureAttribute" + } + } ], "components" : { "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { - "id" : "9350aee2-38d2-4ac0-9ca3-5dc25ac85c1e", + "id" : "d148c15d-e74b-4f8e-be9d-edd4e858ca6b", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "d3b1cbc3-8749-4bef-a349-0d91e7fdd22e", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "45c8b364-0ae7-4ca6-96ba-3432352adc0b", "name" : "Max Clients Limit", "providerId" : "max-clients", "subType" : "anonymous", @@ -1259,118 +1610,114 @@ "max-clients" : [ "200" ] } }, { - "id" : "68f345b0-a14f-4970-af09-40e9f31e3b7b", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", + "id" : "d1e88593-d9af-43d2-a63d-cdda3d981a8a", + "name" : "Consent Required", + "providerId" : "consent-required", "subType" : "anonymous", "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper" ] - } + "config" : { } }, { - "id" : "cd790caa-4f9f-4c3d-b6a2-d4317aa6c462", + "id" : "63e53c78-ed68-48a5-8534-d09196ecc3f8", "name" : "Allowed Client Scopes", "providerId" : "allowed-client-templates", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "d77a6066-5c37-43a5-98e4-c48a93d8e3c7", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", "subType" : "anonymous", "subComponents" : { }, "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] + "allow-default-scopes" : [ "true" ] } }, { - "id" : "ea1b655b-4f39-45d7-bd08-db294086b601", - "name" : "Consent Required", - "providerId" : "consent-required", + "id" : "f79bae00-b451-40f3-8291-cf25d429881a", + "name" : "Allowed Registration Web Origins", + "providerId" : "registration-web-origins", "subType" : "anonymous", "subComponents" : { }, "config" : { } }, { - "id" : "1b3b4311-d437-4d4e-9d8c-fbf5da1eb93c", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", + "id" : "7f1daefc-672c-4449-922b-3df6bed68d57", + "name" : "Allowed Registration Web Origins", + "providerId" : "registration-web-origins", + "subType" : "authenticated", "subComponents" : { }, "config" : { } }, { - "id" : "d46a0e74-2140-46b1-844b-535f1527b23d", + "id" : "73c5bf4e-332a-4ff1-90e5-3a4c8dced7f6", "name" : "Allowed Protocol Mapper Types", "providerId" : "allowed-protocol-mappers", "subType" : "authenticated", "subComponents" : { }, "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper" ] + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper" ] } }, { - "id" : "2cab966a-d2f7-45ab-b6ac-6844563015d6", + "id" : "8e26489d-7272-4901-9a04-702f4e0eaae0", "name" : "Allowed Client Scopes", "providerId" : "allowed-client-templates", - "subType" : "anonymous", + "subType" : "authenticated", "subComponents" : { }, "config" : { "allow-default-scopes" : [ "true" ] } + }, { + "id" : "4d15ff97-dd08-4156-8822-73e83e221cd5", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "oidc-full-name-mapper" ] + } } ], "org.keycloak.keys.KeyProvider" : [ { - "id" : "a418139b-a099-44eb-9b11-587cc2502549", - "name" : "rsa-enc-generated", - "providerId" : "rsa-enc-generated", + "id" : "46d29878-4222-4172-8a43-d09cef39d3ed", + "name" : "aes-generated", + "providerId" : "aes-generated", "subComponents" : { }, "config" : { - "privateKey" : [ "MIIEowIBAAKCAQEApW/+vp2RpK9PKmWy7HE3z0Ks7PA98f35LGnLlV2CbBXnF4fF4QqXGXd4i9AtMq8cSq5krVytcCSlYsaQdg+9BfvnC3HqUMngZPz9Vlg99Oy2yjJOYfNEngw7RIVX2bbkgzSrLhmFobdU2aNtRDabhIb47lpDnBWTmR+dABTFfmbwvmXIKj6uO7qJ/qRFjqzwjaSOsYKLmVhz+efHFYiJKLbHa+U2y9oKOjZzRbABEVn2Ib/5UeOj+5IZehHN2t0p+BrKuSBgJ1bIKvvdlOpbKkFFD/RkTZCQNBH0U+VEZKPr1XnI1T73NVHCx6W9ee46TJyfPp165cTWGmWt8iJowwIDAQABAoIBAAFTV7vcJgO1WFVDTK1EUTCa1bdtoOpSy73eP5XKIOhIzKSNn4B94leb5Tq0OWwKw5d9mHMjJy+3gpAtKHR/DDsf0j+oHckumHc9y0AT3Hs5sIxc3e/ppYbhVG52kGK/TfXeSCqfgUiaNXMro9S2FtsiGNXY9023Tac64WS3cI6NJxPN8lnc6Gbw9CsZc4g/q1UudGlfbCP2cg4YUQDjHGbB2NHUtHV+Ja5ul/KiJAmWqjFjjZ5JqPLYrJSg5rtO3u77pJXjdEjoW0Pk/6Th//nQMHhPzmJqpbTCM+eN9fxuXxvlYWTOwNmnO52Tm2mh45JOMzslVkoEmzR8tr8K56ECgYEA2EVzPmVwDHJdy7qIZ4Ac2za6dxxHQMNxtL3bp+BTdcSQZM08NyZ7gn+g/GYJY7xbcIPZ0jKlZpz7BJlw/TFhWI/nw9lDsURF3Q9NQgyuUVTkczoxJOVyMyKIZ/gIbDCMwIR4DmEkINX+T3uk4+/HKV/+2WZqi+LH1eqWeKjmbFkCgYEAw9P+KaiRSt2cOrgbPAXaEJdewKwr7dt3Qn3zpNm3GhBkj2lfnyE6UKDGI51ONa1hNwvgWnFjqcjV+siBRqWrQpT8hvC+Q6x6B3p030zuYCkigTRsPSGhSHL6APB1SCQZV+3bSjuyrQGS951rFE3TD1ASkbp0Uc3maX+xdtcb6nsCgYEAvocwp9+lftGiYEDMuqHayiTE0PpQq3WDTr+UK6ks3at1qdhFHDECzkyx/qnFy9+8jrsZwlxr6qKRYdPr/qLqJ6NfguJ9CEYlZkJ8xZt2VqB7QigZ829P1Eyv7yhMA0QiO9h4C/L4aRUdHdjHwycSRhkT42Kequ33LzWjqljh5sECgYBI2gv6+YAb5vfhDG7tVIv8kiOo8CRjl7r1XKAQmwI4SxLuG1h8fcMRDc7InxPiej7pWJy9aOOX3WRlqMQXQTjGS2Dq3pMZ4AeB0re5/wfLdGImyRbfYyx6JHQHd21aSju3b4CeTDk7jZNcVQ7p/c3gK3zNBB2T9VKbuuqNeJclEwKBgCCZ2R9IFNC1Wkf7i2sH6HWNb69WKSB4c0kGES8//2UN8t1ogAMxAwHNshHEkyoT4rMC/eEvS0NpRqrBGjs/QooDaDqXktVJsRdZmP95j3mt7YWYabbhsd3CWLylNTYHKjZ/QOksQNEvil5CXdkrHG0B34sZOgAMb4sm3KJ82RlH" ], - "keyUse" : [ "ENC" ], - "certificate" : [ "MIICoTCCAYkCBgGSICaN7TANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlJbnN1cmFuY2UwHhcNMjQwOTIzMTgyOTEwWhcNMzQwOTIzMTgzMDUwWjAUMRIwEAYDVQQDDAlJbnN1cmFuY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQClb/6+nZGkr08qZbLscTfPQqzs8D3x/fksacuVXYJsFecXh8XhCpcZd3iL0C0yrxxKrmStXK1wJKVixpB2D70F++cLcepQyeBk/P1WWD307LbKMk5h80SeDDtEhVfZtuSDNKsuGYWht1TZo21ENpuEhvjuWkOcFZOZH50AFMV+ZvC+ZcgqPq47uon+pEWOrPCNpI6xgouZWHP558cViIkotsdr5TbL2go6NnNFsAERWfYhv/lR46P7khl6Ec3a3Sn4Gsq5IGAnVsgq+92U6lsqQUUP9GRNkJA0EfRT5URko+vVecjVPvc1UcLHpb157jpMnJ8+nXrlxNYaZa3yImjDAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGhanbIOfgnUjJGGKmpDQVWfxxcVe62fSimLLhC9vfCAbr2LZb31j33o4r6E6s3yqgpaXiaK+SknCUehQQ4eVDDXViWingmt5eeW4FVXFyfhB9Jd5NJRYKQay0NImbWl3B+ELfiJlJYqCJiGRjzfLrLwf5ddY4L/XRL0tp9IyWOrzJWBEdg8d0ODtThcjlc43izvRbUKp9E+HjqeMtpjIoKmcNAC5USKbUM1WIe7qN7OVhr0CNDF1fU7EBEzk0KNwgNj2lmVZbmijAE6NxAKt2GtxkP54M4XznZZdfFY3X2IhvUySoVcqXF4DVT11HOyoo6pJsjAnG2INPz+HbH1a6w=" ], - "priority" : [ "100" ], - "algorithm" : [ "RSA-OAEP" ] + "kid" : [ "80720b2a-56f8-4049-8307-736674838497" ], + "secret" : [ "U4_mT1ON2vraMOxYujUgQhbSP9DnKtIP2ZDXEczE0MA" ], + "priority" : [ "100" ] } }, { - "id" : "7d704874-43eb-45ba-a4bd-b7ecf691b91f", + "id" : "2362de8e-28b6-4a35-9589-c7b807695ac8", "name" : "hmac-generated-hs512", "providerId" : "hmac-generated", "subComponents" : { }, "config" : { - "kid" : [ "2f4fbf54-7719-49d6-af2d-3779e29409b6" ], - "secret" : [ "K1kGVhBhZGzty-rd6cTJBRreNgbfKxIxnslH6eAbZOVgCm0S_KhZ6yfi-PD8qzeS41fRkwc1J0KMh2UOORaka3SDs60jFiT7cu7Tvieu8DfnXLNUBmbfm1dce927aBUOZDsY4kz2Tz8nFjQPDJOGyfuABTNYR5WIqXs1alOh2B8" ], + "kid" : [ "629e5ee0-6f7f-4535-b135-4ecf7e961826" ], + "secret" : [ "P9LPtoVEX4y26fX8sPr-kp4rF_b4NBzITrLSsFTRZlGRRdyu1iBF2-GquB2xvBYl5GZVIxEPmWZwOq4h7YnTO0Q5xJiYsrf0zVqSb4SluQVm8macuYrA6gKG-jwZUQWZG_z5utqZR2ptOU_w6lcAYLQJonLEP0HwdT3QaBcNxrk" ], "priority" : [ "100" ], "algorithm" : [ "HS512" ] } }, { - "id" : "1416172c-d799-4aed-b6b0-242b28008f03", - "name" : "aes-generated", - "providerId" : "aes-generated", + "id" : "851149f6-bce0-48ae-b00f-4130bf6cec39", + "name" : "rsa-generated", + "providerId" : "rsa-generated", "subComponents" : { }, "config" : { - "kid" : [ "40d3a060-8409-4aaa-9d80-956211f015a3" ], - "secret" : [ "fsmCpvopbYEMMgYo2J0HSQ" ], + "privateKey" : [ "MIIEpAIBAAKCAQEAvJsiRJGacCFwfh/Of2eWPYi3eSmRsSsNJYjmDkA3112/5f5YKDgvAZ+zzZv3PwYEmo3BskSmiPjtpNXpHb6iYNLgJCxriPO2xLeBgK5aykrPlM7wQrdD0b4l5Kg7gIxb/ASR5vwrraiRiWxn5X9qDRu26IrQwTeSYZizWPsRq2iVTRfDAbTBHgcQYXP8bkQZz95CsLzd0KLlOCCuEoFEpSE4P2BahSAxgTy4Zd+/dpWPDXbEfOhduyZW4xqF6uF5DVGQYGnNk0OSjx4ZR5w190rw3fwCcr6qCTrbU+siiT/oS0bTaNuzh1Vp5i3OXrB/atdz80TX/wqrxht9kOqhuwIDAQABAoIBABWPlodILeOLrxR8BltCOEaojnDnc6RRS5ty3vnaFYglS367aNCQO69v1lo27jjiMzyH4BDFEFSwQFqLqa6g0GdJNB5uhYyOb+JlKATR6ccebkSQs56s3K/pkONm6AZ2BT32N8e0JDoh/yE6p1XxDuqYtHw5AkxUUgOeNUKC0S5K/98+bmcSlKrvpbhKrBCDSxrhO4ejWDcXYkNXsKgG89Ex1Qz8cEIQOzKw1IOTwfDCwqltqFbK2zbrPpOgx8WtMto7EdcECgS6QVYMG2bLasZ0DtRvdCTerN9P0SlRxatGfVxEj8dRdgcIUFlgcUly5cm7jjW6FNpja8c6wbD7SyECgYEA9JLNLnQx0PrECtZGxR/MsegBBla4EJ5u+TeMazQGEKlLixAzX1SXi7JOTauiUVKObjOK6z8m2p911xPnBj14dUmiD8Fyu0xvhp3PAQ3e3J5Y29NyOPcWDP+kdkiRGzNsBMjII3TfDrCTNFC+x7mKTWyI2s5c5a+FMCaYP4Y0BKcCgYEAxWrwUNhgxvIL6uSwJHj+3jIRxl4oV9eZJ6NMGDwerTaM4vCGmabhlSuZSwEHzNd2rZ/SXar9chlrJt6q+g7USixz6G0DVlER5Euaw+6bQyQ6NHXj1rrYQUIDLNSUbNogrj9R2t/aSp0i/8+hx5JH+yncnBt3GRyH3nz7oAy62M0CgYEAoF5GNiiwpaRYufZpL0a7tQg468wfI56Pi9DVvVG+jFxGEaiM1vyj5lEDsUBSzdpBVJdthvXA52faIC6HtPrHqriekJA7R/9FvdJqcvmCYc1e3L3YTuwNxHY4g+rvYxOjx7tUKJOw03QLAinT/yh1PHFnh3n7RgyCW+FiwXyhTU8CgYBsxYAFO0MPOlugn0IBxny+1h1/C2/0/kBPW6TYkX9hdnXnsBipXg5ajzwV3Ep87ZZhEXbpzwV3sVOdhf/0aOlEuPtf63h0PZS7EYEDRVtcggBj2TSgoi/2vLVdJP9mfkSVXSPvkXkHtU6MXc1IVWu9khIQHP3g4xxlVL2bMIheXQKBgQDG/IrigFxG8rnUZZe3cr70ncMC/XpJYUc4XEneZE1O+oA3rF/FRaeEBXQQC9NjQ5Nc3XQI63Fi8F1RDcgGAmLUa4ZFIfyIv39FGmmJVJbF+cVi5gskqEw6aGN6A3EcleADdqC5xkj6hWATH/0MMsUksB7aUiyE71X75zjBEJgT2A==" ], + "keyUse" : [ "SIG" ], + "certificate" : [ "MIICtzCCAZ8CBgGfTL0B+zANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRrZXljbG9hay1uZXQtZml4dHVyZTAeFw0yNjA3MTAxNTUzMDNaFw0zNjA3MTAxNTU0NDNaMB8xHTAbBgNVBAMMFGtleWNsb2FrLW5ldC1maXh0dXJlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvJsiRJGacCFwfh/Of2eWPYi3eSmRsSsNJYjmDkA3112/5f5YKDgvAZ+zzZv3PwYEmo3BskSmiPjtpNXpHb6iYNLgJCxriPO2xLeBgK5aykrPlM7wQrdD0b4l5Kg7gIxb/ASR5vwrraiRiWxn5X9qDRu26IrQwTeSYZizWPsRq2iVTRfDAbTBHgcQYXP8bkQZz95CsLzd0KLlOCCuEoFEpSE4P2BahSAxgTy4Zd+/dpWPDXbEfOhduyZW4xqF6uF5DVGQYGnNk0OSjx4ZR5w190rw3fwCcr6qCTrbU+siiT/oS0bTaNuzh1Vp5i3OXrB/atdz80TX/wqrxht9kOqhuwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAYeSyyNrRiYjGvp8HoHgYUfJsL5DZXcc0IQ5nAO5cRAva+KDMDsvE+amucE3DKov3zy1cwNNYqFAaSNhTgCgF0AzQjkjVyv6IFEKQwoGJ9kztsG6ACnJ3FO96t+ZnGihtnt+NuRXeD4VT2nszvTTaFn9N3STPfXZvXy1HLlsIgsRPSY7+GnwTlpWhC9jxJMn+k9KFNRg+Zo0vnoufFAjT2VWtdUWRNGOMaD0KLaUNuT/Z1FzfVEHFNvOW7DmyLuMrdvHEo2OQpQ9meYvuxvzvfkuLwOJb3F9S32yjRqR+BvCGNEJAv50imQKj0AyCULkuogMV3YHtBq51Bdp6rcRZ8" ], "priority" : [ "100" ] } }, { - "id" : "135e50b5-631f-44ef-b923-6e8ebb3f9089", - "name" : "rsa-generated", - "providerId" : "rsa-generated", + "id" : "5f2d04d9-eec9-4491-a320-bf29b4638524", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", "subComponents" : { }, "config" : { - "privateKey" : [ "MIIEowIBAAKCAQEAx3fwkFAh2hTq3EyG3C31Arq+CACFO0g9b2mmuySB/xuQPKDtPZr/VxBND8M1SstZvp7bccIwQjH0IJ0LYIxzrlCjntGnL7I83QmP+MSUrfdKJO3UodQqPSAnpnXwnJBUU0J3il9DmnenFDtkXgu1t/3PL4l+Ee8HwhuIJwyV89Yp1ux8k5gp3X4HAbRnCyKdDCJ0MS4l5AxtUsWOnH8VNYZpQ/fHWd8630npt/D+bG4WTV4pb0GV0xCTuG/ueLhijVzEln7AViyBRbQ+gkCX9W4eC8YRyqAXo7fi3lOwqYU1iBAaiLNf2rSekngazyueWRZUM2Q9/XHpmQkOTowiFQIDAQABAoIBACs609C7BTMqAGKhVUMH1Md0KHY8gqN/+wyX5bI+bcwXsbFqITCOVJOObV0irfyZSMh2zlF/yAy4ndOppYsVtYaMZIGpp2W/Z9Bx35mHJT/0zcVmJAS0ojjgLKe3fN+5qgTnbVf4YILsNrI8UvrM5+PJ5qrDTibd2p0XcXEhGaigGZnj0B80f7vBjDQbnF2j24IpbIbtBAikEuY+7I5bo+QQSr2Nfw0Vhlb40WcbuUsSONHfKOl7oDyat8w5YTG+elAx+7ZkZmLO+JMee2+m0Rzg3sFisYj2JpxjrrZAeBayr+aOHmbvmEC40eikrpicOz9xGfkDxF6Rn4qrKW6yWcsCgYEA/Rjb463PAZ5dvJzwXpzH5PKEL1nsRdvU6aupHXo2lyEzVHhlxHJPxaoXyXSXKVVB3OGFC0VEbDv1hY4/0jPKCDMlK82klPk9Agj2U6QnTAZLjfNiCw5w3kPsU6XPl4Hpu+NOvWt+LdEnFJ9K2FDVs7SCjah1Uo9QSgc3lCcCEwcCgYEAycGd91Ukp+CDuB6H19pEdQiPXCFVhY8mSGl7bjfPGSSR00pvYsoQLPgAnfrbcVnVTo1q7LaeTLSQ9+N1qltpnb1xA1fVGYZY/fOS0lyl2ZHvQ9LByYPEUKj+RHNVSyP4d4Depy5+G2cfKxCNyA/jqq68gG/02f7FmeenEMWzjwMCgYBdje/R9DBdl81sZ9KOFoPpRB/KZQHqPL0x9ssXY1KEgLg5lBuCBwMnvJz4UYmCtMoYvJ/yL5OAMpWp3ZAHwi7+4vDthSE+E/cSJn/vIPGJr5YEDaADGD5uWkskDFl01oewdPBpIi/M/c/lVpBS72Ze++16MXfUobb69jn8IIMqxwKBgQChnZl+kRPF7tFU4hALVurTnUHJmWI6lMsj4mtfhRE+oM63pL7JMff3LcrAwjya9k0qmZn3eOoho9sk125gQs298AzhkrA/vCD5fO412MV6Ha6+c8uMMyNFQbo89u5yPKRChlbVMScPqHGNO7t3cVL8XPDfKc/H+JAtkyV/B/+oJQKBgBXpJqXVbvNtiff/JWVK9jM5lloyQ3YjMq3nHe+xavjIjfAMohxWSZIL7I5jPNaV8TglFNzm2VLmUvgKRWXixIK+lr2C6rd20XDLFSlyo4WX0EomUZvco6VEhcR7ehI2z2VXUhXeC+OKuvJw3Vh6o14kln6Rpwvl1RVw5eQ7cwDH" ], - "keyUse" : [ "SIG" ], - "certificate" : [ "MIICoTCCAYkCBgGSICaMcTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlJbnN1cmFuY2UwHhcNMjQwOTIzMTgyOTEwWhcNMzQwOTIzMTgzMDUwWjAUMRIwEAYDVQQDDAlJbnN1cmFuY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHd/CQUCHaFOrcTIbcLfUCur4IAIU7SD1vaaa7JIH/G5A8oO09mv9XEE0PwzVKy1m+nttxwjBCMfQgnQtgjHOuUKOe0acvsjzdCY/4xJSt90ok7dSh1Co9ICemdfCckFRTQneKX0Oad6cUO2ReC7W3/c8viX4R7wfCG4gnDJXz1inW7HyTmCndfgcBtGcLIp0MInQxLiXkDG1SxY6cfxU1hmlD98dZ3zrfSem38P5sbhZNXilvQZXTEJO4b+54uGKNXMSWfsBWLIFFtD6CQJf1bh4LxhHKoBejt+LeU7CphTWIEBqIs1/atJ6SeBrPK55ZFlQzZD39cemZCQ5OjCIVAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADHXenOhhn0frYtKZKtabJmEeI+gAnrrblaz5+z2LDBU4dojobpJVdJXVteTTKp68Zy1QHHy8/PVT5UJ/KsujROiVV/tthK8n/hy1U/7Jyn4li/NhcgjpIGMYwwwIIx6GQucLgEKRC0y9J0vKJ+m9kHyuAhmS1miBICZ2pNuSvNtgaRpXv9tlJ8d3FDgN8BKjjKevUIXk90FSEEcjW1X4+vldQhr3USeRu4kyfYNWAgEqfYgFB3qr1lKbwEhjwbbKGAYnKlwF7fHgNbmY7IC/hcOmd8WsVnCi01EBrLInMxun3i4/fXII7k/qGCt14dcrFTjY+BB3s1tnALuXAq4kCc=" ], - "priority" : [ "100" ] + "privateKey" : [ "MIIEpAIBAAKCAQEA4FQ2uVba9ZkIPOOx5qhJ+p+ZmlUc2lDpXr5MWvBKh+9Tz/D3G3kfPK8OUgfy4I0k6qISmYt25u+UCnLhvW7R/oEbX1HrOF+VbEmwulxkD2Bj0hsIUrEw7NnVkdCVeRQBIXjQ83xiLYIz50Xy3dVi0i06V92xQEsGYrUdN74FstCpGd5UZ4S5SJlL7SuH/JVw7GzKCl21+d6gjFGa93dA+7emRSSClmv9EVW1LH2SLJbtcaTnx5K4PyUzVV9i3nQWqHBeYZ5S7WpZ0y5IZ43Ub9CTl96hK9cv2XBGZyDMvdbpjbXbahvBPWjTXq2jzBAj1JEaRrXCwTtoriEgqgUVnQIDAQABAoIBACzuKRTHlOzudPQvHb1nVQPlzf/XjsMaRBemEUiAisj9siF6r5+Yy50dqcZb0bVQh8WX5xZKVOsNrq7GEjkdFmG9baRSlcRxfo3VF5jH8wGSaoPVRr47P6OcwLYnGx0IWO6hkmZGMirPwoIOpEVynQugI+if3kXUkQeZo2u7+0u0N7Tzi+SGLhxhkOWtyKgILt7T/81vtEHi5zEWhQsVywXHpLZWWaqFHV6iiDC2WYl4e3xkilyP0CRhaFtoYjSZ2ThpnSHLmhK48FftYwl3vXMXniKnQucEkCONwbbP0l1pRhgzdWh+RgMpw080BRjbIN5pcvGbqgkE/1R2jTpH0CECgYEA9rcRd7IeDNuwpRslVeabSWmvkvY6V9ppRyvtzY27fACZ3mhYwmYtW9HZcKOZYDRzv5PCHenB3HH0ut9vhYxqdREOqGS/JaW5bqFIHZVyBXn+mxtrTQuwJ9qj9S+6NRauaWvYHtDl3NiqzvuTZSjNWAxu99Nz7sOvAbtHgS2RGOECgYEA6MV4YiukEOh3S5r9BJMU6MtEoYqZQkpclXNVMnDerrPKfSRxh71ldRppjZ8571JVRfINJ1UHYT8SGZKqOOqI3yRsz+Jw1319V45AJ4SQhnJjiTABia9ULqmTzCgQ3moqQDPHTmX0DhyJgY/yqZ0UN/zr55leW6im056dTnlvKD0CgYEA1Q9yCVGMPAR5f4x66L03O+YGVz9HUVlwc6NPQaX11HfcacLpbDC7WUFXq7vNF9UUZMzg5d5aqdrLw5pz//wsb57kbq5amNOO2Sh1U/8csfgR1bePKcE/Rpu93l9ySqikxKv6v1oeOGPw1sFSIBllhHVwW5uD0h2yBCfM75T/amECgYBrosytEKMYUna/llbDo8O6diwxSubduYcgcKmH3puKS4cp4Q1CiHj+8oy2uVdP7FGUO36Lno0AEesruh9OnF1YWf6bDonBi7zHHPdbjrhKA2E1keZUJagWv8GhWTGbt5n8ADV8cjatw9JuAANlHUa5MRJhERGJ7u3d023IWOzmvQKBgQDtVNjAATB6qYUZL+f78GIO/UKRGmIfPzPvXaPIZG7pROHSjJ8tGuNyI0I+51QLV+YALz9zjUpaV1mcdwuGuhopBRsqpqm5EsWZNs1EadYMqRPmw1PBvVNj530igZ5RSEIo1FBihCLS555lljYoBLXpyvHTGCeS+X/CjoYmlDf3Ww==" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICtzCCAZ8CBgGfTL0CgTANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRrZXljbG9hay1uZXQtZml4dHVyZTAeFw0yNjA3MTAxNTUzMDNaFw0zNjA3MTAxNTU0NDNaMB8xHTAbBgNVBAMMFGtleWNsb2FrLW5ldC1maXh0dXJlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4FQ2uVba9ZkIPOOx5qhJ+p+ZmlUc2lDpXr5MWvBKh+9Tz/D3G3kfPK8OUgfy4I0k6qISmYt25u+UCnLhvW7R/oEbX1HrOF+VbEmwulxkD2Bj0hsIUrEw7NnVkdCVeRQBIXjQ83xiLYIz50Xy3dVi0i06V92xQEsGYrUdN74FstCpGd5UZ4S5SJlL7SuH/JVw7GzKCl21+d6gjFGa93dA+7emRSSClmv9EVW1LH2SLJbtcaTnx5K4PyUzVV9i3nQWqHBeYZ5S7WpZ0y5IZ43Ub9CTl96hK9cv2XBGZyDMvdbpjbXbahvBPWjTXq2jzBAj1JEaRrXCwTtoriEgqgUVnQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBwN3OwgKPDzhtfTYubdcPFQe7xuirQGoZE7akNaGZhDggl/ttYGdcWgOEmBdnRSqR9VQxWg9P44kMuguFyfjMiwSnCl0GYk4v6JWkvAPqV3ZN7CZP84QQ59IooW1MR2UfptBy0ojpNZmBhys2hg+WtS8Ay9zxFtq4xXEO/c6lriU3cJTErQh2mInziweu88SMPmCJJ18f7tUjm2aXG5P19oKEWIwNBYhYYs6Js5JC3q/MHKFeJgy82ZnJ7dvO+2+cffVxXy7fv3LnA4DH1KZiVPoAzJm5a4/T8FzUMtway4fXiH+cGvO6WcfN7BZL23L8KIYH5KtY1TuAgzkXtgvLH" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] } } ] }, "internationalizationEnabled" : false, - "supportedLocales" : [ ], "authenticationFlows" : [ { - "id" : "929387c6-fc3e-4bd9-a0d1-1420e7834412", + "id" : "11a9a9ee-d45d-4eb0-a38e-1becfeb3e356", "alias" : "Account verification options", - "description" : "Method with which to verity the existing account", + "description" : "Method with which to verify the existing account", "providerId" : "basic-flow", "topLevel" : false, "builtIn" : true, @@ -1390,9 +1737,9 @@ "userSetupAllowed" : false } ] }, { - "id" : "5750dabd-183f-4a6e-96eb-d37044078be2", - "alias" : "Browser - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", + "id" : "41821524-c6ce-4ec3-89d2-647bcb367e22", + "alias" : "Browser - Conditional 2FA", + "description" : "Flow to determine if any 2FA is required for the authentication", "providerId" : "basic-flow", "topLevel" : false, "builtIn" : true, @@ -1403,16 +1750,60 @@ "priority" : 10, "autheticatorFlow" : false, "userSetupAllowed" : false + }, { + "authenticatorConfig" : "browser-conditional-credential", + "authenticator" : "conditional-credential", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false }, { "authenticator" : "auth-otp-form", "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "webauthn-authenticator", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-recovery-authn-code-form", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "568d24ad-7c72-43ec-952c-1eb4aa28fced", + "alias" : "Browser - Conditional Organization", + "description" : "Flow to determine if the organization identity-first login is to be used", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "organization", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", "priority" : 20, "autheticatorFlow" : false, "userSetupAllowed" : false } ] }, { - "id" : "5ec73e29-e916-437f-9ef5-33410d7b54ab", + "id" : "68da7673-a3f4-47ef-be1a-85ab994616c8", "alias" : "Direct Grant - Conditional OTP", "description" : "Flow to determine if the OTP is required for the authentication", "providerId" : "basic-flow", @@ -1434,9 +1825,9 @@ "userSetupAllowed" : false } ] }, { - "id" : "eebd3c4e-3014-4c4f-bb0e-eb0846e770c8", - "alias" : "First broker login - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", + "id" : "8e350924-d77e-445d-9a3e-d11acee8e407", + "alias" : "First Broker Login - Conditional Organization", + "description" : "Flow to determine if the authenticator that adds organization members is to be used", "providerId" : "basic-flow", "topLevel" : false, "builtIn" : true, @@ -1448,15 +1839,59 @@ "autheticatorFlow" : false, "userSetupAllowed" : false }, { - "authenticator" : "auth-otp-form", + "authenticator" : "idp-add-organization-member", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "2c3fcc21-532d-441b-a2fc-f5260b6e4793", + "alias" : "First broker login - Conditional 2FA", + "description" : "Flow to determine if any 2FA is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorConfig" : "first-broker-login-conditional-credential", + "authenticator" : "conditional-credential", "authenticatorFlow" : false, "requirement" : "REQUIRED", "priority" : 20, "autheticatorFlow" : false, "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "webauthn-authenticator", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-recovery-authn-code-form", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false } ] }, { - "id" : "65631d0c-9e8e-4231-86d5-e843ca870c31", + "id" : "0abd4105-15da-43be-a075-cc3a6dbdaf07", "alias" : "Handle Existing Account", "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", "providerId" : "basic-flow", @@ -1478,7 +1913,21 @@ "userSetupAllowed" : false } ] }, { - "id" : "b7fa5df3-6b4b-4f5d-8ea5-7af7e2c97f10", + "id" : "9a6ca5b6-be68-430e-9168-216bc5efb961", + "alias" : "Organization", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional Organization", + "userSetupAllowed" : false + } ] + }, { + "id" : "b2a52c22-75f9-4ed3-ac46-85b7e52c8077", "alias" : "Reset - Conditional OTP", "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", "providerId" : "basic-flow", @@ -1500,7 +1949,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "381bfe05-48d9-460d-8cd7-2cd45a8a1582", + "id" : "abc9aeb3-496d-4767-a056-453a4dd6d04d", "alias" : "User creation or linking", "description" : "Flow for the existing/non-existing user alternatives", "providerId" : "basic-flow", @@ -1523,7 +1972,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "3fccbbf2-d47e-48b6-9098-68a835a2fecc", + "id" : "bf8e9a83-9c33-48a7-87b9-79565af6a375", "alias" : "Verify Existing Account by Re-authentication", "description" : "Reauthentication of existing account", "providerId" : "basic-flow", @@ -1541,13 +1990,13 @@ "requirement" : "CONDITIONAL", "priority" : 20, "autheticatorFlow" : true, - "flowAlias" : "First broker login - Conditional OTP", + "flowAlias" : "First broker login - Conditional 2FA", "userSetupAllowed" : false } ] }, { - "id" : "3f50de52-b0f4-4525-8961-0d223d9e1c4f", + "id" : "cf6ea26d-9b0b-4794-95a9-b38ef0437e25", "alias" : "browser", - "description" : "browser based authentication", + "description" : "Browser based authentication", "providerId" : "basic-flow", "topLevel" : true, "builtIn" : true, @@ -1572,6 +2021,13 @@ "priority" : 25, "autheticatorFlow" : false, "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 26, + "autheticatorFlow" : true, + "flowAlias" : "Organization", + "userSetupAllowed" : false }, { "authenticatorFlow" : true, "requirement" : "ALTERNATIVE", @@ -1581,7 +2037,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "9d013502-d43b-4f08-aa70-593786de0dda", + "id" : "6d5ad89e-afc2-42ca-ae7a-8bbf983eb2f5", "alias" : "clients", "description" : "Base authentication for clients", "providerId" : "client-flow", @@ -1615,9 +2071,16 @@ "priority" : 40, "autheticatorFlow" : false, "userSetupAllowed" : false + }, { + "authenticator" : "federated-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false } ] }, { - "id" : "21cc6466-598f-4607-b476-1a539bc9ddd6", + "id" : "48dddba0-28ca-4b5b-a2ba-4448d03241b0", "alias" : "direct grant", "description" : "OpenID Connect Resource Owner Grant", "providerId" : "basic-flow", @@ -1646,7 +2109,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "dafe383f-cc08-465d-bdbf-5345ae03bbc7", + "id" : "332ce84b-35f8-4d87-933d-973bae76a434", "alias" : "docker auth", "description" : "Used by Docker clients to authenticate against the IDP", "providerId" : "basic-flow", @@ -1661,7 +2124,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "6fe5b90d-068e-4eeb-bba0-76cf69b0a99b", + "id" : "01d48fa7-3b2e-4b92-a973-6df2b3b4de90", "alias" : "first broker login", "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", "providerId" : "basic-flow", @@ -1682,9 +2145,16 @@ "autheticatorFlow" : true, "flowAlias" : "User creation or linking", "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 60, + "autheticatorFlow" : true, + "flowAlias" : "First Broker Login - Conditional Organization", + "userSetupAllowed" : false } ] }, { - "id" : "5f15216e-4ef1-4ba3-9190-f7479647edff", + "id" : "4760fa46-77ef-4406-95e9-36df21b508f1", "alias" : "forms", "description" : "Username, password, otp and other auth forms.", "providerId" : "basic-flow", @@ -1702,13 +2172,13 @@ "requirement" : "CONDITIONAL", "priority" : 20, "autheticatorFlow" : true, - "flowAlias" : "Browser - Conditional OTP", + "flowAlias" : "Browser - Conditional 2FA", "userSetupAllowed" : false } ] }, { - "id" : "06a0da20-2bfb-46f5-b1a7-f2108987b7e6", + "id" : "27693ddf-f00a-4a9b-8ec2-7a0182eebd54", "alias" : "registration", - "description" : "registration flow", + "description" : "Registration flow", "providerId" : "basic-flow", "topLevel" : true, "builtIn" : true, @@ -1722,9 +2192,9 @@ "userSetupAllowed" : false } ] }, { - "id" : "f9cad234-b532-442e-876c-194f6404d3dd", + "id" : "1b7ed6e5-150a-48ce-a752-e004c50b86e6", "alias" : "registration form", - "description" : "registration form", + "description" : "Registration form", "providerId" : "form-flow", "topLevel" : false, "builtIn" : true, @@ -1758,7 +2228,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "cd715d6f-7758-4d54-a4ae-c900ab24c1d1", + "id" : "e45448cd-1411-4201-a762-aed53c81f655", "alias" : "reset credentials", "description" : "Reset credentials for a user if they forgot their password or something", "providerId" : "basic-flow", @@ -1794,7 +2264,7 @@ "userSetupAllowed" : false } ] }, { - "id" : "cb10cbf0-8a3b-4391-9885-339f66a7b8dc", + "id" : "5bfb72c3-d912-454b-9415-92a5e6416ed1", "alias" : "saml ecp", "description" : "SAML ECP Profile Authentication Flow", "providerId" : "basic-flow", @@ -1810,27 +2280,31 @@ } ] } ], "authenticatorConfig" : [ { - "id" : "901f2b7c-2644-49b0-be4c-a528244fcef8", + "id" : "92b0316d-0316-46fd-87e8-8f911dabcc0b", + "alias" : "browser-conditional-credential", + "config" : { + "credentials" : "webauthn-passwordless" + } + }, { + "id" : "568a571e-1a7a-4338-89ba-51863d55b343", "alias" : "create unique user config", "config" : { "require.password.update.after.registration" : "false" } }, { - "id" : "dc59c261-4115-4f87-94a9-1dfdf1919c7a", + "id" : "e13bc27f-e356-4879-9357-7f2a528f4a78", + "alias" : "first-broker-login-conditional-credential", + "config" : { + "credentials" : "webauthn-passwordless" + } + }, { + "id" : "cff131c7-417a-4091-8fed-4c3503060e6f", "alias" : "review profile config", "config" : { "update.profile.on.first.login" : "missing" } } ], "requiredActions" : [ { - "alias" : "CONFIGURE_TOTP", - "name" : "Configure OTP", - "providerId" : "CONFIGURE_TOTP", - "enabled" : true, - "defaultAction" : false, - "priority" : 10, - "config" : { } - }, { "alias" : "TERMS_AND_CONDITIONS", "name" : "Terms and Conditions", "providerId" : "TERMS_AND_CONDITIONS", @@ -1838,14 +2312,6 @@ "defaultAction" : false, "priority" : 20, "config" : { } - }, { - "alias" : "UPDATE_PASSWORD", - "name" : "Update Password", - "providerId" : "UPDATE_PASSWORD", - "enabled" : true, - "defaultAction" : false, - "priority" : 30, - "config" : { } }, { "alias" : "UPDATE_PROFILE", "name" : "Update Profile", @@ -1862,6 +2328,22 @@ "defaultAction" : false, "priority" : 50, "config" : { } + }, { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 54, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 57, + "config" : { } }, { "alias" : "delete_account", "name" : "Delete Account", @@ -1870,13 +2352,21 @@ "defaultAction" : false, "priority" : 60, "config" : { } + }, { + "alias" : "UPDATE_EMAIL", + "name" : "Update Email", + "providerId" : "UPDATE_EMAIL", + "enabled" : false, + "defaultAction" : false, + "priority" : 70, + "config" : { } }, { "alias" : "webauthn-register", "name" : "Webauthn Register", "providerId" : "webauthn-register", "enabled" : true, "defaultAction" : false, - "priority" : 70, + "priority" : 80, "config" : { } }, { "alias" : "webauthn-register-passwordless", @@ -1884,7 +2374,7 @@ "providerId" : "webauthn-register-passwordless", "enabled" : true, "defaultAction" : false, - "priority" : 80, + "priority" : 90, "config" : { } }, { "alias" : "VERIFY_PROFILE", @@ -1892,7 +2382,7 @@ "providerId" : "VERIFY_PROFILE", "enabled" : true, "defaultAction" : false, - "priority" : 90, + "priority" : 100, "config" : { } }, { "alias" : "delete_credential", @@ -1900,7 +2390,23 @@ "providerId" : "delete_credential", "enabled" : true, "defaultAction" : false, - "priority" : 100, + "priority" : 110, + "config" : { } + }, { + "alias" : "idp_link", + "name" : "Linking Identity Provider", + "providerId" : "idp_link", + "enabled" : true, + "defaultAction" : false, + "priority" : 120, + "config" : { } + }, { + "alias" : "CONFIGURE_RECOVERY_AUTHN_CODES", + "name" : "Recovery Authentication Codes", + "providerId" : "CONFIGURE_RECOVERY_AUTHN_CODES", + "enabled" : true, + "defaultAction" : false, + "priority" : 130, "config" : { } }, { "alias" : "update_user_locale", @@ -1928,9 +2434,12 @@ "cibaInterval" : "5", "realmReusableOtpCode" : "false" }, - "keycloakVersion" : "25.0.6", + "keycloakVersion" : "26.7.0", "userManagedAccessAllowed" : false, "organizationsEnabled" : false, + "verifiableCredentialsEnabled" : false, + "adminPermissionsEnabled" : false, + "scimApiEnabled" : false, "clientProfiles" : { "profiles" : [ ] },