use of org.keycloak.crypto.KeyWrapper in project keycloak by keycloak.
the class JWKSUtilsTest method publicRs256.
@Test
public void publicRs256() throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
String kidRsa1 = "key1";
String kidRsa2 = "key2";
String kidInvalidKey = "ignored";
String kidEC1 = "key3";
String kidEC2 = "key4";
String jwksJson = "{" + "\"keys\": [" + " {" + " \"kty\": \"RSA\"," + " \"alg\": \"RS256\"," + " \"use\": \"sig\"," + " \"kid\": \"" + kidRsa1 + "\"," + " \"n\": \"soFDjoZ5mQ8XAA7reQAFg90inKAHk0DXMTizo4JuOsgzUbhcplIeZ7ks83hsEjm8mP8lUVaHMPMAHEIp3gu6Xxsg-s73ofx1dtt_Fo7aj8j383MFQGl8-FvixTVobNeGeC0XBBQjN8lEl-lIwOa4ZoERNAShplTej0ntDp7TQm0=\"," + " \"e\": \"AQAB\"" + " }" + " ,{" + " \"kty\": \"RSA\"," + " \"use\": \"sig\"," + " \"kid\": \"" + kidRsa2 + "\"," + " \"n\": \"soFDjoZ5mQ8XAA7reQAFg90inKAHk0DXMTizo4JuOsgzUbhcplIeZ7ks83hsEjm8mP8lUVaHMPMAHEIp3gu6Xxsg-s73ofx1dtt_Fo7aj8j383MFQGl8-FvixTVobNeGeC0XBBQjN8lEl-lIwOa4ZoERNAShplTej0ntDp7TQm0=\"," + " \"e\": \"AQAB\"" + " }," + " {" + " \"kty\": \"RSA\"," + " \"kid\": \"" + kidInvalidKey + "\"," + " \"n\": \"soFDjoZ5mQ8XAA7reQAFg90inKAHk0DXMTizo4JuOsgzUbhcplIeZ7ks83hsEjm8mP8lUVaHMPMAHEIp3gu6Xxsg-s73ofx1dtt_Fo7aj8j383MFQGl8-FvixTVobNeGeC0XBBQjN8lEl-lIwOa4ZoERNAShplTej0ntDp7TQm0=\"," + " \"e\": \"AQAB\"" + " }," + " {" + " \"kty\": \"EC\"," + " \"use\": \"sig\"," + " \"crv\": \"P-384\"," + " \"kid\": \"" + kidEC1 + "\"," + " \"x\": \"KVZ5h_W0-8fXmUrxmyRpO_9vwwI7urXfyxGdxm1hpEuhPj2hhDxivnb2BhNvtC6O\"," + " \"y\": \"1J3JVw_zR3uB3biAE7fs3V_4tJy2M1JinzWj9a4je5GSoW6zgGV4bk85OcuyUAhj\"," + " \"alg\": \"ES384\"" + " }," + " {" + " \"kty\": \"EC\"," + " \"use\": \"sig\"," + " \"crv\": \"P-384\"," + " \"kid\": \"" + kidEC2 + "\"," + " \"x\": \"KVZ5h_W0-8fXmUrxmyRpO_9vwwI7urXfyxGdxm1hpEuhPj2hhDxivnb2BhNvtC6O\"," + " \"y\": \"1J3JVw_zR3uB3biAE7fs3V_4tJy2M1JinzWj9a4je5GSoW6zgGV4bk85OcuyUAhj\"" + " }" + "] }";
JSONWebKeySet jsonWebKeySet = JsonSerialization.readValue(jwksJson, JSONWebKeySet.class);
Map<String, KeyWrapper> keyWrappersForUse = JWKSUtils.getKeyWrappersForUse(jsonWebKeySet, JWK.Use.SIG);
assertEquals(4, keyWrappersForUse.size());
KeyWrapper key = keyWrappersForUse.get(kidRsa1);
assertNotNull(key);
assertEquals("RS256", key.getAlgorithmOrDefault());
assertEquals(KeyUse.SIG, key.getUse());
assertEquals(kidRsa1, key.getKid());
assertEquals("RSA", key.getType());
key = keyWrappersForUse.get(kidRsa2);
assertNotNull(key);
assertEquals("RS256", key.getAlgorithmOrDefault());
assertEquals(KeyUse.SIG, key.getUse());
assertEquals(kidRsa2, key.getKid());
assertEquals("RSA", key.getType());
key = keyWrappersForUse.get(kidEC1);
assertNotNull(key);
assertEquals("ES384", key.getAlgorithmOrDefault());
assertEquals(KeyUse.SIG, key.getUse());
assertEquals(kidEC1, key.getKid());
assertEquals("EC", key.getType());
key = keyWrappersForUse.get(kidEC2);
assertNotNull(key);
assertNull(key.getAlgorithmOrDefault());
assertEquals(KeyUse.SIG, key.getUse());
assertEquals(kidEC2, key.getKid());
assertEquals("EC", key.getType());
}
use of org.keycloak.crypto.KeyWrapper in project keycloak by keycloak.
the class DefaultTokenManager method decodeClientJWT.
@Override
public <T> T decodeClientJWT(String jwt, ClientModel client, BiConsumer<JOSE, ClientModel> jwtValidator, Class<T> clazz) {
if (jwt == null) {
return null;
}
JOSE joseToken = JOSEParser.parse(jwt);
jwtValidator.accept(joseToken, client);
if (joseToken instanceof JWE) {
try {
Optional<KeyWrapper> activeKey;
String kid = joseToken.getHeader().getKeyId();
Stream<KeyWrapper> keys = session.keys().getKeysStream(session.getContext().getRealm());
if (kid == null) {
activeKey = keys.filter(k -> KeyUse.ENC.equals(k.getUse()) && k.getPublicKey() != null).sorted(Comparator.comparingLong(KeyWrapper::getProviderPriority).reversed()).findFirst();
} else {
activeKey = keys.filter(k -> KeyUse.ENC.equals(k.getUse()) && k.getKid().equals(kid)).findAny();
}
JWE jwe = JWE.class.cast(joseToken);
Key privateKey = activeKey.map(KeyWrapper::getPrivateKey).orElseThrow(() -> new RuntimeException("Could not find private key for decrypting token"));
jwe.getKeyStorage().setDecryptionKey(privateKey);
byte[] content = jwe.verifyAndDecodeJwe().getContent();
try {
JOSE jws = JOSEParser.parse(new String(content));
if (jws instanceof JWSInput) {
jwtValidator.accept(jws, client);
return verifyJWS(client, clazz, (JWSInput) jws);
}
} catch (Exception ignore) {
// try to decrypt content as is
}
return JsonSerialization.readValue(content, clazz);
} catch (IOException cause) {
throw new RuntimeException("Failed to deserialize JWT", cause);
} catch (JWEException cause) {
throw new RuntimeException("Failed to decrypt JWT", cause);
}
}
return verifyJWS(client, clazz, (JWSInput) joseToken);
}
use of org.keycloak.crypto.KeyWrapper in project keycloak by keycloak.
the class DefaultTokenManager method getEncryptedToken.
private String getEncryptedToken(TokenCategory category, String encodedToken) {
String encryptedToken = null;
String algAlgorithm = cekManagementAlgorithm(category);
String encAlgorithm = encryptAlgorithm(category);
CekManagementProvider cekManagementProvider = session.getProvider(CekManagementProvider.class, algAlgorithm);
JWEAlgorithmProvider jweAlgorithmProvider = cekManagementProvider.jweAlgorithmProvider();
ContentEncryptionProvider contentEncryptionProvider = session.getProvider(ContentEncryptionProvider.class, encAlgorithm);
JWEEncryptionProvider jweEncryptionProvider = contentEncryptionProvider.jweEncryptionProvider();
ClientModel client = session.getContext().getClient();
KeyWrapper keyWrapper = PublicKeyStorageManager.getClientPublicKeyWrapper(session, client, JWK.Use.ENCRYPTION, algAlgorithm);
if (keyWrapper == null) {
throw new RuntimeException("can not get encryption KEK");
}
Key encryptionKek = keyWrapper.getPublicKey();
String encryptionKekId = keyWrapper.getKid();
try {
encryptedToken = TokenUtil.jweKeyEncryptionEncode(encryptionKek, encodedToken.getBytes("UTF-8"), algAlgorithm, encAlgorithm, encryptionKekId, jweAlgorithmProvider, jweEncryptionProvider);
} catch (JWEException | UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encryptedToken;
}
use of org.keycloak.crypto.KeyWrapper in project keycloak by keycloak.
the class AbstractGeneratedSecretKeyProvider method getKeysStream.
@Override
public Stream<KeyWrapper> getKeysStream() {
KeyWrapper key = new KeyWrapper();
key.setProviderId(model.getId());
key.setProviderPriority(model.get("priority", 0l));
key.setKid(kid);
key.setUse(use);
key.setType(type);
key.setAlgorithm(algorithm);
key.setStatus(status);
key.setSecretKey(secretKey);
return Stream.of(key);
}
use of org.keycloak.crypto.KeyWrapper in project keycloak by keycloak.
the class DefaultKeyManager method getActiveKey.
@Override
public KeyWrapper getActiveKey(RealmModel realm, KeyUse use, String algorithm) {
KeyWrapper activeKey = getActiveKey(getProviders(realm), realm, use, algorithm);
if (activeKey != null) {
return activeKey;
}
logger.debugv("Failed to find active key for realm, trying fallback: realm={0} algorithm={1} use={2}", realm.getName(), algorithm, use.name());
Optional<KeyProviderFactory> keyProviderFactory = session.getKeycloakSessionFactory().getProviderFactoriesStream(KeyProvider.class).map(KeyProviderFactory.class::cast).filter(kf -> kf.createFallbackKeys(session, use, algorithm)).findFirst();
if (keyProviderFactory.isPresent()) {
providersMap.remove(realm.getId());
List<KeyProvider> providers = getProviders(realm);
activeKey = getActiveKey(providers, realm, use, algorithm);
if (activeKey != null) {
logger.infov("No keys found for realm={0} and algorithm={1} for use={2}. Generating keys.", realm.getName(), algorithm, use.name());
return activeKey;
}
}
logger.errorv("Failed to create fallback key for realm: realm={0} algorithm={1} use={2", realm.getName(), algorithm, use.name());
throw new RuntimeException("Failed to find key: realm=" + realm.getName() + " algorithm=" + algorithm + " use=" + use.name());
}
Aggregations