keycloak-aplcache

Details

diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java
index a30ecbd..e86e68e 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java
@@ -1,8 +1,10 @@
 package org.keycloak.authentication.authenticators.client;
 
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MultivaluedMap;
@@ -20,6 +22,7 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.provider.ProviderConfigProperty;
+import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.util.BasicAuthHelper;
 
 /**
@@ -149,6 +152,13 @@ public class ClientIdAndSecretAuthenticator extends AbstractClientAuthenticator 
     }
 
     @Override
+    public Map<String, Object> getAdapterConfiguration(ClientModel client) {
+        Map<String, Object> result = new HashMap<>();
+        result.put(CredentialRepresentation.SECRET, client.getSecret());
+        return result;
+    }
+
+    @Override
     public String getId() {
         return PROVIDER_ID;
     }
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
index 4bb2f4f..bb87e34 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
@@ -3,8 +3,10 @@ package org.keycloak.authentication.authenticators.client;
 import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
@@ -166,6 +168,21 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
     }
 
     @Override
+    public Map<String, Object> getAdapterConfiguration(ClientModel client) {
+        Map<String, Object> props = new HashMap<>();
+        props.put("client-keystore-file", "REPLACE WITH THE LOCATION OF YOUR KEYSTORE FILE");
+        props.put("client-keystore-type", "jks");
+        props.put("client-keystore-password", "REPLACE WITH THE KEYSTORE PASSWORD");
+        props.put("client-key-password", "REPLACE WITH THE KEY PASSWORD IN KEYSTORE");
+        props.put("client-key-alias", client.getClientId());
+        props.put("token-timeout", 10);
+
+        Map<String, Object> config = new HashMap<>();
+        config.put("jwt", props);
+        return config;
+    }
+
+    @Override
     public String getId() {
         return PROVIDER_ID;
     }
diff --git a/services/src/main/java/org/keycloak/authentication/ClientAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/ClientAuthenticatorFactory.java
index 08321ea..4b4c100 100644
--- a/services/src/main/java/org/keycloak/authentication/ClientAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/ClientAuthenticatorFactory.java
@@ -1,7 +1,9 @@
 package org.keycloak.authentication;
 
 import java.util.List;
+import java.util.Map;
 
+import org.keycloak.models.ClientModel;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.provider.ProviderFactory;
 
@@ -33,4 +35,12 @@ public interface ClientAuthenticatorFactory extends ProviderFactory<ClientAuthen
      */
     List<ProviderConfigProperty> getConfigPropertiesPerClient();
 
+    /**
+     * Get configuration, which needs to be used for adapter ( keycloak.json ) of particular client. Some implementations
+     * may return just template and user needs to edit the values according to his environment (For example fill the location of keystore file)
+     *
+     * @return
+     */
+    Map<String, Object> getAdapterConfiguration(ClientModel client);
+
 }
diff --git a/services/src/main/java/org/keycloak/services/managers/ClientManager.java b/services/src/main/java/org/keycloak/services/managers/ClientManager.java
index 1b5a4e8..fbf530b 100755
--- a/services/src/main/java/org/keycloak/services/managers/ClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ClientManager.java
@@ -3,6 +3,8 @@ package org.keycloak.services.managers;
 import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.annotate.JsonPropertyOrder;
 import org.jboss.logging.Logger;
+import org.keycloak.authentication.ClientAuthenticator;
+import org.keycloak.authentication.ClientAuthenticatorFactory;
 import org.keycloak.constants.ServiceAccountConstants;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ProtocolMapperModel;
@@ -156,7 +158,7 @@ public class ClientManager {
         @JsonProperty("public-client")
         protected Boolean publicClient;
         @JsonProperty("credentials")
-        protected Map<String, String> credentials;
+        protected Map<String, Object> credentials;
 
         public Boolean isUseResourceRoleMappings() {
             return useResourceRoleMappings;
@@ -174,11 +176,11 @@ public class ClientManager {
             this.resource = resource;
         }
 
-        public Map<String, String> getCredentials() {
+        public Map<String, Object> getCredentials() {
             return credentials;
         }
 
-        public void setCredentials(Map<String, String> credentials) {
+        public void setCredentials(Map<String, Object> credentials) {
             this.credentials = credentials;
         }
 
@@ -214,10 +216,10 @@ public class ClientManager {
         rep.setResource(clientModel.getClientId());
 
         if (!clientModel.isBearerOnly() && !clientModel.isPublicClient()) {
-            Map<String, String> creds = new HashMap<String, String>();
-            String cred = clientModel.getSecret();
-            creds.put(CredentialRepresentation.SECRET, cred);
-            rep.setCredentials(creds);
+            String clientAuthenticator = clientModel.getClientAuthenticatorType();
+            ClientAuthenticatorFactory authenticator = (ClientAuthenticatorFactory) realmManager.getSession().getKeycloakSessionFactory().getProviderFactory(ClientAuthenticator.class, clientAuthenticator);
+            Map<String, Object> adapterConfig = authenticator.getAdapterConfiguration(clientModel);
+            rep.setCredentials(adapterConfig);
         }
 
         return rep;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java
index f457920..1e2b50a 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/PassThroughClientAuthenticator.java
@@ -1,8 +1,10 @@
 package org.keycloak.testsuite.forms;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import org.keycloak.authentication.AuthenticationFlowError;
 import org.keycloak.authentication.ClientAuthenticationFlowContext;
@@ -89,6 +91,17 @@ public class PassThroughClientAuthenticator extends AbstractClientAuthenticator 
     }
 
     @Override
+    public Map<String, Object> getAdapterConfiguration(ClientModel client) {
+        Map<String, Object> props = new HashMap<>();
+        props.put("foo", "some foo value");
+        props.put("bar", true);
+
+        Map<String, Object> config = new HashMap<>();
+        config.put("dummy", props);
+        return config;
+    }
+
+    @Override
     public String getId() {
         return PROVIDER_ID;
     }