KEYCLOAK-13104 Signed and Encrypted ID Token Support : AES 192bit and 256bit key support
This commit is contained in:
parent
54db691b26
commit
c057b994e7
10 changed files with 221 additions and 7 deletions
|
@ -29,6 +29,9 @@ public class JWEConstants {
|
|||
|
||||
public static final String A128CBC_HS256 = "A128CBC-HS256";
|
||||
public static final String A192CBC_HS384 = "A192CBC-HS384";
|
||||
public static final String A256CBC_HS512 = "A256CBC-HS512";
|
||||
public static final String A256CBC_HS512 = "A256CBC-HS512";
|
||||
public static final String A128GCM = "A128GCM";
|
||||
public static final String A192GCM = "A192GCM";
|
||||
public static final String A256GCM = "A256GCM";
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,16 @@ public class AesCbcHmacShaJWEEncryptionProvider extends AesCbcHmacShaEncryptionP
|
|||
expectedAesKeyLength = 16;
|
||||
hmacShaAlgorithm = "HMACSHA256";
|
||||
authenticationTagLength = 16;
|
||||
} else if (JWEConstants.A192CBC_HS384.equals(jwaAlgorithmName)) {
|
||||
expectedCEKLength = 48;
|
||||
expectedAesKeyLength = 24;
|
||||
hmacShaAlgorithm = "HMACSHA384";
|
||||
authenticationTagLength = 24;
|
||||
} else if (JWEConstants.A256CBC_HS512.equals(jwaAlgorithmName)) {
|
||||
expectedCEKLength = 64;
|
||||
expectedAesKeyLength = 32;
|
||||
hmacShaAlgorithm = "HMACSHA512";
|
||||
authenticationTagLength = 32;
|
||||
} else {
|
||||
expectedCEKLength = 0;
|
||||
expectedAesKeyLength = 0;
|
||||
|
|
|
@ -29,6 +29,12 @@ public class AesGcmJWEEncryptionProvider extends AesGcmEncryptionProvider {
|
|||
if (JWEConstants.A128GCM.equals(jwaAlgorithmName)) {
|
||||
expectedAesKeyLength = 16;
|
||||
expectedCEKLength = 16;
|
||||
} else if (JWEConstants.A192GCM.equals(jwaAlgorithmName)) {
|
||||
expectedAesKeyLength = 24;
|
||||
expectedCEKLength = 24;
|
||||
} else if (JWEConstants.A256GCM.equals(jwaAlgorithmName)) {
|
||||
expectedAesKeyLength = 32;
|
||||
expectedCEKLength = 32;
|
||||
} else {
|
||||
expectedAesKeyLength = 0;
|
||||
expectedCEKLength = 0;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2020 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.crypto;
|
||||
|
||||
import org.keycloak.jose.jwe.JWEConstants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
public class Aes192CbcHmacSha384ContentEncryptionProviderFactory implements ContentEncryptionProviderFactory {
|
||||
public static final String ID = JWEConstants.A192CBC_HS384;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentEncryptionProvider create(KeycloakSession session) {
|
||||
return new AesCbcHmacShaContentEncryptionProvider(session, ID);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2020 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.crypto;
|
||||
|
||||
import org.keycloak.jose.jwe.JWEConstants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
public class Aes192GcmContentEncryptionProviderFactory implements ContentEncryptionProviderFactory {
|
||||
public static final String ID = JWEConstants.A192GCM;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentEncryptionProvider create(KeycloakSession session) {
|
||||
return new AesGcmContentEncryptionProvider(session, ID);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2020 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.crypto;
|
||||
|
||||
import org.keycloak.jose.jwe.JWEConstants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
public class Aes256CbcHmacSha512ContentEncryptionProviderFactory implements ContentEncryptionProviderFactory {
|
||||
public static final String ID = JWEConstants.A256CBC_HS512;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentEncryptionProvider create(KeycloakSession session) {
|
||||
return new AesCbcHmacShaContentEncryptionProvider(session, ID);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2020 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.crypto;
|
||||
|
||||
import org.keycloak.jose.jwe.JWEConstants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
public class Aes256GcmContentEncryptionProviderFactory implements ContentEncryptionProviderFactory {
|
||||
public static final String ID = JWEConstants.A256GCM;
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentEncryptionProvider create(KeycloakSession session) {
|
||||
return new AesGcmContentEncryptionProvider(session, ID);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,2 +1,6 @@
|
|||
org.keycloak.crypto.Aes128CbcHmacSha256ContentEncryptionProviderFactory
|
||||
org.keycloak.crypto.Aes192CbcHmacSha384ContentEncryptionProviderFactory
|
||||
org.keycloak.crypto.Aes256CbcHmacSha512ContentEncryptionProviderFactory
|
||||
org.keycloak.crypto.Aes128GcmContentEncryptionProviderFactory
|
||||
org.keycloak.crypto.Aes192GcmContentEncryptionProviderFactory
|
||||
org.keycloak.crypto.Aes256GcmContentEncryptionProviderFactory
|
|
@ -109,11 +109,31 @@ public class IdTokenEncryptionTest extends AbstractTestRealmKeycloakTest {
|
|||
testIdTokenSignatureAndEncryption(Algorithm.ES256, JWEConstants.RSA1_5, JWEConstants.A128CBC_HS256);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA1_5EncA192CBC_HS384() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.PS256, JWEConstants.RSA1_5, JWEConstants.A192CBC_HS384);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA1_5EncA256CBC_HS512() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.PS384, JWEConstants.RSA1_5, JWEConstants.A256CBC_HS512);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA1_5EncA128GCM() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.RS384, JWEConstants.RSA1_5, JWEConstants.A128GCM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA1_5EncA192GCM() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.RS512, JWEConstants.RSA1_5, JWEConstants.A192GCM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA1_5EncA256GCM() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.RS256, JWEConstants.RSA1_5, JWEConstants.A256GCM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA_OAEPEncA128CBC_HS256() {
|
||||
// add key provider explicitly though DefaultKeyManager create fallback key provider if not exist
|
||||
|
@ -121,6 +141,16 @@ public class IdTokenEncryptionTest extends AbstractTestRealmKeycloakTest {
|
|||
testIdTokenSignatureAndEncryption(Algorithm.ES512, JWEConstants.RSA_OAEP, JWEConstants.A128CBC_HS256);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA_OAEPEncA192CBC_HS384() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.PS256, JWEConstants.RSA_OAEP, JWEConstants.A192CBC_HS384);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA_OAEPEncA256CBC_HS512() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.PS512, JWEConstants.RSA_OAEP, JWEConstants.A256CBC_HS512);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA_OAEPEncA128GCM() {
|
||||
// add key provider explicitly though DefaultKeyManager create fallback key provider if not exist
|
||||
|
@ -128,6 +158,16 @@ public class IdTokenEncryptionTest extends AbstractTestRealmKeycloakTest {
|
|||
testIdTokenSignatureAndEncryption(Algorithm.ES256, JWEConstants.RSA_OAEP, JWEConstants.A128GCM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA_OAEPEncA192GCM() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.PS384, JWEConstants.RSA_OAEP, JWEConstants.A192GCM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenEncryptionAlgRSA_OAEPEncA256GCM() {
|
||||
testIdTokenSignatureAndEncryption(Algorithm.PS512, JWEConstants.RSA_OAEP, JWEConstants.A256GCM);
|
||||
}
|
||||
|
||||
private void testIdTokenSignatureAndEncryption(String sigAlgorithm, String algAlgorithm, String encAlgorithm) {
|
||||
ClientResource clientResource = null;
|
||||
ClientRepresentation clientRep = null;
|
||||
|
@ -198,10 +238,17 @@ public class IdTokenEncryptionTest extends AbstractTestRealmKeycloakTest {
|
|||
}
|
||||
private JWEEncryptionProvider getJweEncryptionProvider(String encAlgorithm) {
|
||||
JWEEncryptionProvider jweEncryptionProvider = null;
|
||||
if (JWEConstants.A128CBC_HS256.equals(encAlgorithm)) {
|
||||
jweEncryptionProvider = new AesCbcHmacShaContentEncryptionProvider(null, encAlgorithm).jweEncryptionProvider();
|
||||
} else if (JWEConstants.A128GCM.equals(encAlgorithm)) {
|
||||
jweEncryptionProvider = new AesGcmContentEncryptionProvider(null, encAlgorithm).jweEncryptionProvider();
|
||||
switch(encAlgorithm) {
|
||||
case JWEConstants.A128GCM:
|
||||
case JWEConstants.A192GCM:
|
||||
case JWEConstants.A256GCM:
|
||||
jweEncryptionProvider = new AesGcmContentEncryptionProvider(null, encAlgorithm).jweEncryptionProvider();
|
||||
break;
|
||||
case JWEConstants.A128CBC_HS256:
|
||||
case JWEConstants.A192CBC_HS384:
|
||||
case JWEConstants.A256CBC_HS512:
|
||||
jweEncryptionProvider = new AesCbcHmacShaContentEncryptionProvider(null, encAlgorithm).jweEncryptionProvider();
|
||||
break;
|
||||
}
|
||||
return jweEncryptionProvider;
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
|
||||
// Encryption algorithms
|
||||
Assert.assertNames(oidcConfig.getIdTokenEncryptionAlgValuesSupported(), JWEConstants.RSA1_5, JWEConstants.RSA_OAEP);
|
||||
Assert.assertNames(oidcConfig.getIdTokenEncryptionEncValuesSupported(), JWEConstants.A128CBC_HS256, JWEConstants.A128GCM);
|
||||
Assert.assertNames(oidcConfig.getIdTokenEncryptionEncValuesSupported(), JWEConstants.A128CBC_HS256, JWEConstants.A128GCM, JWEConstants.A192CBC_HS384, JWEConstants.A192GCM, JWEConstants.A256CBC_HS512, JWEConstants.A256GCM);
|
||||
|
||||
// Client authentication
|
||||
Assert.assertNames(oidcConfig.getTokenEndpointAuthMethodsSupported(), "client_secret_basic", "client_secret_post", "private_key_jwt", "client_secret_jwt", "tls_client_auth");
|
||||
|
|
Loading…
Reference in a new issue