You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by bu...@apache.org on 2020/03/04 13:26:30 UTC

[cxf] branch master updated: cxf-systests-rs-security: add test with JwsVerifier from jwks

This is an automated email from the ASF dual-hosted git repository.

buhhunyx pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 3ba61d2  cxf-systests-rs-security: add test with JwsVerifier from jwks
3ba61d2 is described below

commit 3ba61d249544cf5b0270bc82aa0efe1e433c046e
Author: Alexey Markevich <bu...@gmail.com>
AuthorDate: Wed Mar 4 16:25:47 2020 +0300

    cxf-systests-rs-security: add test with JwsVerifier from jwks
---
 .../cxf/rs/security/jose/common/JoseUtils.java     |   6 +-
 .../security/jose/common/KeyManagementUtils.java   |  22 ++--
 .../security/oauth2/common/OAuth2TestUtils.java    |   7 +-
 .../oidc/filters/BookServerOIDCService.java        |  48 --------
 ...ters.java => JwsSignatureVerifierProvider.java} |  37 +++---
 .../security/oidc/filters/OIDCFiltersTest.java     | 126 ++++++++++++++-------
 .../systest/jaxrs/security/oidc/filters/client.xml |  45 --------
 .../security/oidc/filters/filters-jwks-server.xml  | 106 +++++++++++++++++
 .../jaxrs/security/oidc/filters/oidc-server.xml    |  11 +-
 9 files changed, 229 insertions(+), 179 deletions(-)

diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java
index 2f0bb75..99f98e6 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/JoseUtils.java
@@ -205,15 +205,15 @@ public final class JoseUtils {
         return null;
     }
 
-    public static Properties loadProperties(String propertiesLocation, Bus bus) throws Exception {
-        Properties props = new Properties();
+    public static Properties loadProperties(String propertiesLocation, Bus bus) throws IOException {
         try (InputStream is = getResourceStream(propertiesLocation, bus)) {
             if (is == null) {
                 throw new JoseException("The properties file " + propertiesLocation + " could not be read");
             }
+            Properties props = new Properties();
             props.load(is);
+            return props;
         }
-        return props;
     }
 
     //
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java
index d383bb2..46dc1c3 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/common/KeyManagementUtils.java
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.rs.security.jose.common;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -399,13 +400,13 @@ public final class KeyManagementUtils {
             }
             return null;
         }
-        Properties props = null;
+        final Properties props;
         String propLoc =
             (String)MessageUtils.getContextualProperty(m, storeProp1, storeProp2);
         if (propLoc != null) {
             try {
                 props = JoseUtils.loadProperties(propLoc, m.getExchange().getBus());
-            } catch (Exception ex) {
+            } catch (IOException ex) {
                 LOG.warning("Properties resource is not identified");
                 throw new JoseException(ex);
             }
@@ -431,15 +432,18 @@ public final class KeyManagementUtils {
                 if (keyPassword != null) {
                     props.setProperty(JoseConstants.RSSEC_KEY_PSWD, keyPassword);
                 }
+                String signatureAlgorithm = (String)m.getContextualProperty(JoseConstants.RSSEC_SIGNATURE_ALGORITHM);
+                if (signatureAlgorithm != null) {
+                    props.setProperty(JoseConstants.RSSEC_SIGNATURE_ALGORITHM, signatureAlgorithm);
+                }
+            } else {
+                if (required) {
+                    LOG.warning("Properties resource is not identified");
+                    throw new JoseException("Properties resource is not identified");
+                }
+                props = new Properties();
             }
         }
