From 4a08d39cfcdf329822aa8eb42d26cb1dda957a04 Mon Sep 17 00:00:00 2001 From: Miquel Simon Date: Thu, 21 Nov 2024 13:55:21 +0100 Subject: [PATCH] Migrate RealmTest to the new framework Part of #34494 Signed-off-by: Miquel Simon --- .../keycloak/test}/admin/realm/RealmTest.java | 635 +++---- .../test/resources/admin-test/testrealm.json | 105 ++ .../client-descriptions/client-oidc.json | 6 + .../saml-entity-descriptor.xml | 99 + .../import/import-without-clients.json | 660 +++++++ .../import/import-without-roles.json | 1257 +++++++++++++ .../partial-authentication-flows-import.json | 23 + .../test/resources/import/partial-import.json | 637 +++++++ .../import/sample-authz-partial-import.json | 58 + .../testrealm-authenticator-config-null.json | 25 + .../import/testrealm-keycloak-6146-error.json | 265 +++ .../import/testrealm-keycloak-6146.json | 266 +++ .../import/testrealm-user-null-attr.json | 1617 +++++++++++++++++ .../java/org/keycloak/test/utils/IOUtil.java | 337 ++++ .../keycloak/test/utils/JsonTestUtils.java | 9 + .../org/keycloak/test/utils/UserBuilder.java | 204 +++ 16 files changed, 5847 insertions(+), 356 deletions(-) rename {testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite => tests/base/src/test/java/org/keycloak/test}/admin/realm/RealmTest.java (70%) create mode 100755 tests/base/src/test/resources/admin-test/testrealm.json create mode 100644 tests/base/src/test/resources/client-descriptions/client-oidc.json create mode 100644 tests/base/src/test/resources/client-descriptions/saml-entity-descriptor.xml create mode 100644 tests/base/src/test/resources/import/import-without-clients.json create mode 100644 tests/base/src/test/resources/import/import-without-roles.json create mode 100644 tests/base/src/test/resources/import/partial-authentication-flows-import.json create mode 100644 tests/base/src/test/resources/import/partial-import.json create mode 100644 tests/base/src/test/resources/import/sample-authz-partial-import.json create mode 100644 tests/base/src/test/resources/import/testrealm-authenticator-config-null.json create mode 100644 tests/base/src/test/resources/import/testrealm-keycloak-6146-error.json create mode 100644 tests/base/src/test/resources/import/testrealm-keycloak-6146.json create mode 100644 tests/base/src/test/resources/import/testrealm-user-null-attr.json create mode 100644 tests/utils/src/main/java/org/keycloak/test/utils/IOUtil.java create mode 100644 tests/utils/src/main/java/org/keycloak/test/utils/UserBuilder.java diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java b/tests/base/src/test/java/org/keycloak/test/admin/realm/RealmTest.java similarity index 70% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java rename to tests/base/src/test/java/org/keycloak/test/admin/realm/RealmTest.java index 3e7a8c4efb7b..8aafd945609c 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java +++ b/tests/base/src/test/java/org/keycloak/test/admin/realm/RealmTest.java @@ -1,92 +1,42 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.testsuite.admin.realm; +package org.keycloak.test.admin.realm; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.NotFoundException; -import jakarta.ws.rs.core.Response; import org.apache.commons.io.IOUtils; import org.hamcrest.CoreMatchers; -import org.hamcrest.Matchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.keycloak.OAuth2Constants; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; import org.keycloak.admin.client.Keycloak; +import org.keycloak.admin.client.KeycloakBuilder; import org.keycloak.admin.client.resource.RealmResource; -import org.keycloak.common.Profile; -import org.keycloak.common.util.Time; -import org.keycloak.events.EventType; -import org.keycloak.events.admin.OperationType; -import org.keycloak.events.admin.ResourceType; -import org.keycloak.events.log.JBossLoggingEventListenerProviderFactory; import org.keycloak.models.AdminRoles; import org.keycloak.models.CibaConfig; import org.keycloak.models.Constants; import org.keycloak.models.OAuth2DeviceConfig; import org.keycloak.models.OTPPolicy; import org.keycloak.models.ParConfig; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.cache.CacheRealmProvider; -import org.keycloak.models.jpa.entities.RealmAttributes; -import org.keycloak.protocol.oidc.OIDCLoginProtocol; -import org.keycloak.protocol.saml.SamlProtocol; -import org.keycloak.representations.adapters.action.GlobalRequestResult; -import org.keycloak.representations.adapters.action.PushNotBeforeAction; -import org.keycloak.representations.idm.AdminEventRepresentation; import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.ComponentRepresentation; -import org.keycloak.representations.idm.EventRepresentation; import org.keycloak.representations.idm.RealmEventsConfigRepresentation; import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.representations.idm.RoleRepresentation; -import org.keycloak.representations.idm.UserRepresentation; -import org.keycloak.testsuite.Assert; -import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.ProfileAssume; -import org.keycloak.testsuite.admin.AbstractAdminTest; -import org.keycloak.testsuite.admin.ApiUtil; -import org.keycloak.testsuite.auth.page.AuthRealm; -import org.keycloak.testsuite.client.KeycloakTestingClient; -import org.keycloak.testsuite.events.TestEventsListenerProviderFactory; -import org.keycloak.testsuite.runonserver.RunHelpers; -import org.keycloak.testsuite.updaters.Creator; -import org.keycloak.testsuite.util.AdminClientUtil; -import org.keycloak.testsuite.util.AdminEventPaths; -import org.keycloak.testsuite.util.ClientBuilder; -import org.keycloak.testsuite.util.CredentialBuilder; -import org.keycloak.testsuite.util.OAuthClient.AccessTokenResponse; -import org.keycloak.testsuite.util.RealmBuilder; -import org.keycloak.testsuite.util.UserBuilder; -import org.keycloak.testsuite.utils.tls.TLSUtils; +import org.keycloak.test.framework.annotations.InjectAdminClient; +import org.keycloak.test.framework.annotations.InjectKeycloakUrls; +import org.keycloak.test.framework.annotations.InjectRealm; +import org.keycloak.test.framework.annotations.KeycloakIntegrationTest; +import org.keycloak.test.framework.realm.ManagedRealm; +import org.keycloak.test.framework.server.KeycloakUrls; +import org.keycloak.test.utils.Assert; +import org.keycloak.test.utils.JsonTestUtils; +import org.keycloak.test.utils.UserBuilder; import org.keycloak.userprofile.UserProfileProvider; import org.keycloak.util.JsonSerialization; import java.io.IOException; import java.nio.charset.Charset; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -101,45 +51,47 @@ import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThrows; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot; - -/** - * @author Stian Thorgersen - */ -public class RealmTest extends AbstractAdminTest { - - @Rule - public AssertEvents events = new AssertEvents(this); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - - // Remove all realms before first run - @Override - public void beforeAbstractKeycloakTestRealmImport() { - if (testContext.isInitialized()) { - return; - } +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; - removeAllRealmsDespiteMaster(); +@KeycloakIntegrationTest +public class RealmTest { - testContext.setInitialized(true); - } + @InjectRealm(ref = "test") + ManagedRealm testRealm; + + @InjectRealm(ref = "admin-client-test") + ManagedRealm adminClientTestRealm; + + @InjectAdminClient + Keycloak adminClient; + @InjectKeycloakUrls + KeycloakUrls keycloakUrls; + + @AfterEach + public void cleanup() { + // Remove any realm which is not master or any of the injected realms + List realms = adminClient.realms().findAll(); + for (RealmRepresentation realm : realms) { + if (!testRealm.getName().equals(realm.getRealm()) && + !adminClientTestRealm.getName().equals(realm.getRealm()) && + !"master".equals(realm.getRealm())) { + adminClient.realm(realm.getRealm()).remove(); + } + } + } @Test public void getRealms() { List realms = adminClient.realms().findAll(); - Assert.assertNames(realms, "master", AuthRealm.TEST, REALM_NAME); + Assert.assertNames(realms, "master", "test", "admin-client-test"); } @Test @@ -147,10 +99,6 @@ public void renameRealm() { String OLD = "old"; String NEW = "new"; - getCleanup() - .addCleanup(() -> adminClient.realms().realm(OLD).remove()) - .addCleanup(() -> adminClient.realms().realm(NEW).remove()); - RealmRepresentation rep = new RealmRepresentation(); rep.setId(OLD); rep.setRealm(OLD); @@ -202,36 +150,29 @@ public void renameRealm() { newRedirectUris.forEach((clientId, redirectUris) -> { assertEquals(redirectUris, adminClient.realm(NEW).clients().findByClientId(clientId).get(0).getRedirectUris()); }); - } @Test public void createRealmEmpty() { - getCleanup() - .addCleanup(() -> adminClient.realms().realm("new-realm").remove()); - RealmRepresentation rep = new RealmRepresentation(); rep.setRealm("new-realm"); adminClient.realms().create(rep); - Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME, "new-realm"); + Assert.assertNames(adminClient.realms().findAll(), "master", "test", "admin-client-test", "new-realm"); List clients = adminClient.realms().realm("new-realm").clients().findAll().stream().map(ClientRepresentation::getClientId).collect(Collectors.toList()); assertThat(clients, containsInAnyOrder("account", "account-console", "admin-cli", "broker", "realm-management", "security-admin-console")); adminClient.realms().realm("new-realm").remove(); - Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME); + Assert.assertNames(adminClient.realms().findAll(), "master", "test", "admin-client-test"); } @Test public void createRealmWithValidConsoleUris() throws Exception { var realmNameWithSpaces = "new realm"; - getCleanup() - .addCleanup(() -> adminClient.realms().realm(realmNameWithSpaces).remove()); - RealmRepresentation rep = new RealmRepresentation(); rep.setRealm(realmNameWithSpaces); rep.setEnabled(Boolean.TRUE); @@ -246,7 +187,7 @@ public void createRealmWithValidConsoleUris() throws Exception { adminClient.realms().create(rep); - Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME, realmNameWithSpaces); + Assert.assertNames(adminClient.realms().findAll(), "master", "test", "admin-client-test", realmNameWithSpaces); final var urlPlaceHolders = ImmutableSet.of("${authBaseUrl}", "${authAdminUrl}"); @@ -255,9 +196,9 @@ public void createRealmWithValidConsoleUris() throws Exception { .findAll() .stream() .flatMap(client -> Stream.concat(Stream.concat(Stream.concat( - client.getRedirectUris().stream(), - Stream.of(client.getBaseUrl())), - Stream.of(client.getRootUrl())), + client.getRedirectUris().stream(), + Stream.of(client.getBaseUrl())), + Stream.of(client.getRootUrl())), Stream.of(client.getAdminUrl()))) .filter(Objects::nonNull) .filter(uri -> !urlPlaceHolders.contains(uri)) @@ -266,14 +207,19 @@ public void createRealmWithValidConsoleUris() throws Exception { assertThat(clientUris, not(empty())); assertThat(clientUris, everyItem(containsString("/new%20realm/"))); - try (Keycloak client = AdminClientUtil.createAdminClient(true, realmNameWithSpaces, - "new-realm-admin", "password", Constants.ADMIN_CLI_CLIENT_ID, null)) { + try (Keycloak client = KeycloakBuilder.builder() + .serverUrl(keycloakUrls.getBaseUrl().toString()) + .realm(realmNameWithSpaces) + .username("new-realm-admin") + .password("password") + .clientId(Constants.ADMIN_CLI_CLIENT_ID) + .build()) { Assert.assertNotNull(client.serverInfo().getInfo()); } adminClient.realms().realm(realmNameWithSpaces).remove(); - Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME); + Assert.assertNames(adminClient.realms().findAll(), "master", "test", "admin-client-test"); } @Test @@ -297,8 +243,6 @@ public void excludesFieldsFromAttributes() { rep.setRealm("attributes"); adminClient.realms().create(rep); - getCleanup() - .addCleanup(() -> adminClient.realms().realm("attributes").remove()); RealmRepresentation rep2 = adminClient.realm("attributes").toRepresentation(); if (rep2.getAttributes() != null) { @@ -374,7 +318,6 @@ public void testFieldNotErased() { rep.setWebAuthnPolicyPasswordlessAcceptableAaguids(Collections.singletonList("00000000-0000-0000-0000-000000000000")); adminClient.realms().create(rep); - getCleanup().addCleanup(() -> adminClient.realms().realm("attributes").remove()); RealmRepresentation rep2 = new RealmRepresentation(); rep2.setAttributes(Collections.singletonMap("frontendUrl", "http://localhost/frontEnd")); @@ -419,7 +362,7 @@ public void testFieldNotErased() { assertTrue(rep.isWebAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister()); assertEquals(Collections.singletonList("00000000-0000-0000-0000-000000000000"), rep.getWebAuthnPolicyPasswordlessAcceptableAaguids()); } - +/* TODO: See https://github.com/keycloak/keycloak/issues/34488 @Test public void smtpPasswordSecret() { RealmRepresentation rep = RealmBuilder.create().testEventListener().testMail().build(); @@ -429,7 +372,7 @@ public void smtpPasswordSecret() { adminClient.realms().create(rep); getCleanup() - .addCleanup(() -> adminClient.realms().realm("realm-with-smtp").remove()); + .addCleanup(() -> adminClient.realms().realm("realm-with-smtp").remove()); RealmRepresentation returned = adminClient.realm("realm-with-smtp").toRepresentation(); assertEquals(ComponentRepresentation.SECRET_VALUE, returned.getSmtpServer().get("password")); @@ -450,7 +393,7 @@ public void smtpPasswordSecret() { RealmRepresentation realm = adminClient.realms().findAll().stream().filter(r -> r.getRealm().equals("realm-with-smtp")).findFirst().get(); assertEquals(ComponentRepresentation.SECRET_VALUE, realm.getSmtpServer().get("password")); - } + }*/ @Test public void createRealmCheckDefaultPasswordPolicy() { @@ -458,10 +401,8 @@ public void createRealmCheckDefaultPasswordPolicy() { rep.setRealm("new-realm"); adminClient.realms().create(rep); - getCleanup() - .addCleanup(() -> adminClient.realms().realm("new-realm").remove()); - assertEquals(null, adminClient.realm("new-realm").toRepresentation().getPasswordPolicy()); + assertNull(adminClient.realm("new-realm").toRepresentation().getPasswordPolicy()); adminClient.realms().realm("new-realm").remove(); @@ -474,10 +415,8 @@ public void createRealmCheckDefaultPasswordPolicy() { @Test public void createRealmFromJson() { - RealmRepresentation rep = loadJson(getClass().getResourceAsStream("/admin-test/testrealm.json"), RealmRepresentation.class); + RealmRepresentation rep = JsonTestUtils.loadJson(getClass().getResourceAsStream("/admin-test/testrealm.json"), RealmRepresentation.class); adminClient.realms().create(rep); - getCleanup() - .addCleanup(() -> adminClient.realms().realm("admin-test-1").remove()); RealmRepresentation created = adminClient.realms().realm("admin-test-1").toRepresentation(); assertRealm(rep, created); @@ -487,46 +426,36 @@ public void createRealmFromJson() { @Test public void createRealmWithPasswordPolicyFromJsonWithInvalidPasswords() { //try to create realm with password policies and users with plain-text passwords what doesn't met the policies - RealmRepresentation rep = loadJson(getClass().getResourceAsStream("/import/testrealm-keycloak-6146-error.json"), RealmRepresentation.class); - - expectedException.expect(NotFoundException.class); - expectedException.expectMessage(String.valueOf(Response.Status.NOT_FOUND.getStatusCode())); + RealmRepresentation rep = JsonTestUtils.loadJson(getClass().getResourceAsStream("/import/testrealm-keycloak-6146-error.json"), RealmRepresentation.class); - try { + Exception badRequestException = assertThrows(BadRequestException.class, () -> { adminClient.realms().create(rep); - } catch (BadRequestException ex) { - //ensure the realm was not created - log.info("--Caught expected BadRequestException--"); + }); + assertNotNull(badRequestException); + + Exception notFoundException = assertThrows(NotFoundException.class, () -> { adminClient.realms().realm("secure-app").toRepresentation(); - } - //test will fail on AssertionError when both BadRequestException and NotFoundException is not thrown + }); + assertNotNull(notFoundException); } //KEYCLOAK-6146 @Test public void createRealmWithPasswordPolicyFromJsonWithValidPasswords() { - RealmRepresentation rep = loadJson(getClass().getResourceAsStream("/import/testrealm-keycloak-6146.json"), RealmRepresentation.class); - try (Creator c = Creator.create(adminClient, rep)) { - RealmRepresentation created = c.resource().toRepresentation(); - assertRealm(rep, created); - } + RealmRepresentation rep = JsonTestUtils.loadJson(getClass().getResourceAsStream("/import/testrealm-keycloak-6146.json"), RealmRepresentation.class); + adminClient.realms().create(rep); + assertRealm(rep, adminClient.realms().realm("secure-app").toRepresentation()); } @Test public void removeRealm() { - realm.remove(); + RealmRepresentation realm = adminClientTestRealm.admin().toRepresentation(); + adminClientTestRealm.admin().remove(); - Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST); + Assert.assertNames(adminClient.realms().findAll(), "master", "test"); // Re-create realm - reCreateRealm(); - } - - private void reCreateRealm() { - // Re-create realm - RealmRepresentation realmRep = testContext.getTestRealmReps().stream() - .filter(realm -> realm.getRealm().equals(REALM_NAME)).findFirst().get(); - importRealm(realmRep); + adminClient.realms().create(realm); } @Test @@ -539,16 +468,19 @@ public void removeMasterRealm() { } } - @Test + // TODO: TLS support + /*@Test public void loginAfterRemoveRealm() { - realm.remove(); + RealmRepresentation realm = adminClientTestRealm.admin().toRepresentation(); + adminClientTestRealm.admin().remove(); - try (Keycloak client = Keycloak.getInstance(getAuthServerContextRoot() + "/auth", "master", "admin", "admin", Constants.ADMIN_CLI_CLIENT_ID, TLSUtils.initializeTLS())) { + try (Keycloak client = Keycloak.getInstance(keycloakUrls.getBaseUrl() + "/auth", "master", "admin", "admin", Constants.ADMIN_CLI_CLIENT_ID, TLSUtils.initializeTLS())) { client.serverInfo().getInfo(); } - reCreateRealm(); - } + // Re-create realm + adminClient.realms().create(realm); + }*/ /** * KEYCLOAK-1990 1991 @@ -556,10 +488,6 @@ public void loginAfterRemoveRealm() { */ @Test public void renameRealmTest() throws Exception { - getCleanup() - .addCleanup(() -> adminClient.realms().realm("test-immutable").remove()) - .addCleanup(() -> adminClient.realms().realm("test-immutable-old").remove()); - RealmRepresentation realm1 = new RealmRepresentation(); realm1.setRealm("test-immutable"); adminClient.realms().create(realm1); @@ -586,7 +514,7 @@ private RealmEventsConfigRepresentation copyRealmEventsConfigRepresentation(Real } private void checkRealmEventsConfigRepresentation(RealmEventsConfigRepresentation expected, - RealmEventsConfigRepresentation actual) { + RealmEventsConfigRepresentation actual) { assertEquals(expected.getEnabledEventTypes().size(), actual.getEnabledEventTypes().size()); assertTrue(actual.getEnabledEventTypes().containsAll(expected.getEnabledEventTypes())); assertEquals(expected.getEventsListeners().size(), actual.getEventsListeners().size()); @@ -597,9 +525,9 @@ private void checkRealmEventsConfigRepresentation(RealmEventsConfigRepresentatio assertEquals(expected.isAdminEventsDetailsEnabled(), actual.isAdminEventsDetailsEnabled()); } - @Test + /*@Test public void updateRealmEventsConfig() { - RealmEventsConfigRepresentation rep = realm.getRealmEventsConfig(); + RealmEventsConfigRepresentation rep = adminClientTestRealm.admin().getRealmEventsConfig(); RealmEventsConfigRepresentation repOrig = copyRealmEventsConfigRepresentation(rep); // the "event-queue" listener should be enabled by default @@ -612,35 +540,35 @@ public void updateRealmEventsConfig() { rep.setEventsEnabled(true); rep.setAdminEventsEnabled(true); rep.setAdminEventsDetailsEnabled(true); - adminClient.realms().realm(REALM_NAME).updateRealmEventsConfig(rep); - assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, "events/config", rep, ResourceType.REALM); - RealmEventsConfigRepresentation actual = realm.getRealmEventsConfig(); + adminClient.realms().realm("admin-test-client").updateRealmEventsConfig(rep); + assertAdminEvents.assertEvent(adminClientTestRealm.getId(), OperationType.UPDATE, "events/config", rep, ResourceType.REALM); + RealmEventsConfigRepresentation actual = adminClientTestRealm.admin().getRealmEventsConfig(); checkRealmEventsConfigRepresentation(rep, actual); // second modification => should not be sent cos event-queue was removed in the first mod rep.setEnabledEventTypes(Arrays.asList(EventType.LOGIN.name(), EventType.LOGIN_ERROR.name(), EventType.CLIENT_LOGIN.name())); - adminClient.realms().realm(REALM_NAME).updateRealmEventsConfig(rep); + adminClient.realms().realm("admin-test-client").updateRealmEventsConfig(rep); assertAdminEvents.assertEmpty(); - actual = realm.getRealmEventsConfig(); + actual = adminClientTestRealm.admin().getRealmEventsConfig(); checkRealmEventsConfigRepresentation(rep, actual); // third modification => restore queue => should be sent and recovered - adminClient.realms().realm(REALM_NAME).updateRealmEventsConfig(repOrig); + adminClient.realms().realm("admin-test-client").updateRealmEventsConfig(repOrig); assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, "events/config", repOrig, ResourceType.REALM); actual = realm.getRealmEventsConfig(); checkRealmEventsConfigRepresentation(repOrig, actual); - } + }*/ @Test public void updateRealmWithReservedCharInNameOrEmptyName() { - RealmRepresentation rep = realm.toRepresentation(); + RealmRepresentation rep = testRealm.admin().toRepresentation(); rep.setRealm("fo#o"); - assertThrows(BadRequestException.class, () -> realm.update(rep)); + assertThrows(BadRequestException.class, () -> testRealm.admin().update(rep)); rep.setRealm(""); - assertThrows(BadRequestException.class, () -> realm.update(rep)); + assertThrows(BadRequestException.class, () -> testRealm.admin().update(rep)); } - + /* @Test public void updateRealm() { // first change @@ -777,15 +705,15 @@ public void updateRealmAttributes() { assertEquals("bar11", rep.getAttributes().get("foo1")); assertFalse(rep.getAttributes().containsKey("foo2")); assertTrue(rep.getWebAuthnPolicyAcceptableAaguids().isEmpty()); - } + }*/ @Test public void getRealmRepresentation() { - RealmRepresentation rep = realm.toRepresentation(); - Assert.assertEquals(REALM_NAME, rep.getRealm()); + RealmRepresentation rep = adminClientTestRealm.admin().toRepresentation(); + Assert.assertEquals("admin-client-test", rep.getRealm()); assertTrue(rep.isEnabled()); } - +/* @Test // KEYCLOAK-1110 public void deleteDefaultRole() { @@ -796,9 +724,9 @@ public void deleteDefaultRole() { role = realm.roles().get("test").toRepresentation(); assertNotNull(role); - realm.roles().get(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + REALM_NAME).addComposites(Collections.singletonList(role)); + realm.roles().get(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + "admin-test-client").addComposites(Collections.singletonList(role)); - assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourceCompositesPath(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + REALM_NAME), Collections.singletonList(role), ResourceType.REALM_ROLE); + assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.roleResourceCompositesPath(Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + "admin-test-client"), Collections.singletonList(role), ResourceType.REALM_ROLE); realm.roles().deleteRole("test"); assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.roleResourcePath("test"), ResourceType.REALM_ROLE); @@ -809,7 +737,7 @@ public void deleteDefaultRole() { } catch (NotFoundException e) { // Expected } - } + }*/ @Test public void convertKeycloakClientDescription() throws IOException { @@ -817,7 +745,7 @@ public void convertKeycloakClientDescription() throws IOException { description.setClientId("client-id"); description.setRedirectUris(Collections.singletonList("http://localhost")); - ClientRepresentation converted = realm.convertClientDescription(JsonSerialization.writeValueAsString(description)); + ClientRepresentation converted = testRealm.admin().convertClientDescription(JsonSerialization.writeValueAsString(description)); assertEquals("client-id", converted.getClientId()); assertEquals("http://localhost", converted.getRedirectUris().get(0)); } @@ -826,7 +754,7 @@ public void convertKeycloakClientDescription() throws IOException { public void convertOIDCClientDescription() throws IOException { String description = IOUtils.toString(getClass().getResourceAsStream("/client-descriptions/client-oidc.json"), Charset.defaultCharset()); - ClientRepresentation converted = realm.convertClientDescription(description); + ClientRepresentation converted = testRealm.admin().convertClientDescription(description); assertEquals(1, converted.getRedirectUris().size()); assertEquals("http://localhost", converted.getRedirectUris().get(0)); } @@ -835,7 +763,7 @@ public void convertOIDCClientDescription() throws IOException { public void convertSAMLClientDescription() throws IOException { String description = IOUtils.toString(getClass().getResourceAsStream("/client-descriptions/saml-entity-descriptor.xml"), Charset.defaultCharset()); - ClientRepresentation converted = realm.convertClientDescription(description); + ClientRepresentation converted = testRealm.admin().convertClientDescription(description); assertEquals("loadbalancer-9.siroe.com", converted.getClientId()); assertEquals(2, converted.getRedirectUris().size()); assertEquals("https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp", converted.getRedirectUris().get(0)); @@ -917,160 +845,160 @@ public static void assertRealm(RealmRepresentation realm, RealmRepresentation st if (realm.isUserManagedAccessAllowed() != null) assertEquals(realm.isUserManagedAccessAllowed(), storedRealm.isUserManagedAccessAllowed()); } + /* + @Test + public void clearRealmCache() { + RealmRepresentation realmRep = realm.toRepresentation(); + assertTrue(testingClient.testing().cache("realms").contains(realmRep.getId())); - @Test - public void clearRealmCache() { - RealmRepresentation realmRep = realm.toRepresentation(); - assertTrue(testingClient.testing().cache("realms").contains(realmRep.getId())); - - realm.clearRealmCache(); - assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "clear-realm-cache", ResourceType.REALM); + realm.clearRealmCache(); + assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "clear-realm-cache", ResourceType.REALM); - assertFalse(testingClient.testing().cache("realms").contains(realmRep.getId())); - } + assertFalse(testingClient.testing().cache("realms").contains(realmRep.getId())); + } - @Test - public void clearUserCache() { - UserRepresentation user = new UserRepresentation(); - user.setUsername("clearcacheuser"); - Response response = realm.users().create(user); - String userId = ApiUtil.getCreatedId(response); - response.close(); - assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userResourcePath(userId), user, ResourceType.USER); + @Test + public void clearUserCache() { + UserRepresentation user = new UserRepresentation(); + user.setUsername("clearcacheuser"); + Response response = realm.users().create(user); + String userId = ApiUtil.getCreatedId(response); + response.close(); + assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userResourcePath(userId), user, ResourceType.USER); - realm.users().get(userId).toRepresentation(); + realm.users().get(userId).toRepresentation(); - assertTrue(testingClient.testing().cache("users").contains(userId)); + assertTrue(testingClient.testing().cache("users").contains(userId)); - realm.clearUserCache(); - assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "clear-user-cache", ResourceType.REALM); + realm.clearUserCache(); + assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "clear-user-cache", ResourceType.REALM); - assertFalse(testingClient.testing().cache("users").contains(userId)); - } + assertFalse(testingClient.testing().cache("users").contains(userId)); + } - // NOTE: clearKeysCache tested in KcOIDCBrokerWithSignatureTest + // NOTE: clearKeysCache tested in KcOIDCBrokerWithSignatureTest - @Test - public void pushNotBefore() { - setupTestAppAndUser(); + @Test + public void pushNotBefore() { + setupTestAppAndUser(); - int time = Time.currentTime() - 60; + int time = Time.currentTime() - 60; - RealmRepresentation rep = realm.toRepresentation(); - rep.setNotBefore(time); - realm.update(rep); - assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM); + RealmRepresentation rep = realm.toRepresentation(); + rep.setNotBefore(time); + realm.update(rep); + assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM); - GlobalRequestResult globalRequestResult = realm.pushRevocation(); - assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult, ResourceType.REALM); + GlobalRequestResult globalRequestResult = realm.pushRevocation(); + assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult, ResourceType.REALM); - assertThat(globalRequestResult.getSuccessRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin")); - assertNull(globalRequestResult.getFailedRequests()); + assertThat(globalRequestResult.getSuccessRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin")); + assertNull(globalRequestResult.getFailedRequests()); - PushNotBeforeAction adminPushNotBefore = testingClient.testApp().getAdminPushNotBefore(); - assertEquals(time, adminPushNotBefore.getNotBefore()); - } + PushNotBeforeAction adminPushNotBefore = testingClient.testApp().getAdminPushNotBefore(); + assertEquals(time, adminPushNotBefore.getNotBefore()); + } - @Test - public void pushNotBeforeWithSamlApp() { - setupTestAppAndUser(); - setupTestSamlApp(); + @Test + public void pushNotBeforeWithSamlApp() { + setupTestAppAndUser(); + setupTestSamlApp(); - int time = Time.currentTime() - 60; + int time = Time.currentTime() - 60; - RealmRepresentation rep = realm.toRepresentation(); - rep.setNotBefore(time); - realm.update(rep); - assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM); + RealmRepresentation rep = realm.toRepresentation(); + rep.setNotBefore(time); + realm.update(rep); + assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM); - GlobalRequestResult globalRequestResult = realm.pushRevocation(); - assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult, ResourceType.REALM); + GlobalRequestResult globalRequestResult = realm.pushRevocation(); + assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "push-revocation", globalRequestResult, ResourceType.REALM); - assertThat(globalRequestResult.getSuccessRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin")); - assertThat(globalRequestResult.getFailedRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/saml-app/saml")); + assertThat(globalRequestResult.getSuccessRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin")); + assertThat(globalRequestResult.getFailedRequests(), containsInAnyOrder(oauth.AUTH_SERVER_ROOT + "/realms/master/saml-app/saml")); - PushNotBeforeAction adminPushNotBefore = testingClient.testApp().getAdminPushNotBefore(); - assertEquals(time, adminPushNotBefore.getNotBefore()); - } + PushNotBeforeAction adminPushNotBefore = testingClient.testApp().getAdminPushNotBefore(); + assertEquals(time, adminPushNotBefore.getNotBefore()); + } - @Test - public void logoutAll() { - setupTestAppAndUser(); + @Test + public void logoutAll() { + setupTestAppAndUser(); - Response response = realm.users().create(UserBuilder.create().username("user").build()); - String userId = ApiUtil.getCreatedId(response); - response.close(); - assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userResourcePath(userId), ResourceType.USER); + Response response = realm.users().create(UserBuilder.create().username("user").build()); + String userId = ApiUtil.getCreatedId(response); + response.close(); + assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userResourcePath(userId), ResourceType.USER); - realm.users().get(userId).resetPassword(CredentialBuilder.create().password("password").build()); - assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userResetPasswordPath(userId), ResourceType.USER); + realm.users().get(userId).resetPassword(CredentialBuilder.create().password("password").build()); + assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userResetPasswordPath(userId), ResourceType.USER); - oauth.doLogin("user", "password"); + oauth.doLogin("user", "password"); - GlobalRequestResult globalRequestResult = realm.logoutAll(); - assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "logout-all", globalRequestResult, ResourceType.REALM); + GlobalRequestResult globalRequestResult = realm.logoutAll(); + assertAdminEvents.assertEvent(realmId, OperationType.ACTION, "logout-all", globalRequestResult, ResourceType.REALM); - assertEquals(1, globalRequestResult.getSuccessRequests().size()); - assertEquals(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0)); - assertNull(globalRequestResult.getFailedRequests()); + assertEquals(1, globalRequestResult.getSuccessRequests().size()); + assertEquals(oauth.AUTH_SERVER_ROOT + "/realms/master/app/admin", globalRequestResult.getSuccessRequests().get(0)); + assertNull(globalRequestResult.getFailedRequests()); - assertNotNull(testingClient.testApp().getAdminLogoutAction()); - } + assertNotNull(testingClient.testApp().getAdminLogoutAction()); + } - @Test - public void deleteSession() { - setupTestAppAndUser(); + @Test + public void deleteSession() { + setupTestAppAndUser(); - oauth.doLogin("testuser", "password"); - AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "secret"); - assertEquals(200, tokenResponse.getStatusCode()); + oauth.doLogin("testuser", "password"); + AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), "secret"); + assertEquals(200, tokenResponse.getStatusCode()); - EventRepresentation event = events.poll(); - assertNotNull(event); + EventRepresentation event = events.poll(); + assertNotNull(event); - realm.deleteSession(event.getSessionId(), false); - assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.deleteSessionPath(event.getSessionId()), ResourceType.USER_SESSION); - try { realm.deleteSession(event.getSessionId(), false); - fail("Expected 404"); - } catch (NotFoundException e) { - // Expected - assertAdminEvents.assertEmpty(); - } - - tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "secret"); - assertEquals(400, tokenResponse.getStatusCode()); - assertEquals("Session not active", tokenResponse.getErrorDescription()); - } + assertAdminEvents.assertEvent(realmId, OperationType.DELETE, AdminEventPaths.deleteSessionPath(event.getSessionId()), ResourceType.USER_SESSION); + try { + realm.deleteSession(event.getSessionId(), false); + fail("Expected 404"); + } catch (NotFoundException e) { + // Expected + assertAdminEvents.assertEmpty(); + } - @Test - public void clientSessionStats() { - setupTestAppAndUser(); + tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "secret"); + assertEquals(400, tokenResponse.getStatusCode()); + assertEquals("Session not active", tokenResponse.getErrorDescription()); + } - List> sessionStats = realm.getClientSessionStats(); - assertTrue(sessionStats.isEmpty()); + @Test + public void clientSessionStats() { + setupTestAppAndUser(); - System.out.println(sessionStats.size()); + List> sessionStats = realm.getClientSessionStats(); + assertTrue(sessionStats.isEmpty()); - oauth.doLogin("testuser", "password"); - AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), - "secret"); - assertEquals(200, tokenResponse.getStatusCode()); + System.out.println(sessionStats.size()); - sessionStats = realm.getClientSessionStats(); + oauth.doLogin("testuser", "password"); + AccessTokenResponse tokenResponse = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get(OAuth2Constants.CODE), + "secret"); + assertEquals(200, tokenResponse.getStatusCode()); - assertEquals(1, sessionStats.size()); - assertEquals("test-app", sessionStats.get(0).get("clientId")); - assertEquals("1", sessionStats.get(0).get("active")); + sessionStats = realm.getClientSessionStats(); - String clientUuid = sessionStats.get(0).get("id"); - realm.clients().get(clientUuid).remove(); + assertEquals(1, sessionStats.size()); + assertEquals("test-app", sessionStats.get(0).get("clientId")); + assertEquals("1", sessionStats.get(0).get("active")); - sessionStats = realm.getClientSessionStats(); + String clientUuid = sessionStats.get(0).get("id"); + realm.clients().get(clientUuid).remove(); - assertEquals(0, sessionStats.size()); - } + sessionStats = realm.getClientSessionStats(); + assertEquals(0, sessionStats.size()); + } + */ @Test // KEYCLOAK-17342 public void testDefaultSignatureAlgorithm() { @@ -1078,8 +1006,6 @@ public void testDefaultSignatureAlgorithm() { rep.setRealm("new-realm"); adminClient.realms().create(rep); - getCleanup() - .addCleanup(() -> adminClient.realms().realm("new-realm").remove()); assertEquals(Constants.DEFAULT_SIGNATURE_ALGORITHM, adminClient.realm("master").toRepresentation().getDefaultSignatureAlgorithm()); assertEquals(Constants.DEFAULT_SIGNATURE_ALGORITHM, adminClient.realm("new-realm").toRepresentation().getDefaultSignatureAlgorithm()); @@ -1093,8 +1019,6 @@ public void testSupportedOTPApplications() { adminClient.realms().create(rep); RealmResource realm = adminClient.realms().realm("new-realm"); - getCleanup() - .addCleanup(() -> adminClient.realms().realm("new-realm").remove()); rep = realm.toRepresentation(); @@ -1120,60 +1044,60 @@ public void testSupportedOTPApplications() { assertThat(supportedApplications, hasSize(2)); assertThat(supportedApplications, containsInAnyOrder("totpAppFreeOTPName", "totpAppGoogleName")); } + /* + private void setupTestAppAndUser() { + testingClient.testApp().clearAdminActions(); + + String redirectUri = oauth.getRedirectUri().replace("/master/", "/" + "admin-test-client" + "/"); + + ClientRepresentation client = new ClientRepresentation(); + client.setClientId("test-app"); + client.setAdminUrl(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/realms/master/app/admin"); + client.setRedirectUris(Collections.singletonList(redirectUri)); + client.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); + client.setSecret("secret"); + Response resp = realm.clients().create(client); + String clientDbId = ApiUtil.getCreatedId(resp); + getCleanup().addClientUuid(clientDbId); + resp.close(); + + client.setSecret("**********"); // secrets are masked in events + assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientResourcePath(clientDbId), client, ResourceType.CLIENT); + + oauth.realm("admin-test-client"); + oauth.redirectUri(redirectUri); + + UserRepresentation userRep = UserBuilder.create().username("testuser").build(); + Response response = realm.users().create(userRep); + String userId = ApiUtil.getCreatedId(response); + response.close(); + getCleanup().addUserId(userId); + assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userResourcePath(userId), userRep, ResourceType.USER); + + realm.users().get(userId).resetPassword(CredentialBuilder.create().password("password").build()); + assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userResetPasswordPath(userId), ResourceType.USER); + + testingClient.testApp().clearAdminActions(); + } - private void setupTestAppAndUser() { - testingClient.testApp().clearAdminActions(); - - String redirectUri = oauth.getRedirectUri().replace("/master/", "/" + REALM_NAME + "/"); - - ClientRepresentation client = new ClientRepresentation(); - client.setClientId("test-app"); - client.setAdminUrl(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/realms/master/app/admin"); - client.setRedirectUris(Collections.singletonList(redirectUri)); - client.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); - client.setSecret("secret"); - Response resp = realm.clients().create(client); - String clientDbId = ApiUtil.getCreatedId(resp); - getCleanup().addClientUuid(clientDbId); - resp.close(); - - client.setSecret("**********"); // secrets are masked in events - assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientResourcePath(clientDbId), client, ResourceType.CLIENT); - - oauth.realm(REALM_NAME); - oauth.redirectUri(redirectUri); - - UserRepresentation userRep = UserBuilder.create().username("testuser").build(); - Response response = realm.users().create(userRep); - String userId = ApiUtil.getCreatedId(response); - response.close(); - getCleanup().addUserId(userId); - assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.userResourcePath(userId), userRep, ResourceType.USER); - - realm.users().get(userId).resetPassword(CredentialBuilder.create().password("password").build()); - assertAdminEvents.assertEvent(realmId, OperationType.ACTION, AdminEventPaths.userResetPasswordPath(userId), ResourceType.USER); - - testingClient.testApp().clearAdminActions(); - } - - private void setupTestSamlApp() { - String redirectUri = oauth.getRedirectUri().replace("/master/", "/" + REALM_NAME + "/"); - ClientRepresentation client = ClientBuilder.create() - .clientId("test-saml-app") - .protocol(SamlProtocol.LOGIN_PROTOCOL) - .adminUrl(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/realms/master/saml-app/saml") - .addRedirectUri(redirectUri) - .secret("secret") - .build(); - Response resp = realm.clients().create(client); - String clientDbId = ApiUtil.getCreatedId(resp); - getCleanup().addClientUuid(clientDbId); - resp.close(); - - client.setSecret("**********"); // secrets are masked in events - assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientResourcePath(clientDbId), client, ResourceType.CLIENT); - } - + private void setupTestSamlApp() { + String redirectUri = oauth.getRedirectUri().replace("/master/", "/" + "admin-test-client" + "/"); + ClientRepresentation client = ClientBuilder.create() + .clientId("test-saml-app") + .protocol(SamlProtocol.LOGIN_PROTOCOL) + .adminUrl(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/realms/master/saml-app/saml") + .addRedirectUri(redirectUri) + .secret("secret") + .build(); + Response resp = realm.clients().create(client); + String clientDbId = ApiUtil.getCreatedId(resp); + getCleanup().addClientUuid(clientDbId); + resp.close(); + + client.setSecret("**********"); // secrets are masked in events + assertAdminEvents.assertEvent(realmId, OperationType.CREATE, AdminEventPaths.clientResourcePath(clientDbId), client, ResourceType.CLIENT); + } + */ @Test public void testNoUserProfileProviderComponentUponRealmChange() { String realmName = "new-realm"; @@ -1181,7 +1105,6 @@ public void testNoUserProfileProviderComponentUponRealmChange() { rep.setRealm(realmName); adminClient.realms().create(rep); - getCleanup().addCleanup(() -> adminClient.realms().realm(realmName).remove()); assertThat(adminClient.realm(realmName).components().query(null, UserProfileProvider.class.getName()), empty()); @@ -1191,7 +1114,7 @@ public void testNoUserProfileProviderComponentUponRealmChange() { // this used to return non-empty collection assertThat(adminClient.realm(realmName).components().query(null, UserProfileProvider.class.getName()), empty()); } - +/* @Test public void testSetEmptyAttributeValues() { String realmName = "testSetEmptyAttributeValues"; @@ -1229,5 +1152,5 @@ public void testSetEmptyAttributeValues() { } finally { adminClient.realm(realmName).remove(); } - } + }*/ } diff --git a/tests/base/src/test/resources/admin-test/testrealm.json b/tests/base/src/test/resources/admin-test/testrealm.json new file mode 100755 index 000000000000..cd58f83f9e57 --- /dev/null +++ b/tests/base/src/test/resources/admin-test/testrealm.json @@ -0,0 +1,105 @@ +{ + "realm": "admin-test-1", + "enabled": true, + "sslRequired": "external", + "registrationAllowed": true, + "registrationEmailAsUsername": true, + "resetPasswordAllowed": true, + "requiredCredentials": [ "password" ], + "defaultRoles": [ "user" ], + "actionTokenGeneratedByAdminLifespan": "147", + "actionTokenGeneratedByUserLifespan": "258", + "smtpServer": { + "from": "auto@keycloak.org", + "host": "localhost", + "port":"3025" + }, + "users" : [ + { + "username" : "test-user@localhost", + "enabled": true, + "email" : "test-user@localhost", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "realmRoles": ["user"], + "applicationRoles": { + "test-app": [ "customer-user" ], + "account": [ "view-profile", "manage-account" ] + } + } + ], + "oauthClients" : [ + { + "name" : "third-party", + "enabled": true, + "redirectUris": [ + "http://localhost:8081/app/*" + ], + "secret": "password" + } + ], + "scopeMappings": [ + { + "client": "third-party", + "roles": ["user"] + }, + { + "client": "test-app", + "roles": ["user"] + } + ], + "applications": [ + { + "name": "test-app", + "enabled": true, + "baseUrl": "http://localhost:8081/app", + "redirectUris": [ + "http://localhost:8081/app/*" + ], + "adminUrl": "http://localhost:8081/app/logout", + "secret": "password" + } + ], + "roles" : { + "realm" : [ + { + "name": "user", + "description": "Have User privileges" + }, + { + "name": "admin", + "description": "Have Administrator privileges" + } + ], + "application" : { + "test-app" : [ + { + "name": "customer-user", + "description": "Have Customer User privileges" + }, + { + "name": "customer-admin", + "description": "Have Customer Admin privileges" + } + ] + } + + }, + + "applicationScopeMappings": { + "test-app": [ + { + "client": "third-party", + "roles": ["customer-user"] + } + ] + }, + "attributes": { + "string-attr": "foo", + "int-attr": "123", + "long-attr": "1234567890123456", + "bool-attr": "true" + } +} diff --git a/tests/base/src/test/resources/client-descriptions/client-oidc.json b/tests/base/src/test/resources/client-descriptions/client-oidc.json new file mode 100644 index 000000000000..51562fd36173 --- /dev/null +++ b/tests/base/src/test/resources/client-descriptions/client-oidc.json @@ -0,0 +1,6 @@ +{ + "client_name": "Name", + "redirect_uris": [ + "http://localhost" + ] +} \ No newline at end of file diff --git a/tests/base/src/test/resources/client-descriptions/saml-entity-descriptor.xml b/tests/base/src/test/resources/client-descriptions/saml-entity-descriptor.xml new file mode 100644 index 000000000000..0bfce4b308f3 --- /dev/null +++ b/tests/base/src/test/resources/client-descriptions/saml-entity-descriptor.xml @@ -0,0 +1,99 @@ + + + + + + + + +MIICYDCCAgqgAwIBAgICBoowDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +EwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEeMBwGA1UEChMVU3VuIE1pY3Jvc3lz +dGVtcyBJbmMuMRowGAYDVQQLExFJZGVudGl0eSBTZXJ2aWNlczEcMBoGA1UEAxMTQ2VydGlmaWNh +dGUgTWFuYWdlcjAeFw0wNjExMDIxOTExMzRaFw0xMDA3MjkxOTExMzRaMDcxEjAQBgNVBAoTCXNp +cm9lLmNvbTEhMB8GA1UEAxMYbG9hZGJhbGFuY2VyLTkuc2lyb2UuY29tMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCjOwa5qoaUuVnknqf5pdgAJSEoWlvx/jnUYbkSDpXLzraEiy2UhvwpoBgB +EeTSUaPPBvboCItchakPI6Z/aFdH3Wmjuij9XD8r1C+q//7sUO0IGn0ORycddHhoo0aSdnnxGf9V +tREaqKm9dJ7Yn7kQHjo2eryMgYxtr/Z5Il5F+wIDAQABo2AwXjARBglghkgBhvhCAQEEBAMCBkAw +DgYDVR0PAQH/BAQDAgTwMB8GA1UdIwQYMBaAFDugITflTCfsWyNLTXDl7cMDUKuuMBgGA1UdEQQR +MA+BDW1hbGxhQHN1bi5jb20wDQYJKoZIhvcNAQEEBQADQQB/6DOB6sRqCZu2OenM9eQR0gube85e +nTTxU4a7x1naFxzYXK1iQ1vMARKMjDb19QEJIEJKZlDK4uS7yMlf1nFS + + + + + + + + +MIICTDCCAfagAwIBAgICBo8wDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +EwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEeMBwGA1UEChMVU3VuIE1pY3Jvc3lz +dGVtcyBJbmMuMRowGAYDVQQLExFJZGVudGl0eSBTZXJ2aWNlczEcMBoGA1UEAxMTQ2VydGlmaWNh +dGUgTWFuYWdlcjAeFw0wNjExMDcyMzU2MTdaFw0xMDA4MDMyMzU2MTdaMCMxITAfBgNVBAMTGGxv +YWRiYWxhbmNlci05LnNpcm9lLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw574iRU6 +HsSO4LXW/OGTXyfsbGv6XRVOoy3v+J1pZ51KKejcDjDJXNkKGn3/356AwIaqbcymWd59T0zSqYfR +Hn+45uyjYxRBmVJseLpVnOXLub9jsjULfGx0yjH4w+KsZSZCXatoCHbj/RJtkzuZY6V9to/hkH3S +InQB4a3UAgMCAwEAAaNgMF4wEQYJYIZIAYb4QgEBBAQDAgZAMA4GA1UdDwEB/wQEAwIE8DAfBgNV +HSMEGDAWgBQ7oCE35Uwn7FsjS01w5e3DA1CrrjAYBgNVHREEETAPgQ1tYWxsYUBzdW4uY29tMA0G +CSqGSIb3DQEBBAUAA0EAMlbfBg/ff0Xkv4DOR5LEqmfTZKqgdlD81cXynfzlF7XfnOqI6hPIA90I +x5Ql0ejivIJAYcMGUyA+/YwJg2FGoA== + + + + + 128 + + + + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + diff --git a/tests/base/src/test/resources/import/import-without-clients.json b/tests/base/src/test/resources/import/import-without-clients.json new file mode 100644 index 000000000000..1c18e348ef2e --- /dev/null +++ b/tests/base/src/test/resources/import/import-without-clients.json @@ -0,0 +1,660 @@ +{ + "id": "import-without-clients", + "realm": "import-without-clients", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "offlineSessionIdleTimeout": 2592000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "045e743f-43b1-4e60-9d51-be3cbe71d6aa", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "scopeParamRequired": false, + "composite": false, + "clientRole": false, + "containerId": "import-without-clients" + }, + { + "id": "d2d8ee95-b0a2-4e7c-b379-9f840be85935", + "name": "offline_access", + "description": "${role_offline-access}", + "scopeParamRequired": true, + "composite": false, + "clientRole": false, + "containerId": "import-without-clients" + } + ] + }, + "groups": [], + "defaultRoles": [ + "uma_authorization", + "offline_access" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "browserSecurityHeaders": { + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "xXSSProtection": "1; mode=block", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "a2a9471e-0f18-4847-b64a-7ad3cd1f0597", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "efba5b6b-dd97-4e2c-907d-c1c957e20ec4", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "12d8a070-da0e-4825-9fb5-6cb637e998e5", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": {} + }, + { + "id": "956db004-8833-4b95-9266-fedbf564c902", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "c3c67c56-3c88-46bd-8b23-d8f92dcd8231", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-role-list-mapper" + ], + "consent-required-for-all-mappers": [ + "true" + ] + } + }, + { + "id": "fd4d4055-f3fa-491a-8dd4-ee8ee9354b6d", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "1982560c-6689-434f-9a3a-6c6c5513b014", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-address-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper" + ], + "consent-required-for-all-mappers": [ + "true" + ] + } + }, + { + "id": "c5ccbffe-a3fe-4c77-a6a7-3679e7f281f5", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "bb5ce31b-932b-402b-8cc5-14e84e81e639", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "a8ddc80d-b0e3-4365-bd1f-12a47b2eb868", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "e3a30dae-8267-4673-b0f4-454491200cb9", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "662c0102-45d2-4719-b685-61a999d12f2d", + "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", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "a16d6bf5-3c20-41c1-b546-8a18fd64009d", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "5fc097f3-747a-478b-b01c-e0ca7cafdbb0", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f5368d26-e65c-459e-ae80-cb298f895872", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "e02ce186-73d8-4ee7-a442-e1fe6bc66649", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "OPTIONAL", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "417fa197-dc0e-4e32-925b-197065587773", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "a5745cc1-2413-41b3-bb72-a80c33c2e346", + "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", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "17877629-e5a1-46c7-ac08-f8e8c765090f", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "3dd5e424-da91-4401-b56f-b54da15c73cb", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "f0889639-f982-4354-bbec-1d7d80a1d24f", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "07606ef3-c2ef-4b77-9660-2cc7fbe60be1", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "OPTIONAL", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "5bd8314b-75db-4677-9699-e3f5d814cc24", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "19402384-99b2-4088-96ca-e50c2ba56b30", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "388ce6bb-09c8-43a8-a429-5dbd5516510f", + "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, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "_browser_header.xXSSProtection": "1; mode=block", + "_browser_header.xFrameOptions": "SAMEORIGIN", + "_browser_header.strictTransportSecurity": "max-age=31536000; includeSubDomains", + "permanentLockout": "false", + "quickLoginCheckMilliSeconds": "1000", + "_browser_header.xRobotsTag": "none", + "maxFailureWaitSeconds": "900", + "minimumQuickLoginWaitSeconds": "60", + "failureFactor": "30", + "actionTokenGeneratedByUserLifespan": "300", + "maxDeltaTimeSeconds": "43200", + "_browser_header.xContentTypeOptions": "nosniff", + "actionTokenGeneratedByAdminLifespan": "43200", + "bruteForceProtected": "false", + "_browser_header.contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "waitIncrementSeconds": "60" + }, + "userManagedAccessAllowed": false +} diff --git a/tests/base/src/test/resources/import/import-without-roles.json b/tests/base/src/test/resources/import/import-without-roles.json new file mode 100644 index 000000000000..5f0c80091eb9 --- /dev/null +++ b/tests/base/src/test/resources/import/import-without-roles.json @@ -0,0 +1,1257 @@ +{ + "id": "import-without-roles", + "realm": "import-without-roles", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "offlineSessionIdleTimeout": 2592000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "defaultRoles": [ + "uma_authorization", + "offline_access" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "clients": [ + { + "id": "938ba3e1-eabc-4bf2-bf87-43a5824b2824", + "clientId": "account", + "name": "${client_account}", + "baseUrl": "/auth/realms/import-without-roles/account", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": [ + "view-profile", + "manage-account" + ], + "redirectUris": [ + "/auth/realms/import-without-roles/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "d5c720ba-dcbd-4730-a15a-2d2fba1512c9", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "d45c591d-ef75-4816-bc42-487ba44498cc", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "97285777-1f27-4222-87a0-f78dbc49829d", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "8e341cf4-c7dc-40b2-b14e-634a4aacea44", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "cc510e62-52ea-4035-81d0-eb7dd2fb3722", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "3b7ce41b-66e1-4e6b-9ba8-4eafc4fb8b79", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "aceec783-0b6f-4eae-a4b9-4d97217d8c9b", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "0437942b-0e5f-4b08-98e2-2c3a27ad1808", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "52fa0e17-9634-45d5-9e6b-cd6f9803e7e7", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "c9301fee-8e33-47c3-856a-1fdb532c828f", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "be22824c-00b7-4803-9cde-f155b7410aa9", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "149859e9-066a-426e-85bd-5476c0a67c79", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "e668c6e0-72e3-4394-a6fe-19047a9e29c7", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "e156734b-7039-4bf9-acdc-9c2f92b3981e", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "bd70aec6-2696-4936-91f5-18389a7c925c", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "0e8e108b-fa89-411b-a08c-b794e552825e", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "7e45f4b1-8323-4b5a-9009-54ec1ba8bc91", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "ce0da762-de49-4914-b217-cf289ebfd44a", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "9250e31c-fadb-4e7a-9d1b-341626fbe6a3", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "5579d355-06dc-4e9c-b1ab-d968e44005ac", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "57219158-fed9-407c-97ca-aec699ab8389", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "85fdc6bf-47fb-4eec-b277-aa1794b9a5f9", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "e7ddaa35-1627-49e8-987a-53772fbeacbe", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "618c7891-57a0-45dc-80b5-363f6919c550", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "4919911a-f927-4c0d-8cc9-2944abc2dd4a", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "24754ffa-4a34-44b2-8df3-87dc1e4d7698", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "ee2ab491-0b0c-4ac2-89eb-0a3f8e75b61d", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "b97fc203-0297-4eac-a1f7-35a7b6722f86", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "baseUrl": "/auth/admin/import-without-roles/console/index.html", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [ + "/auth/admin/import-without-roles/console/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "abd17ea8-4fb5-4e66-9594-3c22ce38f515", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "26e30623-33ea-435f-9876-fe8469edc01f", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "8a6e66f6-9901-40b3-9469-65396597a6d2", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "5a50bd32-00c0-4d8b-b64c-8bc0c0a7b1a1", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "0cead636-2f98-4f6b-b261-22a258d795e0", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "8698187e-6b0a-4c03-814f-4668de90948d", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "a7c95686-3b2c-4bda-a07b-cda77dfbad6b", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "consentText": "${locale}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + } + ], + "clientTemplates": [], + "browserSecurityHeaders": { + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "xXSSProtection": "1; mode=block", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "5b942906-8a41-4ccd-9ad9-ea3ae24e6d56", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "211d788e-3df1-4c01-9ee2-1085945544f2", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "16c3becf-16d8-4fa1-af72-9ca8f9c2ce31", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": {} + }, + { + "id": "769242e8-bb32-4704-af9f-290944a8420a", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "93ddca2c-e4df-4a00-a0f4-76c6838d56f4", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "95fd31fb-f513-4bea-bca0-61d7d030b1b2", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "bdd962d7-b76b-4f52-9aef-d19f08d7137b", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "saml-user-attribute-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "oidc-address-mapper" + ], + "consent-required-for-all-mappers": [ + "true" + ] + } + }, + { + "id": "f96fa5be-8af3-425e-9a40-a14a6b56bdb3", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper" + ], + "consent-required-for-all-mappers": [ + "true" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "950cd5f7-9e73-434b-926a-463c5d7e8985", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "66a95a1b-788b-4942-805f-5c9552755c76", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "41640c93-40e7-4dc2-beae-2887f8bbebc2", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "bed29d4f-aba7-4992-a600-18c0a28c1fc3", + "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", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "e8b8f564-6d56-4171-ba36-a8922c6eae49", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "83dcb1e4-2c7c-4494-825d-f2677cbc114c", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "b0a80dc3-d473-468e-b6e8-f1d306c21360", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "a1882f46-54be-4738-847a-32e849d53240", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "OPTIONAL", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c727a208-587c-4f27-8f48-ba2a0d4effdd", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "6a6ac775-4000-4ccf-9271-6cb599297d4b", + "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", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "2a84808d-e0c7-4759-aee8-cf9229542429", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "817f990a-1c46-464c-9051-5e0ae39d63db", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "266fca50-7b69-4cd4-80eb-a569e87ff8a2", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "b516cb39-8f6d-4d08-ac82-236377be6500", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "OPTIONAL", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "9b9ae730-11e0-451f-b693-e32f09415e42", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "b6d38dcd-7b53-4991-b4eb-c866ce3c5e70", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "8408f503-b929-422f-b52b-277cebda44ba", + "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, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "_browser_header.xXSSProtection": "1; mode=block", + "_browser_header.xFrameOptions": "SAMEORIGIN", + "_browser_header.strictTransportSecurity": "max-age=31536000; includeSubDomains", + "permanentLockout": "false", + "quickLoginCheckMilliSeconds": "1000", + "_browser_header.xRobotsTag": "none", + "maxFailureWaitSeconds": "900", + "minimumQuickLoginWaitSeconds": "60", + "failureFactor": "30", + "actionTokenGeneratedByUserLifespan": "300", + "maxDeltaTimeSeconds": "43200", + "_browser_header.xContentTypeOptions": "nosniff", + "actionTokenGeneratedByAdminLifespan": "43200", + "bruteForceProtected": "false", + "_browser_header.contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "waitIncrementSeconds": "60" + }, + "keycloakVersion": "4.0.0.Beta2-SNAPSHOT", + "userManagedAccessAllowed": false +} \ No newline at end of file diff --git a/tests/base/src/test/resources/import/partial-authentication-flows-import.json b/tests/base/src/test/resources/import/partial-authentication-flows-import.json new file mode 100644 index 000000000000..d1da7dbaacb6 --- /dev/null +++ b/tests/base/src/test/resources/import/partial-authentication-flows-import.json @@ -0,0 +1,23 @@ +{ + "enabled": true, + "realm": "partial-authentication-flows-import", + "authenticationFlows": [ + { + "alias": "X.509 browser", + "description": "Browser-based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": false, + "authenticationExecutions": [ + { + "requirement": "ALTERNATIVE", + "priority": 10, + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/base/src/test/resources/import/partial-import.json b/tests/base/src/test/resources/import/partial-import.json new file mode 100644 index 000000000000..06e30baeedd0 --- /dev/null +++ b/tests/base/src/test/resources/import/partial-import.json @@ -0,0 +1,637 @@ +{ + "id": "partial-import", + "realm": "partial-import", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "offlineSessionIdleTimeout": 2592000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "defaultRoles": [ + "offline_access", + "uma_authorization" + ], + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": [ + "FreeOTP", + "Google Authenticator" + ], + "browserSecurityHeaders": { + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "xXSSProtection": "1; mode=block", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "81655ead-ccb8-4ccc-8824-fd0edda7ea67", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "3e48a4ae-c5a1-4fb7-a685-4adce3b1157b", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "oidc-address-mapper", + "oidc-full-name-mapper" + ], + "consent-required-for-all-mappers": [ + "true" + ] + } + }, + { + "id": "a46ff320-c841-45b0-800e-9219ed627ffb", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-address-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-full-name-mapper" + ], + "consent-required-for-all-mappers": [ + "true" + ] + } + }, + { + "id": "fe0b7fac-e039-4b43-997d-28e41685c099", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "5813bff1-3f03-48b0-9bba-1a08f2b76dff", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "8febb3aa-3aac-4b76-a950-c96a81b88507", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "bc470e1b-6ec9-4cdd-ae2c-0de565d94f75", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": {} + }, + { + "id": "15685bc6-6696-4dd5-bedc-32148de67997", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "50ad939b-d517-499a-abdb-6a07d7c44189", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "be86234c-d6c4-49d2-908c-84ddadd318b7", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "f0fa644d-6f10-49f2-aec5-d2f9bc810146", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "94d8fa06-b1cd-4a62-8919-04eea95e09e4", + "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", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "6d6ee1c8-20d5-464a-8547-fef968daf7f2", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "9da83947-e030-4097-b8d2-a17990c50da7", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "133ae33d-5cba-4829-9f2d-a50320e43faf", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "c8d171b8-efa5-40d1-8c6f-67c89eb08a54", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "OPTIONAL", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "49e99ea3-dc57-47dd-93f4-25662ab408e3", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "50432c1d-18d9-469c-9e08-2579288442a2", + "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", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "6eb36200-bf93-4a1f-821a-59d683460d35", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "3f4d6db4-de10-49f4-9897-a13327167566", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "3c1935ce-ba99-4395-af59-f0a50454e567", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "ffab670c-90a5-4067-bbb8-61aa605c1481", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "OPTIONAL", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "7af61e40-1647-4411-9bde-4cc89d4e5c3b", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "1c5b8534-ee70-4506-996b-369bbb902b83", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "6afe4d4e-cd76-4bcf-8f1e-6971d72474c7", + "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, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "_browser_header.xXSSProtection": "1; mode=block", + "_browser_header.xFrameOptions": "SAMEORIGIN", + "_browser_header.strictTransportSecurity": "max-age=31536000; includeSubDomains", + "permanentLockout": "false", + "quickLoginCheckMilliSeconds": "1000", + "_browser_header.xRobotsTag": "none", + "maxFailureWaitSeconds": "900", + "minimumQuickLoginWaitSeconds": "60", + "failureFactor": "30", + "actionTokenGeneratedByUserLifespan": "300", + "maxDeltaTimeSeconds": "43200", + "_browser_header.xContentTypeOptions": "nosniff", + "actionTokenGeneratedByAdminLifespan": "43200", + "bruteForceProtected": "false", + "_browser_header.contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "waitIncrementSeconds": "60" + }, + "userManagedAccessAllowed": false +} diff --git a/tests/base/src/test/resources/import/sample-authz-partial-import.json b/tests/base/src/test/resources/import/sample-authz-partial-import.json new file mode 100644 index 000000000000..4c9b9ab724da --- /dev/null +++ b/tests/base/src/test/resources/import/sample-authz-partial-import.json @@ -0,0 +1,58 @@ +{ + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Default Resource", + "type": "urn:test:resources:default", + "ownerManagedAccess": false, + "attributes": {}, + "uris": [ + "/*" + ] + }, + { + "name": "test", + "type": "test", + "ownerManagedAccess": true, + "displayName": "test", + "attributes": {}, + "uris": [ + "/test" + ] + } + ], + "policies": [ + { + "name": "Default Policy", + "description": "A policy that grants access only for users within this realm", + "type": "script-scripts/default-policy.js", + "logic": "POSITIVE", + "decisionStrategy": "AFFIRMATIVE" + }, + { + "name": "Default Permission", + "description": "A permission that applies to the default resource type", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "defaultResourceType": "urn:test:resources:default", + "applyPolicies": "[\"Default Policy\"]" + } + }, + { + "name": "test-permission", + "description": "test-permission", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"test\"]", + "applyPolicies": "[\"Default Policy\"]" + } + } + ], + "scopes": [], + "decisionStrategy": "UNANIMOUS" +} diff --git a/tests/base/src/test/resources/import/testrealm-authenticator-config-null.json b/tests/base/src/test/resources/import/testrealm-authenticator-config-null.json new file mode 100644 index 000000000000..916ac2a22875 --- /dev/null +++ b/tests/base/src/test/resources/import/testrealm-authenticator-config-null.json @@ -0,0 +1,25 @@ +{ + "authenticationFlows": [ + { + "alias": "browser", + "authenticationExecutions": [ + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "priority": 20, + "requirement": "ALTERNATIVE", + "userSetupAllowed": false + } + ], + "builtIn": true, + "description": "browser based authentification2", + "id": "3e6ccf87-5473-4eb0-8cbb-28f6b9e6f4d6", + "providerId": "basic-flow", + "topLevel": true + } + ], + "displayName": "CEZ", + "enabled": true, + "id": "cez", + "realm": "cez" +} diff --git a/tests/base/src/test/resources/import/testrealm-keycloak-6146-error.json b/tests/base/src/test/resources/import/testrealm-keycloak-6146-error.json new file mode 100644 index 000000000000..15f2e5a30b5c --- /dev/null +++ b/tests/base/src/test/resources/import/testrealm-keycloak-6146-error.json @@ -0,0 +1,265 @@ +{ + "id":"secure-app", + "realm":"secure-app", + "enabled":true, + "sslRequired":"external", + "bruteForceProtected" : true, + "permanentLockout": true, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 3, + "eventsEnabled" : true, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ "SEND_RESET_PASSWORD", "REMOVE_CREDENTIAL", "UPDATE_TOTP", "REMOVE_TOTP", "REVOKE_GRANT", "LOGIN_ERROR", "CLIENT_LOGIN", "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "RESTART_AUTHENTICATION", "UPDATE_PROFILE_ERROR", "IMPERSONATE", "LOGIN", "UPDATE_CREDENTIAL_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "REGISTER", "LOGOUT", "CLIENT_REGISTER", "IDENTITY_PROVIDER_LINK_ACCOUNT", "UPDATE_CREDENTIAL", "UPDATE_PASSWORD", "FEDERATED_IDENTITY_LINK_ERROR", "CLIENT_DELETE", "IDENTITY_PROVIDER_FIRST_LOGIN", "VERIFY_EMAIL", "CLIENT_DELETE_ERROR", "CLIENT_LOGIN_ERROR", "RESTART_AUTHENTICATION_ERROR", "REMOVE_FEDERATED_IDENTITY_ERROR", "EXECUTE_ACTIONS", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "EXECUTE_ACTION_TOKEN_ERROR", "SEND_VERIFY_EMAIL", "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "UPDATE_EMAIL", "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "LOGOUT_ERROR", "UPDATE_EMAIL_ERROR", "EXECUTE_ACTION_TOKEN", "CLIENT_UPDATE_ERROR", "UPDATE_PROFILE", "FEDERATED_IDENTITY_LINK", "CLIENT_REGISTER_ERROR", "SEND_VERIFY_EMAIL_ERROR", "SEND_IDENTITY_PROVIDER_LINK", "RESET_PASSWORD", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "REMOVE_CREDENTIAL_ERROR", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "CUSTOM_REQUIRED_ACTION_ERROR", "UPDATE_TOTP_ERROR", "CODE_TO_TOKEN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" ], + "adminEventsEnabled" : true, + "adminEventsDetailsEnabled" : true, + "requiredCredentials":[ + "password" + ], + "passwordPolicy": "length(10) and lowerCase(1) and upperCase(1) and passwordHistory(3) and digits(1) and specialChars(1) and hashAlgorithm(pbkdf2-sha256)", + "users":[ + { + "username":"user1", + "firstName" : "User", + "lastName" : "1", + "email" : "user1@feedhenry.org", + "enabled":true, + "credentials":[ + { + "type":"password", + "value":"123" + } + ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users" ] + }, + { + "username":"user2", + "firstName" : "User", + "lastName" : "2", + "email" : "user2@feedhenry.org", + "enabled":true, + "credentials":[ + { + "type":"password", + "value":"123" + } + ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users" ] + }, + { + "username":"secure-user", + "enabled" : true, + "emailVerified" : true, + "firstName" : "Secure", + "lastName" : "User", + "email" : "secure-user@feedhenry.org", + "credentials":[ + { + "type":"password", + "value":"123" + } + ], + "requiredActions" : [ "CONFIGURE_TOTP" ], + "realmRoles" : [ ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users", "/API Access" ] + }, + { + "username":"secure-user2", + "enabled" : true, + "emailVerified" : true, + "firstName" : "Secure", + "lastName" : "User 2", + "email" : "secure-user2@feedhenry.org", + "credentials":[ + { + "type":"password", + "value":"123" + } + ], + "requiredActions" : [ "CONFIGURE_TOTP" ], + "realmRoles" : [ ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users", "/API Access" ] + }, + { + "username":"superuser", + "enabled" : true, + "emailVerified" : true, + "firstName" : "Super", + "lastName" : "User", + "email" : "superuser@feedhenry.org", + "credentials":[ + { + "type":"password", + "value":"123" + } + ], + "realmRoles" : [ ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users", "/API Access", "Superuser" ] + } + ], + "clients":[ + { + "clientId":"api-server", + "enabled":true, + "bearerOnly":true, + "adminUrl":"http://localhost:8080" + }, + { + "clientId":"client-app", + "enabled":true, + "publicClient":true, + "redirectUris":[ + "com.feedhenry.securenativeandroidtemplate:/callback" + ], + "webOrigins":[ + "*" + ] + } + ], + "clientScopeMappings":{ + "account":[ + { + "client":"api-server", + "roles":[ + "view-profile" + ] + }, + { + "client":"client-app", + "roles":[ + "view-profile" + ] + } + ] + }, + "groups" : [ { + "name" : "Mobile Users", + "path" : "/Mobile Users", + "attributes" : { }, + "realmRoles" : [ "mobile-user" ], + "clientRoles" : { }, + "subGroups" : [ ] + }, + { + "name" : "API Access", + "path" : "/API Access", + "attributes" : { }, + "realmRoles" : [ "mobile-user", "api-access" ], + "clientRoles" : { }, + "subGroups" : [ ] + }, + { + "name" : "Superuser", + "path" : "/Superusers", + "attributes" : { }, + "realmRoles" : [ "mobile-user", "api-access", "superuser" ], + "clientRoles" : { }, + "subGroups" : [ ] + } ], + "roles":{ + "client":{ + "api-server":[ + + ], + "client-app":[ + + ] + } + }, + "authenticatorConfig" : [ { + "alias" : "authenticator config", + "config" : { + "defaultProvider" : "" + } + }, { + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + }, { + "alias" : "x509 browser auth config", + "config" : { + "x509-cert-auth.extendedkeyusage" : "", + "x509-cert-auth.mapper-selection.user-attribute-name" : "usercertificate", + "x509-cert-auth.ocsp-responder-uri" : "", + "x509-cert-auth.regular-expression" : "(.*?)(?:$)", + "x509-cert-auth.crl-checking-enabled" : "", + "x509-cert-auth.confirmation-page-disallowed" : "", + "x509-cert-auth.keyusage" : "", + "x509-cert-auth.mapper-selection" : "Username or Email", + "x509-cert-auth.crl-relative-path" : "crl.pem", + "x509-cert-auth.crldp-checking-enabled" : "false", + "x509-cert-auth.mapping-source-selection" : "Subject's Common Name", + "x509-cert-auth.ocsp-checking-enabled" : "" + } + }, { + "alias" : "x509 direct grant config", + "config" : { + "x509-cert-auth.extendedkeyusage" : "", + "x509-cert-auth.mapper-selection.user-attribute-name" : "usercertificate", + "x509-cert-auth.ocsp-responder-uri" : "", + "x509-cert-auth.regular-expression" : "(.*?)(?:$)", + "x509-cert-auth.crl-checking-enabled" : "", + "x509-cert-auth.confirmation-page-disallowed" : "", + "x509-cert-auth.keyusage" : "", + "x509-cert-auth.mapper-selection" : "Username or Email", + "x509-cert-auth.crl-relative-path" : "crl.pem", + "x509-cert-auth.crldp-checking-enabled" : "false", + "x509-cert-auth.mapping-source-selection" : "Subject's Common Name", + "x509-cert-auth.ocsp-checking-enabled" : "" + } + } ] +} diff --git a/tests/base/src/test/resources/import/testrealm-keycloak-6146.json b/tests/base/src/test/resources/import/testrealm-keycloak-6146.json new file mode 100644 index 000000000000..2891d8d6c7d6 --- /dev/null +++ b/tests/base/src/test/resources/import/testrealm-keycloak-6146.json @@ -0,0 +1,266 @@ +{ + "id":"secure-app", + "realm":"secure-app", + "accessCodeLifespanUserAction" : 300, + "enabled":true, + "sslRequired":"external", + "bruteForceProtected" : true, + "permanentLockout": true, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 3, + "eventsEnabled" : true, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ "SEND_RESET_PASSWORD", "UPDATE_TOTP", "REMOVE_TOTP", "REMOVE_CREDENTIAL", "REVOKE_GRANT", "LOGIN_ERROR", "CLIENT_LOGIN", "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "RESTART_AUTHENTICATION", "UPDATE_PROFILE_ERROR", "IMPERSONATE", "LOGIN", "UPDATE_PASSWORD_ERROR", "UPDATE_CREDENTIAL_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "REGISTER", "LOGOUT", "CLIENT_REGISTER", "IDENTITY_PROVIDER_LINK_ACCOUNT", "UPDATE_CREDENTIAL", "UPDATE_PASSWORD", "FEDERATED_IDENTITY_LINK_ERROR", "CLIENT_DELETE", "IDENTITY_PROVIDER_FIRST_LOGIN", "VERIFY_EMAIL", "CLIENT_DELETE_ERROR", "CLIENT_LOGIN_ERROR", "RESTART_AUTHENTICATION_ERROR", "REMOVE_FEDERATED_IDENTITY_ERROR", "EXECUTE_ACTIONS", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "EXECUTE_ACTION_TOKEN_ERROR", "SEND_VERIFY_EMAIL", "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "UPDATE_EMAIL", "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "LOGOUT_ERROR", "UPDATE_EMAIL_ERROR", "EXECUTE_ACTION_TOKEN", "CLIENT_UPDATE_ERROR", "UPDATE_PROFILE", "FEDERATED_IDENTITY_LINK", "CLIENT_REGISTER_ERROR", "SEND_VERIFY_EMAIL_ERROR", "SEND_IDENTITY_PROVIDER_LINK", "RESET_PASSWORD", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "REMOVE_CREDENTIAL_ERROR", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "CUSTOM_REQUIRED_ACTION_ERROR", "UPDATE_TOTP_ERROR", "CODE_TO_TOKEN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" ], + "adminEventsEnabled" : true, + "adminEventsDetailsEnabled" : true, + "requiredCredentials":[ + "password" + ], + "passwordPolicy": "length(10) and lowerCase(1) and upperCase(1) and passwordHistory(3) and digits(1) and specialChars(1) and hashAlgorithm(pbkdf2-sha256)", + "users":[ + { + "username":"user1", + "firstName" : "User", + "lastName" : "1", + "email" : "user1@feedhenry.org", + "enabled":true, + "credentials":[ + { + "type":"password", + "value":"Password123!" + } + ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users" ] + }, + { + "username":"user2", + "firstName" : "User", + "lastName" : "2", + "email" : "user2@feedhenry.org", + "enabled":true, + "credentials":[ + { + "type":"password", + "value":"Password123!" + } + ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users" ] + }, + { + "username":"secure-user", + "enabled" : true, + "emailVerified" : true, + "firstName" : "Secure", + "lastName" : "User", + "email" : "secure-user@feedhenry.org", + "credentials":[ + { + "type":"password", + "value":"Password123!" + } + ], + "requiredActions" : [ "CONFIGURE_TOTP" ], + "realmRoles" : [ ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users", "/API Access" ] + }, + { + "username":"secure-user2", + "enabled" : true, + "emailVerified" : true, + "firstName" : "Secure", + "lastName" : "User 2", + "email" : "secure-user2@feedhenry.org", + "credentials":[ + { + "type":"password", + "value":"Password123!" + } + ], + "requiredActions" : [ "CONFIGURE_TOTP" ], + "realmRoles" : [ ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users", "/API Access" ] + }, + { + "username":"superuser", + "enabled" : true, + "emailVerified" : true, + "firstName" : "Super", + "lastName" : "User", + "email" : "superuser@feedhenry.org", + "credentials":[ + { + "type":"password", + "value":"Password123!" + } + ], + "realmRoles" : [ ], + "clientRoles":{ + "account":[ + "view-profile", + "manage-account" + ] + }, + "attributes":{ + + }, + "groups" : [ "/Mobile Users", "/API Access", "Superuser" ] + } + ], + "clients":[ + { + "clientId":"api-server", + "enabled":true, + "bearerOnly":true, + "adminUrl":"http://localhost:8080" + }, + { + "clientId":"client-app", + "enabled":true, + "publicClient":true, + "redirectUris":[ + "com.feedhenry.securenativeandroidtemplate:/callback" + ], + "webOrigins":[ + "*" + ] + } + ], + "clientScopeMappings":{ + "account":[ + { + "client":"api-server", + "roles":[ + "view-profile" + ] + }, + { + "client":"client-app", + "roles":[ + "view-profile" + ] + } + ] + }, + "groups" : [ { + "name" : "Mobile Users", + "path" : "/Mobile Users", + "attributes" : { }, + "realmRoles" : [ "mobile-user" ], + "clientRoles" : { }, + "subGroups" : [ ] + }, + { + "name" : "API Access", + "path" : "/API Access", + "attributes" : { }, + "realmRoles" : [ "mobile-user", "api-access" ], + "clientRoles" : { }, + "subGroups" : [ ] + }, + { + "name" : "Superuser", + "path" : "/Superusers", + "attributes" : { }, + "realmRoles" : [ "mobile-user", "api-access", "superuser" ], + "clientRoles" : { }, + "subGroups" : [ ] + } ], + "roles":{ + "client":{ + "api-server":[ + + ], + "client-app":[ + + ] + } + }, + "authenticatorConfig" : [ { + "alias" : "authenticator config", + "config" : { + "defaultProvider" : "" + } + }, { + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + }, { + "alias" : "x509 browser auth config", + "config" : { + "x509-cert-auth.extendedkeyusage" : "", + "x509-cert-auth.mapper-selection.user-attribute-name" : "usercertificate", + "x509-cert-auth.ocsp-responder-uri" : "", + "x509-cert-auth.regular-expression" : "(.*?)(?:$)", + "x509-cert-auth.crl-checking-enabled" : "", + "x509-cert-auth.confirmation-page-disallowed" : "", + "x509-cert-auth.keyusage" : "", + "x509-cert-auth.mapper-selection" : "Username or Email", + "x509-cert-auth.crl-relative-path" : "crl.pem", + "x509-cert-auth.crldp-checking-enabled" : "false", + "x509-cert-auth.mapping-source-selection" : "Subject's Common Name", + "x509-cert-auth.ocsp-checking-enabled" : "" + } + }, { + "alias" : "x509 direct grant config", + "config" : { + "x509-cert-auth.extendedkeyusage" : "", + "x509-cert-auth.mapper-selection.user-attribute-name" : "usercertificate", + "x509-cert-auth.ocsp-responder-uri" : "", + "x509-cert-auth.regular-expression" : "(.*?)(?:$)", + "x509-cert-auth.crl-checking-enabled" : "", + "x509-cert-auth.confirmation-page-disallowed" : "", + "x509-cert-auth.keyusage" : "", + "x509-cert-auth.mapper-selection" : "Username or Email", + "x509-cert-auth.crl-relative-path" : "crl.pem", + "x509-cert-auth.crldp-checking-enabled" : "false", + "x509-cert-auth.mapping-source-selection" : "Subject's Common Name", + "x509-cert-auth.ocsp-checking-enabled" : "" + } + } ] +} diff --git a/tests/base/src/test/resources/import/testrealm-user-null-attr.json b/tests/base/src/test/resources/import/testrealm-user-null-attr.json new file mode 100644 index 000000000000..ba1a0ba7cbe0 --- /dev/null +++ b/tests/base/src/test/resources/import/testrealm-user-null-attr.json @@ -0,0 +1,1617 @@ +{ + "id" : "test-user-null-attr", + "realm" : "test-user-null-attr", + "notBefore" : 0, + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "e161bb37-bffb-44a8-8d39-c0de5e378cd5", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "test-user-null-attr", + "attributes" : { } + }, { + "id" : "6aec0f95-55b4-4fe7-87b1-73c8c1e28556", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "test-user-null-attr", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "47ad2786-2ed4-4614-bfdb-7cb3d0d6d3af", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "77637fb4-2159-47d9-bd02-bbea227f8182", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "fcc75dc3-c08f-4ea9-af33-a94c215bf28e", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "6cb02fc0-d0d6-4b83-bbf3-9fe48844507d", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "d251255e-99ab-4c6d-a53a-f16905ce88b5", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "3e08c460-ac98-4b6d-a895-516583a9daaf", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "7a8b6fe6-7ac6-4683-a964-c58ea38991f0", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "ad54ac19-edf8-4955-9b92-d667b0b7fe36", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "4ebe00a1-327c-47c6-ab57-dd63f2d2029e", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "ee4c2b4e-4322-4d3c-a402-8825fcb84fab", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "77bc5018-fdda-4cae-b2c5-86e78d957f92", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "bee6e333-08c1-478f-be83-a2f5d6b1f4d9", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "view-identity-providers", "view-clients", "manage-clients", "manage-identity-providers", "manage-users", "create-client", "query-groups", "manage-authorization", "view-authorization", "impersonation", "view-realm", "manage-events", "view-events", "view-users", "manage-realm", "query-clients", "query-users", "query-realms" ] + } + }, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "b931dcee-095e-4092-b3da-207efd2af07c", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-groups", "query-users" ] + } + }, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "865df2a3-9908-4562-89a2-7abf97bacc58", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "24ad1a73-4ac4-47aa-a773-9433c212ab29", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "414dbb00-16e9-4ed4-a8f1-041370e3e069", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "af0d82f1-f438-4a37-a37a-e866597a2126", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "a64c5a34-71ad-4f93-aab3-246c93b7c038", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + }, { + "id" : "b3a25a3a-63e4-4d2c-8902-8cbe1de3e30e", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "17611769-2d4d-4b67-8158-afc00a300b3c", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "83744367-aeb8-4ec3-8371-fcc847e15d20", + "attributes" : { } + } ], + "account" : [ { + "id" : "8e2532f1-c892-47f9-9125-d122756d850b", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "618d62a1-1d11-48e5-b14b-41de66877629", + "attributes" : { } + }, { + "id" : "8ab03779-c159-4ae0-aa26-2ef93e0d939c", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "618d62a1-1d11-48e5-b14b-41de66877629", + "attributes" : { } + }, { + "id" : "a1e8df41-0da8-475e-b96e-165b364979ec", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "618d62a1-1d11-48e5-b14b-41de66877629", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRoles" : [ "uma_authorization", "offline_access" ], + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "users" : [ { + "id" : "269d52af-f3c3-48f6-841e-75dc7b808831", + "createdTimestamp" : 1578311988958, + "username" : "testuser", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "attributes" : { + "key1" : [ "value1" ], + "key2" : [ "value2" ], + "key3" : [ null ] + }, + "credentials" : [ ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "offline_access", "uma_authorization" ], + "clientRoles" : { + "account" : [ "view-profile", "manage-account" ] + }, + "notBefore" : 0, + "groups" : [ ] + } ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account" ] + } ] + }, + "clients" : [ { + "id" : "618d62a1-1d11-48e5-b14b-41de66877629", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/test-user-null-attr/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "8766f356-181b-4365-966e-759b37d19ba0", + "defaultRoles" : [ "view-profile", "manage-account" ], + "redirectUris" : [ "/realms/test-user-null-attr/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "c49a7747-3f56-4709-a0cc-248ceb67e199", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/test-user-null-attr/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "315f51c2-bbb6-426a-8b74-777cf7423248", + "redirectUris" : [ "/realms/test-user-null-attr/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "598ed852-1b50-4083-be76-55be502977c5", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "be3a4e6b-523c-46fe-a75a-885191aee1cb", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "804b52c0-5b35-4066-9617-e97b5d801052", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "83744367-aeb8-4ec3-8371-fcc847e15d20", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "c24b44a6-cdfc-43e2-8416-9fb2178dda93", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "759d0356-3c2b-4192-90b2-63b9ebcf46cb", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "f60a8b90-1d0d-4ec1-b95e-c97067d16182", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "03235ba2-ad66-4f53-97f9-0bf8069619aa", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/test-user-null-attr/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "89ce17a6-2fbf-4b94-b09d-0e172a68776d", + "redirectUris" : [ "/admin/test-user-null-attr/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "9e277beb-7ab1-40e1-8537-7efe9206a737", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "1ac2e110-441c-45c4-8e2e-c50d7b2b8994", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "809e4a60-387c-4417-b50d-7ddb03eb0449", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "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" + } + } ] + }, { + "id" : "4cecd387-2fe4-4b0b-baf2-f77ec8810099", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "238514d4-859c-44c8-90ca-a1497473435f", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "76f40b9a-af6c-46a8-8fc6-0687da2d3553", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "5e619211-3659-4121-bebc-42ab0078c428", + "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" : "6dd05ee2-ea89-48b4-877e-d5578dcf37a3", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "93e6f241-846c-48af-ba78-7c8266c7e558", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "f436fe9e-485c-4b74-a1db-19108a78de34", + "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" : "5d41409d-0253-4fac-a4c9-7f76a377f44f", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "1a978dec-da66-4bf1-b773-b009e23e4725", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "7248b788-835f-489d-a14b-ab4498db7007", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "fd4aac27-cc9d-49e2-aa48-41695aa8eb40", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "4a176ee7-dab6-49bd-b644-ee359f7966ff", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "85ec37c1-8430-4984-ad49-cfb01e0780b5", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "032520c0-4356-4c4e-bab6-7b10696b2dd6", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "72a91f75-7a09-4e46-a204-bb11c6093474", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "67dc078b-09fc-405f-8905-70aa32d3532b", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "a7ffb672-9bc7-408d-9301-a872fbe6d670", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "d4a1feb7-1727-40f9-a732-676463d54889", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "2ed6d2e2-0c65-4508-aecb-80b32bb5ced6", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "4e68813a-84be-4e9e-ba83-dcb8d773e4d4", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "String" + } + }, { + "id" : "755b29e5-1df9-4c5c-8796-788c4a39d164", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "6a4872d3-b9d2-4932-827f-11c04bae18d3", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "649cc53c-6ae1-44e1-850a-ecf9afb7eaa3", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "4bff897e-c5ff-46a4-b010-a81f3fa3152c", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "00d048d6-8c89-4a29-843a-020edada37fc", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "4de348f5-b362-448d-809e-edc2a70261fa", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "62cb2960-6885-4a98-b4d0-8987c44e7bec", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "54de406a-cfac-42ae-8d97-f149ad1043b8", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "7bdd6fb0-1055-4c66-8409-34d6d11b6be4", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "f6181634-4eb6-436f-ad95-6d287f260380", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + }, { + "id" : "80ca5dfb-d1f9-4c2f-8f1f-4056b9248259", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + } ] + }, { + "id" : "0875318f-0ebd-4e91-9a44-f12a16d6d966", + "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", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "01139d93-185a-4635-a81b-1b6a2e66f1a0", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { } + } ] + } ], + "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "a5172cf0-6b05-41ee-870a-fd25e6c2e498", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "5bf6b838-1d41-4370-b61f-c51faab98eb7", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "f0de671e-3389-4533-acc9-ca3e3ff7716d", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper" ] + } + }, { + "id" : "927fb360-0adc-4c91-b480-d003768df18a", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "f429d8bf-d042-4b13-aa70-e1b09ef6a3a4", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "2e5317ec-a8c7-47f5-aa3c-de12a99c13ff", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-address-mapper" ] + } + }, { + "id" : "9c089afc-4d32-47e7-bf2d-62ce27d08cb7", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "41f6398e-d9db-4756-b376-0ca589e95bdb", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "6106a56b-47e9-47d0-a3f6-59952d5e597b", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEAhSjJajn/bcNGK49W9tCFVIFGL+MYsAotNGE389X0xnGsWzRI0+4pOF8R+6HlXP3wKOlUdNckCgu7HvzJ/N+mTl6CTVWdnQKQVhRY0NcqccK8iMWkRtL3sqJKbNHZ0iSug6Wccx71AcS8ieEUy7zRB5fdylRR30NUeDhMKlFAVyxMGfWYwISr1Mqx2cq1BPByzyi1+AAkrka9cs58JdcFDzUGxy2yXmxJB5Uuqi5wheFOTVY6mGeZIA1r8ADIrwD3mByYzGVRNI/UB8dN3X7iZgKss2TtDhLKSURwohwRJiXvBZg7VpwVoz4M0oitEHfvb8LTIWCpN5OY2d8+goS19QIDAQABAoIBAHdSExozGmXbA7fo2/6S38bXiHNExkyI8fTr4N2IraxdFBsuAMyXrywqVMztR8BKdLfUTa/dURgHZwffcYg9SKMVISH3RCL7tybLWMLa69fArnzIzeoBBaB2uMZGTS93W0HwVv75kIajKmdK3/2pFo39UesKH8s2ZCzOFcIdyM/TQQHkzQgz9d6xQt9i3XjjZiixSDtWoi6WUixur6LM3rFIdbGke1VzaCFFnzM9maBqtjYLYXDEuiJXsp4Gr5CvwU0doyKyizuZlfUqEPKtlRwpLRQorDRP0P5j0el6TUBYPolW+oxlI/aCy8Iva73GyouGi92rz21MTcYNqX772EECgYEAuNKB2A/4Lk0Hg9SPm0WnsVJlhhtN6qTlVmQE5u9UTGzcqHXt6YPi5COINZmnCbZ3yDsmk0R5iTObIjT0/ydAy7MitlBuIrYjU8PKiABRcbqmk9xjXSPUsOFxR+9I1rfQIQKMRnPFv0YMMOGwGIOTyFfPa7dL9Uw+9cuVCKACvs0CgYEAuHDdm68kCv49xZi/jmssaFUAALxzmqhwEomrmYxZr4gLmSGyrBDMEOKzTTGjW5/ViK7raqEa3wIn97waoLjP+CfDnHk88m6JBWJn7lK1bDuYvLk70Tq4+LFp7QhRPdrClMA7Byvhv43A1PhxgJauAnu/BrDeDzkKFKxU76eig8kCgYEAt0BhZa1P0fimPtv/F2FVB8g+yV1BQCoHCkVZZvBdkPlPP+jN3/7YdIOWhi63JDY7RdkAQnxeVN9KLfx7/pEY+d+/xyywRtJ47JDwuzA1kKIUj/6wtqTUOh0NiNmESwEt58zy8NfRdfkqFT1wsJ2lZbtK+e5f7fOPaX5VYpvknPECgYAqroO6CVev65Hj7is2C/sk0bbEdNfTzHLS92TsjZwbkMIOV8v/IYv3xF512KzTATPrA3+bF1kejmMtYyxOUTZfWORdi3jdKVMwGcuvTRiKyWfZFIyRKKOxeWzn22rhg4RP5ARE7pS5PVaIck3h0fzGulhEdh2NLEf27MJjC0oCcQKBgDOPxaI45A+aQR4NskZvlnuT86+f8JOI950xsO8ZmFmqFngy518a6TnykLl1WA4E8TS+inlCFEiduj1btsccvCBp9qNVRX6I93mbemQFlbg6oQQdj7GrVJVl/uZLY7WaZsGVfy1xpGXKRQHBstWRfKvO6vD88pz+co5UK9Ab9K+e" ], + "certificate" : [ "MIICtTCCAZ0CBgFverl9mDANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDDBN0ZXN0LXVzZXItbnVsbC1hdHRyMB4XDTIwMDEwNjExNTc1NFoXDTMwMDEwNjExNTkzNFowHjEcMBoGA1UEAwwTdGVzdC11c2VyLW51bGwtYXR0cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIUoyWo5/23DRiuPVvbQhVSBRi/jGLAKLTRhN/PV9MZxrFs0SNPuKThfEfuh5Vz98CjpVHTXJAoLux78yfzfpk5egk1VnZ0CkFYUWNDXKnHCvIjFpEbS97KiSmzR2dIkroOlnHMe9QHEvInhFMu80QeX3cpUUd9DVHg4TCpRQFcsTBn1mMCEq9TKsdnKtQTwcs8otfgAJK5GvXLOfCXXBQ81Bsctsl5sSQeVLqoucIXhTk1WOphnmSANa/AAyK8A95gcmMxlUTSP1AfHTd1+4mYCrLNk7Q4SyklEcKIcESYl7wWYO1acFaM+DNKIrRB372/C0yFgqTeTmNnfPoKEtfUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAFrTjRzrYbbkC+G7ASxkmHmvM2mdD92bUS1jwTvdJMrF0tFcZTtRD//Wbg+6GvRtkgimI5EM0Q4LflL4BfGKn9bA6wgXOlnXWaQzRnpmfcoa7/BHvOgvZITcuHUNrbgQhuBtNh/jaDrRr8u4fMwqwvGPe5JcesfZkC9siztl7RO8IAHCgai0NUCKcr9/eFNffGSlU23dLrBME7ZVpMBZxPvVH4zMBzK0FLOCRJAG5yInLxzoOBAhgKmsfnLnwSKOS6AudnsIjmulyO/rLEt8FOtKoKx7GQmtzoJX8qqt2gElQojlff3/LJ+oOgYnrdA2pDVmHKSWZ6pf/pEy6S7TiZg==" ], + "priority" : [ "100" ] + } + }, { + "id" : "2b06c73a-fe38-413d-9fee-626980685c3d", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "694a4045-7b63-402b-8a9f-84a0d8c0b6b5" ], + "secret" : [ "p_QQsM00mP7tJCEW7rTCew" ], + "priority" : [ "100" ] + } + }, { + "id" : "9010959e-17bf-4bc9-9a16-9e6a7c230e4b", + "name" : "hmac-generated", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "9d547d80-029d-44c5-a60b-cf3b4b311375" ], + "secret" : [ "4JFv7rRBmdmBofkkILKx69GpWvckjkya2KBf_V8FfuhuvO_BEXSCRHp9n76bFyexJ6DmK6pKdmgZX__oIHEJ7w" ], + "priority" : [ "100" ], + "algorithm" : [ "HS256" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "4924886a-22ef-4b6d-992e-6d269cb57081", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "requirement" : "ALTERNATIVE", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "ALTERNATIVE", + "priority" : 20, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "d3ea3a35-074b-4827-b3b5-e064ce740df6", + "alias" : "Authentication Options", + "description" : "Authentication options.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "basic-auth", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "basic-auth-otp", + "requirement" : "DISABLED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-spnego", + "requirement" : "DISABLED", + "priority" : 30, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "1dc9bf38-729b-4ee7-9a44-5d9f4cd73f35", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-otp-form", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "fac6529b-4550-45ec-9094-099b6e99a64e", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "76ef3b04-bb13-4271-922e-cda0762c0d3b", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-otp-form", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "77bfe71a-4f2f-4acd-ad61-e6ca0df64d89", + "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", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "REQUIRED", + "priority" : 20, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "18c36a31-72fc-461f-b0c8-524e5167de17", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "reset-otp", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "5c613aa7-a5e6-42d6-8ce8-6fd122a15e5e", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "requirement" : "ALTERNATIVE", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "ALTERNATIVE", + "priority" : 20, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "87d8d3b1-016d-49e2-831b-d311a7040bcb", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "CONDITIONAL", + "priority" : 20, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "782f6021-4cc7-4704-8a42-91fcbfdf5508", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "requirement" : "ALTERNATIVE", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-spnego", + "requirement" : "DISABLED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "identity-provider-redirector", + "requirement" : "ALTERNATIVE", + "priority" : 25, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "ALTERNATIVE", + "priority" : 30, + "flowAlias" : "forms", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "f21c1bce-dcb7-4049-bf7d-c9ab144d917a", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "requirement" : "ALTERNATIVE", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "client-jwt", + "requirement" : "ALTERNATIVE", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "client-secret-jwt", + "requirement" : "ALTERNATIVE", + "priority" : 30, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "client-x509", + "requirement" : "ALTERNATIVE", + "priority" : 40, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "c2ca35fa-6c53-41ce-8000-346300a0b381", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "direct-grant-validate-password", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "CONDITIONAL", + "priority" : 30, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "cca40f39-c6a8-4c98-b8c7-5b416f05c093", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "10f6ff01-24c3-4aff-9040-fa4e12f79ae9", + "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", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "REQUIRED", + "priority" : 20, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "0f6bbf42-7926-4a7c-8167-46331f3cfde4", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "CONDITIONAL", + "priority" : 20, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "0dd2f1c3-a3ce-4380-8ef0-4dc7bdb4297e", + "alias" : "http challenge", + "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "no-cookie-redirect", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "REQUIRED", + "priority" : 20, + "flowAlias" : "Authentication Options", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "5645a178-2e60-42ba-8e55-eb52d0577fa3", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "requirement" : "REQUIRED", + "priority" : 10, + "flowAlias" : "registration form", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "9c8992a2-422a-4624-bb3b-86af4cc99915", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "registration-profile-action", + "requirement" : "REQUIRED", + "priority" : 40, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "registration-password-action", + "requirement" : "REQUIRED", + "priority" : 50, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "registration-recaptcha-action", + "requirement" : "DISABLED", + "priority" : 60, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "d6844f7e-5593-4af4-896a-db5784ca3643", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "reset-credential-email", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "reset-password", + "requirement" : "REQUIRED", + "priority" : 30, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "CONDITIONAL", + "priority" : 40, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "b278f188-d1d5-406f-bb45-0cef0f00c459", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "7ab6e1d9-dda7-4d5b-866b-bb638c965b9b", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "324810cf-c770-4e41-9338-cfae24fff093", + "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", + "enabled" : false, + "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", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "_browser_header.xRobotsTag" : "none", + "webAuthnPolicyRpEntityName" : "keycloak", + "failureFactor" : "30", + "actionTokenGeneratedByUserLifespan" : "300", + "maxDeltaTimeSeconds" : "43200", + "webAuthnPolicySignatureAlgorithms" : "ES256", + "offlineSessionMaxLifespan" : "5184000", + "_browser_header.contentSecurityPolicyReportOnly" : "", + "bruteForceProtected" : "false", + "_browser_header.contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "_browser_header.xXSSProtection" : "1; mode=block", + "_browser_header.xFrameOptions" : "SAMEORIGIN", + "_browser_header.strictTransportSecurity" : "max-age=31536000; includeSubDomains", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "permanentLockout" : "false", + "quickLoginCheckMilliSeconds" : "1000", + "webAuthnPolicyCreateTimeout" : "0", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "maxFailureWaitSeconds" : "900", + "minimumQuickLoginWaitSeconds" : "60", + "webAuthnPolicyAvoidSameAuthenticatorRegister" : "false", + "_browser_header.xContentTypeOptions" : "nosniff", + "actionTokenGeneratedByAdminLifespan" : "43200", + "waitIncrementSeconds" : "60", + "offlineSessionMaxLifespanEnabled" : "false" + }, + "keycloakVersion" : "9.0.0-SNAPSHOT", + "userManagedAccessAllowed" : false +} diff --git a/tests/utils/src/main/java/org/keycloak/test/utils/IOUtil.java b/tests/utils/src/main/java/org/keycloak/test/utils/IOUtil.java new file mode 100644 index 000000000000..78135f01af2b --- /dev/null +++ b/tests/utils/src/main/java/org/keycloak/test/utils/IOUtil.java @@ -0,0 +1,337 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.keycloak.test.utils; + +import org.jboss.logging.Logger; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.util.JsonSerialization; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.*; +import java.util.concurrent.TimeUnit; + +/** + * + * @author tkyjovsk + */ +public class IOUtil { + + private static final Logger log = Logger.getLogger(IOUtil.class); + + public static final File PROJECT_BUILD_DIRECTORY = new File(System.getProperty("project.build.directory", "target")); + + public static T loadJson(InputStream is, Class type) { + try { + return JsonSerialization.readValue(is, type); + } catch (IOException e) { + throw new RuntimeException("Failed to load json.", e); + } + } + + public static RealmRepresentation loadRealm(String realmConfig) { + return loadRealm(IOUtil.class.getResourceAsStream(realmConfig)); + } + + public static RealmRepresentation loadRealm(File realmFile) { + try { + return loadRealm(new FileInputStream(realmFile)); + } catch (FileNotFoundException ex) { + throw new IllegalStateException("Test realm file not found: " + realmFile, ex); + } + } + + public static RealmRepresentation loadRealm(InputStream is) { + RealmRepresentation realm = loadJson(is, RealmRepresentation.class); + System.out.println("Loaded realm " + realm.getRealm()); + return realm; + } + + public static Document loadXML(InputStream is) { + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + return dBuilder.parse(is); + } catch (ParserConfigurationException | SAXException | IOException e) { + throw new RuntimeException(e); + } + } + + public static String documentToString(Document newDoc) { + try { + DOMSource domSource = new DOMSource(newDoc); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + StringWriter sw = new StringWriter(); + StreamResult sr = new StreamResult(sw); + transformer.transform(domSource, sr); + return sw.toString(); + } catch (TransformerException e) { + log.error("Can't transform document to String"); + throw new RuntimeException(e); + } + } + + public static InputStream documentToInputStream(Document doc) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Source xmlSource = new DOMSource(doc); + Result outputTarget = new StreamResult(outputStream); + TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget); + return new ByteArrayInputStream(outputStream.toByteArray()); + } catch (TransformerException e) { + log.error("Can't transform document to InputStream"); + throw new RuntimeException(e); + } + } + + /** + * Modifies attribute value according to the given regex (first occurrence) iff + * there are following conditions accomplished: + * + * - exactly one node is found within the document + * - the attribute of the node exists + * - the regex is found in the value of the attribute + * + * Otherwise there is nothing changed. + * + * @param doc + * @param tagName + * @param attributeName + * @param regex + * @param replacement + */ + public static void modifyDocElementAttribute(Document doc, String tagName, String attributeName, String regex, String replacement) { + NodeList nodes = doc.getElementsByTagName(tagName); + if (nodes.getLength() != 1) { + log.warn("Not able or ambiguous to find element: " + tagName); + return; + } + + Node node = nodes.item(0).getAttributes().getNamedItem(attributeName); + if (node == null || node.getTextContent() == null) { + log.warn("Not able to find attribute " + attributeName + " within element: " + tagName); + return; + } + node.setTextContent(node.getTextContent().replaceFirst(regex, replacement)); + } + + public static void removeNodeByAttributeValue(Document doc, String parentTag, String tagName, String attributeName, String value){ + NodeList parentNodes = doc.getElementsByTagName(parentTag); + if (parentNodes.getLength() != 1) { + log.warn("Not able or ambiguous to find element: " + parentTag); + return; + } + + Element parentElement = (Element) parentNodes.item(0); + if (parentElement == null) { + log.warn("Not able to find element: " + parentTag); + return; + } + + NodeList nodes = doc.getElementsByTagName(tagName); + for (int i = 0; i < nodes.getLength(); i++){ + Node node = nodes.item(i).getAttributes().getNamedItem(attributeName); + if (node.getTextContent().equals(value)){ + parentElement.removeChild(nodes.item(i)); + return; + } + } + } + + /** + * Modifies element text value according to the given regex (first occurrence) iff + * there are following conditions accomplished: + * + * - exactly one node is found within the document + * - the regex is found in the text content of the element + * + * Otherwise there is nothing changed. + * + * @param doc + * @param tagName + * @param regex + * @param replacement + */ + public static void modifyDocElementValue(Document doc, String tagName, String regex, String replacement) { + NodeList nodes = doc.getElementsByTagName(tagName); + if (nodes.getLength() != 1) { + log.warn("Not able or ambiguous to find element: " + tagName); + return; + } + + Node node = nodes.item(0); + if (node == null) { + log.warn("Not able to find element: " + tagName); + return; + } + + node.setTextContent(node.getTextContent().replaceFirst(regex, replacement)); + } + + public static void setDocElementAttributeValue(Document doc, String tagName, String attributeName, String value) { + NodeList nodes = doc.getElementsByTagName(tagName); + if (nodes.getLength() != 1) { + log.warn("Not able or ambiguous to find element: " + tagName); + return; + } + + Element node = (Element) nodes.item(0); + if (node == null) { + log.warn("Not able to find element: " + tagName); + return; + } + + node.setAttribute(attributeName, value); + } + + public static void removeElementsFromDoc(Document doc, String parentTag, String removeNode) { + NodeList nodes = doc.getElementsByTagName(parentTag); + if (nodes.getLength() != 1) { + log.warn("Not able or ambiguous to find element: " + parentTag); + return; + } + + Element parentElement = (Element) nodes.item(0); + if (parentElement == null) { + log.warn("Not able to find element: " + parentTag); + return; + } + + NodeList removeNodes = parentElement.getElementsByTagName(removeNode); + if (removeNodes == null) { + log.warn("Not able to find element: " + removeNode + " within node " + parentTag); + return; + } + + for (int i = 0; i < removeNodes.getLength();){ + Element removeElement = (Element) removeNodes.item(i); + if (removeElement == null) { + log.warn("Not able to find element: " + removeNode + " within node " + parentTag); + return; + } + + log.trace("Removing node " + removeNode); + parentElement.removeChild(removeElement); + + } + + } + + public static String getElementTextContent(Document doc, String path) { + String[] pathSegments = path.split("/"); + + Element currentElement = (Element) doc.getElementsByTagName(pathSegments[0]).item(0); + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[0] + " in document"); + return null; + } + + for (int i = 1; i < pathSegments.length; i++) { + currentElement = (Element) currentElement.getElementsByTagName(pathSegments[i]).item(0); + + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[i] + " in " + pathSegments[i - 1]); + return null; + } + } + + return currentElement.getTextContent(); + } + + public static void appendChildInDocument(Document doc, String parentPath, Element node) { + String[] pathSegments = parentPath.split("/"); + + Element currentElement = (Element) doc.getElementsByTagName(pathSegments[0]).item(0); + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[0] + " in document"); + return; + } + + for (int i = 1; i < pathSegments.length; i++) { + currentElement = (Element) currentElement.getElementsByTagName(pathSegments[i]).item(0); + + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[i] + " in " + pathSegments[i - 1]); + return; + } + } + + currentElement.appendChild(node); + } + + public static void removeElementFromDoc(Document doc, String path) { + String[] pathSegments = path.split("/"); + + Element currentElement = (Element) doc.getElementsByTagName(pathSegments[0]).item(0); + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[0] + " in document"); + return; + } + + for (int i = 1; i < pathSegments.length; i++) { + currentElement = (Element) currentElement.getElementsByTagName(pathSegments[i]).item(0); + + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[i] + " in " + pathSegments[i - 1]); + return; + } + } + + currentElement.getParentNode().removeChild(currentElement); + } + + public static void execCommand(String command, File dir) throws IOException, InterruptedException { + Process process = Runtime.getRuntime().exec(command, null, dir); + if (process.waitFor(10, TimeUnit.SECONDS)) { + if (process.exitValue() != 0) { + getOutput("ERROR", process.getErrorStream()); + throw new RuntimeException("Adapter installation failed. Process exitValue: " + + process.exitValue()); + } + getOutput("OUTPUT", process.getInputStream()); + log.debug("process.isAlive(): " + process.isAlive()); + } else { + if (process.isAlive()) { + process.destroyForcibly(); + } + throw new RuntimeException("Timeout after 10 seconds."); + } + } + + public static void getOutput(String type, InputStream is) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + StringBuilder builder = new StringBuilder(); + builder.append("<").append(type).append(">"); + System.out.println(builder); + builder = new StringBuilder(); + while (reader.ready()) { + System.out.println(reader.readLine()); + } + builder.append(""); + System.out.println(builder); + } + +} diff --git a/tests/utils/src/main/java/org/keycloak/test/utils/JsonTestUtils.java b/tests/utils/src/main/java/org/keycloak/test/utils/JsonTestUtils.java index 040e6709cfa8..fb70a2d04b9e 100644 --- a/tests/utils/src/main/java/org/keycloak/test/utils/JsonTestUtils.java +++ b/tests/utils/src/main/java/org/keycloak/test/utils/JsonTestUtils.java @@ -23,6 +23,7 @@ import org.keycloak.util.JsonSerialization; import java.io.IOException; +import java.io.InputStream; /** * Utility for comparing JSON objects @@ -80,4 +81,12 @@ public static void assertJsonEquals(String o1, String o2, Class clazz) { throw new RuntimeException(ioe); } } + + public static T loadJson(InputStream is, Class type) { + try { + return JsonSerialization.readValue(is, type); + } catch (IOException e) { + throw new RuntimeException("Failed to parse json", e); + } + } } diff --git a/tests/utils/src/main/java/org/keycloak/test/utils/UserBuilder.java b/tests/utils/src/main/java/org/keycloak/test/utils/UserBuilder.java new file mode 100644 index 000000000000..061f88683a67 --- /dev/null +++ b/tests/utils/src/main/java/org/keycloak/test/utils/UserBuilder.java @@ -0,0 +1,204 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.test.utils; + +import org.keycloak.models.credential.OTPCredentialModel; +import org.keycloak.models.utils.HmacOTP; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.FederatedIdentityRepresentation; +import org.keycloak.representations.idm.UserRepresentation; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; + +/** + * @author Stian Thorgersen + */ +public class UserBuilder { + + private final UserRepresentation rep; + + public static UserBuilder create() { + UserRepresentation rep = new UserRepresentation(); + rep.setEnabled(Boolean.TRUE); + return new UserBuilder(rep); + } + + public static UserBuilder edit(UserRepresentation rep) { + return new UserBuilder(rep); + } + + private UserBuilder(UserRepresentation rep) { + this.rep = rep; + } + + public UserBuilder id(String id) { + rep.setId(id); + return this; + } + + public UserBuilder username(String username) { + rep.setUsername(username); + return this; + } + + public UserBuilder firstName(String firstName) { + rep.setFirstName(firstName); + return this; + } + + public UserBuilder lastName(String lastName) { + rep.setLastName(lastName); + return this; + } + + /** + * This method adds additional passwords to the user. + */ + public UserBuilder addPassword(String password) { + if (rep.getCredentials() == null) { + rep.setCredentials(new LinkedList<>()); + } + + CredentialRepresentation credential = new CredentialRepresentation(); + credential.setType(CredentialRepresentation.PASSWORD); + credential.setValue(password); + + rep.getCredentials().add(credential); + return this; + } + + public UserBuilder addAttribute(String name, String... values) { + if (rep.getAttributes() == null) { + rep.setAttributes(new HashMap<>()); + } + + rep.getAttributes().put(name, Arrays.asList(values)); + return this; + } + + /** + * This method makes sure that there is one single password for the user. + */ + public UserBuilder password(String password) { + rep.setCredentials(null); + return addPassword(password); + } + + public UserBuilder email(String email) { + rep.setEmail(email); + return this; + } + + public UserBuilder emailVerified(boolean emailVerified) { + rep.setEmailVerified(emailVerified); + return this; + } + + public UserBuilder enabled(boolean enabled) { + rep.setEnabled(enabled); + return this; + } + + public UserBuilder addRoles(String... roles) { + if (rep.getRealmRoles() == null) { + rep.setRealmRoles(new ArrayList<>()); + } + rep.getRealmRoles().addAll(Arrays.asList(roles)); + return this; + } + + public UserBuilder role(String client, String role) { + if (rep.getClientRoles() == null) { + rep.setClientRoles(new HashMap<>()); + } + if (rep.getClientRoles().get(client) == null) { + rep.getClientRoles().put(client, new LinkedList<>()); + } + rep.getClientRoles().get(client).add(role); + return this; + } + + public UserBuilder requiredAction(String requiredAction) { + if (rep.getRequiredActions() == null) { + rep.setRequiredActions(new LinkedList<>()); + } + rep.getRequiredActions().add(requiredAction); + return this; + } + + public UserBuilder serviceAccountId(String serviceAccountId) { + rep.setServiceAccountClientId(serviceAccountId); + return this; + } + + public UserBuilder secret(CredentialRepresentation credential) { + if (rep.getCredentials() == null) { + rep.setCredentials(new LinkedList<>()); + } + + rep.getCredentials().add(credential); + rep.setTotp(true); + return this; + } + + public UserBuilder totpSecret(String totpSecret) { + CredentialRepresentation credential = ModelToRepresentation.toRepresentation( + OTPCredentialModel.createTOTP(totpSecret, 6, 30, HmacOTP.HMAC_SHA1)); + return secret(credential); + } + + public UserBuilder hotpSecret(String hotpSecret) { + CredentialRepresentation credential = ModelToRepresentation.toRepresentation( + OTPCredentialModel.createHOTP(hotpSecret, 6, 0, HmacOTP.HMAC_SHA1)); + return secret(credential); + } + + public UserBuilder otpEnabled() { + rep.setTotp(Boolean.TRUE); + return this; + } + + public UserBuilder addGroups(String... group) { + if (rep.getGroups() == null) { + rep.setGroups(new ArrayList<>()); + } + rep.getGroups().addAll(Arrays.asList(group)); + return this; + } + + public UserBuilder federatedLink(String identityProvider, String federatedUserId) { + if (rep.getFederatedIdentities() == null) { + rep.setFederatedIdentities(new LinkedList<>()); + } + FederatedIdentityRepresentation federatedIdentity = new FederatedIdentityRepresentation(); + federatedIdentity.setUserId(federatedUserId); + federatedIdentity.setUserName(rep.getUsername()); + federatedIdentity.setIdentityProvider(identityProvider); + + rep.getFederatedIdentities().add(federatedIdentity); + return this; + } + + public UserRepresentation build() { + return rep; + } +}