Encode realm name in console URIs (#29102)
Before this fix console uris (including the client redirect uris) did not contain the url encoded realm name and therefore were invalid. closes #25807 Signed-off-by: Philip Sanetra <code@psanetra.de> Signed-off-by: rmartinc <rmartinc@redhat.com> Co-authored-by: Philip Sanetra <code@psanetra.de> Co-authored-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
parent
879fe082dd
commit
65bdf1a604
4 changed files with 71 additions and 4 deletions
|
@ -59,7 +59,7 @@ export const PersonalInfoRoute: IndexRouteObject = {
|
|||
};
|
||||
|
||||
export const RootRoute: RouteObject = {
|
||||
path: new URL(environment.baseUrl).pathname,
|
||||
path: decodeURIComponent(new URL(environment.baseUrl).pathname),
|
||||
element: <Root />,
|
||||
errorElement: <ErrorPage />,
|
||||
children: [
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.services.managers;
|
|||
import org.keycloak.Config;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
import org.keycloak.common.util.Encode;
|
||||
import org.keycloak.models.AbstractKeycloakTransaction;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
|
@ -178,7 +179,8 @@ public class RealmManager {
|
|||
adminConsole.setName("${client_" + Constants.ADMIN_CONSOLE_CLIENT_ID + "}");
|
||||
|
||||
adminConsole.setRootUrl(Constants.AUTH_ADMIN_URL_PROP);
|
||||
String baseUrl = "/admin/" + realm.getName() + "/console/";
|
||||
|
||||
String baseUrl = "/admin/" + Encode.encodePathAsIs(realm.getName()) + "/console/";
|
||||
adminConsole.setBaseUrl(baseUrl);
|
||||
adminConsole.addRedirectUri(baseUrl + "*");
|
||||
adminConsole.setAttribute(OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS, "+");
|
||||
|
@ -424,7 +426,8 @@ public class RealmManager {
|
|||
accountClient.setFullScopeAllowed(false);
|
||||
|
||||
accountClient.setRootUrl(Constants.AUTH_BASE_URL_PROP);
|
||||
String baseUrl = "/realms/" + realm.getName() + "/account/";
|
||||
|
||||
String baseUrl = "/realms/" + Encode.encodePathAsIs(realm.getName()) + "/account/";
|
||||
accountClient.setBaseUrl(baseUrl);
|
||||
accountClient.addRedirectUri(baseUrl + "*");
|
||||
accountClient.setAttribute(OIDCConfigAttributes.POST_LOGOUT_REDIRECT_URIS, "+");
|
||||
|
@ -529,6 +532,7 @@ public class RealmManager {
|
|||
try {
|
||||
session.getContext().setRealm(realm);
|
||||
ReservedCharValidator.validate(rep.getRealm());
|
||||
ReservedCharValidator.validateLocales(rep.getSupportedLocales());
|
||||
realm.setName(rep.getRealm());
|
||||
|
||||
// setup defaults
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.keycloak.http.HttpResponse;
|
|||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.NotAuthorizedException;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.Encode;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.JWSInputException;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -170,7 +171,7 @@ public class AdminRoot {
|
|||
} catch (JWSInputException e) {
|
||||
throw new NotAuthorizedException("Bearer token format error");
|
||||
}
|
||||
String realmName = token.getIssuer().substring(token.getIssuer().lastIndexOf('/') + 1);
|
||||
String realmName = Encode.decodePath(token.getIssuer().substring(token.getIssuer().lastIndexOf('/') + 1));
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.getRealmByName(realmName);
|
||||
if (realm == null) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.keycloak.testsuite.admin.realm;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import jakarta.ws.rs.BadRequestException;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
|
@ -36,6 +37,7 @@ 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;
|
||||
|
@ -67,6 +69,7 @@ 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;
|
||||
|
@ -86,15 +89,20 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
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;
|
||||
|
@ -217,6 +225,57 @@ public class RealmTest extends AbstractAdminTest {
|
|||
Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME);
|
||||
}
|
||||
|
||||
@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);
|
||||
rep.setUsers(Collections.singletonList(UserBuilder.create()
|
||||
.username("new-realm-admin")
|
||||
.firstName("new-realm-admin")
|
||||
.lastName("new-realm-admin")
|
||||
.email("new-realm-admin@keycloak.org")
|
||||
.password("password")
|
||||
.role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.REALM_ADMIN)
|
||||
.build()));
|
||||
|
||||
adminClient.realms().create(rep);
|
||||
|
||||
Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME, realmNameWithSpaces);
|
||||
|
||||
final var urlPlaceHolders = ImmutableSet.of("${authBaseUrl}", "${authAdminUrl}");
|
||||
|
||||
RealmResource newRealm = adminClient.realms().realm(realmNameWithSpaces);
|
||||
List<String> clientUris = newRealm.clients()
|
||||
.findAll()
|
||||
.stream()
|
||||
.flatMap(client -> Stream.concat(Stream.concat(Stream.concat(
|
||||
client.getRedirectUris().stream(),
|
||||
Stream.of(client.getBaseUrl())),
|
||||
Stream.of(client.getRootUrl())),
|
||||
Stream.of(client.getAdminUrl())))
|
||||
.filter(Objects::nonNull)
|
||||
.filter(uri -> !urlPlaceHolders.contains(uri))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
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)) {
|
||||
Assert.assertNotNull(client.serverInfo().getInfo());
|
||||
}
|
||||
|
||||
adminClient.realms().realm(realmNameWithSpaces).remove();
|
||||
|
||||
Assert.assertNames(adminClient.realms().findAll(), "master", AuthRealm.TEST, REALM_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createRealmRejectReservedCharOrEmptyName() {
|
||||
RealmRepresentation rep = new RealmRepresentation();
|
||||
|
@ -224,6 +283,9 @@ public class RealmTest extends AbstractAdminTest {
|
|||
assertThrows(BadRequestException.class, () -> adminClient.realms().create(rep));
|
||||
rep.setRealm("");
|
||||
assertThrows(BadRequestException.class, () -> adminClient.realms().create(rep));
|
||||
rep.setRealm("new-realm");
|
||||
rep.setId("invalid;id");
|
||||
assertThrows(BadRequestException.class, () -> adminClient.realms().create(rep));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue