keycloak-uncached
Changes
services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java 19(+17 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java 41(+30 -11)
testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem 34(+21 -13)
Details
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
index f29ed8c..152d632 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
@@ -66,6 +66,10 @@ import java.util.Map;
*/
public class ClientAttributeCertificateResource {
+ public static final String CERTIFICATE_PEM = "Certificate PEM";
+ public static final String PUBLIC_KEY_PEM = "Public Key PEM";
+ public static final String JSON_WEB_KEY_SET = "JSON Web Key Set";
+
protected RealmModel realm;
private RealmAuth auth;
protected ClientModel client;
@@ -195,12 +199,23 @@ public class ClientAttributeCertificateResource {
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
String keystoreFormat = uploadForm.get("keystoreFormat").get(0).getBodyAsString();
List<InputPart> inputParts = uploadForm.get("file");
- if (keystoreFormat.equals("Certificate PEM")) {
+ if (keystoreFormat.equals(CERTIFICATE_PEM)) {
String pem = StreamUtil.readString(inputParts.get(0).getBody(InputStream.class, null));
+
+ // Validate format
+ KeycloakModelUtils.getCertificate(pem);
+
info.setCertificate(pem);
return info;
+ } else if (keystoreFormat.equals(PUBLIC_KEY_PEM)) {
+ String pem = StreamUtil.readString(inputParts.get(0).getBody(InputStream.class, null));
+
+ // Validate format
+ KeycloakModelUtils.getPublicKey(pem);
- } else if (keystoreFormat.equals("JSON Web Key Set (JWK)")) {
+ info.setPublicKey(pem);
+ return info;
+ } else if (keystoreFormat.equals(JSON_WEB_KEY_SET)) {
InputStream stream = inputParts.get(0).getBody(InputStream.class, null);
JSONWebKeySet keySet = JsonSerialization.readValue(stream, JSONWebKeySet.class);
PublicKey publicKey = JWKSUtils.getKeyForUse(keySet, JWK.Use.SIG);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java
index 087a1e6..c1cbdea 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java
@@ -55,7 +55,9 @@ import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.services.util.CertificateInfoHelper;
import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.auth.page.AuthRealm;
@@ -70,6 +72,7 @@ import java.net.URL;
import java.nio.file.Files;
import java.security.KeyStore;
import java.security.PrivateKey;
+import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.*;
@@ -81,7 +84,6 @@ import static org.junit.Assert.assertNotEquals;
* @author Vaclav Muzikar <vmuzikar@redhat.com>
*/
public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
- public static final String CERTIFICATE_PEM = "Certificate PEM";
@Rule
public AssertEvents events = new AssertEvents(this);
@@ -349,8 +351,18 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
}
@Test
- public void testUploadPEM() throws Exception {
- testUploadKeystore(CERTIFICATE_PEM, "client-auth-test/certificate.pem", "undefined", "undefined");
+ public void testUploadCertificatePEM() throws Exception {
+ testUploadKeystore(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.CERTIFICATE_PEM, "client-auth-test/certificate.pem", "undefined", "undefined");
+ }
+
+ @Test
+ public void testUploadPublicKeyPEM() throws Exception {
+ testUploadKeystore(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.PUBLIC_KEY_PEM, "client-auth-test/publickey.pem", "undefined", "undefined");
+ }
+
+ @Test
+ public void testUploadJWKS() throws Exception {
+ testUploadKeystore(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.JSON_WEB_KEY_SET, "clientreg-test/jwks.json", "undefined", "undefined");
}
// We need to test this as a genuine REST API HTTP request
@@ -395,20 +407,27 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
assertEquals(200, httpResponse.getStatusLine().getStatusCode());
client = getClient(testRealm.getRealm(), client.getId()).toRepresentation();
- String pem;
// Assert the uploaded certificate
- if (!keystoreFormat.equals(CERTIFICATE_PEM)) {
+ if (keystoreFormat.equals(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.PUBLIC_KEY_PEM)) {
+ String pem = new String(Files.readAllBytes(keystoreFile.toPath()));
+ final String publicKeyNew = client.getAttributes().get(JWTClientAuthenticator.ATTR_PREFIX + "." + CertificateInfoHelper.PUBLIC_KEY);
+ assertEquals("Certificates don't match", pem, publicKeyNew);
+ } else if (keystoreFormat.equals(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.JSON_WEB_KEY_SET)) {
+ final String publicKeyNew = client.getAttributes().get(JWTClientAuthenticator.ATTR_PREFIX + "." + CertificateInfoHelper.PUBLIC_KEY);
+ // Just assert it's valid public key
+ PublicKey pk = KeycloakModelUtils.getPublicKey(publicKeyNew);
+ Assert.assertNotNull(pk);
+ } else if (keystoreFormat.equals(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.CERTIFICATE_PEM)) {
+ String pem = new String(Files.readAllBytes(keystoreFile.toPath()));
+ assertCertificate(client, certOld, pem);
+ } else {
InputStream keystoreIs = new FileInputStream(keystoreFile);
KeyStore keyStore = getKeystore(keystoreIs, storePassword, keystoreFormat);
keystoreIs.close();
- pem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) keyStore.getCertificate(keyAlias));
+ String pem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) keyStore.getCertificate(keyAlias));
+ assertCertificate(client, certOld, pem);
}
- else {
- pem = new String(Files.readAllBytes(keystoreFile.toPath()));
- }
-
- assertCertificate(client, certOld, pem);
}
// TEST ERRORS
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem
index 4c589e8..a526c93 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem
@@ -1,13 +1,21 @@
-MIICWwIBAAKBgQCqXOsp76WfwXSNCU5AOix6SDhNR7MOdEtawJRmdUcBuJd/QeFh
-usLVOwm3a7s1134nlVKBEhOYBzKOY6LulvGDT4wHZUxE6cGJW+dEUd/6jrfZz9Ka
-XyATzLUn2BKBQZqRleQPKupwaOGQqQGQ4OmJrWKqG77Rb5O7GLNNDRCGpwIDAQAB
-AoGAA4sJLQcZ57erR9+gq/9Ju4VS/nB2Td+nTYzhyTu5LVT8eZ4SJOkwciTXL+Ri
-sVz497PIUnzgwXGs4H87/UBQZ4UJNz+kTC3L6nr4b5bWoIxoiY76R+gzlYiNEV9s
-QsX+K1FNKKMnEVa7t3DvbCFdlmt+4Agh/KQCU92Q13mj+WECQQDRF+BY1emtFfVC
-2miuSWorMLoaKv5At3BMgcs4KPzlfpMiEOMM/m1jmGrqUm40RZlnkhKEqQB0VeqF
-27gMGZuxAkEA0JTHqZDfcf5bBYhWzE3+Ec9A22/ZQgCiuV+DmWhCYxHLFsOYPkhT
-0jAibfJc8E8VchXMjeDktBAyotylQO1V1wJAcZisLPdCdeOpFMH9/zopcP+PC+px
-qY0/eIFHe+JgyvnCS86q3ANaQLKs21MfRkzNtAQbBXGfqpSGzmR5kDFVcQJAX1YR
-qMSKDS2IZw/5NGrVnUhQybvm3s8xkW9B1GWeKnAglqgSNy2R+nl70ys7Ja/QCpRC
-KftILbFVo7Eca3/PgwJAM5xMmg3Yx/WKkiCREvKXIGKOKN5rGWhHoLnYJHlsOi1r
-Z7Bef90rMp2kDrfLUAgrIJH06kxB+3oPRcmgjWlmDQ==
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJAIzE3vQp7EQWMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwMjI5MDgzMDU0WhcNNDMwNzE2MDgzMDU0WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAp1+GzdEkt2FZbISXYO12503FL6Oh8s4+tJ2fE66N8IezhugP8xiySDfW
+TEMaO5Z2TaTnQQoF9SSZ9Edq1GPxpBX0cdkCOBopEGdlb3hUYDeMaDMs18KGemUc
+Fj+CWB5VVcbmWMJ36WCz7FC+Oe38tmujR1AJpJL3pwqazyWIZzPqX8rW+rrNPGKP
+C96oBPZMb4RJWivLBJi/o5MGSpo1sJNtxyF4zUUI00LX0wZAV1HH1XErd1Vz41on
+nmB+tj9nevVRR4rDV280IELp9Ud0PIb3w843uJtwfSAwVG0pT6hv1VBDrBxTS08N
+dPU8CtkQAXzCCr8nqfAbUFOhcWRQgQIDAQABo1AwTjAdBgNVHQ4EFgQUFE+uUZAI
+n57ArEylqhCmHkAenTEwHwYDVR0jBBgwFoAUFE+uUZAIn57ArEylqhCmHkAenTEw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEApkgD3OCtw3+sk7GR1YaJ
+xNd8HT+fxXmnLqGnCQWX8lRIg5vj1PDMRev6vlIK3JfQV3zajcpKFfpy96klWsJy
+ZLYBVW2QOtMzDdQ9I8dS4Pn/SJ/Vo/M/ucfY4ttcuUL3oQCrI/c/u9tcamGMfbwd
+658MlXrUvt4B6qXY5AbgUvYR25P86uw7hSFMq5tQftNQsLbOh2FEeIiKhpgI7w8S
+SPajaWjUXsfHc5H7f9MciE2NS1Vd3AViGrVWP1rgQ1Iv0UyQVQrnjmIs12ENJmTd
+5lDqra5FJhaO7+RUG6er8n8HwXzhHkPmezGqtxWKikjitqvDY9prB3omJSa4Led+
+AQ==
+-----END CERTIFICATE-----
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem
index 906ff55..3169a04 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem
@@ -1 +1,9 @@
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApnZ/E2BUULHjsRiSnEgZ
+4vGe15BRqZPdkHR+NcvVYpThc7JqY6nZrdrwO9sOjlMC5e2Q18Fypi4KbJpGSe9r
+0DPgcbPsHSoe2xFO3M8XBE0DyoRblaQFhe6p/sj3ak32k2zn+fMZUmlx/MTNQh1I
+Cki7So0NDCBXt8XGZNnEyvKeXOUZP5qicP9KxVAQiWJvlkaTjc8rrRTmf+HWw/Qf
+gQC0tzBRpa7T+RpW9O+rnWfOaNfTkTb9itIc+ZOa2Z4iidZ7+ifMOp9cNT641Wb6
+iYqJ2ufqY+msxI54tYM1tPgGS7r4SnCwmnqTaO383wXUl8TQ7qStmAWIepV3nNyu
+AQIDAQAB
+-----END PUBLIC KEY-----
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index d1041c7..acbe6ec 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -365,11 +365,12 @@ module.controller('ClientCertificateImportCtrl', function($scope, $location, $ht
];
if (callingContext == 'jwt-credentials') {
- $scope.keyFormats.push('JSON Web Key Set (JWK)');
+ $scope.keyFormats.push('Public Key PEM');
+ $scope.keyFormats.push('JSON Web Key Set');
}
$scope.hideKeystoreSettings = function() {
- return $scope.uploadKeyFormat == 'Certificate PEM' || $scope.uploadKeyFormat == 'JSON Web Key Set (JWK)';
+ return $scope.uploadKeyFormat == 'Certificate PEM' || $scope.uploadKeyFormat == 'Public Key PEM' || $scope.uploadKeyFormat == 'JSON Web Key Set';
}
$scope.uploadKeyFormat = $scope.keyFormats[0];