mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 15:02:05 -03:30
Key generation for client authentication is always RSA 2048 with a 10-year validity, regardless of the selected algorithm
Closes #38620 Signed-off-by: Douglas Palmer <dpalmer@redhat.com>
This commit is contained in:
parent
30979dc873
commit
1183157d86
@ -29,6 +29,8 @@ public class KeyStoreConfig {
|
||||
protected String keyAlias;
|
||||
protected String realmAlias;
|
||||
protected String format;
|
||||
protected Integer keySize;
|
||||
protected Integer validity;
|
||||
|
||||
public Boolean isRealmCertificate() {
|
||||
return realmCertificate;
|
||||
@ -77,4 +79,20 @@ public class KeyStoreConfig {
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public Integer getKeySize() {
|
||||
return keySize;
|
||||
}
|
||||
|
||||
public void setKeySize(Integer keySize) {
|
||||
this.keySize = keySize;
|
||||
}
|
||||
|
||||
public Integer getValidity() {
|
||||
return validity;
|
||||
}
|
||||
|
||||
public void setValidity(Integer validity) {
|
||||
this.validity = validity;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
package org.keycloak.admin.client.resource;
|
||||
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import org.keycloak.representations.KeyStoreConfig;
|
||||
import org.keycloak.representations.idm.CertificateRepresentation;
|
||||
|
||||
|
||||
@ -480,7 +480,7 @@ userInfoResponseEncryptionKeyManagementAlgorithmHelp=JWA Algorithm used for key
|
||||
authnContextDeclRefsHelp=Ordered list of requested AuthnContext DeclRefs.
|
||||
inherent=Inherited
|
||||
tableTitle=Attributes groups
|
||||
generateNewKeys=Generate new keys
|
||||
generateNewKeys=Generate RSA keys
|
||||
updateClientPolicySuccess=Client policy updated
|
||||
unlock=Unlock
|
||||
validateRealm=You must enter a realm
|
||||
@ -826,6 +826,8 @@ removeImported=Remove imported
|
||||
endpoints=Endpoints
|
||||
roleSaveError=Could not save role\: {{error}}
|
||||
keySize=Key size
|
||||
validity=Certificate expiration
|
||||
validityHelp=Number of years the generated certificate is valid for.
|
||||
membershipUserLdapAttributeHelp=Used only if the Membership Attribute Type is UID. It is the name of the LDAP attribute on the user, which is used for membership mappings. It is typically 'uid'. For example, if the value of 'Membership User LDAP Attribute' is 'uid' and the LDAP group has 'memberUid\: john', it is expected that particular LDAP user will have the attribute 'uid\: john'.
|
||||
samlCapabilityConfig=SAML capabilities
|
||||
accessTokenSignatureAlgorithmHelp=JWA algorithm used for signing access tokens.
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type KeyStoreConfig from "@keycloak/keycloak-admin-client/lib/defs/keystoreConfig";
|
||||
import {
|
||||
HelpItem,
|
||||
NumberControl,
|
||||
SelectControl,
|
||||
FileUploadControl,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
@ -59,6 +60,7 @@ export const KeyForm = ({
|
||||
...(cryptoInfo?.supportedKeystoreTypes ?? []),
|
||||
...(hasPem ? [CERT_PEM] : []),
|
||||
];
|
||||
const keySizes = ["4096", "3072", "2048"];
|
||||
|
||||
return (
|
||||
<Form className="pf-v5-u-pt-lg">
|
||||
@ -91,6 +93,25 @@ export const KeyForm = ({
|
||||
{format !== CERT_PEM && (
|
||||
<StoreSettings hidePassword={useFile} isSaml={isSaml} />
|
||||
)}
|
||||
<SelectControl
|
||||
name="keySize"
|
||||
label={t("keySize")}
|
||||
labelIcon={t("keySizeHelp")}
|
||||
controller={{
|
||||
defaultValue: keySizes[0],
|
||||
}}
|
||||
menuAppendTo="parent"
|
||||
options={keySizes}
|
||||
/>
|
||||
<NumberControl
|
||||
name="validity"
|
||||
label={t("validity")}
|
||||
labelIcon={t("validityHelp")}
|
||||
controller={{
|
||||
defaultValue: 3,
|
||||
rules: { required: t("required"), min: 1, max: 10 },
|
||||
}}
|
||||
/>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
@ -8,4 +8,6 @@ export default interface KeyStoreConfig {
|
||||
keyAlias?: string;
|
||||
realmAlias?: string;
|
||||
format?: string;
|
||||
keySize?: number;
|
||||
validity?: number;
|
||||
}
|
||||
|
||||
@ -65,6 +65,7 @@ import jakarta.transaction.InvalidTransactionException;
|
||||
import jakarta.transaction.SystemException;
|
||||
import jakarta.transaction.Transaction;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.math.BigInteger;
|
||||
import java.security.Key;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
@ -72,6 +73,7 @@ import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@ -218,8 +220,14 @@ public final class KeycloakModelUtils {
|
||||
}
|
||||
|
||||
public static CertificateRepresentation generateKeyPairCertificate(String subject) {
|
||||
KeyPair keyPair = KeyUtils.generateRsaKeyPair(2048);
|
||||
X509Certificate certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, subject);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.YEAR, 3);
|
||||
return generateKeyPairCertificate(subject, 4096, calendar);
|
||||
}
|
||||
|
||||
public static CertificateRepresentation generateKeyPairCertificate(String subject, int keysize, Calendar endDate) {
|
||||
KeyPair keyPair = KeyUtils.generateRsaKeyPair(keysize);
|
||||
X509Certificate certificate = CertificateUtils.generateV1SelfSignedCertificate(keyPair, subject, BigInteger.valueOf(System.currentTimeMillis()), endDate.getTime());
|
||||
|
||||
String privateKeyPem = PemUtils.encodeKey(keyPair.getPrivate());
|
||||
String certPem = PemUtils.encodeCertificate(certificate);
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import org.eclipse.microprofile.openapi.annotations.Operation;
|
||||
import org.eclipse.microprofile.openapi.annotations.extensions.Extension;
|
||||
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
|
||||
@ -64,6 +65,7 @@ import java.security.PrivateKey;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Calendar;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -340,7 +342,15 @@ public class ClientAttributeCertificateResource {
|
||||
throw new ErrorResponseException("password-missing", "Need to specify a store password for jks generation and download", Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
CertificateRepresentation info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId());
|
||||
CertificateRepresentation info;
|
||||
if (config.getKeySize() <= 0 || config.getValidity() <= 0) {
|
||||
info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId());
|
||||
}
|
||||
else {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.YEAR, config.getValidity());
|
||||
info = KeycloakModelUtils.generateKeyPairCertificate(client.getClientId(), config.getKeySize(), calendar);
|
||||
}
|
||||
byte[] rtn = getKeystore(config, info.getPrivateKey(), info.getCertificate());
|
||||
|
||||
info.setPrivateKey(null);
|
||||
|
||||
@ -240,6 +240,8 @@ public class CredentialsTest extends AbstractClientTest {
|
||||
config.setKeyAlias("alias");
|
||||
config.setKeyPassword("keyPass");
|
||||
config.setStorePassword("storePass");
|
||||
config.setKeySize(4096);
|
||||
config.setValidity(3);
|
||||
byte[] result = certRsc.generateAndGetKeystore(config);
|
||||
KeyStore keyStore = CryptoIntegration.getProvider().getKeyStore(preferredKeystoreType);
|
||||
keyStore.load(new ByteArrayInputStream(result), "storePass".toCharArray());
|
||||
|
||||
@ -389,6 +389,8 @@ public abstract class AbstractClientAuthSignedJWTTest extends AbstractKeycloakTe
|
||||
keyStoreConfig.setKeyPassword(keyPassword);
|
||||
keyStoreConfig.setStorePassword(storePassword);
|
||||
keyStoreConfig.setKeyAlias(keyAlias);
|
||||
keyStoreConfig.setKeySize(4096);
|
||||
keyStoreConfig.setValidity(3);
|
||||
|
||||
client = getClient(testRealm.getRealm(), client.getId()).toRepresentation();
|
||||
final String certOld = client.getAttributes().get(JWTClientAuthenticator.CERTIFICATE_ATTR);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user