You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2026/07/20 08:30:15 UTC
(cxf) 01/03: Enforce TLS client certificate and store the application certificates for dynamic registration (#3316)
This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch 3.6.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
commit d53fe8aa238d30746a4ed0d06b756374ffdc6153
Author: Colm O hEigeartaigh <co...@users.noreply.github.com>
AuthorDate: Mon Jul 20 09:11:06 2026 +0100
Enforce TLS client certificate and store the application certificates for dynamic registration (#3316)
(cherry picked from commit 413d75ec1d9bd1b6a2b50e72bf4e7f0e53258218)
---
.../oauth2/services/AbstractTokenService.java | 37 ++++----
.../services/DynamicRegistrationService.java | 59 ++++++++++++
.../oauth2/services/AbstractTokenServiceTest.java | 91 ++++++++++++++++++
.../services/DynamicRegistrationServiceTest.java | 102 +++++++++++++++++++++
.../cxf/systest/jaxrs/security/oidc/client.xml | 3 +
.../jaxrs/security/oidc/oidc-server-dynreg.xml | 2 +-
6 files changed, 276 insertions(+), 18 deletions(-)
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
index f3f91121746..de5851d29f4 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
@@ -162,26 +162,29 @@ public class AbstractTokenService extends AbstractOAuthService {
}
protected void checkCertificateBinding(Client client, TLSSessionInfo tlsSessionInfo) {
- String subjectDn = client.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN);
- if (subjectDn == null && client.getApplicationCertificates().isEmpty()) {
- LOG.warning("Client \"" + client.getClientId() + "\" can not be bound to the TLS certificate");
- reportInvalidClient();
- }
X509Certificate cert = OAuthUtils.getRootTLSCertificate(tlsSessionInfo);
-
- if (subjectDn != null
- && !subjectDn.equals(OAuthUtils.getSubjectDnFromTLSCertificates(cert))) {
- LOG.warning("Client \"" + client.getClientId() + "\" can not be bound to the TLS certificate");
- reportInvalidClient();
- }
- String issuerDn = client.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN);
- if (issuerDn != null
- && !issuerDn.equals(OAuthUtils.getIssuerDnFromTLSCertificates(cert))) {
- LOG.warning("Client \"" + client.getClientId() + "\" can not be bound to the TLS certificate");
- reportInvalidClient();
- }
if (!client.getApplicationCertificates().isEmpty()) {
compareTlsCertificates(tlsSessionInfo, client.getApplicationCertificates());
+ } else {
+ String subjectDn = client.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN);
+ String issuerDn = client.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN);
+ if (subjectDn == null && issuerDn == null) {
+ LOG.warning("Client \"" + client.getClientId()
+ + "\" can not be bound to the TLS certificate");
+ reportInvalidClient();
+ }
+ if (subjectDn != null
+ && !subjectDn.equals(OAuthUtils.getSubjectDnFromTLSCertificates(cert))) {
+ LOG.warning("Client \"" + client.getClientId()
+ + "\" can not be bound to the TLS certificate");
+ reportInvalidClient();
+ }
+ if (issuerDn != null
+ && !issuerDn.equals(OAuthUtils.getIssuerDnFromTLSCertificates(cert))) {
+ LOG.warning("Client \"" + client.getClientId()
+ + "\" can not be bound to the TLS certificate");
+ reportInvalidClient();
+ }
}
OAuthUtils.setCertificateThumbprintConfirmation(getMessageContext(), cert);
}
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
index 53e3a282a53..6e0ff8bc1a0 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationService.java
@@ -18,6 +18,7 @@
*/
package org.apache.cxf.rs.security.oauth2.services;
+import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -38,7 +39,10 @@ import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder;
+import javax.security.auth.x500.X500Principal;
+
import org.apache.cxf.common.util.Base64UrlUtility;
+import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.utils.ExceptionUtils;
@@ -52,6 +56,7 @@ import org.apache.cxf.rs.security.oauth2.utils.AuthorizationUtils;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
import org.apache.cxf.rt.security.crypto.CryptoUtils;
+import org.apache.cxf.security.transport.TLSSessionInfo;
@Path("register")
public class DynamicRegistrationService {
@@ -63,6 +68,7 @@ public class DynamicRegistrationService {
private int clientIdSizeInBytes = DEFAULT_CLIENT_ID_SIZE;
private MessageContext mc;
private boolean supportRegistrationAccessTokens = true;
+ private boolean enforceTlsClientAuthCertificateBinding = true;
private String userRole;
private List<String> allowedClientScopes;
@@ -275,6 +281,8 @@ public class DynamicRegistrationService {
newClient.setTokenEndpointAuthMethod(tokenEndpointAuthMethod);
if (OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS.equals(tokenEndpointAuthMethod)) {
+ X509Certificate cert = enforceTlsClientAuthCertificateBinding
+ ? validateTlsClientAuthCertificateBinding(request) : getTlsClientCertificate();
String subjectDn = (String)request.getProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN);
if (subjectDn != null) {
newClient.getProperties().put(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, subjectDn);
@@ -283,6 +291,15 @@ public class DynamicRegistrationService {
if (issuerDn != null) {
newClient.getProperties().put(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN, issuerDn);
}
+ if (cert != null) {
+ try {
+ newClient.getApplicationCertificates().add(Base64Utility.encode(cert.getEncoded()));
+ } catch (Exception ex) {
+ OAuthError error =
+ new OAuthError(INVALID_CLIENT_METADATA, "Unable to register TLS client certificate");
+ reportInvalidRequestError(error);
+ }
+ }
}
// Client Registration Time
newClient.setRegisteredAt(System.currentTimeMillis() / 1000L);
@@ -299,6 +316,44 @@ public class DynamicRegistrationService {
return newClient;
}
+ protected X509Certificate getTlsClientCertificate() {
+ TLSSessionInfo tlsSessionInfo = (TLSSessionInfo)mc.get(TLSSessionInfo.class.getName());
+ return tlsSessionInfo == null ? null : OAuthUtils.getRootTLSCertificate(tlsSessionInfo);
+ }
+
+ protected X509Certificate validateTlsClientAuthCertificateBinding(ClientRegistration request) {
+ X509Certificate cert = getTlsClientCertificate();
+ if (cert == null) {
+ OAuthError error =
+ new OAuthError(INVALID_CLIENT_METADATA, "TLS client certificate is required");
+ reportInvalidRequestError(error);
+ }
+
+ String subjectDn = (String)request.getProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN);
+ if (subjectDn != null
+ && !isSameDistinguishedName(subjectDn, OAuthUtils.getSubjectDnFromTLSCertificates(cert))) {
+ OAuthError error =
+ new OAuthError(INVALID_CLIENT_METADATA, "Invalid tls_client_auth_subject_dn metadata");
+ reportInvalidRequestError(error);
+ }
+ String issuerDn = (String)request.getProperty(OAuthConstants.TLS_CLIENT_AUTH_ISSUER_DN);
+ if (issuerDn != null
+ && !isSameDistinguishedName(issuerDn, OAuthUtils.getIssuerDnFromTLSCertificates(cert))) {
+ OAuthError error =
+ new OAuthError(INVALID_CLIENT_METADATA, "Invalid tls_client_auth_root_dn metadata");
+ reportInvalidRequestError(error);
+ }
+ return cert;
+ }
+
+ private boolean isSameDistinguishedName(String expectedDn, String actualDn) {
+ try {
+ return new X500Principal(expectedDn).equals(new X500Principal(actualDn));
+ } catch (IllegalArgumentException ex) {
+ return false;
+ }
+ }
+
protected void fromClientRegistrationToClient(ClientRegistration request, Client client) {
final List<String> grantTypes = client.getAllowedGrantTypes();
@@ -420,6 +475,10 @@ public class DynamicRegistrationService {
this.supportRegistrationAccessTokens = supportRegistrationAccessTokens;
}
+ public void setEnforceTlsClientAuthCertificateBinding(boolean enforceTlsClientAuthCertificateBinding) {
+ this.enforceTlsClientAuthCertificateBinding = enforceTlsClientAuthCertificateBinding;
+ }
+
public void setUserRole(String userRole) {
this.userRole = userRole;
}
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenServiceTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenServiceTest.java
index 03411d35936..40444e77160 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenServiceTest.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenServiceTest.java
@@ -18,13 +18,23 @@
*/
package org.apache.cxf.rs.security.oauth2.services;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import javax.security.auth.x500.X500Principal;
+
import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.SecurityContext;
+
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.impl.MetadataMap;
import org.apache.cxf.rs.security.oauth2.common.Client;
import org.apache.cxf.rs.security.oauth2.common.OAuthError;
import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.security.transport.TLSSessionInfo;
import org.junit.Test;
@@ -32,6 +42,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class AbstractTokenServiceTest {
@@ -80,6 +92,76 @@ public class AbstractTokenServiceTest {
assertSame(expected, actual);
}
+ @Test
+ public void testCheckCertificateBindingAcceptsDnOnlyClient() {
+ TestTokenService service = new TestTokenService();
+ Client client = new Client("c1", null, true);
+ client.getProperties().put(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, "CN=peer,O=Test,C=US");
+
+ service.callCheckCertificateBinding(client,
+ makeTlsSession("CN=peer,O=Test,C=US", "CN=issuer,O=Test,C=US"));
+ }
+
+ @Test
+ public void testCheckCertificateBindingRejectsDnOnlyClientMismatch() {
+ TestTokenService service = new TestTokenService();
+ Client client = new Client("c1", null, true);
+ client.getProperties().put(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, "CN=peer,O=Test,C=US");
+
+ InvalidClientException ex = assertThrows(InvalidClientException.class,
+ () -> service.callCheckCertificateBinding(client,
+ makeTlsSession("CN=other,O=Test,C=US", "CN=issuer,O=Test,C=US")));
+
+ assertNotNull(ex.getError());
+ assertEquals(OAuthConstants.INVALID_CLIENT, ex.getError().getError());
+ }
+
+ @Test
+ public void testCheckCertificateBindingRejectsCertificateMismatch() {
+ TestTokenService service = new TestTokenService();
+ Client client = new Client("c2", null, true);
+ client.getApplicationCertificates().add(Base64Utility.encode(new byte[] {9, 9, 9}));
+
+ InvalidClientException ex = assertThrows(InvalidClientException.class,
+ () -> service.callCheckCertificateBinding(client,
+ makeTlsSession("CN=peer,O=Test,C=US", "CN=issuer,O=Test,C=US")));
+
+ assertNotNull(ex.getError());
+ assertEquals(OAuthConstants.INVALID_CLIENT, ex.getError().getError());
+ }
+
+ @Test
+ public void testCheckCertificateBindingAcceptsCertificateMatch() throws Exception {
+ TestTokenService service = new TestTokenService();
+ X509Certificate cert = createCertificate("CN=peer,O=Test,C=US", "CN=issuer,O=Test,C=US");
+
+ Client client = new Client("c3", null, true);
+ client.getApplicationCertificates().add(Base64Utility.encode(cert.getEncoded()));
+
+ service.callCheckCertificateBinding(client, makeTlsSession(cert));
+ }
+
+ private static TLSSessionInfo makeTlsSession(String subjectDn, String issuerDn) {
+ X509Certificate cert = createCertificate(subjectDn, issuerDn);
+ return makeTlsSession(cert);
+ }
+
+ private static TLSSessionInfo makeTlsSession(X509Certificate cert) {
+ return new TLSSessionInfo("TLS_FAKE", null, new Certificate[] {cert});
+ }
+
+ private static X509Certificate createCertificate(String subjectDn, String issuerDn) {
+ X509Certificate cert = mock(X509Certificate.class);
+ when(cert.getSubjectX500Principal()).thenReturn(new X500Principal(subjectDn));
+ when(cert.getIssuerX500Principal()).thenReturn(new X500Principal(issuerDn));
+ try {
+ when(cert.getEncoded()).thenReturn(new byte[] {1, 2, 3});
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ return cert;
+ }
+
private static final class TestTokenService extends AbstractTokenService {
private Client client;
private OAuthServiceException exception;
@@ -88,6 +170,15 @@ public class AbstractTokenServiceTest {
return getClient(clientId, clientSecret, params);
}
+ void callCheckCertificateBinding(Client boundClient, TLSSessionInfo tlsSessionInfo) {
+ MessageContext mc = mock(MessageContext.class);
+ SecurityContext sc = mock(SecurityContext.class);
+ when(sc.getAuthenticationScheme()).thenReturn("");
+ when(mc.getSecurityContext()).thenReturn(sc);
+ setMessageContext(mc);
+ checkCertificateBinding(boundClient, tlsSessionInfo);
+ }
+
void setClient(Client client) {
this.client = client;
}
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java
index 0d38c34c67e..e7b170c9b15 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/services/DynamicRegistrationServiceTest.java
@@ -18,20 +18,29 @@
*/
package org.apache.cxf.rs.security.oauth2.services;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collections;
+import javax.security.auth.x500.X500Principal;
+
import javax.ws.rs.BadRequestException;
+import javax.ws.rs.core.SecurityContext;
+import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.rs.security.oauth2.common.Client;
import org.apache.cxf.rs.security.oauth2.common.OAuthError;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.security.transport.TLSSessionInfo;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class DynamicRegistrationServiceTest {
@@ -81,6 +90,95 @@ public class DynamicRegistrationServiceTest {
assertEquals(Collections.singletonList("openid"), client.getRegisteredScopes());
}
+ @Test
+ public void testRejectsTlsClientAuthWithoutTlsCertificate() {
+ TestDynamicRegistrationService service = new TestDynamicRegistrationService();
+ service.setEnforceTlsClientAuthCertificateBinding(true);
+ service.setMessageContext(createMessageContext("", null));
+
+ ClientRegistration request = new ClientRegistration();
+ request.setGrantTypes(Collections.singletonList(OAuthConstants.CLIENT_CREDENTIALS_GRANT));
+ request.setTokenEndpointAuthMethod(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS);
+ request.setProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN,
+ "CN=client,OU=Test,O=Apache,C=US");
+
+ BadRequestException ex = assertThrows(BadRequestException.class,
+ () -> service.createClient(request));
+
+ assertInvalidClientMetadata(ex);
+ }
+
+ @Test
+ public void testRejectsTlsClientAuthWhenSubjectDnDoesNotMatchCertificate() {
+ TestDynamicRegistrationService service = new TestDynamicRegistrationService();
+ service.setEnforceTlsClientAuthCertificateBinding(true);
+ X509Certificate cert = createCertificate(
+ "CN=actual,OU=Test,O=Apache,C=US",
+ "CN=issuer,OU=Test,O=Apache,C=US");
+ service.setMessageContext(createMessageContext("", cert));
+
+ ClientRegistration request = new ClientRegistration();
+ request.setGrantTypes(Collections.singletonList(OAuthConstants.CLIENT_CREDENTIALS_GRANT));
+ request.setTokenEndpointAuthMethod(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS);
+ request.setProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN,
+ "CN=expected,OU=Test,O=Apache,C=US");
+
+ BadRequestException ex = assertThrows(BadRequestException.class,
+ () -> service.createClient(request));
+
+ assertInvalidClientMetadata(ex);
+ }
+
+ @Test
+ public void testAcceptsTlsClientAuthWhenSubjectDnMatchesCertificate() {
+ TestDynamicRegistrationService service = new TestDynamicRegistrationService();
+ service.setEnforceTlsClientAuthCertificateBinding(true);
+ String subjectDn = "CN=client,OU=Test,O=Apache,C=US";
+ X509Certificate cert = createCertificate(subjectDn, "CN=issuer,OU=Test,O=Apache,C=US");
+ service.setMessageContext(createMessageContext("", cert));
+
+ ClientRegistration request = new ClientRegistration();
+ request.setGrantTypes(Collections.singletonList(OAuthConstants.CLIENT_CREDENTIALS_GRANT));
+ request.setTokenEndpointAuthMethod(OAuthConstants.TOKEN_ENDPOINT_AUTH_TLS);
+ request.setProperty(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, subjectDn);
+
+ Client client = service.createClient(request);
+ assertEquals(subjectDn, client.getProperties().get(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN));
+ assertEquals(1, client.getApplicationCertificates().size());
+ }
+
+ private static void assertInvalidClientMetadata(BadRequestException ex) {
+ assertNotNull(ex.getResponse());
+ OAuthError error = (OAuthError)ex.getResponse().getEntity();
+ assertNotNull(error);
+ assertEquals("invalid_client_metadata", error.getError());
+ }
+
+ private static MessageContext createMessageContext(String authScheme, X509Certificate cert) {
+ SecurityContext sc = mock(SecurityContext.class);
+ when(sc.getAuthenticationScheme()).thenReturn(authScheme);
+
+ MessageContext mc = mock(MessageContext.class);
+ when(mc.getSecurityContext()).thenReturn(sc);
+ if (cert != null) {
+ TLSSessionInfo tlsInfo = new TLSSessionInfo("TLS_FAKE", null, new Certificate[] {cert});
+ when(mc.get(TLSSessionInfo.class.getName())).thenReturn(tlsInfo);
+ }
+ return mc;
+ }
+
+ private static X509Certificate createCertificate(String subjectDn, String issuerDn) {
+ X509Certificate cert = mock(X509Certificate.class);
+ when(cert.getSubjectX500Principal()).thenReturn(new X500Principal(subjectDn));
+ when(cert.getIssuerX500Principal()).thenReturn(new X500Principal(issuerDn));
+ try {
+ when(cert.getEncoded()).thenReturn(new byte[] {1, 2, 3});
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ return cert;
+ }
+
private static Client createClient() {
Client client = new Client("client", "secret", true);
client.setAllowedGrantTypes(Collections.singletonList(OAuthConstants.CLIENT_CREDENTIALS_GRANT));
@@ -91,5 +189,9 @@ public class DynamicRegistrationServiceTest {
void applyClientRegistration(ClientRegistration request, Client client) {
fromClientRegistrationToClient(request, client);
}
+
+ Client createClient(ClientRegistration request) {
+ return createNewClient(request);
+ }
}
}
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/client.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/client.xml
index b90f73d9835..a0fdf5f7977 100644
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/client.xml
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/client.xml
@@ -36,6 +36,9 @@
<http:conduit name="https://localhost.*">
<http:client ConnectionTimeout="3000000" ReceiveTimeout="3000000"/>
<http:tlsClientParameters disableCNCheck="true">
+ <sec:keyManagers keyPassword="password">
+ <sec:keyStore type="JKS" password="password" resource="keys/Morpit.jks"/>
+ </sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="password" resource="keys/Truststore.jks"/>
</sec:trustManagers>
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/oidc-server-dynreg.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/oidc-server-dynreg.xml
index bc4c6b47d82..a9fd1cbc8b8 100644
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/oidc-server-dynreg.xml
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/oidc-server-dynreg.xml
@@ -56,7 +56,7 @@ under the License.
<sec:trustManagers>
<sec:keyStore type="JKS" password="password" resource="keys/Truststore.jks"/>
</sec:trustManagers>
- <sec:clientAuthentication want="false" required="false"/>
+ <sec:clientAuthentication want="true" required="false"/>
</httpj:tlsServerParameters>
<httpj:sessionSupport>true</httpj:sessionSupport>
</httpj:engine>