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
new file mode 100644
index 0000000..1388e3d
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminCorsPreflightService.java
@@ -0,0 +1,32 @@
+package org.keycloak.services.resources.admin;
+
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.services.resources.Cors;
+
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+/**
+ * Created by st on 21/03/17.
+ */
+public class AdminCorsPreflightService {
+
+ private HttpRequest request;
+
+ public AdminCorsPreflightService(HttpRequest request) {
+ this.request = request;
+ }
+
+ /**
+ * CORS preflight
+ *
+ * @return
+ */
+ @Path("{any:.*}")
+ @OPTIONS
+ public Response preflight() {
+ return Cors.add(request, Response.ok()).preflight().allowedMethods("GET", "PUT", "POST", "DELETE").auth().build();
+ }
+
+}
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 650ac75..a550a71 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
@@ -19,14 +19,12 @@ package org.keycloak.services.resources.admin;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
-import org.jboss.resteasy.spi.NoLogWebApplicationException;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.UnauthorizedException;
import org.keycloak.common.ClientConnection;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
-import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -39,11 +37,11 @@ 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.services.resources.admin.permissions.RealmsPermissionEvaluator;
import org.keycloak.theme.Theme;
import org.keycloak.theme.ThemeProvider;
import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
@@ -197,7 +195,6 @@ public class AdminRoot {
return adminBaseUrl(base).path(AdminRoot.class, "getRealmsAdmin");
}
-
/**
* Base Path to realm admin REST interface
*
@@ -205,8 +202,10 @@ public class AdminRoot {
* @return
*/
@Path("realms")
- public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
- handlePreflightRequest();
+ public Object getRealmsAdmin(@Context final HttpHeaders headers) {
+ if (request.getHttpMethod().equals(HttpMethod.OPTIONS)) {
+ return new AdminCorsPreflightService(request);
+ }
AdminAuth auth = authenticateRealmAdminRequest(headers);
if (auth != null) {
@@ -227,8 +226,10 @@ public class AdminRoot {
* @return
*/
@Path("serverinfo")
- public ServerInfoAdminResource getServerInfo(@Context final HttpHeaders headers) {
- handlePreflightRequest();
+ public Object getServerInfo(@Context final HttpHeaders headers) {
+ if (request.getHttpMethod().equals(HttpMethod.OPTIONS)) {
+ return new AdminCorsPreflightService(request);
+ }
AdminAuth auth = authenticateRealmAdminRequest(headers);
if (!AdminPermissions.realms(session, auth).isAdmin()) {
@@ -246,14 +247,6 @@ public class AdminRoot {
return adminResource;
}
- protected void handlePreflightRequest() {
- if (request.getHttpMethod().equalsIgnoreCase("OPTIONS")) {
- logger.debug("Cors admin pre-flight");
- Response response = Cors.add(request, Response.ok()).preflight().allowedMethods("GET", "PUT", "POST", "DELETE").auth().build();
- throw new NoLogWebApplicationException(response);
- }
- }
-
public static Theme getTheme(KeycloakSession session, RealmModel realm) throws IOException {
ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending");
return themeProvider.getTheme(realm.getAdminTheme(), Theme.Type.ADMIN);
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
new file mode 100644
index 0000000..ae73d22
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminPreflightTest.java
@@ -0,0 +1,55 @@
+package org.keycloak.testsuite.admin;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpOptions;
+import org.apache.http.impl.client.CloseableHttpClient;
+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 java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class AdminPreflightTest extends AbstractAdminTest {
+
+
+ private CloseableHttpClient client;
+
+ @Before
+ public void before() {
+ client = HttpClientBuilder.create().build();
+ }
+
+ @After
+ public void after() {
+ try {
+ client.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void testPreflight() throws IOException {
+ HttpOptions options = new HttpOptions(getAdminUrl("realms/master/users"));
+ options.setHeader("Origin", "http://test");
+
+ CloseableHttpResponse response = client.execute(options);
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals("true", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_CREDENTIALS).getValue());
+ assertEquals("DELETE, POST, GET, PUT", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_METHODS).getValue());
+ assertEquals("http://test", response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_ORIGIN).getValue());
+ assertEquals("3600", response.getFirstHeader(Cors.ACCESS_CONTROL_MAX_AGE).getValue());
+ assertTrue(response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_HEADERS).getValue().contains("Authorization"));
+ assertTrue(response.getFirstHeader(Cors.ACCESS_CONTROL_ALLOW_HEADERS).getValue().contains("Content-Type"));
+ }
+
+ private String getAdminUrl(String resource) {
+ return suiteContext.getAuthServerInfo().getContextRoot().toString() + "/auth/admin/" + resource;
+ }
+
+}