diff --git a/docs/documentation/release_notes/topics/22_0_0.adoc b/docs/documentation/release_notes/topics/22_0_0.adoc
index f08629b2e7..ce52071004 100644
--- a/docs/documentation/release_notes/topics/22_0_0.adoc
+++ b/docs/documentation/release_notes/topics/22_0_0.adoc
@@ -149,3 +149,7 @@ picked (`Always`), or the global JVM one (`Never`).
Deployments where `Only for ldaps` was used will automatically behave as if `Always` option was
selected for TLS-secured LDAP connections.
+
+= Support for JWE encrypted ID Tokens and UserInfo responses in OpenID Connect providers
+
+The OpenID Connect providers now support https://datatracker.ietf.org/doc/html/rfc7516[Json Web Encryption (JWE)] for the ID Token and the UserInfo response. The providers use the realm keys defined for the selected encryption algorithm to perform the decryption.
diff --git a/docs/documentation/server_admin/topics/identity-broker/oidc.adoc b/docs/documentation/server_admin/topics/identity-broker/oidc.adoc
index 4c56ca16b9..2fc28440a1 100644
--- a/docs/documentation/server_admin/topics/identity-broker/oidc.adoc
+++ b/docs/documentation/server_admin/topics/identity-broker/oidc.adoc
@@ -78,3 +78,5 @@ If the user is unauthenticated in the IDP, the client still receives a `login_re
|===
You can import all this configuration data by providing a URL or file that points to OpenID Provider Metadata. If you connect to a {project_name} external IDP, you can import the IDP settings from `{kc_realms_path}/{realm-name}/.well-known/openid-configuration`. This link is a JSON document describing metadata about the IDP.
+
+If you want to use https://datatracker.ietf.org/doc/html/rfc7516[Json Web Encryption (JWE)] ID Tokens or UserInfo responses in the provider, the IDP needs to know the public key to use with {project_name}. The provider uses the <> defined for the different encryption algorithms to decrypt the tokens. {project_name} provides a standard xref:con-server-oidc-uri-endpoints_{context}[JWKS endpoint] which the IDP can use for downloading the keys automatically.
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
index 5217a03465..83b371aae9 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java
@@ -32,14 +32,18 @@ import org.keycloak.common.util.Base64Url;
import org.keycloak.common.util.SecretGenerator;
import org.keycloak.common.util.Time;
import org.keycloak.connections.httpclient.HttpClientProvider;
+import org.keycloak.crypto.KeyUse;
import org.keycloak.crypto.KeyWrapper;
import org.keycloak.crypto.SignatureProvider;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
+import org.keycloak.jose.JOSE;
+import org.keycloak.jose.JOSEParser;
+import org.keycloak.jose.jwe.JWE;
+import org.keycloak.jose.jwe.JWEException;
import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.keys.loader.PublicKeyStorageManager;
import org.keycloak.models.AbstractKeycloakTransaction;
import org.keycloak.models.ClientModel;
@@ -484,19 +488,7 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProviderTests the broker using a JWE encrypted token for id token and user info. The test
+ * can be extended to use different algorithms. The default uses RSA-OAEP as
+ * encryption key management algorithm, A256GCM as the content encryption
+ * algorithm and RS512 as the signature algorithm.
+ *
+ * @author rmartinc
+ */
+public class KcOidcBrokerJWETest extends AbstractBrokerTest {
+
+ private final String encAlg;
+ private final String encEnc;
+ private final String sigAlg;
+
+ public KcOidcBrokerJWETest() {
+ this(JWEConstants.RSA_OAEP, JWEConstants.A256GCM, Algorithm.RS512);
+ }
+
+ protected KcOidcBrokerJWETest(String encAlg, String encEnc, String sigAlg) {
+ this.encAlg = encAlg;
+ this.encEnc = encEnc;
+ this.sigAlg = sigAlg;
+ }
+
+ @Override
+ protected BrokerConfiguration getBrokerConfiguration() {
+ return new KcOidcBrokerConfiguration() {
+ @Override
+ public List createProviderClients() {
+ List clientsRepList = super.createProviderClients();
+ for (ClientRepresentation client : clientsRepList) {
+ Map attrs = client.getAttributes();
+
+ // use the certs from the consumer realm to perform the encryption
+ attrs.put(OIDCConfigAttributes.USE_JWKS_URL, "true");
+ attrs.put(OIDCConfigAttributes.JWKS_URL, BrokerTestTools.getConsumerRoot() +
+ "/auth/realms/" + BrokerTestConstants.REALM_CONS_NAME + "/protocol/openid-connect/certs");
+
+ // assign the encryption and signature attributes
+ if (encAlg != null) {
+ attrs.put(OIDCConfigAttributes.ID_TOKEN_ENCRYPTED_RESPONSE_ALG, encAlg);
+ attrs.put(OIDCConfigAttributes.USER_INFO_ENCRYPTED_RESPONSE_ALG, encAlg);
+ }
+
+ if (encEnc != null) {
+ attrs.put(OIDCConfigAttributes.ID_TOKEN_ENCRYPTED_RESPONSE_ENC, encEnc);
+ attrs.put(OIDCConfigAttributes.USER_INFO_ENCRYPTED_RESPONSE_ENC, encEnc);
+ }
+
+ if (sigAlg != null) {
+ attrs.put(OIDCConfigAttributes.ID_TOKEN_SIGNED_RESPONSE_ALG, sigAlg);
+ attrs.put(OIDCConfigAttributes.USER_INFO_RESPONSE_SIGNATURE_ALG, sigAlg);
+ }
+ }
+ return clientsRepList;
+ }
+
+ @Override
+ public RealmRepresentation createConsumerRealm() {
+ RealmRepresentation realm = super.createConsumerRealm();
+
+ if (encAlg != null) {
+ // create the RSA component for the encryption in the specified alg
+ ComponentExportRepresentation component = new ComponentExportRepresentation();
+ component.setName("rsa-enc-generated");
+ component.setProviderId("rsa-enc-generated");
+
+ MultivaluedHashMap config = new MultivaluedHashMap<>();
+ config.putSingle("priority", DefaultKeyProviders.DEFAULT_PRIORITY);
+ config.putSingle("keyUse", KeyUse.ENC.name());
+ config.putSingle("algorithm", encAlg);
+ component.setConfig(config);
+
+ MultivaluedHashMap components = realm.getComponents();
+ if (components == null) {
+ components = new MultivaluedHashMap<>();
+ realm.setComponents(components);
+ }
+ components.add(KeyProvider.class.getName(), component);
+ }
+
+ return realm;
+ }
+ };
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerJWEUserInfoJustEncryptedTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerJWEUserInfoJustEncryptedTest.java
new file mode 100644
index 0000000000..f57872cc7a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerJWEUserInfoJustEncryptedTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 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.testsuite.broker;
+
+import org.keycloak.jose.jwe.JWEConstants;
+
+/**
+ * Extension of the KcOidcBrokerJWETest test to use a different key algorithm (RSA1_5),
+ * the default content encryption algorithm (A128CBC-HS256) and the default signature
+ * algorithm (RS256 for id token and none/unsigned for user info).
+ *
+ * @author rmartinc
+ */
+public class KcOidcBrokerJWEUserInfoJustEncryptedTest extends KcOidcBrokerJWETest {
+
+ public KcOidcBrokerJWEUserInfoJustEncryptedTest() {
+ super(JWEConstants.RSA1_5, null, null);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/testsuites/fips-suite b/testsuite/integration-arquillian/tests/base/testsuites/fips-suite
index eca4400478..a4b646c153 100644
--- a/testsuite/integration-arquillian/tests/base/testsuites/fips-suite
+++ b/testsuite/integration-arquillian/tests/base/testsuites/fips-suite
@@ -17,6 +17,8 @@ KcAdmTest
KcAdmCreateTest
SAMLServletAdapterTest
SamlSignatureTest
+KcOidcBrokerJWETest
+KcOidcBrokerJWEUserInfoJustEncryptedTest
KcSamlBrokerTest
KcSamlFirstBrokerLoginTest
KcSamlEncryptedIdTest