task: remove usage of resteasy-core-spi (#27387)

closes: #27242

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins 2024-03-21 10:28:34 -04:00 committed by GitHub
parent bf1248d062
commit 35b9d8aa49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
52 changed files with 326 additions and 250 deletions

View file

@ -32,7 +32,6 @@ import org.jboss.logging.Logger;
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider; import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider;
import org.keycloak.connections.jpa.updater.liquibase.ThreadLocalSessionContext; import org.keycloak.connections.jpa.updater.liquibase.ThreadLocalSessionContext;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
@ -45,8 +44,6 @@ import java.util.List;
*/ */
public abstract class CustomKeycloakTask implements CustomSqlChange { public abstract class CustomKeycloakTask implements CustomSqlChange {
private final Logger logger = Logger.getLogger(getClass());
protected KeycloakSession kcSession; protected KeycloakSession kcSession;
protected Database database; protected Database database;
@ -73,18 +70,8 @@ public abstract class CustomKeycloakTask implements CustomSqlChange {
@Override @Override
public void setUp() throws SetupException { public void setUp() throws SetupException {
this.kcSession = ThreadLocalSessionContext.getCurrentSession(); this.kcSession = ThreadLocalSessionContext.getCurrentSession();
if (this.kcSession == null) { if (this.kcSession == null) {
// Probably running Liquibase from maven plugin. Try to create kcSession programmatically throw new SetupException("Thread bound session is null");
logger.info("No KeycloakSession provided in ThreadLocal. Initializing KeycloakSessionFactory");
try {
DefaultKeycloakSessionFactory factory = new DefaultKeycloakSessionFactory();
factory.init();
this.kcSession = factory.create();
} catch (Exception e) {
throw new SetupException("Exception when initializing factory", e);
}
} }
} }

View file

@ -1313,6 +1313,12 @@
<artifactId>keycloak-services</artifactId> <artifactId>keycloak-services</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
</dependency>
<!-- Authorization --> <!-- Authorization -->
<dependency> <dependency>

View file

@ -103,7 +103,6 @@ import org.keycloak.representations.provider.ScriptProviderMetadata;
import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.representations.userprofile.config.UPConfig;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.services.resources.JsResource; import org.keycloak.services.resources.JsResource;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.LoadBalancerResource; import org.keycloak.services.resources.LoadBalancerResource;
import org.keycloak.services.resources.admin.AdminRoot; import org.keycloak.services.resources.admin.AdminRoot;
import org.keycloak.theme.ClasspathThemeProviderFactory; import org.keycloak.theme.ClasspathThemeProviderFactory;
@ -623,9 +622,6 @@ class KeycloakProcessor {
void configureResteasy(CombinedIndexBuildItem index, void configureResteasy(CombinedIndexBuildItem index,
BuildProducer<BuildTimeConditionBuildItem> buildTimeConditionBuildItemBuildProducer, BuildProducer<BuildTimeConditionBuildItem> buildTimeConditionBuildItemBuildProducer,
BuildProducer<MethodScannerBuildItem> scanner) { BuildProducer<MethodScannerBuildItem> scanner) {
buildTimeConditionBuildItemBuildProducer.produce(new BuildTimeConditionBuildItem(index.getIndex().getClassByName(DotName.createSimple(
KeycloakApplication.class.getName())), false));
if (!Profile.isFeatureEnabled(Profile.Feature.ADMIN_API)) { if (!Profile.isFeatureEnabled(Profile.Feature.ADMIN_API)) {
buildTimeConditionBuildItemBuildProducer.produce(new BuildTimeConditionBuildItem(index.getIndex().getClassByName(DotName.createSimple( buildTimeConditionBuildItemBuildProducer.produce(new BuildTimeConditionBuildItem(index.getIndex().getClassByName(DotName.createSimple(
AdminRoot.class.getName())), false)); AdminRoot.class.getName())), false));

View file

@ -548,10 +548,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core-spi</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>

View file

@ -27,8 +27,6 @@ import org.keycloak.quarkus.runtime.integration.QuarkusKeycloakSessionFactory;
import org.keycloak.quarkus.runtime.integration.QuarkusPlatform; import org.keycloak.quarkus.runtime.integration.QuarkusPlatform;
import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.KeycloakApplication;
import java.util.Set;
import jakarta.enterprise.event.Observes; import jakarta.enterprise.event.Observes;
import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.ApplicationPath;
@ -59,13 +57,4 @@ public class QuarkusKeycloakApplication extends KeycloakApplication {
// no need to load config provider because we force quarkus impl // no need to load config provider because we force quarkus impl
} }
@Override
public Set<Object> getSingletons() {
return Set.of();
}
@Override
public Set<Class<?>> getClasses() {
return Set.of();
}
} }

View file

@ -4,6 +4,7 @@ import static org.keycloak.utils.StreamsUtil.throwIfEmpty;
import java.util.stream.Stream; import java.util.stream.Stream;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
@ -17,7 +18,6 @@ import org.jboss.resteasy.reactive.NoCache;
import org.keycloak.admin.ui.rest.model.RealmNameRepresentation; import org.keycloak.admin.ui.rest.model.RealmNameRepresentation;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.resources.admin.permissions.AdminPermissions; import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.resources.admin.permissions.RealmsPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.RealmsPermissionEvaluator;

View file

@ -137,6 +137,7 @@
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core-spi</artifactId> <artifactId>resteasy-core-spi</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId> <groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
@ -249,6 +250,16 @@
</compilerArgument> </compilerArgument>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>

View file

@ -19,6 +19,8 @@ package org.keycloak.authentication.requiredactions;
import java.util.Objects; import java.util.Objects;
import jakarta.ws.rs.ForbiddenException;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.authentication.AuthenticationProcessor; import org.keycloak.authentication.AuthenticationProcessor;
@ -39,7 +41,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.UserManager; import org.keycloak.models.UserManager;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages; import org.keycloak.services.messages.Messages;

View file

@ -22,7 +22,6 @@ import java.util.Map;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.authorization.AuthorizationProvider; import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy; import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.ResourceServer; import org.keycloak.authorization.model.ResourceServer;

View file

@ -40,7 +40,7 @@ import java.util.Map;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
public class DefaultKeycloakContext implements KeycloakContext { public abstract class DefaultKeycloakContext implements KeycloakContext {
private RealmModel realm; private RealmModel realm;
@ -131,12 +131,12 @@ public class DefaultKeycloakContext implements KeycloakContext {
public Locale resolveLocale(UserModel user) { public Locale resolveLocale(UserModel user) {
return session.getProvider(LocaleSelectorProvider.class).resolveLocale(getRealm(), user); return session.getProvider(LocaleSelectorProvider.class).resolveLocale(getRealm(), user);
} }
@Override @Override
public AuthenticationSessionModel getAuthenticationSession() { public AuthenticationSessionModel getAuthenticationSession() {
return authenticationSession; return authenticationSession;
} }
@Override @Override
public void setAuthenticationSession(AuthenticationSessionModel authenticationSession) { public void setAuthenticationSession(AuthenticationSessionModel authenticationSession) {
this.authenticationSession = authenticationSession; this.authenticationSession = authenticationSession;
@ -170,13 +170,9 @@ public class DefaultKeycloakContext implements KeycloakContext {
return response; return response;
} }
protected HttpRequest createHttpRequest() { protected abstract HttpRequest createHttpRequest();
return new HttpRequestImpl(getContextObject(org.jboss.resteasy.spi.HttpRequest.class));
}
protected HttpResponse createHttpResponse() { protected abstract HttpResponse createHttpResponse();
return new HttpResponseImpl(getContextObject(org.jboss.resteasy.spi.HttpResponse.class));
}
protected KeycloakSession getSession() { protected KeycloakSession getSession() {
return session; return session;

View file

@ -67,7 +67,7 @@ import java.util.stream.Collectors;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
public class DefaultKeycloakSession implements KeycloakSession { public abstract class DefaultKeycloakSession implements KeycloakSession {
private final DefaultKeycloakSessionFactory factory; private final DefaultKeycloakSessionFactory factory;
private final Map<Integer, Provider> providers = new HashMap<>(); private final Map<Integer, Provider> providers = new HashMap<>();
@ -253,6 +253,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
return provider; return provider;
} }
@Override
public <T extends Provider> Set<String> listProviderIds(Class<T> clazz) { public <T extends Provider> Set<String> listProviderIds(Class<T> clazz) {
return factory.getAllProviderIds(clazz); return factory.getAllProviderIds(clazz);
} }
@ -418,9 +419,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
return String.format("session @ %08x", System.identityHashCode(this)); return String.format("session @ %08x", System.identityHashCode(this));
} }
protected DefaultKeycloakContext createKeycloakContext(KeycloakSession session) { protected abstract DefaultKeycloakContext createKeycloakContext(KeycloakSession session);
return new DefaultKeycloakContext(session);
}
public boolean isClosed() { public boolean isClosed() {
return closed; return closed;

View file

@ -52,7 +52,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, ProviderManagerDeployer { public abstract class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, ProviderManagerDeployer {
private static final Logger logger = Logger.getLogger(DefaultKeycloakSessionFactory.class); private static final Logger logger = Logger.getLogger(DefaultKeycloakSessionFactory.class);
@ -74,7 +74,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
private Long roleStorageProviderTimeout; private Long roleStorageProviderTimeout;
protected ComponentFactoryProviderFactory componentFactoryPF; protected ComponentFactoryProviderFactory componentFactoryPF;
@Override @Override
public void register(ProviderEventListener listener) { public void register(ProviderEventListener listener) {
listeners.add(listener); listeners.add(listener);
@ -318,11 +318,6 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
return true; return true;
} }
public KeycloakSession create() {
KeycloakSession session = new DefaultKeycloakSession(this);
return session;
}
@Override @Override
public Set<Spi> getSpis() { public Set<Spi> getSpis() {
return spis; return spis;
@ -396,6 +391,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
return null; return null;
} }
@Override
public void close() { public void close() {
ProviderManagerRegistry.SINGLETON.setDeployer(null); ProviderManagerRegistry.SINGLETON.setDeployer(null);
for (Map<String, ProviderFactory> factories : factoriesMap.values()) { for (Map<String, ProviderFactory> factories : factoriesMap.values()) {

View file

@ -1,65 +0,0 @@
/*
* 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.services;
import org.jboss.resteasy.spi.LoggableFailure;
import jakarta.ws.rs.core.Response;
/**
* To provide a typed exception for Forbidden (This doesn't exist in Resteasy 2.3.7)
*/
public class ForbiddenException extends LoggableFailure
{
public ForbiddenException()
{
super(403);
}
public ForbiddenException(String s)
{
super(s, 403);
}
public ForbiddenException(String s, Response response)
{
super(s, response);
}
public ForbiddenException(String s, Throwable throwable, Response response)
{
super(s, throwable, response);
}
public ForbiddenException(String s, Throwable throwable)
{
super(s, throwable, 403);
}
public ForbiddenException(Throwable throwable)
{
super(throwable, 403);
}
public ForbiddenException(Throwable throwable, Response response)
{
super(throwable, response);
}
}

View file

@ -40,7 +40,6 @@ import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation; import org.keycloak.representations.oidc.OIDCClientRepresentation;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.clientpolicy.ClientPolicyException; import org.keycloak.services.clientpolicy.ClientPolicyException;
import org.keycloak.services.clientpolicy.context.DynamicClientRegisteredContext; import org.keycloak.services.clientpolicy.context.DynamicClientRegisteredContext;
import org.keycloak.services.clientpolicy.context.DynamicClientUpdatedContext; import org.keycloak.services.clientpolicy.context.DynamicClientUpdatedContext;
@ -50,6 +49,7 @@ import org.keycloak.services.managers.ClientManager;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.validation.ValidationUtil; import org.keycloak.validation.ValidationUtil;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
/** /**

View file

@ -17,7 +17,6 @@
package org.keycloak.services.clientregistration; package org.keycloak.services.clientregistration;
import org.jboss.resteasy.spi.Failure;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
import org.keycloak.authentication.AuthenticationProcessor; import org.keycloak.authentication.AuthenticationProcessor;
@ -46,6 +45,7 @@ import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyM
import org.keycloak.services.clientregistration.policy.RegistrationAuth; import org.keycloak.services.clientregistration.policy.RegistrationAuth;
import org.keycloak.util.TokenUtil; import org.keycloak.util.TokenUtil;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import java.util.List; import java.util.List;
@ -380,21 +380,21 @@ public class ClientRegistrationAuth {
return true; return true;
} }
private Failure unauthorized(String errorDescription) { private WebApplicationException unauthorized(String errorDescription) {
event.detail(Details.REASON, errorDescription).error(Errors.INVALID_TOKEN); event.detail(Details.REASON, errorDescription).error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, errorDescription, Response.Status.UNAUTHORIZED); throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, errorDescription, Response.Status.UNAUTHORIZED);
} }
private Failure forbidden() { private WebApplicationException forbidden() {
return forbidden("Forbidden"); return forbidden("Forbidden");
} }
private Failure forbidden(String errorDescription) { private WebApplicationException forbidden(String errorDescription) {
event.error(Errors.NOT_ALLOWED); event.error(Errors.NOT_ALLOWED);
throw new ErrorResponseException(OAuthErrorException.INSUFFICIENT_SCOPE, errorDescription, Response.Status.FORBIDDEN); throw new ErrorResponseException(OAuthErrorException.INSUFFICIENT_SCOPE, errorDescription, Response.Status.FORBIDDEN);
} }
private Failure notFound() { private WebApplicationException notFound() {
event.error(Errors.CLIENT_NOT_FOUND); event.error(Errors.CLIENT_NOT_FOUND);
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "Client not found", Response.Status.NOT_FOUND); throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "Client not found", Response.Status.NOT_FOUND);
} }

View file

@ -6,7 +6,6 @@ import static org.keycloak.services.resources.KeycloakApplication.getSessionFact
import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.Failure;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
import org.keycloak.forms.login.freemarker.model.UrlBean; import org.keycloak.forms.login.freemarker.model.UrlBean;
@ -122,10 +121,6 @@ public class KeycloakErrorHandler implements ExceptionMapper<Throwable> {
WebApplicationException ex = (WebApplicationException) throwable; WebApplicationException ex = (WebApplicationException) throwable;
status = ex.getResponse().getStatus(); status = ex.getResponse().getStatus();
} }
if (throwable instanceof Failure) {
Failure f = (Failure) throwable;
status = f.getErrorCode();
}
if (throwable instanceof JsonProcessingException) { if (throwable instanceof JsonProcessingException) {
status = Response.Status.BAD_REQUEST.getStatusCode(); status = Response.Status.BAD_REQUEST.getStatusCode();
} }

View file

@ -23,7 +23,8 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.keycloak.services.ForbiddenException;
import jakarta.ws.rs.ForbiddenException;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -17,7 +17,6 @@
package org.keycloak.services.resources; package org.keycloak.services.resources;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.BadRequestException;
import org.keycloak.http.HttpRequest; import org.keycloak.http.HttpRequest;
import org.keycloak.AbstractOAuthClient; import org.keycloak.AbstractOAuthClient;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
@ -29,11 +28,12 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.Auth; import org.keycloak.services.managers.Auth;
import org.keycloak.services.messages.Messages; import org.keycloak.services.messages.Messages;
import org.keycloak.util.TokenUtil; import org.keycloak.util.TokenUtil;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.QueryParam;

View file

@ -17,7 +17,6 @@
package org.keycloak.services.resources; package org.keycloak.services.resources;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.BadRequestException;
import org.keycloak.http.HttpRequest; import org.keycloak.http.HttpRequest;
import jakarta.ws.rs.NotAuthorizedException; import jakarta.ws.rs.NotAuthorizedException;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
@ -33,8 +32,9 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil; import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
import org.keycloak.representations.idm.OAuth2ErrorRepresentation; import org.keycloak.representations.idm.OAuth2ErrorRepresentation;
import org.keycloak.services.ForbiddenException;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.HeaderParam; import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;

View file

@ -16,10 +16,8 @@
*/ */
package org.keycloak.services.resources; package org.keycloak.services.resources;
import com.fasterxml.jackson.core.type.TypeReference;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.common.Profile;
import org.keycloak.common.crypto.CryptoIntegration; import org.keycloak.common.crypto.CryptoIntegration;
import org.keycloak.common.util.Resteasy; import org.keycloak.common.util.Resteasy;
import org.keycloak.config.ConfigProviderFactory; import org.keycloak.config.ConfigProviderFactory;
@ -42,51 +40,39 @@ import org.keycloak.platform.Platform;
import org.keycloak.platform.PlatformProvider; import org.keycloak.platform.PlatformProvider;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.DefaultKeycloakSessionFactory;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.services.error.KeycloakErrorHandler;
import org.keycloak.services.error.KcUnrecognizedPropertyExceptionHandler;
import org.keycloak.services.error.KeycloakMismatchedInputExceptionHandler;
import org.keycloak.services.filters.KeycloakSecurityHeadersFilter;
import org.keycloak.services.managers.ApplianceBootstrap; import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.admin.AdminRoot;
import org.keycloak.services.util.ObjectMapperResolver;
import org.keycloak.transaction.JtaTransactionManagerLookup; import org.keycloak.transaction.JtaTransactionManagerLookup;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.ServiceLoader;
import com.fasterxml.jackson.core.type.TypeReference;
import jakarta.transaction.SystemException; import jakarta.transaction.SystemException;
import jakarta.transaction.Transaction; import jakarta.transaction.Transaction;
import jakarta.ws.rs.core.Application; import jakarta.ws.rs.core.Application;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.ServiceLoader;
import java.util.Set;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $
* *
* Note: the classes and singletons are not used by Quarkus - see the KeycloakProcessor to do exclusions
*/ */
public class KeycloakApplication extends Application { public abstract class KeycloakApplication extends Application {
private static final Logger logger = Logger.getLogger(KeycloakApplication.class); private static final Logger logger = Logger.getLogger(KeycloakApplication.class);
protected final PlatformProvider platform = Platform.getPlatform(); protected final PlatformProvider platform = Platform.getPlatform();
protected Set<Object> singletons = new HashSet<>();
protected Set<Class<?>> classes = new HashSet<>();
private static KeycloakSessionFactory sessionFactory; private static KeycloakSessionFactory sessionFactory;
public KeycloakApplication() { public KeycloakApplication() {
try { try {
logger.debugv("PlatformProvider: {0}", platform.getClass().getName()); logger.debugv("PlatformProvider: {0}", platform.getClass().getName());
@ -94,38 +80,12 @@ public class KeycloakApplication extends Application {
loadConfig(); loadConfig();
classes.add(RobotsResource.class);
classes.add(RealmsResource.class);
if (Profile.isFeatureEnabled(Profile.Feature.ADMIN_API)) {
classes.add(AdminRoot.class);
}
classes.add(ThemeResource.class);
if (Profile.isFeatureEnabled(Profile.Feature.JS_ADAPTER)) {
classes.add(JsResource.class);
}
classes.add(KeycloakSecurityHeadersFilter.class);
classes.add(KeycloakErrorHandler.class);
classes.add(KcUnrecognizedPropertyExceptionHandler.class);
classes.add(KeycloakMismatchedInputExceptionHandler.class);
singletons.add(new ObjectMapperResolver());
classes.add(WelcomeResource.class);
if (Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE)) {
// If we are running in multi-site mode, we need to add a resource which to expose
// an endpoint for the load balancer to gather information whether this site should receive requests or not.
classes.add(LoadBalancerResource.class);
}
platform.onStartup(this::startup); platform.onStartup(this::startup);
platform.onShutdown(this::shutdown); platform.onShutdown(this::shutdown);
} catch (Throwable t) { } catch (Throwable t) {
platform.exit(t); platform.exit(t);
} }
} }
protected void startup() { protected void startup() {
@ -225,26 +185,12 @@ public class KeycloakApplication extends Application {
} }
protected KeycloakSessionFactory createSessionFactory() { protected abstract KeycloakSessionFactory createSessionFactory();
DefaultKeycloakSessionFactory factory = new DefaultKeycloakSessionFactory();
factory.init();
return factory;
}
public static KeycloakSessionFactory getSessionFactory() { public static KeycloakSessionFactory getSessionFactory() {
return sessionFactory; return sessionFactory;
} }
@Override
public Set<Class<?>> getClasses() {
return classes;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
public void importRealms(ExportImportManager exportImportManager) { public void importRealms(ExportImportManager exportImportManager) {
String dir = System.getProperty("keycloak.import"); String dir = System.getProperty("keycloak.import");
if (dir != null) { if (dir != null) {

View file

@ -17,6 +17,7 @@
package org.keycloak.services.resources; package org.keycloak.services.resources;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
@ -42,7 +43,6 @@ import org.keycloak.cookie.CookieProvider;
import org.keycloak.cookie.CookieType; import org.keycloak.cookie.CookieType;
import org.keycloak.http.HttpRequest; import org.keycloak.http.HttpRequest;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.ApplianceBootstrap; import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.util.CacheControlUtil; import org.keycloak.services.util.CacheControlUtil;

View file

@ -29,7 +29,6 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.cors.Cors; import org.keycloak.services.cors.Cors;
import org.keycloak.services.managers.AppAuthManager; import org.keycloak.services.managers.AppAuthManager;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
@ -39,6 +38,7 @@ import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.theme.Theme; import org.keycloak.theme.Theme;
import org.keycloak.urls.UrlType; import org.keycloak.urls.UrlType;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.HttpMethod; import jakarta.ws.rs.HttpMethod;
import jakarta.ws.rs.OPTIONS; import jakarta.ws.rs.OPTIONS;

View file

@ -24,7 +24,6 @@ import jakarta.ws.rs.core.Response.Status;
import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.jboss.resteasy.reactive.NoCache; import org.jboss.resteasy.reactive.NoCache;
import org.jboss.resteasy.spi.BadRequestException;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
import org.keycloak.authorization.admin.AuthorizationService; import org.keycloak.authorization.admin.AuthorizationService;
import org.keycloak.common.ClientConnection; import org.keycloak.common.ClientConnection;
@ -78,6 +77,7 @@ import org.keycloak.utils.ProfileHelper;
import org.keycloak.utils.ReservedCharValidator; import org.keycloak.utils.ReservedCharValidator;
import org.keycloak.validation.ValidationUtil; import org.keycloak.validation.ValidationUtil;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;

View file

@ -38,7 +38,6 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation; import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
import org.keycloak.services.ErrorResponse; import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.clientpolicy.ClientPolicyException; import org.keycloak.services.clientpolicy.ClientPolicyException;
import org.keycloak.services.clientpolicy.context.AdminClientRegisterContext; import org.keycloak.services.clientpolicy.context.AdminClientRegisterContext;
import org.keycloak.services.clientpolicy.context.AdminClientRegisteredContext; import org.keycloak.services.clientpolicy.context.AdminClientRegisteredContext;
@ -51,6 +50,7 @@ import org.keycloak.validation.ValidationUtil;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;

View file

@ -27,7 +27,6 @@ import org.keycloak.http.FormPartValue;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.resources.KeycloakOpenAPI; import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
@ -40,6 +39,7 @@ import java.util.stream.Stream;
import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;

View file

@ -38,7 +38,6 @@ import org.keycloak.policy.PasswordPolicyNotMetException;
import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.ErrorResponse; import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakOpenAPI; import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
@ -48,6 +47,7 @@ import org.keycloak.storage.ExportImportManager;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;

View file

@ -71,7 +71,6 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation; import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.services.ErrorResponse; import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
import org.keycloak.services.Urls; import org.keycloak.services.Urls;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
@ -93,6 +92,7 @@ import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
@ -160,7 +160,7 @@ public class UserResource {
this.adminEvent = adminEvent.resource(ResourceType.USER); this.adminEvent = adminEvent.resource(ResourceType.USER);
this.headers = session.getContext().getRequestHeaders(); this.headers = session.getContext().getRequestHeaders();
} }
/** /**
* Update the user * Update the user
* *

View file

@ -40,7 +40,6 @@ import org.keycloak.models.utils.RepresentationToModel;
import org.keycloak.policy.PasswordPolicyNotMetException; import org.keycloak.policy.PasswordPolicyNotMetException;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.ErrorResponse; import org.keycloak.services.ErrorResponse;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.resources.KeycloakOpenAPI; import org.keycloak.services.resources.KeycloakOpenAPI;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
import org.keycloak.services.resources.admin.permissions.UserPermissionEvaluator; import org.keycloak.services.resources.admin.permissions.UserPermissionEvaluator;
@ -49,6 +48,7 @@ import org.keycloak.userprofile.UserProfileProvider;
import org.keycloak.utils.SearchQueryUtils; import org.keycloak.utils.SearchQueryUtils;
import jakarta.ws.rs.Consumes; import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;

View file

@ -33,7 +33,6 @@ import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.services.ForbiddenException;
import org.keycloak.storage.StorageId; import org.keycloak.storage.StorageId;
import java.util.Arrays; import java.util.Arrays;
@ -45,6 +44,8 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jakarta.ws.rs.ForbiddenException;
import static org.keycloak.services.resources.admin.permissions.AdminPermissionManagement.TOKEN_EXCHANGE; import static org.keycloak.services.resources.admin.permissions.AdminPermissionManagement.TOKEN_EXCHANGE;
/** /**

View file

@ -28,7 +28,6 @@ import org.keycloak.authorization.store.ResourceStore;
import org.keycloak.models.AdminRoles; import org.keycloak.models.AdminRoles;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.services.ForbiddenException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -40,6 +39,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jakarta.ws.rs.ForbiddenException;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $
@ -348,13 +349,13 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
if (!root.isAdminSameRealm()) { if (!root.isAdminSameRealm()) {
return false; return false;
} }
ResourceServer server = root.realmResourceServer(); ResourceServer server = root.realmResourceServer();
if (server == null) return false; if (server == null) return false;
return hasPermission(group, VIEW_MEMBERS_SCOPE); return hasPermission(group, VIEW_MEMBERS_SCOPE);
} }
@Override @Override
public boolean canManageMembers(GroupModel group) { public boolean canManageMembers(GroupModel group) {
if (root.users().canManage()) return true; if (root.users().canManage()) return true;
@ -379,7 +380,7 @@ class GroupPermissions implements GroupPermissionEvaluator, GroupPermissionManag
return hasPermission(group, MANAGE_MEMBERSHIP_SCOPE); return hasPermission(group, MANAGE_MEMBERSHIP_SCOPE);
} }
@Override @Override
public void requireManageMembership(GroupModel group) { public void requireManageMembership(GroupModel group) {
if (!canManageMembership(group)) { if (!canManageMembership(group)) {

View file

@ -37,7 +37,6 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.admin.AdminAuth; import org.keycloak.services.resources.admin.AdminAuth;
@ -45,6 +44,8 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import jakarta.ws.rs.ForbiddenException;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $

View file

@ -20,9 +20,10 @@ package org.keycloak.services.resources.admin.permissions;
import org.keycloak.models.AdminRoles; import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ImpersonationConstants; import org.keycloak.models.ImpersonationConstants;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.resources.admin.AdminAuth; import org.keycloak.services.resources.admin.AdminAuth;
import jakarta.ws.rs.ForbiddenException;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -21,7 +21,8 @@ import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.models.AdminRoles; import org.keycloak.models.AdminRoles;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.services.ForbiddenException;
import jakarta.ws.rs.ForbiddenException;
/** /**
* Manages default policies for all users. * Manages default policies for all users.

View file

@ -34,7 +34,6 @@ import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.representations.idm.authorization.DecisionStrategy; import org.keycloak.representations.idm.authorization.DecisionStrategy;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.services.ForbiddenException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -43,6 +42,8 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jakarta.ws.rs.ForbiddenException;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $ * @version $Revision: 1 $

View file

@ -36,7 +36,6 @@ import org.keycloak.models.ImpersonationConstants;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.services.ForbiddenException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -49,6 +48,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
import jakarta.ws.rs.ForbiddenException;
/** /**
* Manages default policies for all users. * Manages default policies for all users.
* *

View file

@ -35,8 +35,8 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.Assume; import org.junit.Assume;
import org.junit.Test; import org.junit.Test;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakSession; import org.keycloak.services.resteasy.ResteasyKeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.resteasy.ResteasyKeycloakSessionFactory;
import org.keycloak.utils.ScopeUtil; import org.keycloak.utils.ScopeUtil;
public class DefaultHttpClientFactoryTest { public class DefaultHttpClientFactoryTest {
@ -49,7 +49,7 @@ public class DefaultHttpClientFactoryTest {
values.put(DISABLE_TRUST_MANAGER_PROPERTY, "true"); values.put(DISABLE_TRUST_MANAGER_PROPERTY, "true");
DefaultHttpClientFactory factory = new DefaultHttpClientFactory(); DefaultHttpClientFactory factory = new DefaultHttpClientFactory();
factory.init(ScopeUtil.createScope(values)); factory.init(ScopeUtil.createScope(values));
KeycloakSession session = new DefaultKeycloakSession(new DefaultKeycloakSessionFactory()); KeycloakSession session = new ResteasyKeycloakSession(new ResteasyKeycloakSessionFactory());
HttpClientProvider provider = factory.create(session); HttpClientProvider provider = factory.create(session);
Optional<String> testURL = getTestURL(); Optional<String> testURL = getTestURL();
Assume.assumeTrue( "Could not get test url for domain", testURL.isPresent() ); Assume.assumeTrue( "Could not get test url for domain", testURL.isPresent() );
@ -63,7 +63,7 @@ public class DefaultHttpClientFactoryTest {
public void createHttpClientProviderWithUnvailableURL() throws IOException { public void createHttpClientProviderWithUnvailableURL() throws IOException {
DefaultHttpClientFactory factory = new DefaultHttpClientFactory(); DefaultHttpClientFactory factory = new DefaultHttpClientFactory();
factory.init(ScopeUtil.createScope(new HashMap<>())); factory.init(ScopeUtil.createScope(new HashMap<>()));
KeycloakSession session = new DefaultKeycloakSession(new DefaultKeycloakSessionFactory()); KeycloakSession session = new ResteasyKeycloakSession(new ResteasyKeycloakSessionFactory());
HttpClientProvider provider = factory.create(session); HttpClientProvider provider = factory.create(session);
try (CloseableHttpClient httpClient = provider.getHttpClient()) { try (CloseableHttpClient httpClient = provider.getHttpClient()) {
Optional<String> testURL = getTestURL(); Optional<String> testURL = getTestURL();

View file

@ -30,9 +30,9 @@ import org.keycloak.common.crypto.CryptoIntegration;
import org.keycloak.common.crypto.CryptoProvider; import org.keycloak.common.crypto.CryptoProvider;
import org.keycloak.http.HttpRequest; import org.keycloak.http.HttpRequest;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakSession; import org.keycloak.services.resteasy.HttpRequestImpl;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.resteasy.ResteasyKeycloakSession;
import org.keycloak.services.HttpRequestImpl; import org.keycloak.services.resteasy.ResteasyKeycloakSessionFactory;
/** /**
* <p>Little test class for RedirectUtils methods.</p> * <p>Little test class for RedirectUtils methods.</p>
@ -49,9 +49,9 @@ public class RedirectUtilsTest {
ResteasyContext.getContextDataMap().put(HttpRequest.class, httpRequest); ResteasyContext.getContextDataMap().put(HttpRequest.class, httpRequest);
Profile.defaults(); Profile.defaults();
CryptoIntegration.init(CryptoProvider.class.getClassLoader()); CryptoIntegration.init(CryptoProvider.class.getClassLoader());
DefaultKeycloakSessionFactory sessionFactory = new DefaultKeycloakSessionFactory(); ResteasyKeycloakSessionFactory sessionFactory = new ResteasyKeycloakSessionFactory();
sessionFactory.init(); sessionFactory.init();
session = new DefaultKeycloakSession(sessionFactory); session = new ResteasyKeycloakSession(sessionFactory);
} }
@Test @Test

View file

@ -47,8 +47,8 @@ import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder; import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil; import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil; import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
import org.keycloak.services.DefaultKeycloakSession; import org.keycloak.services.resteasy.ResteasyKeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.resteasy.ResteasyKeycloakSessionFactory;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
@ -118,7 +118,7 @@ public class SamlEncryptionTest {
.nameIdentifier(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get(), "nameId"); .nameIdentifier(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get(), "nameId");
ResponseType samlModel = builder.buildModel(); ResponseType samlModel = builder.buildModel();
KeycloakSession session = new DefaultKeycloakSession(new DefaultKeycloakSessionFactory()); KeycloakSession session = new ResteasyKeycloakSession(new ResteasyKeycloakSessionFactory());
JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(session); JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(session);
if (alg != null) { if (alg != null) {
bindingBuilder.encryptionAlgorithm(alg); bindingBuilder.encryptionAlgorithm(alg);

View file

@ -51,8 +51,8 @@ import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request; import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder; import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.services.DefaultKeycloakSession; import org.keycloak.services.resteasy.ResteasyKeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.resteasy.ResteasyKeycloakSessionFactory;
import org.keycloak.utils.ScopeUtil; import org.keycloak.utils.ScopeUtil;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -112,9 +112,9 @@ public class SoapTest {
Document doc = SAML2Request.convert(request); Document doc = SAML2Request.convert(request);
Profile.defaults(); Profile.defaults();
CryptoIntegration.init(CryptoProvider.class.getClassLoader()); CryptoIntegration.init(CryptoProvider.class.getClassLoader());
DefaultKeycloakSessionFactory sessionFactory = new DefaultKeycloakSessionFactory(); ResteasyKeycloakSessionFactory sessionFactory = new ResteasyKeycloakSessionFactory();
sessionFactory.init(); sessionFactory.init();
KeycloakSession session = new DefaultKeycloakSession(sessionFactory); KeycloakSession session = new ResteasyKeycloakSession(sessionFactory);
SOAPMessage soapResponse = Soap.createMessage() SOAPMessage soapResponse = Soap.createMessage()
.addMimeHeader("SOAPAction", "http://www.oasis-open.org/committees/security") .addMimeHeader("SOAPAction", "http://www.oasis-open.org/committees/security")
@ -154,9 +154,9 @@ public class SoapTest {
return ScopeUtil.createScope(new HashMap<>()); return ScopeUtil.createScope(new HashMap<>());
} }
}); });
DefaultKeycloakSessionFactory sessionFactory = new DefaultKeycloakSessionFactory(); ResteasyKeycloakSessionFactory sessionFactory = new ResteasyKeycloakSessionFactory();
sessionFactory.init(); sessionFactory.init();
KeycloakSession session = new DefaultKeycloakSession(sessionFactory); KeycloakSession session = new ResteasyKeycloakSession(sessionFactory);
SOAPException ex = Assert.assertThrows(SOAPException.class, () -> { SOAPException ex = Assert.assertThrows(SOAPException.class, () -> {
Soap.createMessage() Soap.createMessage()

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.keycloak.services; package org.keycloak.services.resteasy;
import static jakarta.ws.rs.core.MediaType.MULTIPART_FORM_DATA_TYPE; import static jakarta.ws.rs.core.MediaType.MULTIPART_FORM_DATA_TYPE;
@ -36,6 +36,7 @@ import org.jboss.resteasy.reactive.server.multipart.MultipartFormDataInput;
import org.keycloak.common.util.Resteasy; import org.keycloak.common.util.Resteasy;
import org.keycloak.http.FormPartValue; import org.keycloak.http.FormPartValue;
import org.keycloak.http.HttpRequest; import org.keycloak.http.HttpRequest;
import org.keycloak.services.FormPartValueImpl;
public class HttpRequestImpl implements HttpRequest { public class HttpRequestImpl implements HttpRequest {

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.keycloak.services; package org.keycloak.services.resteasy;
import jakarta.ws.rs.core.NewCookie; import jakarta.ws.rs.core.NewCookie;
import org.keycloak.http.HttpResponse; import org.keycloak.http.HttpResponse;

View file

@ -0,0 +1,88 @@
/*
* Copyright 2024 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.services.resteasy;
import org.keycloak.common.Profile;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.services.error.KcUnrecognizedPropertyExceptionHandler;
import org.keycloak.services.error.KeycloakErrorHandler;
import org.keycloak.services.error.KeycloakMismatchedInputExceptionHandler;
import org.keycloak.services.filters.KeycloakSecurityHeadersFilter;
import org.keycloak.services.resources.JsResource;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.LoadBalancerResource;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.RobotsResource;
import org.keycloak.services.resources.ThemeResource;
import org.keycloak.services.resources.WelcomeResource;
import org.keycloak.services.resources.admin.AdminRoot;
import org.keycloak.services.util.ObjectMapperResolver;
import java.util.HashSet;
import java.util.Set;
public class ResteasyKeycloakApplication extends KeycloakApplication {
protected Set<Object> singletons = new HashSet<>();
protected Set<Class<?>> classes = new HashSet<>();
public ResteasyKeycloakApplication() {
classes.add(RobotsResource.class);
classes.add(RealmsResource.class);
if (Profile.isFeatureEnabled(Profile.Feature.ADMIN_API)) {
classes.add(AdminRoot.class);
}
classes.add(ThemeResource.class);
if (Profile.isFeatureEnabled(Profile.Feature.JS_ADAPTER)) {
classes.add(JsResource.class);
}
classes.add(KeycloakSecurityHeadersFilter.class);
classes.add(KeycloakErrorHandler.class);
classes.add(KcUnrecognizedPropertyExceptionHandler.class);
classes.add(KeycloakMismatchedInputExceptionHandler.class);
singletons.add(new ObjectMapperResolver());
classes.add(WelcomeResource.class);
if (Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE)) {
// If we are running in multi-site mode, we need to add a resource which to expose
// an endpoint for the load balancer to gather information whether this site should receive requests or not.
classes.add(LoadBalancerResource.class);
}
}
@Override
public Set<Class<?>> getClasses() {
return classes;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
@Override
protected KeycloakSessionFactory createSessionFactory() {
ResteasyKeycloakSessionFactory factory = new ResteasyKeycloakSessionFactory();
factory.init();
return factory;
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright 2024 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.services.resteasy;
import org.keycloak.http.HttpRequest;
import org.keycloak.http.HttpResponse;
import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakContext;
public class ResteasyKeycloakContext extends DefaultKeycloakContext {
public ResteasyKeycloakContext(KeycloakSession session) {
super(session);
}
@Override
protected HttpRequest createHttpRequest() {
return new HttpRequestImpl(getContextObject(org.jboss.resteasy.spi.HttpRequest.class));
}
@Override
protected HttpResponse createHttpResponse() {
return new HttpResponseImpl(getContextObject(org.jboss.resteasy.spi.HttpResponse.class));
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2024 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.services.resteasy;
import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakContext;
import org.keycloak.services.DefaultKeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory;
public class ResteasyKeycloakSession extends DefaultKeycloakSession {
public ResteasyKeycloakSession(DefaultKeycloakSessionFactory factory) {
super(factory);
}
@Override
protected DefaultKeycloakContext createKeycloakContext(KeycloakSession session) {
return new ResteasyKeycloakContext(session);
}
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2024 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.services.resteasy;
import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory;
public class ResteasyKeycloakSessionFactory extends DefaultKeycloakSessionFactory {
@Override
public KeycloakSession create() {
return new ResteasyKeycloakSession(this);
}
}

View file

@ -5,8 +5,8 @@ import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakSession; import org.keycloak.services.resteasy.ResteasyKeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.resteasy.ResteasyKeycloakSessionFactory;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
@ -27,7 +27,7 @@ public class PlainTextVaultProviderFactoryTest {
public void shouldInitializeVaultCorrectly() { public void shouldInitializeVaultCorrectly() {
//given //given
VaultConfig config = new VaultConfig(Scenario.EXISTING.getAbsolutePathAsString()); VaultConfig config = new VaultConfig(Scenario.EXISTING.getAbsolutePathAsString());
KeycloakSession session = new DefaultKeycloakSession(new DefaultKeycloakSessionFactory()); KeycloakSession session = new ResteasyKeycloakSession(new ResteasyKeycloakSessionFactory());
FilesPlainTextVaultProviderFactory factory = new FilesPlainTextVaultProviderFactory() { FilesPlainTextVaultProviderFactory factory = new FilesPlainTextVaultProviderFactory() {
@Override @Override
protected String getRealmName(KeycloakSession session) { protected String getRealmName(KeycloakSession session) {

View file

@ -79,6 +79,12 @@
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-jakarta-servlet-filter-adapter</artifactId> <artifactId>keycloak-jakarta-servlet-filter-adapter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<type>test-jar</type>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>

View file

@ -51,6 +51,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.DefaultKeycloakSessionFactory;
import org.keycloak.services.managers.ApplianceBootstrap; import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resteasy.ResteasyKeycloakApplication;
import org.keycloak.testsuite.JsonConfigProviderFactory; import org.keycloak.testsuite.JsonConfigProviderFactory;
import org.keycloak.testsuite.KeycloakServer; import org.keycloak.testsuite.KeycloakServer;
import org.keycloak.testsuite.UndertowRequestFilter; import org.keycloak.testsuite.UndertowRequestFilter;
@ -83,7 +84,7 @@ public class KeycloakOnUndertow implements DeployableContainer<KeycloakOnUnderto
private DeploymentInfo createAuthServerDeploymentInfo() { private DeploymentInfo createAuthServerDeploymentInfo() {
ResteasyDeployment deployment = new ResteasyDeploymentImpl(); ResteasyDeployment deployment = new ResteasyDeploymentImpl();
deployment.setApplicationClass(KeycloakApplication.class.getName()); deployment.setApplicationClass(ResteasyKeycloakApplication.class.getName());
// RESTEASY-2034 // RESTEASY-2034
deployment.setProperty(ResteasyContextParameters.RESTEASY_DISABLE_HTML_SANITIZER, true); deployment.setProperty(ResteasyContextParameters.RESTEASY_DISABLE_HTML_SANITIZER, true);

View file

@ -64,6 +64,12 @@
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId> <artifactId>keycloak-services</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId> <artifactId>keycloak-server-spi-private</artifactId>

View file

@ -1,13 +1,13 @@
/* /*
* Copyright 2020 Red Hat, Inc. and/or its affiliates * Copyright 2020 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags. * and other contributors as indicated by the @author tags.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -53,6 +53,7 @@ import org.keycloak.provider.ProviderManager;
import org.keycloak.provider.Spi; import org.keycloak.provider.Spi;
import org.keycloak.services.DefaultComponentFactoryProviderFactory; import org.keycloak.services.DefaultComponentFactoryProviderFactory;
import org.keycloak.services.DefaultKeycloakSessionFactory; import org.keycloak.services.DefaultKeycloakSessionFactory;
import org.keycloak.services.resteasy.ResteasyKeycloakSessionFactory;
import org.keycloak.storage.DatastoreProviderFactory; import org.keycloak.storage.DatastoreProviderFactory;
import org.keycloak.storage.DatastoreSpi; import org.keycloak.storage.DatastoreSpi;
import org.keycloak.timer.TimerSpi; import org.keycloak.timer.TimerSpi;
@ -304,7 +305,7 @@ public abstract class KeycloakModelTest {
LOG.debugf("Creating factory %d in %s using the following configuration:\n %s", factoryIndex, threadName, CONFIG); LOG.debugf("Creating factory %d in %s using the following configuration:\n %s", factoryIndex, threadName, CONFIG);
DefaultKeycloakSessionFactory res = new DefaultKeycloakSessionFactory() { DefaultKeycloakSessionFactory res = new ResteasyKeycloakSessionFactory() {
@Override @Override
public void init() { public void init() {

View file

@ -56,6 +56,11 @@
<artifactId>keycloak-dependencies-server-all</artifactId> <artifactId>keycloak-dependencies-server-all</artifactId>
<type>pom</type> <type>pom</type>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<type>test-jar</type>
</dependency>
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-rest-admin-ui-ext</artifactId> <artifactId>keycloak-rest-admin-ui-ext</artifactId>

View file

@ -52,6 +52,7 @@ import org.keycloak.services.DefaultKeycloakSessionFactory;
import org.keycloak.services.managers.ApplianceBootstrap; import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resteasy.ResteasyKeycloakApplication;
import org.keycloak.testsuite.util.cli.TestsuiteCLI; import org.keycloak.testsuite.util.cli.TestsuiteCLI;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import io.undertow.servlet.api.InstanceHandle; import io.undertow.servlet.api.InstanceHandle;
@ -408,7 +409,7 @@ public class KeycloakServer {
ResteasyDeployment deployment = new ResteasyDeploymentImpl(); ResteasyDeployment deployment = new ResteasyDeploymentImpl();
deployment.setApplicationClass(KeycloakApplication.class.getName()); deployment.setApplicationClass(ResteasyKeycloakApplication.class.getName());
Builder builder = Undertow.builder() Builder builder = Undertow.builder()
.addHttpListener(config.getPort(), config.getHost()) .addHttpListener(config.getPort(), config.getHost())