Search in sources :

Example 1 with KeyWrapper

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());
}
Also used : KeyWrapper(org.keycloak.crypto.KeyWrapper) Test(org.junit.Test)

Example 2 with KeyWrapper

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);
}
Also used : KeyWrapper(org.keycloak.crypto.KeyWrapper) ClientModel(org.keycloak.models.ClientModel) KeycloakModelUtils(org.keycloak.models.utils.KeycloakModelUtils) LogoutToken(org.keycloak.representations.LogoutToken) Logger(org.jboss.logging.Logger) SignatureSignerContext(org.keycloak.crypto.SignatureSignerContext) Constants(org.keycloak.models.Constants) Algorithm(org.keycloak.crypto.Algorithm) JWEEncryptionProvider(org.keycloak.jose.jwe.enc.JWEEncryptionProvider) Function(java.util.function.Function) Supplier(java.util.function.Supplier) Token(org.keycloak.Token) SignatureProvider(org.keycloak.crypto.SignatureProvider) TokenUtil(org.keycloak.util.TokenUtil) UserModel(org.keycloak.models.UserModel) ContentEncryptionProvider(org.keycloak.crypto.ContentEncryptionProvider) JWEAlgorithmProvider(org.keycloak.jose.jwe.alg.JWEAlgorithmProvider) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) OIDCAdvancedConfigWrapper(org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper) BiConsumer(java.util.function.BiConsumer) TokenManager(org.keycloak.models.TokenManager) JOSEParser(org.keycloak.jose.JOSEParser) RealmModel(org.keycloak.models.RealmModel) JWE(org.keycloak.jose.jwe.JWE) JWK(org.keycloak.jose.jwk.JWK) Predicate(java.util.function.Predicate) JWEException(org.keycloak.jose.jwe.JWEException) PublicKeyStorageManager(org.keycloak.keys.loader.PublicKeyStorageManager) KeycloakSession(org.keycloak.models.KeycloakSession) IOException(java.io.IOException) CekManagementProvider(org.keycloak.crypto.CekManagementProvider) TokenCategory(org.keycloak.TokenCategory) JsonSerialization(org.keycloak.util.JsonSerialization) Key(java.security.Key) OIDCConfigAttributes(org.keycloak.protocol.oidc.OIDCConfigAttributes) Stream(java.util.stream.Stream) KeyUse(org.keycloak.crypto.KeyUse) PrivateKey(java.security.PrivateKey) OIDCLoginProtocol(org.keycloak.protocol.oidc.OIDCLoginProtocol) Optional(java.util.Optional) JOSE(org.keycloak.jose.JOSE) Comparator(java.util.Comparator) ClientSignatureVerifierProvider(org.keycloak.crypto.ClientSignatureVerifierProvider) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JWEException(org.keycloak.jose.jwe.JWEException) IOException(java.io.IOException) JWEException(org.keycloak.jose.jwe.JWEException) IOException(java.io.IOException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) KeyWrapper(org.keycloak.crypto.KeyWrapper) JOSE(org.keycloak.jose.JOSE) JWE(org.keycloak.jose.jwe.JWE) Key(java.security.Key) PrivateKey(java.security.PrivateKey)

Example 3 with KeyWrapper

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;
}
Also used : KeyWrapper(org.keycloak.crypto.KeyWrapper) ClientModel(org.keycloak.models.ClientModel) ContentEncryptionProvider(org.keycloak.crypto.ContentEncryptionProvider) JWEAlgorithmProvider(org.keycloak.jose.jwe.alg.JWEAlgorithmProvider) JWEException(org.keycloak.jose.jwe.JWEException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) JWEEncryptionProvider(org.keycloak.jose.jwe.enc.JWEEncryptionProvider) Key(java.security.Key) PrivateKey(java.security.PrivateKey) CekManagementProvider(org.keycloak.crypto.CekManagementProvider)

Example 4 with KeyWrapper

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);
}
Also used : KeyWrapper(org.keycloak.crypto.KeyWrapper)

Example 5 with KeyWrapper

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());
}
Also used : KeyWrapper(org.keycloak.crypto.KeyWrapper) KeyWrapper(org.keycloak.crypto.KeyWrapper) RealmModel(org.keycloak.models.RealmModel) Logger(org.jboss.logging.Logger) KeycloakSession(org.keycloak.models.KeycloakSession) Algorithm(org.keycloak.crypto.Algorithm) PublicKey(java.security.PublicKey) HashMap(java.util.HashMap) Collectors(java.util.stream.Collectors) KeyManager(org.keycloak.models.KeyManager) Objects(java.util.Objects) Consumer(java.util.function.Consumer) List(java.util.List) Certificate(java.security.cert.Certificate) Stream(java.util.stream.Stream) KeyUse(org.keycloak.crypto.KeyUse) PrivateKey(java.security.PrivateKey) Map(java.util.Map) ComponentModel(org.keycloak.component.ComponentModel) Optional(java.util.Optional) SecretKey(javax.crypto.SecretKey) Comparator(java.util.Comparator) ProviderFactory(org.keycloak.provider.ProviderFactory)

Aggregations

KeyWrapper (org.keycloak.crypto.KeyWrapper)19 PublicKey (java.security.PublicKey)5 PrivateKey (java.security.PrivateKey)3 SecretKey (javax.crypto.SecretKey)3 SignatureSignerContext (org.keycloak.crypto.SignatureSignerContext)3 JSONWebKeySet (org.keycloak.jose.jwk.JSONWebKeySet)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 Key (java.security.Key)2 Comparator (java.util.Comparator)2 Optional (java.util.Optional)2 Stream (java.util.stream.Stream)2 SecretKeySpec (javax.crypto.spec.SecretKeySpec)2 Logger (org.jboss.logging.Logger)2 Algorithm (org.keycloak.crypto.Algorithm)2 CekManagementProvider (org.keycloak.crypto.CekManagementProvider)2 ContentEncryptionProvider (org.keycloak.crypto.ContentEncryptionProvider)2 KeyUse (org.keycloak.crypto.KeyUse)2 JWEException (org.keycloak.jose.jwe.JWEException)2 JWEAlgorithmProvider (org.keycloak.jose.jwe.alg.JWEAlgorithmProvider)2 JWEEncryptionProvider (org.keycloak.jose.jwe.enc.JWEEncryptionProvider)2