diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/applications.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/applications.js
index 9e9758a55b..07b59ccc1a 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/applications.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/applications.js
@@ -230,117 +230,6 @@ module.controller('ApplicationCertificateExportCtrl', function($scope, $location
});
});
-module.controller('ApplicationCertificateCtrl', function($scope, $location, $http, $upload, realm, application,
- ApplicationCertificate, ApplicationCertificateGenerate,
- ApplicationCertificateDownload, Notifications) {
- $scope.realm = realm;
- $scope.application = application;
- var jks = {
- keyAlias: application.name,
- realmAlias: realm.realm
- };
-
- $scope.files = [];
-
- $scope.onFileSelect = function($files) {
- $scope.files = $files;
- };
-
- $scope.clearFileSelect = function() {
- $scope.files = null;
- }
-
- $scope.keyFormats = [
- "JKS",
- "PKCS12"
- ];
-
- $scope.jks = jks;
- $scope.jks.format = $scope.keyFormats[0];
- $scope.uploadKeyFormat = $scope.keyFormats[0];
-
- $scope.uploadFile = function() {
- //$files: an array of files selected, each file has name, size, and type.
- for (var i = 0; i < $scope.files.length; i++) {
- var $file = $scope.files[i];
- $scope.upload = $upload.upload({
- url: authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/certificates/upload/jks',
- // method: POST or PUT,
- // headers: {'headerKey': 'headerValue'}, withCredential: true,
- data: {keystoreFormat: $scope.uploadKeyFormat,
- keyAlias: $scope.uploadKeyAlias,
- keyPassword: $scope.uploadKeyPassword,
- storePassword: $scope.uploadStorePassword
- },
- file: $file
- /* set file formData name for 'Content-Desposition' header. Default: 'file' */
- //fileFormDataName: myFile,
- /* customize how data is added to formData. See #40#issuecomment-28612000 for example */
- //formDataAppender: function(formData, key, val){}
- }).progress(function(evt) {
- console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
- }).success(function(data, status, headers) {
- $scope.keyInfo = data;
- Notifications.success("Keystore uploaded successfully.");
- })
- .error(function() {
- Notifications.error("The key store can not be uploaded. Please verify the file.");
-
- });
- //.then(success, error, progress);
- }
- };
-
-
-
-
- var keyInfo = ApplicationCertificate.get({ realm : realm.realm, application : application.id },
- function() {
- $scope.keyInfo = keyInfo;
- }
- );
-
- $scope.generate = function() {
- var keyInfo = ApplicationCertificateGenerate.generate({ realm : realm.realm, application : application.id },
- function() {
- Notifications.success('Client keypair and cert has been changed.');
- $scope.keyInfo = keyInfo;
- },
- function() {
- Notifications.error("Client keypair and cert was not changed due to a problem.");
- }
- );
- };
-
- $scope.downloadJKS = function() {
- $http({
- url: authUrl + '/admin/realms/' + realm.realm + '/applications-by-id/' + application.id + '/certificates/download',
- method: 'POST',
- responseType: 'arraybuffer',
- data: $scope.jks,
- headers: {
- 'Content-Type': 'application/json',
- 'Accept': 'application/octet-stream'
- }
- }).success(function(data){
- var blob = new Blob([data], {
- type: 'application/octet-stream'
- });
- var ext = ".jks";
- if ($scope.jks.format == 'PKCS12') ext = ".p12";
- saveAs(blob, 'keystore' + ext);
- }).error(function(){
- Notifications.error("Error downloading.");
- });
- }
-
- $scope.$watch(function() {
- return $location.path();
- }, function() {
- $scope.path = $location.path().substring(1).split("/");
- });
-});
-
module.controller('ApplicationSessionsCtrl', function($scope, realm, sessionCount, application,
ApplicationUserSessions) {
$scope.realm = realm;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientCertificateResource.java
deleted file mode 100755
index 068ee09558..0000000000
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientCertificateResource.java
+++ /dev/null
@@ -1,284 +0,0 @@
-package org.keycloak.services.resources.admin;
-
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.plugins.providers.multipart.InputPart;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
-import org.jboss.resteasy.spi.BadRequestException;
-import org.jboss.resteasy.spi.NotAcceptableException;
-import org.jboss.resteasy.spi.NotFoundException;
-import org.keycloak.models.AdminRoles;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.resources.flows.Flows;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.PemUtils;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.StreamingOutput;
-import javax.ws.rs.core.UriInfo;
-import java.io.ByteArrayOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class ClientCertificateResource {
- protected RealmModel realm;
- private RealmAuth auth;
- protected ClientModel client;
- protected KeycloakSession session;
-
- public ClientCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session) {
- this.realm = realm;
- this.auth = auth;
- this.client = client;
- this.session = session;
- }
-
- public static class ClientKeyPairInfo {
- protected String privateKey;
- protected String publicKey;
- protected String certificate;
-
- public String getPrivateKey() {
- return privateKey;
- }
-
- public void setPrivateKey(String privateKey) {
- this.privateKey = privateKey;
- }
-
- public String getPublicKey() {
- return publicKey;
- }
-
- public void setPublicKey(String publicKey) {
- this.publicKey = publicKey;
- }
-
- public String getCertificate() {
- return certificate;
- }
-
- public void setCertificate(String certificate) {
- this.certificate = certificate;
- }
- }
-
- @GET
- @NoCache
- @Produces(MediaType.APPLICATION_JSON)
- public ClientKeyPairInfo getKeyInfo() {
- ClientKeyPairInfo info = new ClientKeyPairInfo();
- info.setCertificate(client.getAttribute(ClientModel.X509CERTIFICATE));
- info.setPrivateKey(client.getAttribute(ClientModel.PRIVATE_KEY));
- info.setPublicKey(client.getAttribute(ClientModel.PUBLIC_KEY));
- return info;
- }
-
-
- @POST
- @NoCache
- @Path("generate")
- @Produces(MediaType.APPLICATION_JSON)
- public ClientKeyPairInfo generate() {
- auth.requireManage();
-
- KeycloakModelUtils.generateClientKeyPairCertificate(client);
- ClientKeyPairInfo info = new ClientKeyPairInfo();
- info.setCertificate(client.getAttribute(ClientModel.X509CERTIFICATE));
- info.setPrivateKey(client.getAttribute(ClientModel.PRIVATE_KEY));
- info.setPublicKey(client.getAttribute(ClientModel.PUBLIC_KEY));
- return info;
- }
-
- @POST
- @Path("upload/jks")
- @Consumes(MediaType.MULTIPART_FORM_DATA)
- @Produces(MediaType.APPLICATION_JSON)
- public ClientKeyPairInfo uploadJks(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
- auth.requireManage();
- Map> uploadForm = input.getFormDataMap();
- List inputParts = uploadForm.get("file");
-
- String keystoreFormat = uploadForm.get("keystoreFormat").get(0).getBodyAsString();
- String keyAlias = uploadForm.get("keyAlias").get(0).getBodyAsString();
- String keyPassword = uploadForm.get("keyPassword").get(0).getBodyAsString();
- String storePassword = uploadForm.get("storePassword").get(0).getBodyAsString();
- System.out.println("format = '" + keystoreFormat + "'");
- PrivateKey privateKey = null;
- X509Certificate certificate = null;
- try {
- KeyStore keyStore = null;
- if (keystoreFormat.equals("JKS")) keyStore = KeyStore.getInstance("JKS");
- else keyStore = KeyStore.getInstance(keystoreFormat, "BC");
- keyStore.load(inputParts.get(0).getBody(InputStream.class, null), storePassword.toCharArray());
- privateKey = (PrivateKey)keyStore.getKey(keyAlias, keyPassword.toCharArray());
- certificate = (X509Certificate)keyStore.getCertificate(keyAlias);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
- String publicKeyPem = KeycloakModelUtils.getPemFromKey(certificate.getPublicKey());
- String certPem = KeycloakModelUtils.getPemFromCertificate(certificate);
- client.setAttribute(ClientModel.PRIVATE_KEY, privateKeyPem);
- client.setAttribute(ClientModel.PUBLIC_KEY, publicKeyPem);
- client.setAttribute(ClientModel.X509CERTIFICATE, certPem);
-
- ClientKeyPairInfo info = new ClientKeyPairInfo();
- info.setCertificate(client.getAttribute(ClientModel.X509CERTIFICATE));
- info.setPrivateKey(client.getAttribute(ClientModel.PRIVATE_KEY));
- info.setPublicKey(client.getAttribute(ClientModel.PUBLIC_KEY));
-
-
- return info;
- }
-
-
- public static class KeyStoreConfig {
- protected Boolean realmCertificate;
- protected String storePassword;
- protected String keyPassword;
- protected String keyAlias;
- protected String realmAlias;
- protected String format;
-
- public Boolean isRealmCertificate() {
- return realmCertificate;
- }
-
- public void setRealmCertificate(Boolean realmCertificate) {
- this.realmCertificate = realmCertificate;
- }
-
- public String getStorePassword() {
- return storePassword;
- }
-
- public void setStorePassword(String storePassword) {
- this.storePassword = storePassword;
- }
-
- public String getKeyPassword() {
- return keyPassword;
- }
-
- public void setKeyPassword(String keyPassword) {
- this.keyPassword = keyPassword;
- }
-
- public String getKeyAlias() {
- return keyAlias;
- }
-
- public void setKeyAlias(String keyAlias) {
- this.keyAlias = keyAlias;
- }
-
- public String getRealmAlias() {
- return realmAlias;
- }
-
- public void setRealmAlias(String realmAlias) {
- this.realmAlias = realmAlias;
- }
-
- public String getFormat() {
- return format;
- }
-
- public void setFormat(String format) {
- this.format = format;
- }
- }
-
- @POST
- @NoCache
- @Path("/download")
- @Produces(MediaType.APPLICATION_OCTET_STREAM)
- @Consumes(MediaType.APPLICATION_JSON)
- public byte[] getKeystore(final KeyStoreConfig config) {
- auth.requireView();
- if (config.getFormat() != null && !config.getFormat().equals("JKS") && !config.getFormat().equals("PKCS12")) {
- throw new NotAcceptableException("Only support jks format.");
- }
- String format = config.getFormat();
- if (client.getAttribute(ClientModel.PRIVATE_KEY) == null) {
- throw new NotFoundException("keypair not generated for client");
- }
- if (config.getKeyPassword() == null) {
- throw new BadRequestException("Need to specify a key password for jks download");
- }
- if (config.getStorePassword() == null) {
- throw new BadRequestException("Need to specify a store password for jks download");
- }
- final KeyStore keyStore;
- try {
- if (format.equals("JKS")) keyStore = KeyStore.getInstance("JKS");
- else keyStore = KeyStore.getInstance(format, "BC");
- keyStore.load(null, null);
- String keyAlias = config.getKeyAlias();
- if (keyAlias == null) keyAlias = client.getClientId();
- PrivateKey privateKey = PemUtils.decodePrivateKey(client.getAttribute(ClientModel.PRIVATE_KEY));
- X509Certificate clientCert = PemUtils.decodeCertificate(client.getAttribute(ClientModel.X509CERTIFICATE));
-
-
- Certificate[] chain = {clientCert};
-
- keyStore.setKeyEntry(keyAlias, privateKey, config.getKeyPassword().trim().toCharArray(), chain);
-
- if (config.isRealmCertificate() == null || config.isRealmCertificate().booleanValue()) {
- X509Certificate certificate = realm.getCertificate();
- if (certificate == null) {
- KeycloakModelUtils.generateRealmCertificate(realm);
- certificate = realm.getCertificate();
- }
- String certificateAlias = config.getRealmAlias();
- if (certificateAlias == null) certificateAlias = realm.getName();
- keyStore.setCertificateEntry(certificateAlias, certificate);
-
- }
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- keyStore.store(stream, config.getStorePassword().trim().toCharArray());
- stream.flush();
- stream.close();
- byte[] rtn = stream.toByteArray();
- return rtn;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
-
-}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
index 4a03d08a30..63805e4447 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
@@ -24,6 +24,7 @@ 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.Context;
import javax.ws.rs.core.MediaType;
@@ -72,9 +73,9 @@ public class OAuthClientResource {
return new ClaimResource(oauthClient, auth);
}
- @Path("certificates")
- public ClientCertificateResource getCertficateResource() {
- return new ClientCertificateResource(realm, auth, oauthClient, session);
+ @Path("certificates/{attr}")
+ public ClientAttributeCertificateResource getCertficateResource(@PathParam("attr") String attributePrefix) {
+ return new ClientAttributeCertificateResource(realm, auth, oauthClient, session, attributePrefix);
}