-        if (props == null) {
-            if (required) {
-                LOG.warning("Properties resource is not identified");
-                throw new JoseException("Properties resource is not identified");
-            }
-            props = new Properties();
-        }
         return props;
     }
     public static PrivateKey loadPrivateKey(Message m, Properties props,
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java
index a1d0e72..1c7edee 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/OAuth2TestUtils.java
@@ -22,7 +22,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.security.GeneralSecurityException;
 import java.security.KeyStore;
-import java.time.Instant;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -53,6 +52,7 @@ import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData;
 import org.apache.cxf.rs.security.oauth2.grants.code.AuthorizationCodeGrant;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider;
 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.transport.http.HTTPConduit;
 import org.apache.cxf.transport.http.HTTPConduitConfigurer;
@@ -243,10 +243,9 @@ public final class OAuth2TestUtils {
         if (issuer != null) {
             claims.setIssuer(issuer);
         }
-        Instant now = Instant.now();
-        claims.setIssuedAt(now.getEpochSecond());
+        claims.setIssuedAt(OAuthUtils.getIssuedAt());
         if (expiry) {
-            claims.setExpiryTime(now.plusSeconds(60L).getEpochSecond());
+            claims.setExpiryTime(claims.getIssuedAt() + 60L);
         }
         if (audience != null) {
             claims.setAudiences(Collections.singletonList(audience));
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/BookServerOIDCService.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/BookServerOIDCService.java
deleted file mode 100644
index 0ff5330..0000000
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/BookServerOIDCService.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.cxf.systest.jaxrs.security.oidc.filters;
-
-import java.net.URL;
-
-import org.apache.cxf.Bus;
-import org.apache.cxf.BusFactory;
-import org.apache.cxf.bus.spring.SpringBusFactory;
-import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
-import org.apache.cxf.testutil.common.TestUtil;
-
-public class BookServerOIDCService extends AbstractBusTestServerBase {
-    public static final String PORT = TestUtil.getPortNumber("jaxrs-filters-oidc-service");
-    private static final URL SERVER_CONFIG_FILE =
-        BookServerOIDCService.class.getResource("oidc-server.xml");
-
-    protected void run() {
-        SpringBusFactory bf = new SpringBusFactory();
-        Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
-        BusFactory.setDefaultBus(springBus);
-        setBus(springBus);
-
-        try {
-            new BookServerOIDCService();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-}
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/BookServerOIDCFilters.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/JwsSignatureVerifierProvider.java
similarity index 50%
rename from systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/BookServerOIDCFilters.java
rename to systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/JwsSignatureVerifierProvider.java
index a185093..b0b5e9b 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/BookServerOIDCFilters.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/JwsSignatureVerifierProvider.java
@@ -16,33 +16,26 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.cxf.systest.jaxrs.security.oidc.filters;
 
-import java.net.URL;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKeys;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+import org.apache.cxf.rs.security.jose.jws.JwsUtils;
 
-import org.apache.cxf.Bus;
-import org.apache.cxf.BusFactory;
-import org.apache.cxf.bus.spring.SpringBusFactory;
-import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
-import org.apache.cxf.testutil.common.TestUtil;
+public class JwsSignatureVerifierProvider {
 
-public class BookServerOIDCFilters extends AbstractBusTestServerBase {
-    public static final String PORT = TestUtil.getPortNumber("jaxrs-oidc-filters");
-    private static final URL SERVER_CONFIG_FILE =
-        BookServerOIDCFilters.class.getResource("filters-server.xml");
+    private WebClient jwksClient;
 
-    protected void run() {
-        SpringBusFactory bf = new SpringBusFactory();
-        Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
-        BusFactory.setDefaultBus(springBus);
-        setBus(springBus);
+    public void setJwksClient(WebClient jwksClient) {
+        this.jwksClient = jwksClient;
+    }
 
-        try {
-            new BookServerOIDCFilters();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+    public JwsSignatureVerifier getJwsSignatureVerifier() {
+        for (JsonWebKey jwk : jwksClient.get(JsonWebKeys.class).getKeys()) {
+            return JwsUtils.getSignatureVerifier(jwk);
         }
+        return null;
     }
-
-}
+}
\ No newline at end of file
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/OIDCFiltersTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/OIDCFiltersTest.java
index a9342e4..3312a81 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/OIDCFiltersTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oidc/filters/OIDCFiltersTest.java
@@ -18,16 +18,26 @@
  */
 package org.apache.cxf.systest.jaxrs.security.oidc.filters;
 
-import java.net.URL;
+import java.net.URI;
+import java.util.Collections;
 
-import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 
+import org.apache.cxf.bus.spring.SpringBusFactory;
 import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.oauth2.client.AccessTokenClientFilter;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
 import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData;
+import org.apache.cxf.rs.security.oidc.utils.OidcUtils;
 import org.apache.cxf.systest.jaxrs.security.Book;
 import org.apache.cxf.systest.jaxrs.security.oauth2.common.OAuth2TestUtils;
+import org.apache.cxf.systest.jaxrs.security.oidc.SpringBusTestServer;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.testutil.common.TestUtil;
+import org.apache.cxf.transport.http.HTTPConduitConfigurer;
 
 import org.junit.BeforeClass;
 
@@ -40,44 +50,49 @@ import static org.junit.Assert.assertTrue;
  */
 public class OIDCFiltersTest extends AbstractBusClientServerTestBase {
 
-    public static final String PORT = BookServerOIDCFilters.PORT;
-    public static final String OIDC_PORT = BookServerOIDCService.PORT;
+    private static final String PORT = BookServerOIDCFilters.PORT;
+    private static final String OIDC_PORT = BookServerOIDCService.PORT;
+    private static final SpringBusTestServer BOOK_JWK_SERVER = new SpringBusTestServer("filters-jwks-server") {
+    };
 
     @BeforeClass
     public static void startServers() throws Exception {
-        assertTrue("server did not launch correctly",
-                   launchServer(BookServerOIDCFilters.class, true));
-        assertTrue("server did not launch correctly",
-                   launchServer(BookServerOIDCService.class, true));
+        createStaticBus().setExtension(OAuth2TestUtils.clientHTTPConduitConfigurer(), HTTPConduitConfigurer.class);
+
+        assertTrue("server did not launch correctly", launchServer(BookServerOIDCFilters.class));
+        assertTrue("server did not launch correctly", launchServer(BookServerOIDCService.class));
+        assertTrue("server did not launch correctly", launchServer(BOOK_JWK_SERVER));
     }
 
     @org.junit.Test
     public void testClientCodeRequestFilter() throws Exception {
-        URL busFile = OIDCFiltersTest.class.getResource("client.xml");
-
         // Make an invocation + get back the redirection to the OIDC IdP
         String address = "https://localhost:" + PORT + "/secured/bookstore/books";
-        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(), busFile.toString());
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(), null);
 
         WebClient.getConfig(client).getRequestContext().put(
                 org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
 
         Response response = client.get();
 
-        String location = response.getHeaderString("Location");
+        URI location = response.getLocation();
         // Now make an invocation on the OIDC IdP using another WebClient instance
 
-        WebClient idpClient = WebClient.create(location, OAuth2TestUtils.setupProviders(),
-                                               "bob", "security", busFile.toString());
+        WebClient idpClient = WebClient.create(location.toString(), OAuth2TestUtils.setupProviders(),
+                                               "bob", "security", null)
+            .type("application/json").accept("application/json");
         // Save the Cookie for the second request...
         WebClient.getConfig(idpClient).getRequestContext().put(
             org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
 
+        // Make initial authorization request
+        final OAuthAuthorizationData authzData = idpClient.get(OAuthAuthorizationData.class);
+
         // Get Authorization Code + State
-        String authzCodeLocation = makeAuthorizationCodeInvocation(idpClient);
-        String state = getSubstring(authzCodeLocation, "state");
+        String authzCodeLocation = OAuth2TestUtils.getLocation(idpClient, authzData, null);
+        String state = OAuth2TestUtils.getSubstring(authzCodeLocation, "state");
         assertNotNull(state);
-        String code = getSubstring(authzCodeLocation, "code");
+        String code = OAuth2TestUtils.getSubstring(authzCodeLocation, "code");
         assertNotNull(code);
 
         // Add Referer
@@ -96,39 +111,64 @@ public class OIDCFiltersTest extends AbstractBusClientServerTestBase {
         assertEquals(returnedBook.getId(), 123L);
     }
 
-    private String makeAuthorizationCodeInvocation(WebClient client) {
-        // Make initial authorization request
-        client.type("application/json").accept("application/json");
-        Response response = client.get();
+    @org.junit.Test
+    public void testJwsVerifierRequestFilter() throws Exception {
+        final String request = "echo";
+        final Response response = WebClient.create(
+            "https://localhost:" + BOOK_JWK_SERVER.getPort() + "/secured/bookstore/books")
+            .type(MediaType.TEXT_PLAIN).accept(MediaType.TEXT_PLAIN)
+            .post(request);
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+
+        String address = "https://localhost:" + OIDC_PORT + "/services/";
+        WebClient idpClient = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "bob", "security", null);
 
-        OAuthAuthorizationData authzData = response.readEntity(OAuthAuthorizationData.class);
+        // Save the Cookie for the second request...
+        WebClient.getConfig(idpClient).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
 
-        // Now call "decision" to get the authorization code grant
-        client.path("decision");
-        client.type("application/x-www-form-urlencoded");
+        // Get Authorization Code
+        String code = OAuth2TestUtils.getAuthorizationCode(idpClient, OidcUtils.getOpenIdScope());
+        assertNotNull(code);
 
-        Form form = new Form();
-        form.param("session_authenticity_token", authzData.getAuthenticityToken());
-        form.param("client_id", authzData.getClientId());
-        form.param("redirect_uri", authzData.getRedirectUri());
-        if (authzData.getProposedScope() != null) {
-            form.param("scope", authzData.getProposedScope());
-        }
-        form.param("state", authzData.getState());
-        form.param("oauthDecision", "allow");
+        // Now get the access token
+        idpClient = WebClient.create(address, "consumer-id", "this-is-a-secret", null);
+
+        ClientAccessToken accessToken =
+            OAuth2TestUtils.getAccessTokenWithAuthorizationCode(idpClient, code);
 
-        response = client.post(form);
-        return response.getHeaderString("Location");
+        // Make an invocation
+        final AccessTokenClientFilter accessTokenClientFilter = new AccessTokenClientFilter();
+        accessTokenClientFilter.setAccessToken(accessToken.getTokenKey());
+        final String echo = WebClient.create(
+            "https://localhost:" + BOOK_JWK_SERVER.getPort() + "/secured/bookstore/books",
+            Collections.singletonList(accessTokenClientFilter))
+            .type(MediaType.TEXT_PLAIN).accept(MediaType.TEXT_PLAIN)
+            .post(request, String.class);
+
+        assertEquals(request, echo);
     }
 
-    private String getSubstring(String parentString, String substringName) {
-        String foundString =
-            parentString.substring(parentString.indexOf(substringName + "=") + (substringName + "=").length());
-        int ampersandIndex = foundString.indexOf('&');
-        if (ampersandIndex < 1) {
-            ampersandIndex = foundString.length();
+    //
+    // Server implementations
+    //
+    public static class BookServerOIDCFilters extends AbstractBusTestServerBase {
+        public static final String PORT = TestUtil.getPortNumber("jaxrs-oidc-filters");
+
+        @Override
+        protected void run() {
+            setBus(new SpringBusFactory().createBus(getClass().getResource("filters-server.xml")));
+        }
+    }
+
+    public static class BookServerOIDCService extends AbstractBusTestServerBase {
+        public static final String PORT = TestUtil.getPortNumber("jaxrs-filters-oidc-service");
+
+        @Override
+        protected void run() {
+            setBus(new SpringBusFactory().createBus(getClass().getResource("oidc-server.xml")));
         }
-        return foundString.substring(0, ampersandIndex);
     }
 
 }
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/client.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/client.xml
deleted file mode 100644
index fe6c5a5..0000000
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/client.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you 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.
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:http="http://cxf.apache.org/transports/http/configuration"
-    xmlns:jaxws="http://cxf.apache.org/jaxws"
-    xmlns:cxf="http://cxf.apache.org/core"
-    xmlns:p="http://cxf.apache.org/policy"
-    xmlns:sec="http://cxf.apache.org/configuration/security"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache [...]
-    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
-    <cxf:bus>
-        <cxf:features>
-            <cxf:logging/>
-        </cxf:features>
-    </cxf:bus>
-    <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>
-        </http:tlsClientParameters>
-    </http:conduit>
-</beans>
\ No newline at end of file
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/filters-jwks-server.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/filters-jwks-server.xml
new file mode 100644
index 0000000..9c22e42
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/filters-jwks-server.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans" 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xmlns:http="http://cxf.apache.org/transports/http/configuration" 
+    xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" 
+    xmlns:sec="http://cxf.apache.org/configuration/security" 
+    xmlns:cxf="http://cxf.apache.org/core" 
+    xmlns:jaxrs="http://cxf.apache.org/jaxrs" 
+    xmlns:jaxrs-client="http://cxf.apache.org/jaxrs-client"
+    xsi:schemaLocation="http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
+             http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
+             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+             http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
+             http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd 
+             http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+             http://cxf.apache.org/jaxrs-client http://cxf.apache.org/schemas/jaxrs-client.xsd">
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+    </cxf:bus>
+
+   <jaxrs-client:client id="jwksClient" serviceClass="org.apache.cxf.jaxrs.client.WebClient"
+        address="https://localhost:${testutil.ports.jaxrs-filters-oidc-service}/services/keys"
+        username="bob" password="security" >
+        <jaxrs-client:headers>
+           <entry key="Accept" value="application/json"/>
+        </jaxrs-client:headers>
+        <jaxrs-client:providers>
+            <bean class="org.apache.cxf.rs.security.jose.jaxrs.JsonWebKeysProvider" />
+        </jaxrs-client:providers>
+   </jaxrs-client:client>
+
+    <bean id="jwsSignatureVerifierProvider"
+        class="org.apache.cxf.systest.jaxrs.security.oidc.filters.JwsSignatureVerifierProvider" >
+        <property name="jwksClient" ref="jwksClient"/>
+    </bean>
+
+    <bean id="jwsVerifier"
+        factory-bean="jwsSignatureVerifierProvider" 
+        factory-method="getJwsSignatureVerifier" >
+    </bean>
+
+   <bean id="jwtAccessTokenValidator" class="org.apache.cxf.rs.security.oauth2.filters.JwtAccessTokenValidator">
+       <property name="jwsVerifier" ref="jwsVerifier"/>
+   </bean>
+
+   <bean id="authFilter" class="org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter">
+       <property name="tokenValidator" ref="jwtAccessTokenValidator"/>
+   </bean>
+
+   <jaxrs:server
+       depends-on="tls-config" 
+       address="https://localhost:${testutil.ports.filters-jwks-server}/secured">
+       <jaxrs:serviceBeans>
+           <bean class="org.apache.cxf.systest.jaxrs.security.jose.BookStore"/>
+       </jaxrs:serviceBeans>
+       <jaxrs:providers>
+           <ref bean="authFilter"/>
+       </jaxrs:providers>
+   </jaxrs:server>
+
+    <httpj:engine-factory id="tls-config">
+        <httpj:engine port="${testutil.ports.filters-jwks-server}">
+            <httpj:tlsServerParameters>
+                <sec:keyManagers keyPassword="password">
+                    <sec:keyStore type="JKS" password="password" resource="keys/Bethal.jks"/>
+                </sec:keyManagers>
+                <sec:trustManagers>
+                    <sec:keyStore type="JKS" password="password" resource="keys/Truststore.jks"/>
+                </sec:trustManagers>
+                <sec:clientAuthentication want="true" required="true"/>
+            </httpj:tlsServerParameters>
+            <httpj:sessionSupport>true</httpj:sessionSupport>
+        </httpj:engine>
+    </httpj:engine-factory>
+
+   <http:conduit name="https://localhost.*">
+        <http:client ConnectionTimeout="3000000" ReceiveTimeout="3000000"/>
+        <http:tlsClientParameters disableCNCheck="true">
+            <sec:trustManagers>
+                <sec:keyStore type="JKS" password="password" resource="keys/Truststore.jks"/>
+            </sec:trustManagers>
+        </http:tlsClientParameters>
+    </http:conduit>
+
+</beans>
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/oidc-server.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/oidc-server.xml
index 054ee00..4ddfe97 100644
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/oidc-server.xml
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oidc/filters/oidc-server.xml
@@ -61,11 +61,12 @@ under the License.
             <httpj:sessionSupport>true</httpj:sessionSupport>
         </httpj:engine>
     </httpj:engine-factory>
-    
-   <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JCacheOAuthDataProviderImpl">
-       <constructor-arg><value>${testutil.ports.jaxrs-oidc-filters}</value></constructor-arg>
-   </bean>
-   
+
+    <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JCacheOAuthDataProviderImpl">
+        <constructor-arg><value>${testutil.ports.jaxrs-oidc-filters}</value></constructor-arg>
+        <property name="useJwtFormatForAccessTokens" value="true"/>
+    </bean>
+
    <bean id="authorizationService" class="org.apache.cxf.rs.security.oidc.idp.OidcAuthorizationCodeService">
       <property name="dataProvider" ref="oauthProvider"/>
    </bean>