proxyClass, URI absoluteURI) {
+ return ((WebTargetImpl) client.target(absoluteURI)).register(newAuthFilter()).proxy(proxyClass);
+ }
+
+ /**
+ * Closes the underlying client. After calling this method, this Keycloak
instance cannot be reused.
+ */
+ @Override
+ public void close() {
+ closed = true;
+ client.close();
+ }
+
+ /**
+ * @return true if the underlying client is closed.
+ */
+ public boolean isClosed() {
+ return closed;
+ }
+}
diff --git a/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/KeycloakBuilder.java b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/KeycloakBuilder.java
new file mode 100644
index 0000000000000..56331dc37ae10
--- /dev/null
+++ b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/KeycloakBuilder.java
@@ -0,0 +1,155 @@
+/*
+ * 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 io.quarkus.keycloak.admin.client.reactive;
+
+import static org.keycloak.OAuth2Constants.CLIENT_CREDENTIALS;
+import static org.keycloak.OAuth2Constants.PASSWORD;
+
+/**
+ * Provides a {@link Keycloak} client builder with the ability to customize the underlying
+ * REST Client used to communicate with the Keycloak server.
+ *
+ *
+ * Example usage with a connection pool size of 20:
+ *
+ *
+ *
+ * Keycloak keycloak = KeycloakBuilder.builder()
+ * .serverUrl("https://sso.example.com/auth")
+ * .realm("realm")
+ * .username("user")
+ * .password("pass")
+ * .clientId("client")
+ * .clientSecret("secret")
+ * .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(20).build())
+ * .build();
+ *
+ *
+ * Example usage with grant_type=client_credentials
+ *
+ *
+ *
+ * Keycloak keycloak = KeycloakBuilder.builder()
+ * .serverUrl("https://sso.example.com/auth")
+ * .realm("example")
+ * .grantType(OAuth2Constants.CLIENT_CREDENTIALS)
+ * .clientId("client")
+ * .clientSecret("secret")
+ * .build();
+ *
+ *
+ * @author Scott Rossillo
+ */
+public class KeycloakBuilder {
+ private String serverUrl;
+ private String realm;
+ private String username;
+ private String password;
+ private String clientId;
+ private String clientSecret;
+ private String grantType;
+ private String authorization;
+
+ public KeycloakBuilder serverUrl(String serverUrl) {
+ this.serverUrl = serverUrl;
+ return this;
+ }
+
+ public KeycloakBuilder realm(String realm) {
+ this.realm = realm;
+ return this;
+ }
+
+ public KeycloakBuilder grantType(String grantType) {
+ Config.checkGrantType(grantType);
+ this.grantType = grantType;
+ return this;
+ }
+
+ public KeycloakBuilder username(String username) {
+ this.username = username;
+ return this;
+ }
+
+ public KeycloakBuilder password(String password) {
+ this.password = password;
+ return this;
+ }
+
+ public KeycloakBuilder clientId(String clientId) {
+ this.clientId = clientId;
+ return this;
+ }
+
+ public KeycloakBuilder clientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ return this;
+ }
+
+ public KeycloakBuilder authorization(String auth) {
+ this.authorization = auth;
+ return this;
+ }
+
+ /**
+ * Builds a new Keycloak client from this builder.
+ */
+ public Keycloak build() {
+ if (serverUrl == null) {
+ throw new IllegalStateException("serverUrl required");
+ }
+
+ if (realm == null) {
+ throw new IllegalStateException("realm required");
+ }
+
+ if (authorization == null && grantType == null) {
+ grantType = PASSWORD;
+ }
+
+ if (PASSWORD.equals(grantType)) {
+ if (username == null) {
+ throw new IllegalStateException("username required");
+ }
+
+ if (password == null) {
+ throw new IllegalStateException("password required");
+ }
+ } else if (CLIENT_CREDENTIALS.equals(grantType)) {
+ if (clientSecret == null) {
+ throw new IllegalStateException("clientSecret required with grant_type=client_credentials");
+ }
+ }
+
+ if (authorization == null && clientId == null) {
+ throw new IllegalStateException("clientId required");
+ }
+
+ return new Keycloak(serverUrl, realm, username, password, clientId, clientSecret, grantType, authorization);
+ }
+
+ private KeycloakBuilder() {
+ }
+
+ /**
+ * Returns a new Keycloak builder.
+ */
+ public static KeycloakBuilder builder() {
+ return new KeycloakBuilder();
+ }
+}
diff --git a/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AggregatePoliciesResource.java b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AggregatePoliciesResource.java
new file mode 100644
index 0000000000000..3bd6c0548bfcc
--- /dev/null
+++ b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AggregatePoliciesResource.java
@@ -0,0 +1,48 @@
+/*
+ * 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 io.quarkus.keycloak.admin.client.reactive.resource;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+
+/**
+ * @author Pedro Igor
+ */
+public interface AggregatePoliciesResource {
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ Response create(AggregatePolicyRepresentation representation);
+
+ @Path("{id}")
+ AggregatePolicyResource findById(@PathParam("id") String id);
+
+ @Path("/search")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ AggregatePolicyRepresentation findByName(@QueryParam("name") String name);
+}
diff --git a/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AggregatePolicyResource.java b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AggregatePolicyResource.java
new file mode 100644
index 0000000000000..58f268811066e
--- /dev/null
+++ b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AggregatePolicyResource.java
@@ -0,0 +1,64 @@
+/*
+ * 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 io.quarkus.keycloak.admin.client.reactive.resource;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.keycloak.representations.idm.authorization.AggregatePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+
+/**
+ * @author Pedro Igor
+ */
+public interface AggregatePolicyResource {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ AggregatePolicyRepresentation toRepresentation();
+
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ void update(AggregatePolicyRepresentation representation);
+
+ @DELETE
+ void remove();
+
+ @Path("/associatedPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ List associatedPolicies();
+
+ @Path("/dependentPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ List dependentPolicies();
+
+ @Path("/resources")
+ @GET
+ @Produces("application/json")
+ List resources();
+
+}
diff --git a/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AttackDetectionResource.java b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AttackDetectionResource.java
new file mode 100644
index 0000000000000..79a2bc6a773d7
--- /dev/null
+++ b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AttackDetectionResource.java
@@ -0,0 +1,47 @@
+/*
+ * 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 io.quarkus.keycloak.admin.client.reactive.resource;
+
+import java.util.Map;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Stian Thorgersen
+ */
+public interface AttackDetectionResource {
+
+ @GET
+ @Path("brute-force/users/{userId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ Map bruteForceUserStatus(@PathParam("userId") String userId);
+
+ @Path("brute-force/users/{userId}")
+ @DELETE
+ void clearBruteForceForUser(@PathParam("userId") String userId);
+
+ @Path("brute-force/users")
+ @DELETE
+ void clearAllBruteForce();
+
+}
diff --git a/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AuthenticationManagementResource.java b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AuthenticationManagementResource.java
new file mode 100644
index 0000000000000..d356aeda7d19c
--- /dev/null
+++ b/extensions/keycloak-admin-client-reactive/runtime/src/main/java/io/quarkus/keycloak/admin/client/reactive/resource/AuthenticationManagementResource.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.quarkus.keycloak.admin.client.reactive.resource;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
+import org.keycloak.representations.idm.AuthenticationExecutionRepresentation;
+import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
+import org.keycloak.representations.idm.AuthenticatorConfigInfoRepresentation;
+import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
+import org.keycloak.representations.idm.ConfigPropertyRepresentation;
+import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
+import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentation;
+
+/**
+ * @author Marko Strukelj
+ */
+public interface AuthenticationManagementResource {
+
+ @GET
+ @Path("/form-providers")
+ @Produces(MediaType.APPLICATION_JSON)
+ List