diff --git a/http/oidc/pom.xml b/http/oidc/pom.xml
index 1ec97179c85..568abc525ab 100644
--- a/http/oidc/pom.xml
+++ b/http/oidc/pom.xml
@@ -133,6 +133,11 @@
slf4j-jboss-logmanagertest
+
+ net.minidev
+ json-smart
+ test
+ net.sourceforge.htmlunithtmlunit
@@ -148,6 +153,21 @@
mockwebservertest
+
+ com.nimbusds
+ nimbus-jose-jwt
+ test
+
+
+ org.glassfish
+ javax.json
+ test
+
+
+ org.jmockit
+ jmockit
+ test
+
diff --git a/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java b/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java
index 1f5925df1ef..78e1fc7c1bc 100644
--- a/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java
+++ b/http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java
@@ -102,6 +102,7 @@ public class Oidc {
static final String KEYCLOAK_CLIENT_CLUSTER_HOST = "client_cluster_host";
static final String KEYCLOAK_QUERY_BEARER_TOKEN = "k_query_bearer_token";
static final String DEFAULT_TOKEN_SIGNATURE_ALGORITHM = "RS256";
+ public static final String DISABLE_TYP_CLAIM_VALIDATION_PROPERTY_NAME = "wildfly.elytron.oidc.disable.typ.claim.validation";
// keycloak-specific request parameter used to specify the identifier of the identity provider that should be used to authenticate a user
diff --git a/http/oidc/src/main/java/org/wildfly/security/http/oidc/TokenValidator.java b/http/oidc/src/main/java/org/wildfly/security/http/oidc/TokenValidator.java
index a549331b842..e1feae3f140 100644
--- a/http/oidc/src/main/java/org/wildfly/security/http/oidc/TokenValidator.java
+++ b/http/oidc/src/main/java/org/wildfly/security/http/oidc/TokenValidator.java
@@ -20,6 +20,7 @@
import static org.wildfly.security.http.oidc.ElytronMessages.log;
import static org.wildfly.security.http.oidc.IDToken.AT_HASH;
+import static org.wildfly.security.http.oidc.Oidc.DISABLE_TYP_CLAIM_VALIDATION_PROPERTY_NAME;
import static org.wildfly.security.http.oidc.Oidc.INVALID_AT_HASH_CLAIM;
import static org.wildfly.security.http.oidc.Oidc.INVALID_ISSUED_FOR_CLAIM;
import static org.wildfly.security.http.oidc.Oidc.INVALID_TYPE_CLAIM;
@@ -27,8 +28,10 @@
import static org.wildfly.security.jose.jwk.JWKUtil.BASE64_URL;
import java.nio.charset.StandardCharsets;
+import java.security.AccessController;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
import java.util.Arrays;
import javax.crypto.SecretKey;
@@ -52,6 +55,17 @@
*/
public class TokenValidator {
+ static final boolean DISABLE_TYP_CLAIM_VALIDATION_PROPERTY;
+
+ static {
+ DISABLE_TYP_CLAIM_VALIDATION_PROPERTY = AccessController.doPrivileged(new PrivilegedAction() {
+ @Override
+ public Boolean run() {
+ return Boolean.parseBoolean(System.getProperty(DISABLE_TYP_CLAIM_VALIDATION_PROPERTY_NAME, "false"));
+ }
+ });
+ }
+
private static final int HEADER_INDEX = 0;
private JwtConsumerBuilder jwtConsumerBuilder;
private OidcClientConfiguration clientConfiguration;
@@ -98,7 +112,9 @@ public AccessToken parseAndVerifyToken(final String bearerToken) throws OidcExce
try {
JwtContext jwtContext = setVerificationKey(bearerToken, jwtConsumerBuilder);
jwtConsumerBuilder.setRequireSubject();
- jwtConsumerBuilder.registerValidator(new TypeValidator("Bearer"));
+ if (! DISABLE_TYP_CLAIM_VALIDATION_PROPERTY) {
+ jwtConsumerBuilder.registerValidator(new TypeValidator("Bearer"));
+ }
if (clientConfiguration.isVerifyTokenAudience()) {
jwtConsumerBuilder.setExpectedAudience(clientConfiguration.getResourceName());
} else {
diff --git a/http/oidc/src/test/java/org/wildfly/security/http/oidc/TypClaimValidationBaseTest.java b/http/oidc/src/test/java/org/wildfly/security/http/oidc/TypClaimValidationBaseTest.java
new file mode 100644
index 00000000000..22ffea0cd54
--- /dev/null
+++ b/http/oidc/src/test/java/org/wildfly/security/http/oidc/TypClaimValidationBaseTest.java
@@ -0,0 +1,116 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2023 Red Hat, Inc., and individual 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.wildfly.security.http.oidc;
+
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSObject;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.Payload;
+import com.nimbusds.jose.crypto.RSASSASigner;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+
+import javax.json.Json;
+import javax.json.JsonObjectBuilder;
+
+import mockit.Mock;
+import mockit.MockUp;
+
+/**
+ * Base test class for typ claim validation tests.
+ *
+ * @author Farah Juma
+ */
+public class TypClaimValidationBaseTest {
+
+ public static String ISSUER_URL = "http://localhost:8080/realms/myrealm";
+ public static String SUBJECT = "bf8ce366-0a74-4628-bd9a-1e69084ae558";
+
+ /**
+ * The issuerUrl gets set using OIDC discovery. Since this test class isn't
+ * making use of the Keycloak OpenID provider, we are mocking the return
+ * value for the issuer URL.
+ *
+ * @param issuerUrl
+ */
+ protected static void mockIssuerUrl(String issuerUrl) {
+ Class> classToMock;
+ try {
+ classToMock = Class.forName("org.wildfly.security.http.oidc.OidcClientConfiguration",
+ true, OidcClientConfiguration.class.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new NoClassDefFoundError(e.getMessage());
+ }
+ new MockUp