diff --git a/services/src/main/java/org/keycloak/common/util/Resteasy.java b/common/src/main/java/org/keycloak/common/util/Resteasy.java similarity index 100% rename from services/src/main/java/org/keycloak/common/util/Resteasy.java rename to common/src/main/java/org/keycloak/common/util/Resteasy.java diff --git a/services/src/main/java/org/keycloak/common/util/ResteasyProvider.java b/common/src/main/java/org/keycloak/common/util/ResteasyProvider.java similarity index 100% rename from services/src/main/java/org/keycloak/common/util/ResteasyProvider.java rename to common/src/main/java/org/keycloak/common/util/ResteasyProvider.java diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/services/resources/DebugHostnameSettingsResource.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/services/resources/DebugHostnameSettingsResource.java index 41bd2e25fb..e5ba299919 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/services/resources/DebugHostnameSettingsResource.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/services/resources/DebugHostnameSettingsResource.java @@ -23,7 +23,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.configuration.Configuration; import org.keycloak.services.Urls; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import org.keycloak.theme.FreeMarkerException; import org.keycloak.theme.Theme; import org.keycloak.theme.freemarker.FreeMarkerProvider; diff --git a/server-spi-private/src/main/java/org/keycloak/protocol/oidc/TokenExchangeContext.java b/server-spi-private/src/main/java/org/keycloak/protocol/oidc/TokenExchangeContext.java index ea1798edf9..fda5e73a09 100644 --- a/server-spi-private/src/main/java/org/keycloak/protocol/oidc/TokenExchangeContext.java +++ b/server-spi-private/src/main/java/org/keycloak/protocol/oidc/TokenExchangeContext.java @@ -23,6 +23,7 @@ import org.keycloak.events.EventBuilder; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; +import org.keycloak.services.cors.Cors; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MultivaluedMap; @@ -40,7 +41,7 @@ public class TokenExchangeContext { private final MultivaluedMap formParams; // TODO: resolve deps issue and use correct types - private final Object cors; + private final Cors cors; private final Object tokenManager; private final ClientModel client; @@ -55,7 +56,7 @@ public class TokenExchangeContext { public TokenExchangeContext(KeycloakSession session, MultivaluedMap formParams, - Object cors, + Cors cors, RealmModel realm, EventBuilder event, ClientModel client, @@ -83,7 +84,7 @@ public class TokenExchangeContext { return formParams; } - public Object getCors() { + public Cors getCors() { return cors; } diff --git a/server-spi-private/src/main/java/org/keycloak/services/cors/Cors.java b/server-spi-private/src/main/java/org/keycloak/services/cors/Cors.java new file mode 100755 index 0000000000..792a74a215 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/cors/Cors.java @@ -0,0 +1,92 @@ +/* + * 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.cors; + +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; + +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.ResponseBuilder; + +import org.keycloak.common.util.Resteasy; +import org.keycloak.http.HttpRequest; +import org.keycloak.http.HttpResponse; +import org.keycloak.models.ClientModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.provider.Provider; +import org.keycloak.representations.AccessToken; + +/** + * @author Stian Thorgersen + */ +public interface Cors extends Provider { + + public static final long DEFAULT_MAX_AGE = TimeUnit.HOURS.toSeconds(1); + public static final String DEFAULT_ALLOW_METHODS = "GET, HEAD, OPTIONS"; + public static final String DEFAULT_ALLOW_HEADERS = "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, DPoP"; + + public static final String ORIGIN_HEADER = "Origin"; + public static final String AUTHORIZATION_HEADER = "Authorization"; + + public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; + public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; + public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; + public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; + public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; + public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; + + public static final String ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD = "*"; + public static final String INCLUDE_REDIRECTS = "+"; + + public static Cors add(HttpRequest request, ResponseBuilder response) { + KeycloakSession session = Resteasy.getContextData(KeycloakSession.class); + return session.getProvider(Cors.class).request(request).builder(response); + } + + public static Cors add(HttpRequest request) { + KeycloakSession session = Resteasy.getContextData(KeycloakSession.class); + return session.getProvider(Cors.class).request(request); + } + + public Cors request(HttpRequest request); + + public Cors builder(ResponseBuilder builder); + + public Cors preflight(); + + public Cors auth(); + + public Cors allowAllOrigins(); + + public Cors allowedOrigins(KeycloakSession session, ClientModel client); + + public Cors allowedOrigins(AccessToken token); + + public Cors allowedOrigins(String... allowedOrigins); + + public Cors allowedMethods(String... allowedMethods); + + public Cors exposedHeaders(String... exposedHeaders); + + public Response build(); + + public boolean build(HttpResponse response); + + public boolean build(BiConsumer addHeader); + +} diff --git a/server-spi-private/src/main/java/org/keycloak/services/cors/CorsFactory.java b/server-spi-private/src/main/java/org/keycloak/services/cors/CorsFactory.java new file mode 100644 index 0000000000..44194792b9 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/cors/CorsFactory.java @@ -0,0 +1,27 @@ +/* + * 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.cors; + +import org.keycloak.provider.ProviderFactory; + +/** + * @author Dmitry Telegin + */ +public interface CorsFactory extends ProviderFactory { + +} diff --git a/server-spi-private/src/main/java/org/keycloak/services/cors/CorsSpi.java b/server-spi-private/src/main/java/org/keycloak/services/cors/CorsSpi.java new file mode 100644 index 0000000000..db9e01e841 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/cors/CorsSpi.java @@ -0,0 +1,53 @@ +/* + * 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.cors; + +import org.keycloak.provider.Provider; +import org.keycloak.provider.ProviderFactory; +import org.keycloak.provider.Spi; + +/** + * @author Dmitry Telegin + */ +public class CorsSpi implements Spi { + + private static final String SPI_ID = "cors"; + + @Override + public boolean isInternal() { + return true; + } + + @Override + public String getName() { + return SPI_ID; + } + + @Override + public Class getProviderClass() { + return Cors.class; + } + + @Override + public Class getProviderFactoryClass() { + return CorsFactory.class; + } + +} diff --git a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi index 64c2a0d586..e3a3c5bde0 100755 --- a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -90,6 +90,7 @@ org.keycloak.headers.SecurityHeadersSpi org.keycloak.services.clientpolicy.condition.ClientPolicyConditionSpi org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorSpi org.keycloak.services.clientpolicy.ClientPolicyManagerSpi +org.keycloak.services.cors.CorsSpi org.keycloak.userprofile.UserProfileSpi org.keycloak.device.DeviceRepresentationSpi org.keycloak.health.LoadBalancerCheckSpi diff --git a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java index e10df7293f..96ecf9e19f 100644 --- a/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java +++ b/services/src/main/java/org/keycloak/authorization/authorization/AuthorizationTokenService.java @@ -91,10 +91,10 @@ import org.keycloak.representations.idm.authorization.PermissionTicketToken; import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.ErrorResponseException; import org.keycloak.services.Urls; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationSessionManager; import org.keycloak.services.managers.UserSessionManager; -import org.keycloak.services.resources.Cors; import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.sessions.RootAuthenticationSessionModel; import org.keycloak.util.JsonSerialization; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java index 8975517d45..cf658ef9a8 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java @@ -60,11 +60,11 @@ import org.keycloak.representations.JsonWebToken; import org.keycloak.saml.common.constants.GeneralConstants; import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.Urls; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationSessionManager; import org.keycloak.services.managers.BruteForceProtector; import org.keycloak.services.managers.UserSessionManager; -import org.keycloak.services.resources.Cors; import org.keycloak.services.resources.IdentityBrokerService; import org.keycloak.services.resources.admin.AdminAuth; import org.keycloak.services.resources.admin.permissions.AdminPermissions; @@ -120,7 +120,7 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider { public Response exchange(TokenExchangeContext context) { this.formParams = context.getFormParams(); this.session = context.getSession(); - this.cors = (Cors)context.getCors(); + this.cors = context.getCors(); this.realm = context.getRealm(); this.client = context.getClient(); this.event = context.getEvent(); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java index 7f4e88f07d..4862526566 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java @@ -42,7 +42,7 @@ import org.keycloak.protocol.oidc.endpoints.TokenRevocationEndpoint; import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint; import org.keycloak.protocol.oidc.ext.OIDCExtProvider; import org.keycloak.services.CorsErrorResponseException; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.util.CacheControlUtil; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpointChecker.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpointChecker.java index 1e6e12e225..5732771e79 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpointChecker.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpointChecker.java @@ -47,8 +47,8 @@ import org.keycloak.protocol.oidc.utils.RedirectUtils; import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.ErrorPageException; import org.keycloak.services.ServicesLogger; +import org.keycloak.services.cors.Cors; import org.keycloak.services.messages.Messages; -import org.keycloak.services.resources.Cors; import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.util.TokenUtil; import org.keycloak.utils.StringUtil; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java index 8cc4459c3c..956014f196 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java @@ -64,12 +64,12 @@ import org.keycloak.services.ErrorPage; import org.keycloak.services.ErrorResponseException; import org.keycloak.services.clientpolicy.ClientPolicyException; import org.keycloak.services.clientpolicy.context.LogoutRequestContext; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationSessionManager; import org.keycloak.services.managers.ClientSessionCode; import org.keycloak.services.managers.UserSessionManager; import org.keycloak.services.messages.Messages; -import org.keycloak.services.resources.Cors; import org.keycloak.services.resources.LogoutSessionCodeChecks; import org.keycloak.services.resources.SessionCodeChecks; import org.keycloak.services.util.LocaleUtil; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java index f43d2934e0..fe9cb0f822 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java @@ -85,13 +85,13 @@ import org.keycloak.services.clientpolicy.context.TokenRefreshContext; import org.keycloak.services.clientpolicy.context.TokenRefreshResponseContext; import org.keycloak.services.clientpolicy.context.TokenRequestContext; import org.keycloak.services.clientpolicy.context.TokenResponseContext; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AppAuthManager; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationSessionManager; import org.keycloak.services.managers.ClientManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.UserSessionManager; -import org.keycloak.services.resources.Cors; import org.keycloak.services.util.AuthorizationContextUtil; import org.keycloak.services.util.DefaultClientSessionContext; import org.keycloak.services.util.DPoPUtil; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java index f02456aa7e..f81f28dc68 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java @@ -51,10 +51,10 @@ import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.clientpolicy.ClientPolicyException; import org.keycloak.services.clientpolicy.context.TokenRevokeContext; import org.keycloak.services.clientpolicy.context.TokenRevokeResponseContext; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.UserConsentManager; import org.keycloak.services.managers.UserSessionCrossDCManager; import org.keycloak.services.managers.UserSessionManager; -import org.keycloak.services.resources.Cors; import org.keycloak.util.TokenUtil; /** diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java index 3745360694..ff129355f9 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java @@ -56,8 +56,8 @@ import org.keycloak.representations.dpop.DPoP; import org.keycloak.services.Urls; import org.keycloak.services.clientpolicy.ClientPolicyException; import org.keycloak.services.clientpolicy.context.UserInfoRequestContext; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AppAuthManager; -import org.keycloak.services.resources.Cors; import org.keycloak.services.util.DPoPUtil; import org.keycloak.services.util.DefaultClientSessionContext; import org.keycloak.services.util.MtlsHoKTokenUtil; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java b/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java index ee3bbe6411..d6ad256ba2 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java @@ -54,9 +54,9 @@ import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.ErrorResponseException; import org.keycloak.services.Urls; import org.keycloak.services.clientpolicy.ClientPolicyException; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.UserConsentManager; -import org.keycloak.services.resources.Cors; import org.keycloak.services.util.DefaultClientSessionContext; import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.sessions.RootAuthenticationSessionModel; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/channel/HttpAuthenticationChannelProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/channel/HttpAuthenticationChannelProvider.java index faece93f00..93bd9f78b8 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/channel/HttpAuthenticationChannelProvider.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/channel/HttpAuthenticationChannelProvider.java @@ -29,7 +29,7 @@ import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.representations.AccessToken; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import org.keycloak.util.TokenUtil; /** diff --git a/services/src/main/java/org/keycloak/protocol/oidc/grants/device/DeviceGrantType.java b/services/src/main/java/org/keycloak/protocol/oidc/grants/device/DeviceGrantType.java index 25a36fc01b..a4eacc24b0 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/grants/device/DeviceGrantType.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/grants/device/DeviceGrantType.java @@ -49,9 +49,9 @@ import org.keycloak.protocol.oidc.utils.PkceUtils; import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.ErrorResponseException; import org.keycloak.services.clientpolicy.ClientPolicyException; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.UserSessionCrossDCManager; -import org.keycloak.services.resources.Cors; import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.util.DefaultClientSessionContext; import org.keycloak.sessions.AuthenticationSessionModel; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/grants/device/endpoints/DeviceEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/grants/device/endpoints/DeviceEndpoint.java index 1e28db76ac..9afce96ac9 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/grants/device/endpoints/DeviceEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/grants/device/endpoints/DeviceEndpoint.java @@ -50,9 +50,9 @@ import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ServicesLogger; import org.keycloak.services.Urls; import org.keycloak.services.clientpolicy.ClientPolicyException; +import org.keycloak.services.cors.Cors; import org.keycloak.services.messages.Messages; import org.keycloak.services.resource.RealmResourceProvider; -import org.keycloak.services.resources.Cors; import org.keycloak.services.util.CacheControlUtil; import org.keycloak.sessions.AuthenticationSessionModel; import org.keycloak.util.JsonSerialization; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/AbstractParEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/AbstractParEndpoint.java index e109f42b95..c65b50973d 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/AbstractParEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/AbstractParEndpoint.java @@ -31,7 +31,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil; import org.keycloak.services.CorsErrorResponseException; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; public abstract class AbstractParEndpoint { diff --git a/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/ParEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/ParEndpoint.java index 1df489b236..e94639fb81 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/ParEndpoint.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/par/endpoints/ParEndpoint.java @@ -32,7 +32,7 @@ import org.keycloak.protocol.oidc.par.ParResponse; import org.keycloak.protocol.oidc.par.clientpolicy.context.PushedAuthorizationRequestContext; import org.keycloak.protocol.oidc.par.endpoints.request.ParEndpointRequestParserProcessor; import org.keycloak.services.clientpolicy.ClientPolicyException; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import org.keycloak.utils.ProfileHelper; import jakarta.ws.rs.Consumes; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java index 5adeb11af6..f7063d14e9 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/AuthorizeClientUtil.java @@ -31,7 +31,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.ErrorResponseException; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Response; diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/PkceUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/PkceUtils.java index 62081ed7e0..0ba06945dd 100644 --- a/services/src/main/java/org/keycloak/protocol/oidc/utils/PkceUtils.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/PkceUtils.java @@ -9,7 +9,7 @@ import org.keycloak.events.Errors; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.services.CorsErrorResponseException; import org.keycloak.events.EventBuilder; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; diff --git a/services/src/main/java/org/keycloak/services/CorsErrorResponseException.java b/services/src/main/java/org/keycloak/services/CorsErrorResponseException.java index 86f6af50ca..e2d903c2da 100644 --- a/services/src/main/java/org/keycloak/services/CorsErrorResponseException.java +++ b/services/src/main/java/org/keycloak/services/CorsErrorResponseException.java @@ -18,7 +18,7 @@ package org.keycloak.services; import org.keycloak.representations.idm.OAuth2ErrorRepresentation; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.MediaType; diff --git a/services/src/main/java/org/keycloak/services/cors/DefaultCorsFactory.java b/services/src/main/java/org/keycloak/services/cors/DefaultCorsFactory.java new file mode 100644 index 0000000000..b5a99b8b15 --- /dev/null +++ b/services/src/main/java/org/keycloak/services/cors/DefaultCorsFactory.java @@ -0,0 +1,53 @@ +/* + * 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.cors; + +import org.keycloak.Config; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; + +/** + * @author Dmitry Telegin + */ +public class DefaultCorsFactory implements CorsFactory { + + private static final String PROVIDER_ID = "default"; + + @Override + public Cors create(KeycloakSession session) { + return new DefaultCorsImpl(session.getContext().getHttpRequest()); + } + + @Override + public void init(Config.Scope config) { + } + + @Override + public void postInit(KeycloakSessionFactory factory) { + } + + @Override + public void close() { + } + + @Override + public String getId() { + return PROVIDER_ID; + } + +} diff --git a/services/src/main/java/org/keycloak/services/resources/Cors.java b/services/src/main/java/org/keycloak/services/cors/DefaultCorsImpl.java similarity index 68% rename from services/src/main/java/org/keycloak/services/resources/Cors.java rename to services/src/main/java/org/keycloak/services/cors/DefaultCorsImpl.java index 0ba5c6f3fa..d752686ca0 100755 --- a/services/src/main/java/org/keycloak/services/resources/Cors.java +++ b/services/src/main/java/org/keycloak/services/cors/DefaultCorsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Red Hat, Inc. and/or its affiliates + * 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"); @@ -14,16 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.keycloak.services.resources; + +package org.keycloak.services.cors; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; + import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.ResponseBuilder; + import org.jboss.logging.Logger; import org.keycloak.http.HttpRequest; import org.keycloak.common.util.CollectionUtil; @@ -36,26 +38,9 @@ import org.keycloak.representations.AccessToken; /** * @author Stian Thorgersen */ -public class Cors { +public class DefaultCorsImpl implements Cors { - private static final Logger logger = Logger.getLogger(Cors.class); - - public static final long DEFAULT_MAX_AGE = TimeUnit.HOURS.toSeconds(1); - public static final String DEFAULT_ALLOW_METHODS = "GET, HEAD, OPTIONS"; - public static final String DEFAULT_ALLOW_HEADERS = "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, DPoP"; - - public static final String ORIGIN_HEADER = "Origin"; - public static final String AUTHORIZATION_HEADER = "Authorization"; - - public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; - public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; - public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; - public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; - public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; - public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; - - public static final String ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD = "*"; - public static final String INCLUDE_REDIRECTS = "+"; + private static final Logger logger = Logger.getLogger(DefaultCorsImpl.class); private HttpRequest request; private ResponseBuilder builder; @@ -66,43 +51,41 @@ public class Cors { private boolean preflight; private boolean auth; - public Cors(HttpRequest request, ResponseBuilder response) { - this.request = request; - this.builder = response; - } - - public Cors(HttpRequest request) { + DefaultCorsImpl(HttpRequest request) { this.request = request; } - public static Cors add(HttpRequest request, ResponseBuilder response) { - return new Cors(request, response); - } - - public static Cors add(HttpRequest request) { - return new Cors(request); + @Override + public Cors request(HttpRequest request) { + this.request = request; + return this; } + @Override public Cors builder(ResponseBuilder builder) { this.builder = builder; return this; } + @Override public Cors preflight() { preflight = true; return this; } + @Override public Cors auth() { auth = true; return this; } + @Override public Cors allowAllOrigins() { allowedOrigins = Collections.singleton(ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD); return this; } + @Override public Cors allowedOrigins(KeycloakSession session, ClientModel client) { if (client != null) { allowedOrigins = WebOriginsUtils.resolveValidWebOrigins(session, client); @@ -110,6 +93,7 @@ public class Cors { return this; } + @Override public Cors allowedOrigins(AccessToken token) { if (token != null) { allowedOrigins = token.getAllowedOrigins(); @@ -117,6 +101,7 @@ public class Cors { return this; } + @Override public Cors allowedOrigins(String... allowedOrigins) { if (allowedOrigins != null && allowedOrigins.length > 0) { this.allowedOrigins = new HashSet<>(Arrays.asList(allowedOrigins)); @@ -124,39 +109,56 @@ public class Cors { return this; } + @Override public Cors allowedMethods(String... allowedMethods) { this.allowedMethods = new HashSet<>(Arrays.asList(allowedMethods)); return this; } + @Override public Cors exposedHeaders(String... exposedHeaders) { this.exposedHeaders = new HashSet<>(Arrays.asList(exposedHeaders)); return this; } + @Override public Response build() { - build(builder::header); - logger.debug("Added CORS headers to response"); + if (builder == null) { + throw new IllegalStateException("builder is not set"); + } + + if (build(builder::header)) { + logger.debug("Added CORS headers to response"); + } return builder.build(); } - public void build(HttpResponse response) { - build(response::addHeader); - logger.debug("Added CORS headers to response"); + @Override + public boolean build(HttpResponse response) { + if (build(response::addHeader)) { + logger.debug("Added CORS headers to response"); + return true; + } + return false; } - public void build(BiConsumer addHeader) { + @Override + public boolean build(BiConsumer addHeader) { + if (request == null) { + throw new IllegalStateException("request is not set"); + } + String origin = request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN_HEADER); if (origin == null) { - logger.trace("No origin header ignoring"); - return; + logger.trace("No Origin header, ignoring"); + return false; } if (!preflight && (allowedOrigins == null || (!allowedOrigins.contains(origin) && !allowedOrigins.contains(ACCESS_CONTROL_ALLOW_ORIGIN_WILDCARD)))) { if (logger.isDebugEnabled()) { logger.debugv("Invalid CORS request: origin {0} not in allowed origins {1}", origin, allowedOrigins); } - return; + return false; } addHeader.accept(ACCESS_CONTROL_ALLOW_ORIGIN, origin); @@ -186,6 +188,12 @@ public class Cors { if (preflight) { addHeader.accept(ACCESS_CONTROL_MAX_AGE, String.valueOf(DEFAULT_MAX_AGE)); } + + return true; + } + + @Override + public void close() { } } diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java index 708c076a90..370a72c47f 100755 --- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java +++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java @@ -82,6 +82,7 @@ import org.keycloak.services.managers.AuthenticationSessionManager; import org.keycloak.services.managers.BruteForceProtector; import org.keycloak.services.managers.ClientSessionCode; import org.keycloak.services.messages.Messages; +import org.keycloak.services.cors.Cors; import org.keycloak.services.resources.account.AccountConsole; import org.keycloak.services.util.AuthenticationFlowURLHelper; import org.keycloak.services.util.BrowserHistoryHelper; diff --git a/services/src/main/java/org/keycloak/services/resources/JsResource.java b/services/src/main/java/org/keycloak/services/resources/JsResource.java index f34f09dfa3..6ed836693f 100755 --- a/services/src/main/java/org/keycloak/services/resources/JsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/JsResource.java @@ -21,6 +21,7 @@ import org.keycloak.common.Version; import org.keycloak.encoding.ResourceEncodingHelper; import org.keycloak.encoding.ResourceEncodingProvider; import org.keycloak.models.KeycloakSession; +import org.keycloak.services.cors.Cors; import org.keycloak.services.util.CacheControlUtil; import org.keycloak.utils.MediaType; diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java index dc0e5c8e74..39de90191a 100755 --- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java +++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java @@ -25,6 +25,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.representations.idm.PublishedRealmRepresentation; +import org.keycloak.services.cors.Cors; import org.keycloak.services.Urls; import jakarta.ws.rs.GET; diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java index 46ab7d0f33..c86a1bc616 100755 --- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java @@ -31,6 +31,7 @@ import org.keycloak.protocol.LoginProtocol; import org.keycloak.protocol.LoginProtocolFactory; import org.keycloak.services.CorsErrorResponseException; import org.keycloak.services.clientregistration.ClientRegistrationService; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.resource.RealmResourceProvider; import org.keycloak.services.resources.account.AccountLoader; diff --git a/services/src/main/java/org/keycloak/services/resources/ThemeResource.java b/services/src/main/java/org/keycloak/services/resources/ThemeResource.java index 39bbb96995..43cafad8b7 100644 --- a/services/src/main/java/org/keycloak/services/resources/ThemeResource.java +++ b/services/src/main/java/org/keycloak/services/resources/ThemeResource.java @@ -30,6 +30,7 @@ import org.keycloak.encoding.ResourceEncodingProvider; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.services.ServicesLogger; +import org.keycloak.services.cors.Cors; import org.keycloak.services.util.CacheControlUtil; import org.keycloak.services.util.LocaleUtil; import org.keycloak.theme.Theme; diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountLoader.java b/services/src/main/java/org/keycloak/services/resources/account/AccountLoader.java index d247721abe..5cce601e3d 100644 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountLoader.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountLoader.java @@ -26,11 +26,11 @@ import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AppAuthManager; import org.keycloak.services.managers.Auth; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.resource.AccountResourceProvider; -import org.keycloak.services.resources.Cors; import org.keycloak.theme.Theme; import jakarta.ws.rs.HttpMethod; diff --git a/services/src/main/java/org/keycloak/services/resources/account/CorsPreflightService.java b/services/src/main/java/org/keycloak/services/resources/account/CorsPreflightService.java index 18c102f5b3..c205caab8f 100644 --- a/services/src/main/java/org/keycloak/services/resources/account/CorsPreflightService.java +++ b/services/src/main/java/org/keycloak/services/resources/account/CorsPreflightService.java @@ -1,7 +1,7 @@ package org.keycloak.services.resources.account; import org.keycloak.http.HttpRequest; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import jakarta.ws.rs.OPTIONS; import jakarta.ws.rs.Path; diff --git a/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java b/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java index 159fae9584..aa0c211eff 100644 --- a/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/account/LinkedAccountsResource.java @@ -56,9 +56,9 @@ import org.keycloak.representations.account.AccountLinkUriRepresentation; import org.keycloak.representations.account.LinkedAccountRepresentation; import org.keycloak.services.ErrorResponse; import org.keycloak.services.Urls; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.Auth; import org.keycloak.services.messages.Messages; -import org.keycloak.services.resources.Cors; import org.keycloak.services.validation.Validation; import static org.keycloak.models.Constants.ACCOUNT_CONSOLE_CLIENT_ID; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java index fc8ed5650d..aa62abd2f8 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java @@ -36,11 +36,11 @@ import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.services.Urls; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AppAuthManager; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.ClientManager; import org.keycloak.services.managers.RealmManager; -import org.keycloak.services.resources.Cors; import org.keycloak.theme.FreeMarkerException; import org.keycloak.theme.Theme; import org.keycloak.theme.freemarker.FreeMarkerProvider; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminCorsPreflightService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminCorsPreflightService.java index 3d8aa0ca66..57ac467637 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminCorsPreflightService.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminCorsPreflightService.java @@ -1,7 +1,7 @@ package org.keycloak.services.resources.admin; import org.keycloak.http.HttpRequest; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import jakarta.ws.rs.OPTIONS; import jakarta.ws.rs.Path; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java index 7c98ca0007..5c31296fed 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java @@ -30,10 +30,10 @@ import org.keycloak.models.RealmModel; import org.keycloak.protocol.oidc.TokenManager; import org.keycloak.representations.AccessToken; import org.keycloak.services.ForbiddenException; +import org.keycloak.services.cors.Cors; import org.keycloak.services.managers.AppAuthManager; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; -import org.keycloak.services.resources.Cors; import org.keycloak.services.resources.admin.info.ServerInfoAdminResource; import org.keycloak.services.resources.admin.permissions.AdminPermissions; import org.keycloak.theme.Theme; diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResourcePreflight.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResourcePreflight.java index e1e068057f..79e8c26b9d 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResourcePreflight.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResourcePreflight.java @@ -23,7 +23,7 @@ import jakarta.ws.rs.core.Response; import org.keycloak.http.HttpRequest; import org.keycloak.models.KeycloakSession; import org.keycloak.protocol.oidc.TokenManager; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; public class RealmsAdminResourcePreflight extends RealmsAdminResource { diff --git a/services/src/main/java/org/keycloak/utils/OAuth2Error.java b/services/src/main/java/org/keycloak/utils/OAuth2Error.java index 89c0d8ff6c..19fbaf9b25 100644 --- a/services/src/main/java/org/keycloak/utils/OAuth2Error.java +++ b/services/src/main/java/org/keycloak/utils/OAuth2Error.java @@ -38,7 +38,7 @@ import jakarta.ws.rs.core.Response; import org.keycloak.OAuthErrorException; import org.keycloak.models.RealmModel; import org.keycloak.representations.idm.OAuth2ErrorRepresentation; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import static jakarta.ws.rs.core.HttpHeaders.WWW_AUTHENTICATE; diff --git a/services/src/main/resources/META-INF/services/org.keycloak.services.cors.CorsFactory b/services/src/main/resources/META-INF/services/org.keycloak.services.cors.CorsFactory new file mode 100644 index 0000000000..57a5444aa3 --- /dev/null +++ b/services/src/main/resources/META-INF/services/org.keycloak.services.cors.CorsFactory @@ -0,0 +1,20 @@ +# +# 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. +# +# + +org.keycloak.services.cors.DefaultCorsFactory diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java index ae73d221fa..19c74663fc 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java @@ -7,7 +7,7 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import java.io.IOException; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/DPoPTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/DPoPTest.java index 1a2f4de8d9..0e8f7cce66 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/DPoPTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/DPoPTest.java @@ -77,7 +77,7 @@ import org.keycloak.representations.oidc.TokenMetadataRepresentation; import org.keycloak.services.clientpolicy.ClientPolicyException; import org.keycloak.services.clientpolicy.condition.ClientAccessTypeConditionFactory; import org.keycloak.services.clientpolicy.executor.DPoPBindEnforcerExecutorFactory; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.AssertEvents; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java index e7b5a35835..b33a6a663d 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java @@ -41,7 +41,7 @@ import org.keycloak.representations.IDToken; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.services.clientregistration.ClientRegistrationService; import org.keycloak.services.clientregistration.oidc.OIDCClientRegistrationProviderFactory; -import org.keycloak.services.resources.Cors; +import org.keycloak.services.cors.Cors; import org.keycloak.services.resources.RealmsResource; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.Assert;