KEYCLOAK-3424 Possibility to import JWK key through admin console
This commit is contained in:
parent
3eb9134e02
commit
2cba13db9c
11 changed files with 193 additions and 51 deletions
|
@ -25,6 +25,7 @@ package org.keycloak.representations.idm;
|
|||
public class CertificateRepresentation {
|
||||
|
||||
protected String privateKey;
|
||||
protected String publicKey;
|
||||
protected String certificate;
|
||||
|
||||
public String getPrivateKey() {
|
||||
|
@ -35,6 +36,14 @@ public class CertificateRepresentation {
|
|||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public void setPublicKey(String publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public String getCertificate() {
|
||||
return certificate;
|
||||
}
|
||||
|
|
|
@ -44,8 +44,10 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.JsonWebToken;
|
||||
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
import org.keycloak.services.Urls;
|
||||
import org.keycloak.services.util.CertificateInfoHelper;
|
||||
|
||||
/**
|
||||
* Client authentication based on JWT signed by client private key .
|
||||
|
@ -61,8 +63,8 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
|
|||
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
|
||||
|
||||
public static final String PROVIDER_ID = "client-jwt";
|
||||
public static final String ATTR_PREFIX = "jwt.credential";
|
||||
public static final String CERTIFICATE_ATTR = "jwt.credential.certificate";
|
||||
public static final String PUBLIC_KEY_ATTR = "jwt.credential.publicKey";
|
||||
|
||||
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
|
||||
AuthenticationExecutionModel.Requirement.ALTERNATIVE,
|
||||
|
@ -161,15 +163,17 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
|
|||
}
|
||||
|
||||
protected PublicKey getSignatureValidationKey(ClientModel client, ClientAuthenticationFlowContext context) {
|
||||
String encodedCertificate = client.getAttribute(CERTIFICATE_ATTR);
|
||||
String encodedPublicKey = client.getAttribute(PUBLIC_KEY_ATTR);
|
||||
CertificateRepresentation certInfo = CertificateInfoHelper.getCertificateFromClient(client, ATTR_PREFIX);
|
||||
|
||||
String encodedCertificate = certInfo.getCertificate();
|
||||
String encodedPublicKey = certInfo.getPublicKey();
|
||||
|
||||
if (encodedCertificate == null && encodedPublicKey == null) {
|
||||
Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client '" + client.getClientId() + "' doesn't have certificate or publicKey configured");
|
||||
context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Needs to be improved. Maybe just publicKey should be saved and existing clients migrated from certificate to publicKey...
|
||||
if (encodedCertificate != null && encodedPublicKey != null) {
|
||||
Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client '" + client.getClientId() + "' has both publicKey and certificate configured");
|
||||
context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
package org.keycloak.protocol.saml;
|
||||
|
||||
import org.keycloak.services.resources.admin.ClientAttributeCertificateResource;
|
||||
import org.keycloak.services.util.CertificateInfoHelper;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -35,7 +35,7 @@ public interface SamlConfigAttributes {
|
|||
String SAML_ASSERTION_SIGNATURE = "saml.assertion.signature";
|
||||
String SAML_ENCRYPT = "saml.encrypt";
|
||||
String SAML_CLIENT_SIGNATURE_ATTRIBUTE = "saml.client.signature";
|
||||
String SAML_SIGNING_CERTIFICATE_ATTRIBUTE = "saml.signing." + ClientAttributeCertificateResource.X509CERTIFICATE;
|
||||
String SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.X509CERTIFICATE;
|
||||
String SAML_ENCRYPTION_PRIVATE_KEY_ATTRIBUTE = "saml.encryption." + ClientAttributeCertificateResource.PRIVATE_KEY;
|
||||
String SAML_SIGNING_CERTIFICATE_ATTRIBUTE = "saml.signing." + CertificateInfoHelper.X509CERTIFICATE;
|
||||
String SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE = "saml.encryption." + CertificateInfoHelper.X509CERTIFICATE;
|
||||
String SAML_ENCRYPTION_PRIVATE_KEY_ATTRIBUTE = "saml.encryption." + CertificateInfoHelper.PRIVATE_KEY;
|
||||
}
|
||||
|
|
|
@ -30,16 +30,17 @@ import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
|||
import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
|
||||
import org.keycloak.protocol.oidc.utils.JWKSUtils;
|
||||
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
|
||||
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.oidc.OIDCClientRepresentation;
|
||||
import org.keycloak.services.clientregistration.ClientRegistrationException;
|
||||
import org.keycloak.services.util.CertificateInfoHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -95,10 +96,10 @@ public class DescriptionConverter {
|
|||
}
|
||||
|
||||
String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
|
||||
if (client.getAttributes() == null) {
|
||||
client.setAttributes(new HashMap<>());
|
||||
}
|
||||
client.getAttributes().put(JWTClientAuthenticator.PUBLIC_KEY_ATTR, publicKeyPem);
|
||||
|
||||
CertificateRepresentation rep = new CertificateRepresentation();
|
||||
rep.setPublicKey(publicKeyPem);
|
||||
CertificateInfoHelper.updateClientRepresentationCertificateInfo(client, rep, JWTClientAuthenticator.ATTR_PREFIX);
|
||||
}
|
||||
|
||||
return client;
|
||||
|
|
|
@ -25,14 +25,19 @@ import org.jboss.resteasy.spi.NotFoundException;
|
|||
import org.keycloak.common.util.StreamUtil;
|
||||
import org.keycloak.events.admin.OperationType;
|
||||
import org.keycloak.events.admin.ResourceType;
|
||||
import org.keycloak.jose.jwk.JSONWebKeySet;
|
||||
import org.keycloak.jose.jwk.JWK;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.oidc.utils.JWKSUtils;
|
||||
import org.keycloak.representations.KeyStoreConfig;
|
||||
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||
import org.keycloak.services.ErrorResponseException;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.services.util.CertificateInfoHelper;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
|
@ -49,6 +54,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
|
@ -60,17 +66,12 @@ import java.util.Map;
|
|||
*/
|
||||
public class ClientAttributeCertificateResource {
|
||||
|
||||
public static final String PRIVATE_KEY = "private.key";
|
||||
public static final String X509CERTIFICATE = "certificate";
|
||||
|
||||
protected RealmModel realm;
|
||||
private RealmAuth auth;
|
||||
protected ClientModel client;
|
||||
protected KeycloakSession session;
|
||||
protected AdminEventBuilder adminEvent;
|
||||
protected String attributePrefix;
|
||||
protected String privateAttribute;
|
||||
protected String certificateAttribute;
|
||||
|
||||
public ClientAttributeCertificateResource(RealmModel realm, RealmAuth auth, ClientModel client, KeycloakSession session, String attributePrefix, AdminEventBuilder adminEvent) {
|
||||
this.realm = realm;
|
||||
|
@ -78,8 +79,6 @@ public class ClientAttributeCertificateResource {
|
|||
this.client = client;
|
||||
this.session = session;
|
||||
this.attributePrefix = attributePrefix;
|
||||
this.privateAttribute = attributePrefix + "." + PRIVATE_KEY;
|
||||
this.certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
|
||||
this.adminEvent = adminEvent.resource(ResourceType.CLIENT);
|
||||
}
|
||||
|
||||
|
@ -98,9 +97,7 @@ public class ClientAttributeCertificateResource {
|
|||
throw new NotFoundException("Could not find client");
|
||||
}
|
||||
|
||||
CertificateRepresentation info = new CertificateRepresentation();
|
||||
info.setCertificate(client.getAttribute(certificateAttribute));
|
||||
info.setPrivateKey(client.getAttribute(privateAttribute));
|
||||
CertificateRepresentation info = CertificateInfoHelper.getCertificateFromClient(client, attributePrefix);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
@ -122,8 +119,7 @@ public class ClientAttributeCertificateResource {
|
|||
|
||||
CertificateRepresentation info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId());
|
||||
|
||||
client.setAttribute(privateAttribute, info.getPrivateKey());
|
||||
client.setAttribute(certificateAttribute, info.getCertificate());
|
||||
CertificateInfoHelper.updateClientModelCertificateInfo(client, info, attributePrefix);
|
||||
|
||||
adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
|
||||
|
||||
|
@ -151,18 +147,12 @@ public class ClientAttributeCertificateResource {
|
|||
|
||||
CertificateRepresentation info = getCertFromRequest(uriInfo, input);
|
||||
|
||||
if (info.getPrivateKey() != null) {
|
||||
client.setAttribute(privateAttribute, info.getPrivateKey());
|
||||
} else if (info.getCertificate() != null) {
|
||||
client.removeAttribute(privateAttribute);
|
||||
} else {
|
||||
try {
|
||||
CertificateInfoHelper.updateClientModelCertificateInfo(client, info, attributePrefix);
|
||||
} catch (IllegalStateException ise) {
|
||||
throw new ErrorResponseException("certificate-not-found", "Certificate or key with given alias not found in the keystore", Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (info.getCertificate() != null) {
|
||||
client.setAttribute(certificateAttribute, info.getCertificate());
|
||||
}
|
||||
|
||||
adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
|
||||
return info;
|
||||
}
|
||||
|
@ -187,12 +177,12 @@ public class ClientAttributeCertificateResource {
|
|||
}
|
||||
|
||||
CertificateRepresentation info = getCertFromRequest(uriInfo, input);
|
||||
info.setPrivateKey(null);
|
||||
|
||||
if (info.getCertificate() != null) {
|
||||
client.setAttribute(certificateAttribute, info.getCertificate());
|
||||
client.removeAttribute(privateAttribute);
|
||||
} else {
|
||||
throw new ErrorResponseException("certificate-not-found", "Certificate with given alias not found in the keystore", Response.Status.BAD_REQUEST);
|
||||
try {
|
||||
CertificateInfoHelper.updateClientModelCertificateInfo(client, info, attributePrefix);
|
||||
} catch (IllegalStateException ise) {
|
||||
throw new ErrorResponseException("certificate-not-found", "Certificate or key with given alias not found in the keystore", Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
|
||||
|
@ -210,10 +200,16 @@ public class ClientAttributeCertificateResource {
|
|||
info.setCertificate(pem);
|
||||
return info;
|
||||
|
||||
} else if (keystoreFormat.equals("JSON Web Key Set (JWK)")) {
|
||||
InputStream stream = inputParts.get(0).getBody(InputStream.class, null);
|
||||
JSONWebKeySet keySet = JsonSerialization.readValue(stream, JSONWebKeySet.class);
|
||||
PublicKey publicKey = JWKSUtils.getKeyForUse(keySet, JWK.Use.SIG);
|
||||
String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
|
||||
info.setPublicKey(publicKeyPem);
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
String keyAlias = uploadForm.get("keyAlias").get(0).getBodyAsString();
|
||||
List<InputPart> keyPasswordPart = uploadForm.get("keyPassword");
|
||||
char[] keyPassword = keyPasswordPart != null ? keyPasswordPart.get(0).getBodyAsString().toCharArray() : null;
|
||||
|
@ -272,8 +268,10 @@ public class ClientAttributeCertificateResource {
|
|||
throw new NotAcceptableException("Only support jks or pkcs12 format.");
|
||||
}
|
||||
|
||||
String privatePem = client.getAttribute(privateAttribute);
|
||||
String certPem = client.getAttribute(certificateAttribute);
|
||||
CertificateRepresentation info = CertificateInfoHelper.getCertificateFromClient(client, attributePrefix);
|
||||
String privatePem = info.getPrivateKey();
|
||||
String certPem = info.getCertificate();
|
||||
|
||||
if (privatePem == null && certPem == null) {
|
||||
throw new NotFoundException("keypair not generated for client");
|
||||
}
|
||||
|
@ -322,7 +320,10 @@ public class ClientAttributeCertificateResource {
|
|||
CertificateRepresentation info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId());
|
||||
byte[] rtn = getKeystore(config, info.getPrivateKey(), info.getCertificate());
|
||||
|
||||
client.setAttribute(certificateAttribute, info.getCertificate());
|
||||
info.setPrivateKey(null);
|
||||
|
||||
CertificateInfoHelper.updateClientModelCertificateInfo(client, info, attributePrefix);
|
||||
|
||||
adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).representation(info).success();
|
||||
return rtn;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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 org.keycloak.services.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CertificateInfoHelper {
|
||||
|
||||
|
||||
public static final String PRIVATE_KEY = "private.key";
|
||||
public static final String X509CERTIFICATE = "certificate";
|
||||
public static final String PUBLIC_KEY = "public.key";
|
||||
|
||||
|
||||
public static CertificateRepresentation getCertificateFromClient(ClientModel client, String attributePrefix) {
|
||||
String privateKeyAttribute = attributePrefix + "." + PRIVATE_KEY;
|
||||
String certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
|
||||
String publicKeyAttribute = attributePrefix + "." + PUBLIC_KEY;
|
||||
|
||||
CertificateRepresentation rep = new CertificateRepresentation();
|
||||
rep.setCertificate(client.getAttribute(certificateAttribute));
|
||||
rep.setPublicKey(client.getAttribute(publicKeyAttribute));
|
||||
rep.setPrivateKey(client.getAttribute(privateKeyAttribute));
|
||||
|
||||
return rep;
|
||||
}
|
||||
|
||||
|
||||
public static void updateClientModelCertificateInfo(ClientModel client, CertificateRepresentation rep, String attributePrefix) {
|
||||
String privateKeyAttribute = attributePrefix + "." + PRIVATE_KEY;
|
||||
String certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
|
||||
String publicKeyAttribute = attributePrefix + "." + PUBLIC_KEY;
|
||||
|
||||
if (rep.getPublicKey() == null && rep.getCertificate() == null) {
|
||||
throw new IllegalStateException("Both certificate and publicKey are null!");
|
||||
}
|
||||
|
||||
if (rep.getPublicKey() != null && rep.getCertificate() != null) {
|
||||
throw new IllegalStateException("Both certificate and publicKey are not null!");
|
||||
}
|
||||
|
||||
setOrRemoveAttr(client, privateKeyAttribute, rep.getPrivateKey());
|
||||
setOrRemoveAttr(client, publicKeyAttribute, rep.getPublicKey());
|
||||
setOrRemoveAttr(client, certificateAttribute, rep.getCertificate());
|
||||
}
|
||||
|
||||
private static void setOrRemoveAttr(ClientModel client, String attrName, String attrValue) {
|
||||
if (attrValue != null) {
|
||||
client.setAttribute(attrName, attrValue);
|
||||
} else {
|
||||
client.removeAttribute(attrName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void updateClientRepresentationCertificateInfo(ClientRepresentation client, CertificateRepresentation rep, String attributePrefix) {
|
||||
String privateKeyAttribute = attributePrefix + "." + PRIVATE_KEY;
|
||||
String certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
|
||||
String publicKeyAttribute = attributePrefix + "." + PUBLIC_KEY;
|
||||
|
||||
if (rep.getPublicKey() == null && rep.getCertificate() == null) {
|
||||
throw new IllegalStateException("Both certificate and publicKey are null!");
|
||||
}
|
||||
|
||||
if (rep.getPublicKey() != null && rep.getCertificate() != null) {
|
||||
throw new IllegalStateException("Both certificate and publicKey are not null!");
|
||||
}
|
||||
|
||||
setOrRemoveAttr(client, privateKeyAttribute, rep.getPrivateKey());
|
||||
setOrRemoveAttr(client, publicKeyAttribute, rep.getPublicKey());
|
||||
setOrRemoveAttr(client, certificateAttribute, rep.getCertificate());
|
||||
}
|
||||
|
||||
private static void setOrRemoveAttr(ClientRepresentation client, String attrName, String attrValue) {
|
||||
if (attrValue != null) {
|
||||
if (client.getAttributes() == null) {
|
||||
client.setAttributes(new HashMap<>());
|
||||
}
|
||||
client.getAttributes().put(attrName, attrValue);
|
||||
} else {
|
||||
if (client.getAttributes() != null) {
|
||||
client.getAttributes().remove(attrName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB
|
|
@ -275,6 +275,7 @@ service-account-roles.tooltip=Allows you to authenticate role mappings for the s
|
|||
client-authenticator=Client Authenticator
|
||||
client-authenticator.tooltip=Client Authenticator used for authentication this client against Keycloak server
|
||||
certificate.tooltip=Client Certificate for validate JWT issued by client and signed by Client private key from your keystore.
|
||||
publicKey.tooltip=Public Key for validate JWT issued by client and signed by Client private key.
|
||||
no-client-certificate-configured=No client certificate configured
|
||||
gen-new-keys-and-cert=Generate new keys and certificate
|
||||
import-certificate=Import Certificate
|
||||
|
|
|
@ -364,8 +364,12 @@ module.controller('ClientCertificateImportCtrl', function($scope, $location, $ht
|
|||
"Certificate PEM"
|
||||
];
|
||||
|
||||
if (callingContext == 'jwt-credentials') {
|
||||
$scope.keyFormats.push('JSON Web Key Set (JWK)');
|
||||
}
|
||||
|
||||
$scope.hideKeystoreSettings = function() {
|
||||
return $scope.uploadKeyFormat == 'Certificate PEM';
|
||||
return $scope.uploadKeyFormat == 'Certificate PEM' || $scope.uploadKeyFormat == 'JSON Web Key Set (JWK)';
|
||||
}
|
||||
|
||||
$scope.uploadKeyFormat = $scope.keyFormats[0];
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
</div>
|
||||
<kc-tooltip>{{:: 'archive-format.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" data-ng-hide="hideKeystoreSettings()">
|
||||
<label class="col-md-2 control-label" for="uploadKeyAlias">{{:: 'key-alias' | translate}}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" type="text" id="uploadKeyAlias" name="uploadKeyAlias" data-ng-model="uploadKeyAlias" autofocus required>
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'jwt-import.key-alias.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" data-ng-hide="hideKeystoreSettings()">
|
||||
<label class="col-md-2 control-label" for="uploadStorePassword">{{:: 'store-password' | translate}}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" type="password" id="uploadStorePassword" name="uploadStorePassword" data-ng-model="uploadStorePassword" autofocus required>
|
||||
|
|
|
@ -1,13 +1,26 @@
|
|||
<div>
|
||||
<form class="form-horizontal no-margin-top" name="keyForm" novalidate kc-read-only="!access.manageClients" data-ng-controller="ClientSignedJWTCtrl">
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="signingCert">{{:: 'certificate' | translate}}</label>
|
||||
<kc-tooltip>{{:: 'certificate.tooltip' | translate}}</kc-tooltip>
|
||||
|
||||
<div class="col-sm-10" data-ng-show="signingKeyInfo.certificate">
|
||||
<textarea type="text" id="signingCert" name="signingCert" class="form-control" rows="5" kc-select-action="click" readonly>{{signingKeyInfo.certificate}}</textarea>
|
||||
<div data-ng-show="signingKeyInfo.certificate">
|
||||
<label class="col-md-2 control-label" for="signingCert">{{:: 'certificate' | translate}}</label>
|
||||
<kc-tooltip>{{:: 'certificate.tooltip' | translate}}</kc-tooltip>
|
||||
|
||||
<div class="col-sm-10" data-ng-show="signingKeyInfo.certificate">
|
||||
<textarea type="text" id="signingCert" name="signingCert" class="form-control" rows="5" kc-select-action="click" readonly>{{signingKeyInfo.certificate}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-10" data-ng-hide="signingKeyInfo.certificate">
|
||||
|
||||
<div data-ng-show="signingKeyInfo.publicKey">
|
||||
<label class="col-md-2 control-label" for="publicKey">{{:: 'publicKey' | translate}}</label>
|
||||
<kc-tooltip>{{:: 'publicKey.tooltip' | translate}}</kc-tooltip>
|
||||
|
||||
<div class="col-sm-10" data-ng-show="signingKeyInfo.publicKey">
|
||||
<textarea type="text" id="publicKey" name="publicKey" class="form-control" rows="5" kc-select-action="click" readonly>{{signingKeyInfo.publicKey}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-10" data-ng-hide="signingKeyInfo.certificate || signingKeyInfo.publicKey">
|
||||
{{:: 'no-client-certificate-configured' | translate}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue