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 2019/09/16 12:20:21 UTC

[cxf] branch master updated (3c4147f -> f54062e)

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

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


    from 3c4147f  Update to Spring Boot 2.1.8.RELEASE
     new 337609d  Make sure that the OAuth authenticate principal name matches the client_id (if specified)
     new 39e32c4  Fixing OAuth scope test
     new 2e7278c  Change OAuthUtils.generateRandomTokenKey to use 32 bytes by default
     new 9933ba2  Adding a couple more OAuth system tests
     new 0295f5c  Adding a test to show how to configure TLS to get the WSDL programatically
     new 28d2656  Adding OAuth token revocation tests
     new faeb1a0  Updating http client
     new f3e2a52  Updating Netty
     new 4c5cf7e  Adding OAuth token introspection systests + requiring a client register a redirect URI for authz code + implicit grants
     new f54062e  Generate a default client secret of length 32 for the dynamic reg service

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 parent/pom.xml                                     |   4 +-
 .../client/MemoryClientCodeStateManager.java       |   2 +-
 .../oauth2/services/AbstractTokenService.java      |  25 +-
 .../services/DynamicRegistrationService.java       |  45 +++-
 .../services/RedirectionBasedGrantService.java     |   3 +-
 .../cxf/rs/security/oauth2/utils/OAuthUtils.java   |   2 +-
 .../oauth2/common/CallbackHandlerImpl.java         |  16 ++
 .../grants/AuthorizationGrantNegativeTest.java     | 209 +++++++++++++++-
 .../oauth2/grants/AuthorizationGrantTest.java      |   4 +-
 .../oauth2/grants/DynamicRegistrationTest.java     | 222 +++++++++++++++++
 .../oauth2/grants/RevocationServiceTest.java       | 266 +++++++++++++++++++++
 ...e-jwt.xml => dynamic-reg-server-jcache-jwt.xml} |  15 +-
 ...er-jcache.xml => dynamic-reg-server-jcache.xml} |  15 +-
 ...n-server-jpa.xml => dynamic-reg-server-jpa.xml} |  15 +-
 ...ersist.xml => revocation-server-jcache-jwt.xml} |  12 +-
 ...ver-jcache.xml => revocation-server-jcache.xml} |  10 +-
 ...on-server-jpa.xml => revocation-server-jpa.xml} |  10 +-
 .../cxf/systest/ws/ut/UsernameTokenTest.java       |  55 +++++
 18 files changed, 875 insertions(+), 55 deletions(-)
 create mode 100644 systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/DynamicRegistrationTest.java
 create mode 100644 systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java
 copy systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/{introspection-server-jcache-jwt.xml => dynamic-reg-server-jcache-jwt.xml} (90%)
 copy systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/{introspection-server-jcache.xml => dynamic-reg-server-jcache.xml} (89%)
 copy systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/{introspection-server-jpa.xml => dynamic-reg-server-jpa.xml} (90%)
 copy systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/{introspection-server-jcache-jwt-non-persist.xml => revocation-server-jcache-jwt.xml} (93%)
 copy systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/{introspection-server-jcache.xml => revocation-server-jcache.xml} (92%)
 copy systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/{introspection-server-jpa.xml => revocation-server-jpa.xml} (93%)


[cxf] 04/10: Adding a couple more OAuth system tests

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9933ba2c19e1341d291eb4aa48fb24a19533261f
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Sep 11 19:28:22 2019 +0100

    Adding a couple more OAuth system tests
---
 .../grants/AuthorizationGrantNegativeTest.java     | 82 ++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
index 5b70662..1cd5e51 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
@@ -41,6 +41,7 @@ import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
 import org.apache.cxf.rs.security.jose.jws.JwsUtils;
 import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
 import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData;
 import org.apache.cxf.systest.jaxrs.security.SecurityTestUtil;
 import org.apache.cxf.systest.jaxrs.security.oauth2.common.OAuth2TestUtils;
 import org.apache.cxf.systest.jaxrs.security.oauth2.common.SamlCallbackHandler;
@@ -58,6 +59,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized.Parameters;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -168,6 +170,46 @@ public class AuthorizationGrantNegativeTest extends AbstractBusClientServerTestB
         assertEquals(400, response.getStatus());
     }
 
+    // The redirect URI if in the authz request, must be in the token request and must match
+    @org.junit.Test
+    public void testNonMatchingRedirectURI() throws Exception {
+        URL busFile = AuthorizationGrantTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        // Get Authorization Code
+        String code = OAuth2TestUtils.getAuthorizationCode(client);
+        assertNotNull(code);
+
+        // Now get the access token
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        client.type("application/x-www-form-urlencoded").accept("application/json");
+        client.path("token");
+
+        Form form = new Form();
+        form.param("grant_type", "authorization_code");
+        form.param("code", code);
+        form.param("client_id", "consumer-id");
+        form.param("redirect_uri", "http://www.bad.blah.apache.org");
+        Response response = client.post(form);
+        try {
+            response.readEntity(ClientAccessToken.class);
+            fail("Failure expected on not sending the correct redirect URI");
+        } catch (ResponseProcessingException ex) {
+            //expected
+        }
+    }
+
     @org.junit.Test
     public void testResponseType() throws Exception {
         URL busFile = AuthorizationGrantTest.class.getResource("client.xml");
@@ -673,6 +715,46 @@ public class AuthorizationGrantNegativeTest extends AbstractBusClientServerTestB
         }
     }
 
+    // We shouldn't be able to get a refresh token using the implicit grant
+    @org.junit.Test
+    public void testRefreshImplicitGrant() throws Exception {
+        URL busFile = AuthorizationGrantTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        // Get Access Token
+        client.type("application/json").accept("application/json");
+        client.query("client_id", "consumer-id");
+        client.query("redirect_uri", "http://www.blah.apache.org");
+        client.query("response_type", "token");
+        client.path("authorize-implicit/");
+        Response response = client.get();
+
+        OAuthAuthorizationData authzData = response.readEntity(OAuthAuthorizationData.class);
+
+        // Now call "decision" to get the access token
+        client.path("decision");
+        client.type("application/x-www-form-urlencoded");
+
+        Form form = new Form();
+        form.param("session_authenticity_token", authzData.getAuthenticityToken());
+        form.param("client_id", authzData.getClientId());
+        form.param("redirect_uri", authzData.getRedirectUri());
+        form.param("oauthDecision", "allow");
+
+        response = client.post(form);
+
+        String location = response.getHeaderString("Location");
+        String accessToken = OAuth2TestUtils.getSubstring(location, "access_token");
+        assertNotNull(accessToken);
+        assertFalse(location.contains("refresh"));
+    }
+
     //
     // SAML Authorization grants
     //


[cxf] 05/10: Adding a test to show how to configure TLS to get the WSDL programatically

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 0295f5cb98fd48bd19f68aea49acecb111a614f6
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Sep 11 23:07:18 2019 +0100

    Adding a test to show how to configure TLS to get the WSDL programatically
---
 .../cxf/systest/ws/ut/UsernameTokenTest.java       | 55 ++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
index b7b16de..1028beb 100644
--- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
+++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/ut/UsernameTokenTest.java
@@ -46,6 +46,7 @@ import org.apache.cxf.systest.ws.common.SecurityTestUtil;
 import org.apache.cxf.systest.ws.common.TestParam;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
 import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.HTTPConduitConfigurer;
 import org.apache.cxf.ws.policy.WSPolicyFeature;
 import org.apache.cxf.ws.security.SecurityConstants;
 import org.apache.wss4j.common.ext.WSSecurityException;
@@ -257,6 +258,60 @@ public class UsernameTokenTest extends AbstractBusClientServerTestBase {
     }
 
     @org.junit.Test
+    public void testPlaintextWSDLOverHTTPSViaCode() throws Exception {
+
+        TrustManagerFactory tmf =
+            TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        final KeyStore ts = KeyStore.getInstance("JKS");
+        try (InputStream trustStore =
+            ClassLoaderUtils.getResourceAsStream("keys/Truststore.jks", UsernameTokenTest.class)) {
+            ts.load(trustStore, "password".toCharArray());
+        }
+        tmf.init(ts);
+
+        TLSClientParameters tlsParams = new TLSClientParameters();
+        tlsParams.setTrustManagers(tmf.getTrustManagers());
+        tlsParams.setDisableCNCheck(true);
+
+        HTTPConduitConfigurer myHttpConduitConfig = new HTTPConduitConfigurer() {
+            public void configure(String name, String address, HTTPConduit c) {
+                if ("{http://cxf.apache.org}TransportURIResolver.http-conduit".equals(name)) {
+                    c.setTlsClientParameters(tlsParams);
+                }
+            }
+        };
+
+        BusFactory busFactory = BusFactory.newInstance();
+        bus = busFactory.createBus();
+        bus.setExtension(myHttpConduitConfig, HTTPConduitConfigurer.class);
+        BusFactory.setThreadDefaultBus(bus);
+
+        URL wsdl = new URL("https://localhost:" + PORT + "/DoubleItUTPlaintext?wsdl");
+        Service service = Service.create(wsdl, SERVICE_QNAME);
+        QName portQName = new QName(NAMESPACE, "DoubleItPlaintextPort");
+        DoubleItPortType utPort =
+                service.getPort(portQName, DoubleItPortType.class);
+        updateAddressPort(utPort, test.getPort());
+
+        if (test.isStreaming()) {
+            SecurityTestUtil.enableStreaming(utPort);
+        }
+
+        ((BindingProvider)utPort).getRequestContext().put(SecurityConstants.USERNAME, "Alice");
+
+        ((BindingProvider)utPort).getRequestContext().put(SecurityConstants.CALLBACK_HANDLER,
+                                                          "org.apache.cxf.systest.ws.common.UTPasswordCallback");
+
+        Client client = ClientProxy.getClient(utPort);
+        HTTPConduit http = (HTTPConduit) client.getConduit();
+        http.setTlsClientParameters(tlsParams);
+
+        assertEquals(50, utPort.doubleIt(25));
+
+        ((java.io.Closeable)utPort).close();
+    }
+
+    @org.junit.Test
     public void testPlaintextCreated() throws Exception {
 
         SpringBusFactory bf = new SpringBusFactory();


[cxf] 07/10: Updating http client

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit faeb1a0d83104062eb60dc095d9b80663e307249
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Mon Sep 16 10:09:12 2019 +0100

    Updating http client
---
 parent/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/parent/pom.xml b/parent/pom.xml
index d44f2e1..d335785 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -127,7 +127,7 @@
         <cxf.hsqldb.version>2.4.1</cxf.hsqldb.version>
         <cxf.httpcomponents.asyncclient.version.range>[4.0,4.2)</cxf.httpcomponents.asyncclient.version.range>
         <cxf.httpcomponents.asyncclient.version>4.1.4</cxf.httpcomponents.asyncclient.version>
-        <cxf.httpcomponents.client.version>4.5.9</cxf.httpcomponents.client.version>
+        <cxf.httpcomponents.client.version>4.5.10</cxf.httpcomponents.client.version>
         <cxf.httpcomponents.core.version.range>[4.3,4.5.0)</cxf.httpcomponents.core.version.range>
         <cxf.httpcomponents.core.version>4.4.12</cxf.httpcomponents.core.version>
         <cxf.jackson.version>2.9.9</cxf.jackson.version>


[cxf] 03/10: Change OAuthUtils.generateRandomTokenKey to use 32 bytes by default

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 2e7278c35f3fadc94e03dcf8c9b10a5f46053fce
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Sep 11 18:32:40 2019 +0100

    Change OAuthUtils.generateRandomTokenKey to use 32 bytes by default
---
 .../cxf/rs/security/oauth2/client/MemoryClientCodeStateManager.java     | 2 +-
 .../main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateManager.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateManager.java
index 668910f..78ebcaa 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateManager.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/client/MemoryClientCodeStateManager.java
@@ -44,7 +44,7 @@ public class MemoryClientCodeStateManager implements ClientCodeStateManager {
         MultivaluedMap<String, String> redirectMap = new MetadataMap<>();
 
         if (generateNonce) {
-            String nonceParam = MessageDigestUtils.generate(CryptoUtils.generateSecureRandomBytes(16));
+            String nonceParam = MessageDigestUtils.generate(CryptoUtils.generateSecureRandomBytes(32));
             requestState.putSingle(OAuthConstants.NONCE, nonceParam);
             redirectMap.putSingle(OAuthConstants.NONCE, nonceParam);
         }
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
index 356f599..f975a31 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
@@ -271,7 +271,7 @@ public final class OAuthUtils {
     }
 
     public static String generateRandomTokenKey() throws OAuthServiceException {
-        return generateRandomTokenKey(16);
+        return generateRandomTokenKey(32);
     }
     public static String generateRandomTokenKey(int byteSize) {
         if (byteSize < 16) {


[cxf] 10/10: Generate a default client secret of length 32 for the dynamic reg service

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f54062eb331fcf35d9f3a840f532417fccbb2673
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Mon Sep 16 13:16:31 2019 +0100

    Generate a default client secret of length 32 for the dynamic reg service
---
 .../cxf/rs/security/oauth2/services/DynamicRegistrationService.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 12155d9..439ce51 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
@@ -382,7 +382,7 @@ public class DynamicRegistrationService {
                     Collections.singleton(OAuthConstants.BEARER_AUTHORIZATION_SCHEME))[1];
     }
     protected int getClientSecretSizeInBytes(ClientRegistration request) {
-        return 16;
+        return 32;
     }
 
     @Context


[cxf] 08/10: Updating Netty

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f3e2a52faec1210b1a45eaa36e3812ca03a4969d
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Mon Sep 16 11:03:07 2019 +0100

    Updating Netty
---
 parent/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/parent/pom.xml b/parent/pom.xml
index d335785..291623d 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -169,7 +169,7 @@
         <cxf.msv.version>2013.6.1</cxf.msv.version>
         <cxf.neethi.version>3.1.1</cxf.neethi.version>
         <cxf.netty.version.range>[4,5)</cxf.netty.version.range>
-        <cxf.netty.version>4.1.39.Final</cxf.netty.version>
+        <cxf.netty.version>4.1.41.Final</cxf.netty.version>
         <cxf.oauth.version>20100527</cxf.oauth.version>
         <cxf.olingo.version>2.0.11</cxf.olingo.version>
         <cxf.openjpa.version>3.1.0</cxf.openjpa.version>


[cxf] 01/10: Make sure that the OAuth authenticate principal name matches the client_id (if specified)

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 337609d81a9f53e7680cb79d9ab733a79f4cd769
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Sep 11 00:43:48 2019 +0100

    Make sure that the OAuth authenticate principal name matches the client_id (if specified)
---
 .../oauth2/services/AbstractTokenService.java      |  25 +++--
 .../grants/AuthorizationGrantNegativeTest.java     | 123 +++++++++++++++++++++
 .../oauth2/grants/AuthorizationGrantTest.java      |   4 +-
 3 files changed, 138 insertions(+), 14 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 a5e82a2..8e32cca 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
@@ -56,8 +56,8 @@ public class AbstractTokenService extends AbstractOAuthService {
         SecurityContext sc = getMessageContext().getSecurityContext();
         Principal principal = sc.getUserPrincipal();
 
+        String clientId = retrieveClientId(params);
         if (principal == null) {
-            String clientId = retrieveClientId(params);
             if (clientId != null) {
                 String clientSecret = params.getFirst(OAuthConstants.CLIENT_SECRET);
                 if (clientSecret != null) {
@@ -77,11 +77,12 @@ public class AbstractTokenService extends AbstractOAuthService {
                 }
             }
         } else {
-            String clientId = retrieveClientId(params);
             if (clientId != null) {
-                if (clientId.equals(principal.getName())) {
-                    client = (Client)getMessageContext().get(Client.class.getName());
+                if (!clientId.equals(principal.getName())) {
+                    reportInvalidClient();
                 }
+
+                client = (Client)getMessageContext().get(Client.class.getName());
                 if (client == null) {
                     client = getClient(clientId, params);
                 }
@@ -108,7 +109,7 @@ public class AbstractTokenService extends AbstractOAuthService {
             reportInvalidClient(new OAuthError(OAuthConstants.UNAUTHORIZED_CLIENT));
         }
     }
-    
+
     protected String retrieveClientId(MultivaluedMap<String, String> params) {
         String clientId = params.getFirst(OAuthConstants.CLIENT_ID);
         if (clientId == null) {
@@ -164,14 +165,14 @@ public class AbstractTokenService extends AbstractOAuthService {
             reportInvalidClient();
         }
         X509Certificate cert = OAuthUtils.getRootTLSCertificate(tlsSessionInfo);
-        
-        if (subjectDn != null 
+
+        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 
+        if (issuerDn != null
             && !issuerDn.equals(OAuthUtils.getIssuerDnFromTLSCertificates(cert))) {
             LOG.warning("Client \"" + client.getClientId() + "\" can not be bound to the TLS certificate");
             reportInvalidClient();
@@ -187,7 +188,7 @@ public class AbstractTokenService extends AbstractOAuthService {
         return (TLSSessionInfo)getMessageContext().get(TLSSessionInfo.class.getName());
     }
 
-    
+
     protected Client getClientFromTLSCertificates(SecurityContext sc,
                                                   TLSSessionInfo tlsSessionInfo,
                                                   MultivaluedMap<String, String> params) {
@@ -206,11 +207,11 @@ public class AbstractTokenService extends AbstractOAuthService {
         }
         return client;
     }
-    
+
     protected void compareTlsCertificates(TLSSessionInfo tlsInfo,
                                           List<String> base64EncodedCerts) {
         if (!OAuthUtils.compareTlsCertificates(tlsInfo, base64EncodedCerts)) {
-            reportInvalidClient();    
+            reportInvalidClient();
         }
     }
 
@@ -244,7 +245,7 @@ public class AbstractTokenService extends AbstractOAuthService {
     protected Client getClient(String clientId, MultivaluedMap<String, String> params) {
         return getClient(clientId, params.getFirst(OAuthConstants.CLIENT_SECRET), params);
     }
-    
+
     protected Client getClient(String clientId, String clientSecret, MultivaluedMap<String, String> params) {
         if (clientId == null) {
             reportInvalidRequestError("Client ID is null");
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
index f854e09..8bbb662 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
@@ -550,6 +550,129 @@ public class AuthorizationGrantNegativeTest extends AbstractBusClientServerTestB
         }
     }
 
+    // Here we are sending a different client Id in both the authz + token requests
+    @org.junit.Test
+    public void testNonMatchingClientId() throws Exception {
+        URL busFile = AuthorizationGrantTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        // Get Authorization Code
+        String code = OAuth2TestUtils.getAuthorizationCode(client);
+        assertNotNull(code);
+
+        // Now get the access token using a different client id
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id-aud", "this-is-a-secret", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        client.type("application/x-www-form-urlencoded").accept("application/json");
+        client.path("token");
+
+        Form form = new Form();
+        form.param("grant_type", "authorization_code");
+        form.param("code", code);
+        form.param("client_id", "consumer-id-aud");
+
+        // Now try to get a token
+        Response response = client.post(form);
+        try {
+            response.readEntity(ClientAccessToken.class);
+            fail("Failure expected on trying to get a token");
+        } catch (ResponseProcessingException ex) {
+            //expected
+        }
+    }
+
+    // Here we are sending a different client Id in both the authz + token requests
+    @org.junit.Test
+    public void testNonMatchingClientIdBasicAuth() throws Exception {
+        URL busFile = AuthorizationGrantTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        // Get Authorization Code
+        String code = OAuth2TestUtils.getAuthorizationCode(client);
+        assertNotNull(code);
+
+        // Now get the access token using a different client id
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id-aud", "this-is-a-secret", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        client.type("application/x-www-form-urlencoded").accept("application/json");
+        client.path("token");
+
+        Form form = new Form();
+        form.param("grant_type", "authorization_code");
+        form.param("code", code);
+
+        // Now try to get a token
+        Response response = client.post(form);
+        try {
+            response.readEntity(ClientAccessToken.class);
+            fail("Failure expected on trying to get a token");
+        } catch (ResponseProcessingException ex) {
+            //expected
+        }
+    }
+
+    // Here we are sending a different client Id in both the authz + token requests, where in the
+    // token request we authenticate using a different clientId
+    @org.junit.Test
+    public void testNonMatchingClientDifferentClientIds() throws Exception {
+        URL busFile = AuthorizationGrantTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        // Get Authorization Code
+        String code = OAuth2TestUtils.getAuthorizationCode(client);
+        assertNotNull(code);
+
+        // Now get the access token using a different client id
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id-aud", "this-is-a-secret", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        client.type("application/x-www-form-urlencoded").accept("application/json");
+        client.path("token");
+
+        Form form = new Form();
+        form.param("grant_type", "authorization_code");
+        form.param("code", code);
+        form.param("client_id", "consumer-id");
+
+        // Now try to get a token
+        Response response = client.post(form);
+        try {
+            response.readEntity(ClientAccessToken.class);
+            fail("Failure expected on trying to get a token");
+        } catch (ResponseProcessingException ex) {
+            //expected
+        }
+    }
+
     //
     // SAML Authorization grants
     //
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java
index 99d36d5..161da2f 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java
@@ -484,7 +484,7 @@ public class AuthorizationGrantTest extends AbstractBusClientServerTestBase {
 
         String address = "https://localhost:" + port + "/services/";
         WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
-                                            "alice", "security", busFile.toString());
+                                            "consumer-id", "this-is-a-secret", busFile.toString());
 
         // Create the SAML Assertion
         String assertion = OAuth2TestUtils.createToken(address + "token");
@@ -514,7 +514,7 @@ public class AuthorizationGrantTest extends AbstractBusClientServerTestBase {
 
         String address = "https://localhost:" + port + "/services/";
         WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
-                                            "alice", "security", busFile.toString());
+                                            "consumer-id", "this-is-a-secret", busFile.toString());
 
         // Create the JWT Token
         String token = OAuth2TestUtils.createToken("DoubleItSTSIssuer", "consumer-id",


[cxf] 06/10: Adding OAuth token revocation tests

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 28d265696ec788fae048aa7ec49ef7938ad8c2ed
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Thu Sep 12 22:14:11 2019 +0100

    Adding OAuth token revocation tests
---
 .../oauth2/grants/RevocationServiceTest.java       | 266 +++++++++++++++++++++
 .../oauth2/grants/revocation-server-jcache-jwt.xml | 139 +++++++++++
 .../oauth2/grants/revocation-server-jcache.xml     | 128 ++++++++++
 .../oauth2/grants/revocation-server-jpa.xml        | 141 +++++++++++
 4 files changed, 674 insertions(+)

diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java
new file mode 100644
index 0000000..057eda6
--- /dev/null
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/RevocationServiceTest.java
@@ -0,0 +1,266 @@
+/**
+ * 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.oauth2.grants;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.TokenIntrospection;
+import org.apache.cxf.systest.jaxrs.security.SecurityTestUtil;
+import org.apache.cxf.systest.jaxrs.security.oauth2.common.OAuth2TestUtils;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.testutil.common.TestUtil;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Some unit tests for the token revocation service in CXF. The tests are run multiple times with different
+ * OAuthDataProvider implementations:
+ * a) JCACHE_PORT - JCache
+ * b) JWT_JCACHE_PORT - JCache with useJwtFormatForAccessTokens enabled
+ * c) JPA_PORT - JPA provider
+ */
+@RunWith(value = org.junit.runners.Parameterized.class)
+public class RevocationServiceTest extends AbstractBusClientServerTestBase {
+
+    public static final String JCACHE_PORT = TestUtil.getPortNumber("jaxrs-oauth2-revocation-jcache");
+    public static final String JCACHE_PORT2 = TestUtil.getPortNumber("jaxrs-oauth2-revocation2-jcache");
+    public static final String JWT_JCACHE_PORT = TestUtil.getPortNumber("jaxrs-oauth2-revocation-jcache-jwt");
+    public static final String JWT_JCACHE_PORT2 = TestUtil.getPortNumber("jaxrs-oauth2-revocation2-jcache-jwt");
+    public static final String JPA_PORT = TestUtil.getPortNumber("jaxrs-oauth2-revocation-jpa");
+    public static final String JPA_PORT2 = TestUtil.getPortNumber("jaxrs-oauth2-revocation2-jpa");
+
+    final String port;
+
+    public RevocationServiceTest(String port) {
+        this.port = port;
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue("server did not launch correctly",
+                   launchServer(BookServerOAuth2RevocationJCache.class, true));
+        assertTrue("server did not launch correctly",
+                   launchServer(BookServerOAuth2RevocationJCacheJWT.class, true));
+        assertTrue("server did not launch correctly",
+                   launchServer(BookServerOAuth2RevocationJPA.class, true));
+    }
+
+    @AfterClass
+    public static void cleanup() throws Exception {
+        SecurityTestUtil.cleanup();
+    }
+
+    @Parameters(name = "{0}")
+    public static Collection<String> data() {
+
+        return Arrays.asList(JCACHE_PORT, JWT_JCACHE_PORT, JPA_PORT);
+    }
+
+    @org.junit.Test
+    public void testAccessTokenRevocation() throws Exception {
+        URL busFile = RevocationServiceTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        // Get Authorization Code
+        String code = OAuth2TestUtils.getAuthorizationCode(client);
+        assertNotNull(code);
+
+        // Now get the access token
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        ClientAccessToken accessToken = OAuth2TestUtils.getAccessTokenWithAuthorizationCode(client, code);
+        assertNotNull(accessToken.getTokenKey());
+
+        // Now query the token introspection service to make sure the token is valid
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        client.accept("application/json").type("application/x-www-form-urlencoded");
+        Form form = new Form();
+        form.param("token", accessToken.getTokenKey());
+        client.path("introspect/");
+        Response response = client.post(form);
+
+        TokenIntrospection tokenIntrospection = response.readEntity(TokenIntrospection.class);
+        assertTrue(tokenIntrospection.isActive());
+
+        // Now revoke the token
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        client.accept("application/json").type("application/x-www-form-urlencoded");
+        form = new Form();
+        form.param("token", accessToken.getTokenKey());
+        client.path("revoke/");
+        response = client.post(form);
+        assertEquals(200, response.getStatus());
+
+        // Now check the token introspection service again to make sure the token is not valid
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        client.accept("application/json").type("application/x-www-form-urlencoded");
+        form = new Form();
+        form.param("token", accessToken.getTokenKey());
+        client.path("introspect/");
+        response = client.post(form);
+
+        tokenIntrospection = response.readEntity(TokenIntrospection.class);
+        assertFalse(tokenIntrospection.isActive());
+    }
+
+    @org.junit.Test
+    public void testRefreshTokenRevocation() throws Exception {
+        URL busFile = RevocationServiceTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        // Get Authorization Code
+        String code = OAuth2TestUtils.getAuthorizationCode(client);
+        assertNotNull(code);
+
+        // Now get the access token
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        ClientAccessToken accessToken = OAuth2TestUtils.getAccessTokenWithAuthorizationCode(client, code);
+        assertNotNull(accessToken.getTokenKey());
+        assertNotNull(accessToken.getRefreshToken());
+
+        // Now revoke the refresh token
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        client.accept("application/json").type("application/x-www-form-urlencoded");
+        Form form = new Form();
+        form.param("token", accessToken.getRefreshToken());
+        client.path("revoke/");
+        Response response = client.post(form);
+        assertEquals(200, response.getStatus());
+
+        // Now check we can't get an access token with the revoked refresh token
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "consumer-id", "this-is-a-secret", busFile.toString());
+        client.type("application/x-www-form-urlencoded").accept("application/json");
+
+        form = new Form();
+        form.param("grant_type", "refresh_token");
+        form.param("refresh_token", accessToken.getRefreshToken());
+        form.param("client_id", "consumer-id");
+        client.path("token");
+        response = client.post(form);
+        assertEquals(400, response.getStatus());
+    }
+
+    //
+    // Server implementations
+    //
+
+    public static class BookServerOAuth2RevocationJCache extends AbstractBusTestServerBase {
+        private static final URL SERVER_CONFIG_FILE =
+            BookServerOAuth2RevocationJCache.class.getResource("revocation-server-jcache.xml");
+
+        protected void run() {
+            SpringBusFactory bf = new SpringBusFactory();
+            Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
+            BusFactory.setDefaultBus(springBus);
+            setBus(springBus);
+
+            try {
+                new BookServerOAuth2RevocationJCache();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+    public static class BookServerOAuth2RevocationJCacheJWT extends AbstractBusTestServerBase {
+        private static final URL SERVER_CONFIG_FILE =
+            BookServerOAuth2RevocationJCacheJWT.class.getResource("revocation-server-jcache-jwt.xml");
+
+        protected void run() {
+            SpringBusFactory bf = new SpringBusFactory();
+            Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
+            BusFactory.setDefaultBus(springBus);
+            setBus(springBus);
+
+            try {
+                new BookServerOAuth2RevocationJCacheJWT();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+    public static class BookServerOAuth2RevocationJPA extends AbstractBusTestServerBase {
+        private static final URL SERVER_CONFIG_FILE =
+            BookServerOAuth2RevocationJPA.class.getResource("revocation-server-jpa.xml");
+
+        protected void run() {
+            SpringBusFactory bf = new SpringBusFactory();
+            Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
+            BusFactory.setDefaultBus(springBus);
+            setBus(springBus);
+
+            try {
+                new BookServerOAuth2RevocationJPA();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+
+}
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jcache-jwt.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jcache-jwt.xml
new file mode 100644
index 0000000..a846f9e
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jcache-jwt.xml
@@ -0,0 +1,139 @@
+<?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:util="http://www.springframework.org/schema/util"
+    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://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-4.2.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">
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+        <cxf:properties> 
+          <entry key="org.apache.cxf.jaxrs.bus.providers" value-ref="busProviders"/> 
+        </cxf:properties>
+    </cxf:bus>
+    <!-- providers -->
+    <util:list id="busProviders"> 
+        <ref bean="oauthJson"/> 
+    </util:list> 
+    <bean id="oauthJson" class="org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider"/>
+    
+    <httpj:engine-factory id="tls-config">
+        <httpj:engine port="${testutil.ports.jaxrs-oauth2-revocation-jcache-jwt}">
+            <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>
+    
+   <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JCacheOAuthDataProviderImpl">
+       <constructor-arg><value>${testutil.ports.jaxrs-oauth2-revocation2-jcache-jwt}</value></constructor-arg>
+       <property name="useJwtFormatForAccessTokens" value="true"/>
+   </bean>
+   
+   <bean id="authorizationService" class="org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="refreshGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandlerLoginHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CallbackHandlerLoginHandler">
+      <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <bean id="passwordGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="loginHandler" ref="callbackHandlerLoginHandler"/>
+   </bean>
+   
+   <bean id="clientCredsGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.clientcred.ClientCredentialsGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="tokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="grantHandlers">
+         <list>
+             <ref bean="refreshGrantHandler"/>
+             <ref bean="passwordGrantHandler"/>
+             <ref bean="clientCredsGrantHandler"/>
+         </list>
+      </property>
+   </bean>
+   
+   <bean id="tokenRevocationService" class="org.apache.cxf.rs.security.oauth2.services.TokenRevocationService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="tokenIntrospectionService" class="org.apache.cxf.rs.security.oauth2.services.TokenIntrospectionService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.CallbackHandlerImpl"/>
+   <bean id="basicAuthFilter" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.WSS4JBasicAuthFilter">
+       <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <jaxrs:server 
+       depends-on="tls-config" 
+       address="https://localhost:${testutil.ports.jaxrs-oauth2-revocation-jcache-jwt}/services">
+       <jaxrs:serviceBeans>
+           <ref bean="authorizationService"/>
+           <ref bean="tokenService"/>
+           <ref bean="tokenRevocationService"/>
+           <ref bean="tokenIntrospectionService"/>
+       </jaxrs:serviceBeans>
+       <jaxrs:providers>
+           <ref bean="basicAuthFilter"/>
+       </jaxrs:providers>
+       <jaxrs:properties>
+           <entry key="security.signature.properties" 
+                  value="org/apache/cxf/systest/jaxrs/security/bob.properties"/>
+           <entry key="rs.security.keystore.type" value="jks" />
+           <entry key="rs.security.keystore.alias" value="alice"/>
+           <entry key="rs.security.keystore.password" value="password"/>
+           <entry key="rs.security.key.password" value="password"/>
+           <entry key="rs.security.keystore.file" value="keys/alice.jks" />
+           <entry key="rs.security.signature.algorithm" value="RS256" />
+       </jaxrs:properties>
+   </jaxrs:server>
+   
+
+</beans>
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jcache.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jcache.xml
new file mode 100644
index 0000000..9350e9a
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jcache.xml
@@ -0,0 +1,128 @@
+<?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:util="http://www.springframework.org/schema/util"
+    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://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-4.2.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">
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+        <cxf:properties> 
+          <entry key="org.apache.cxf.jaxrs.bus.providers" value-ref="busProviders"/> 
+        </cxf:properties>
+    </cxf:bus>
+    <!-- providers -->
+    <util:list id="busProviders"> 
+        <ref bean="oauthJson"/> 
+    </util:list> 
+    <bean id="oauthJson" class="org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider"/>
+    
+    <httpj:engine-factory id="tls-config">
+        <httpj:engine port="${testutil.ports.jaxrs-oauth2-revocation-jcache}">
+            <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>
+    
+   <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JCacheOAuthDataProviderImpl">
+       <constructor-arg><value>${testutil.ports.jaxrs-oauth2-revocation2-jcache}</value></constructor-arg>
+   </bean>
+   
+   <bean id="authorizationService" class="org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="refreshGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandlerLoginHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CallbackHandlerLoginHandler">
+      <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <bean id="passwordGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="loginHandler" ref="callbackHandlerLoginHandler"/>
+   </bean>
+   
+   <bean id="clientCredsGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.clientcred.ClientCredentialsGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="tokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="grantHandlers">
+         <list>
+             <ref bean="refreshGrantHandler"/>
+             <ref bean="passwordGrantHandler"/>
+             <ref bean="clientCredsGrantHandler"/>
+         </list>
+      </property>
+   </bean>
+   
+   <bean id="tokenRevocationService" class="org.apache.cxf.rs.security.oauth2.services.TokenRevocationService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="tokenIntrospectionService" class="org.apache.cxf.rs.security.oauth2.services.TokenIntrospectionService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.CallbackHandlerImpl"/>
+   <bean id="basicAuthFilter" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.WSS4JBasicAuthFilter">
+       <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <jaxrs:server 
+       depends-on="tls-config" 
+       address="https://localhost:${testutil.ports.jaxrs-oauth2-revocation-jcache}/services">
+       <jaxrs:serviceBeans>
+           <ref bean="authorizationService"/>
+           <ref bean="tokenService"/>
+           <ref bean="tokenRevocationService"/>
+           <ref bean="tokenIntrospectionService"/>
+       </jaxrs:serviceBeans>
+       <jaxrs:providers>
+           <ref bean="basicAuthFilter"/>
+       </jaxrs:providers>
+   </jaxrs:server>
+   
+
+</beans>
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jpa.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jpa.xml
new file mode 100644
index 0000000..cb77014
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/revocation-server-jpa.xml
@@ -0,0 +1,141 @@
+<?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:util="http://www.springframework.org/schema/util"
+    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://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-4.2.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">
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+        <cxf:properties> 
+          <entry key="org.apache.cxf.jaxrs.bus.providers" value-ref="busProviders"/> 
+        </cxf:properties>
+    </cxf:bus>
+    <!-- providers -->
+    <util:list id="busProviders"> 
+        <ref bean="oauthJson"/> 
+    </util:list> 
+    <bean id="oauthJson" class="org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider"/>
+    
+    <httpj:engine-factory id="tls-config">
+        <httpj:engine port="${testutil.ports.jaxrs-oauth2-revocation-jpa}">
+            <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>
+    
+    <bean id="entityManagerFactory"
+		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+		<property name="persistenceUnitName"
+			value="test-hibernate-cxf-systests-rs-security" />
+		<property name="jpaPropertyMap">
+			<map>
+				<entry key="hibernate.jdbc.fetch_size" value="400" />
+				<entry key="hibernate.jdbc.batch_size" value="100" />
+			</map>
+		</property>
+	</bean>
+    
+   <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JPAOAuthDataProviderImpl">
+       <constructor-arg><value>${testutil.ports.jaxrs-oauth2-revocation2-jpa}</value></constructor-arg>
+        <constructor-arg ref="entityManagerFactory"/>
+   </bean>
+   
+   <bean id="authorizationService" class="org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="refreshGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandlerLoginHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CallbackHandlerLoginHandler">
+      <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <bean id="passwordGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="loginHandler" ref="callbackHandlerLoginHandler"/>
+   </bean>
+   
+   <bean id="clientCredsGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.clientcred.ClientCredentialsGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="tokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="grantHandlers">
+         <list>
+             <ref bean="refreshGrantHandler"/>
+             <ref bean="passwordGrantHandler"/>
+             <ref bean="clientCredsGrantHandler"/>
+         </list>
+      </property>
+   </bean>
+   
+   <bean id="tokenRevocationService" class="org.apache.cxf.rs.security.oauth2.services.TokenRevocationService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="tokenIntrospectionService" class="org.apache.cxf.rs.security.oauth2.services.TokenIntrospectionService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.CallbackHandlerImpl"/>
+   <bean id="basicAuthFilter" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.WSS4JBasicAuthFilter">
+       <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <jaxrs:server 
+       depends-on="tls-config" 
+       address="https://localhost:${testutil.ports.jaxrs-oauth2-revocation-jpa}/services">
+       <jaxrs:serviceBeans>
+           <ref bean="authorizationService"/>
+           <ref bean="tokenService"/>
+           <ref bean="tokenRevocationService"/>
+           <ref bean="tokenIntrospectionService"/>
+       </jaxrs:serviceBeans>
+       <jaxrs:providers>
+           <ref bean="basicAuthFilter"/>
+       </jaxrs:providers>
+   </jaxrs:server>
+   
+
+</beans>


[cxf] 02/10: Fixing OAuth scope test

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 39e32c4a3cf4b6dd35dae7cfccf47e2f23b8d253
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Wed Sep 11 01:08:19 2019 +0100

    Fixing OAuth scope test
---
 .../cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java | 3 +--
 .../jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java  | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
index d6e16f2..e4af350 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/RedirectionBasedGrantService.java
@@ -396,8 +396,7 @@ public abstract class RedirectionBasedGrantService extends AbstractOAuthService
                 approvedScope.add(rScope);
             }
         }
-        if (!requestedScope.containsAll(approvedScope)
-            || !OAuthUtils.validateScopes(requestedScope, client.getRegisteredScopes(),
+        if (!OAuthUtils.validateScopes(requestedScope, client.getRegisteredScopes(),
                                          partialMatchScopeValidation)) {
             return createErrorResponse(params, redirectUri, OAuthConstants.INVALID_SCOPE);
         }
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
index 8bbb662..5b70662 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java
@@ -212,13 +212,13 @@ public class AuthorizationGrantNegativeTest extends AbstractBusClientServerTestB
         client.type("application/json").accept("application/json");
         client.query("client_id", "consumer-id");
         client.query("response_type", "code");
-        client.query("redirect_uri", "http://www.blah.bad.apache.org");
+        client.query("redirect_uri", "http://www.blah.apache.org");
         client.query("scope", "unknown-scope");
         client.path("authorize/");
 
         // No redirect URI
         Response response = client.get();
-        assertEquals(400, response.getStatus());
+        assertEquals(303, response.getStatus());
     }
 
     // Send the authorization code twice to get an access token


[cxf] 09/10: Adding OAuth token introspection systests + requiring a client register a redirect URI for authz code + implicit grants

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4c5cf7e31db3937fd746964add5cee343070a673
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Mon Sep 16 13:12:46 2019 +0100

    Adding OAuth token introspection systests + requiring a client register a redirect URI for authz code + implicit grants
---
 .../services/DynamicRegistrationService.java       |  43 +++-
 .../oauth2/common/CallbackHandlerImpl.java         |  16 ++
 .../oauth2/grants/DynamicRegistrationTest.java     | 222 +++++++++++++++++++++
 .../grants/dynamic-reg-server-jcache-jwt.xml       | 142 +++++++++++++
 .../oauth2/grants/dynamic-reg-server-jcache.xml    | 131 ++++++++++++
 .../oauth2/grants/dynamic-reg-server-jpa.xml       | 144 +++++++++++++
 6 files changed, 689 insertions(+), 9 deletions(-)

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 56cff1f..12155d9 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
@@ -31,7 +31,9 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriBuilder;
 
@@ -39,7 +41,9 @@ import org.apache.cxf.common.util.Base64UrlUtility;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.jaxrs.ext.MessageContext;
 import org.apache.cxf.jaxrs.utils.ExceptionUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 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.common.UserSubject;
 import org.apache.cxf.rs.security.oauth2.provider.ClientRegistrationProvider;
 import org.apache.cxf.rs.security.oauth2.utils.AuthorizationUtils;
@@ -81,13 +85,13 @@ public class DynamicRegistrationService {
         }
 
     }
-    
+
 
     protected void checkSecurityContext() {
         SecurityContext sc = mc.getSecurityContext();
         if (sc.getUserPrincipal() == null) {
             throw ExceptionUtils.toNotAuthorizedException(null, null);
-        }  
+        }
         if (userRole != null && !sc.isUserInRole(userRole)) {
             throw ExceptionUtils.toForbiddenException(null, null);
         }
@@ -198,7 +202,7 @@ public class DynamicRegistrationService {
                 }
             }
         }
-        
+
         return reg;
     }
 
@@ -236,10 +240,10 @@ public class DynamicRegistrationService {
         if (grantTypes == null) {
             grantTypes = Collections.singletonList(OAuthConstants.AUTHORIZATION_CODE_GRANT);
         }
-        
+
         String tokenEndpointAuthMethod = request.getTokenEndpointAuthMethod();
         //TODO: default is expected to be set to OAuthConstants.TOKEN_ENDPOINT_AUTH_BASIC
-        
+
         boolean passwordRequired = isPasswordRequired(grantTypes, tokenEndpointAuthMethod);
 
         // Application Type
@@ -255,7 +259,7 @@ public class DynamicRegistrationService {
 
         // Client Secret
         String clientSecret = passwordRequired ? generateClientSecret(request) : null;
-            
+
         Client newClient = new Client(clientId, clientSecret, isConfidential, clientName);
 
         newClient.setAllowedGrantTypes(grantTypes);
@@ -272,7 +276,7 @@ public class DynamicRegistrationService {
             }
         }
         // Client Registration Time
-        newClient.setRegisteredAt(System.currentTimeMillis() / 1000);
+        newClient.setRegisteredAt(System.currentTimeMillis() / 1000L);
 
         // Client Redirect URIs
         List<String> redirectUris = request.getRedirectUris();
@@ -283,6 +287,15 @@ public class DynamicRegistrationService {
             newClient.setRedirectUris(redirectUris);
         }
 
+        if (newClient.getRedirectUris().isEmpty()
+            && (grantTypes.contains(OAuthConstants.AUTHORIZATION_CODE_GRANT)
+                || grantTypes.contains(OAuthConstants.IMPLICIT_GRANT))) {
+            // Throw an error as we need a redirect URI for these grants.
+            OAuthError error =
+                new OAuthError(OAuthConstants.INVALID_REQUEST, "A Redirection URI is required");
+            reportInvalidRequestError(error);
+        }
+
         // Client Resource Audience URIs
         List<String> resourceUris = request.getResourceUris();
         if (resourceUris != null) {
@@ -314,7 +327,7 @@ public class DynamicRegistrationService {
             UserSubject subject = new UserSubject(sc.getUserPrincipal().getName());
             newClient.setResourceOwnerSubject(subject);
         }
-        
+
         newClient.setRegisteredDynamically(true);
         return newClient;
     }
@@ -326,7 +339,7 @@ public class DynamicRegistrationService {
         if (tokenEndpointAuthMethod == null) {
             return true;
         }
-        
+
         return !OAuthConstants.TOKEN_ENDPOINT_AUTH_NONE.equals(tokenEndpointAuthMethod)
             && (OAuthConstants.TOKEN_ENDPOINT_AUTH_BASIC.equals(tokenEndpointAuthMethod)
                 || OAuthConstants.TOKEN_ENDPOINT_AUTH_POST.equals(tokenEndpointAuthMethod));
@@ -388,4 +401,16 @@ public class DynamicRegistrationService {
     public void setUserRole(String userRole) {
         this.userRole = userRole;
     }
+
+    private void reportInvalidRequestError(OAuthError entity) {
+        reportInvalidRequestError(entity, MediaType.APPLICATION_JSON_TYPE);
+    }
+
+    private void reportInvalidRequestError(OAuthError entity, MediaType mt) {
+        ResponseBuilder rb = JAXRSUtils.toResponseBuilder(400);
+        if (mt != null) {
+            rb.type(mt);
+        }
+        throw ExceptionUtils.toBadRequestException(null, rb.entity(entity).build());
+    }
 }
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/CallbackHandlerImpl.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/CallbackHandlerImpl.java
index c8ce14d..ba0e884 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/CallbackHandlerImpl.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/common/CallbackHandlerImpl.java
@@ -24,10 +24,14 @@ import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
 
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthDataProvider;
 import org.apache.wss4j.common.ext.WSPasswordCallback;
 
 public class CallbackHandlerImpl implements CallbackHandler {
 
+    private OAuthDataProvider dataProvider;
+
     public void handle(Callback[] callbacks) throws IOException,
             UnsupportedCallbackException {
         for (int i = 0; i < callbacks.length; i++) {
@@ -46,8 +50,20 @@ public class CallbackHandlerImpl implements CallbackHandler {
                 } else if ("service".equals(pc.getIdentifier())) {
                     pc.setPassword("service-pass");
                     break;
+                } else if (dataProvider != null) {
+                    Client client = dataProvider.getClient(pc.getIdentifier());
+                    pc.setPassword(client.getClientSecret());
+                    break;
                 }
             }
         }
     }
+
+    public OAuthDataProvider getDataProvider() {
+        return dataProvider;
+    }
+
+    public void setDataProvider(OAuthDataProvider dataProvider) {
+        this.dataProvider = dataProvider;
+    }
 }
\ No newline at end of file
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/DynamicRegistrationTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/DynamicRegistrationTest.java
new file mode 100644
index 0000000..8f65497
--- /dev/null
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/DynamicRegistrationTest.java
@@ -0,0 +1,222 @@
+/**
+ * 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.oauth2.grants;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oauth2.services.ClientRegistration;
+import org.apache.cxf.rs.security.oauth2.services.ClientRegistrationResponse;
+import org.apache.cxf.systest.jaxrs.security.SecurityTestUtil;
+import org.apache.cxf.systest.jaxrs.security.oauth2.common.OAuth2TestUtils;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+import org.apache.cxf.testutil.common.TestUtil;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Some unit tests for the dynamic registration service in CXF. The tests are run multiple times with different
+ * OAuthDataProvider implementations:
+ * a) JCACHE_PORT - JCache
+ * b) JWT_JCACHE_PORT - JCache with useJwtFormatForAccessTokens enabled
+ * c) JPA_PORT - JPA provider
+ */
+@RunWith(value = org.junit.runners.Parameterized.class)
+public class DynamicRegistrationTest extends AbstractBusClientServerTestBase {
+
+    public static final String JCACHE_PORT = TestUtil.getPortNumber("jaxrs-oauth2-dynamic-reg-jcache");
+    public static final String JCACHE_PORT2 = TestUtil.getPortNumber("jaxrs-oauth2-dynamic-reg2-jcache");
+    public static final String JWT_JCACHE_PORT = TestUtil.getPortNumber("jaxrs-oauth2-dynamic-reg-jcache-jwt");
+    public static final String JWT_JCACHE_PORT2 = TestUtil.getPortNumber("jaxrs-oauth2-dynamic-reg2-jcache-jwt");
+    public static final String JPA_PORT = TestUtil.getPortNumber("jaxrs-oauth2-dynamic-reg-jpa");
+    public static final String JPA_PORT2 = TestUtil.getPortNumber("jaxrs-oauth2-dynamic-reg2-jpa");
+
+    final String port;
+
+    public DynamicRegistrationTest(String port) {
+        this.port = port;
+    }
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue("server did not launch correctly",
+                   launchServer(BookServerOAuth2DynamicRegistrationJCache.class, true));
+        assertTrue("server did not launch correctly",
+                   launchServer(BookServerOAuth2DynamicRegistrationJCacheJWT.class, true));
+        assertTrue("server did not launch correctly",
+                   launchServer(BookServerOAuth2DynamicRegistrationJPA.class, true));
+    }
+
+    @AfterClass
+    public static void cleanup() throws Exception {
+        SecurityTestUtil.cleanup();
+    }
+
+    @Parameters(name = "{0}")
+    public static Collection<String> data() {
+
+        return Arrays.asList(JCACHE_PORT, JWT_JCACHE_PORT, JPA_PORT);
+    }
+
+    @org.junit.Test
+    public void testDynamicRegistration() throws Exception {
+        URL busFile = DynamicRegistrationTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+
+        // 1. Register a client
+        client.accept("application/json").type("application/json");
+        client.path("register/");
+
+        ClientRegistration registration = new ClientRegistration();
+        registration.setClientName("new client");
+        registration.setRedirectUris(Collections.singletonList("http://www.blah.apache.org"));
+
+        Response response = client.post(registration);
+
+        ClientRegistrationResponse registrationResponse = response.readEntity(ClientRegistrationResponse.class);
+        assertNotNull(registrationResponse.getClientId());
+        assertNotNull(registrationResponse.getClientSecret());
+        assertNotNull(registrationResponse.getRegistrationClientUri());
+        assertNotNull(registrationResponse.getRegistrationAccessToken());
+
+        // 2. Get Authorization Code
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  "alice", "security", busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+        String code = OAuth2TestUtils.getAuthorizationCode(client, null, registrationResponse.getClientId());
+        assertNotNull(code);
+
+        // 3. Now get the access token
+        client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                  registrationResponse.getClientId(), registrationResponse.getClientSecret(),
+                                  busFile.toString());
+        // Save the Cookie for the second request...
+        WebClient.getConfig(client).getRequestContext().put(
+            org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);
+
+        ClientAccessToken accessToken =
+            OAuth2TestUtils.getAccessTokenWithAuthorizationCode(client, code, registrationResponse.getClientId(), null);
+        assertNotNull(accessToken.getTokenKey());
+    }
+
+    @org.junit.Test
+    public void testRedirectURIIsRequired() throws Exception {
+        URL busFile = DynamicRegistrationTest.class.getResource("client.xml");
+
+        String address = "https://localhost:" + port + "/services/";
+        WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(),
+                                            "alice", "security", busFile.toString());
+
+        // 1. Register a client
+        client.accept("application/json").type("application/json");
+        client.path("register/");
+
+        ClientRegistration registration = new ClientRegistration();
+        registration.setClientName("new client");
+        registration.setScope("newscope");
+
+        Response response = client.post(registration);
+        assertEquals(400, response.getStatus());
+    }
+
+    //
+    // Server implementations
+    //
+
+    public static class BookServerOAuth2DynamicRegistrationJCache extends AbstractBusTestServerBase {
+        private static final URL SERVER_CONFIG_FILE =
+            BookServerOAuth2DynamicRegistrationJCache.class.getResource("dynamic-reg-server-jcache.xml");
+
+        protected void run() {
+            SpringBusFactory bf = new SpringBusFactory();
+            Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
+            BusFactory.setDefaultBus(springBus);
+            setBus(springBus);
+
+            try {
+                new BookServerOAuth2DynamicRegistrationJCache();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+    public static class BookServerOAuth2DynamicRegistrationJCacheJWT extends AbstractBusTestServerBase {
+        private static final URL SERVER_CONFIG_FILE =
+            BookServerOAuth2DynamicRegistrationJCacheJWT.class.getResource("dynamic-reg-server-jcache-jwt.xml");
+
+        protected void run() {
+            SpringBusFactory bf = new SpringBusFactory();
+            Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
+            BusFactory.setDefaultBus(springBus);
+            setBus(springBus);
+
+            try {
+                new BookServerOAuth2DynamicRegistrationJCacheJWT();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+    public static class BookServerOAuth2DynamicRegistrationJPA extends AbstractBusTestServerBase {
+        private static final URL SERVER_CONFIG_FILE =
+            BookServerOAuth2DynamicRegistrationJPA.class.getResource("dynamic-reg-server-jpa.xml");
+
+        protected void run() {
+            SpringBusFactory bf = new SpringBusFactory();
+            Bus springBus = bf.createBus(SERVER_CONFIG_FILE);
+            BusFactory.setDefaultBus(springBus);
+            setBus(springBus);
+
+            try {
+                new BookServerOAuth2DynamicRegistrationJPA();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+
+}
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jcache-jwt.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jcache-jwt.xml
new file mode 100644
index 0000000..cfcb5b3
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jcache-jwt.xml
@@ -0,0 +1,142 @@
+<?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:util="http://www.springframework.org/schema/util"
+    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://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-4.2.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">
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+        <cxf:properties> 
+          <entry key="org.apache.cxf.jaxrs.bus.providers" value-ref="busProviders"/> 
+        </cxf:properties>
+    </cxf:bus>
+    <!-- providers -->
+    <util:list id="busProviders"> 
+        <ref bean="oauthJson"/> 
+    </util:list> 
+    <bean id="oauthJson" class="org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider"/>
+    
+    <httpj:engine-factory id="tls-config">
+        <httpj:engine port="${testutil.ports.jaxrs-oauth2-dynamic-reg-jcache-jwt}">
+            <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>
+    
+   <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JCacheOAuthDataProviderImpl">
+       <constructor-arg><value>${testutil.ports.jaxrs-oauth2-dynamic-reg2-jcache-jwt}</value></constructor-arg>
+       <property name="useJwtFormatForAccessTokens" value="true"/>
+   </bean>
+   
+   <bean id="authorizationService" class="org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="refreshGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandlerLoginHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CallbackHandlerLoginHandler">
+      <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <bean id="passwordGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="loginHandler" ref="callbackHandlerLoginHandler"/>
+   </bean>
+   
+   <bean id="clientCredsGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.clientcred.ClientCredentialsGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="tokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="grantHandlers">
+         <list>
+             <ref bean="refreshGrantHandler"/>
+             <ref bean="passwordGrantHandler"/>
+             <ref bean="clientCredsGrantHandler"/>
+         </list>
+      </property>
+   </bean>
+   
+   <bean id="dynamicRegistrationService" class="org.apache.cxf.rs.security.oauth2.services.DynamicRegistrationService">
+       <property name="clientProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="tokenIntrospectionService" class="org.apache.cxf.rs.security.oauth2.services.TokenIntrospectionService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.CallbackHandlerImpl">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="basicAuthFilter" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.WSS4JBasicAuthFilter">
+       <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <jaxrs:server 
+       depends-on="tls-config" 
+       address="https://localhost:${testutil.ports.jaxrs-oauth2-dynamic-reg-jcache-jwt}/services">
+       <jaxrs:serviceBeans>
+           <ref bean="authorizationService"/>
+           <ref bean="tokenService"/>
+           <ref bean="dynamicRegistrationService"/>
+           <ref bean="tokenIntrospectionService"/>
+       </jaxrs:serviceBeans>
+       <jaxrs:providers>
+           <ref bean="basicAuthFilter"/>
+           <bean class="org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider"/>
+       </jaxrs:providers>
+       <jaxrs:properties>
+           <entry key="security.signature.properties" 
+                  value="org/apache/cxf/systest/jaxrs/security/bob.properties"/>
+           <entry key="rs.security.keystore.type" value="jks" />
+           <entry key="rs.security.keystore.alias" value="alice"/>
+           <entry key="rs.security.keystore.password" value="password"/>
+           <entry key="rs.security.key.password" value="password"/>
+           <entry key="rs.security.keystore.file" value="keys/alice.jks" />
+           <entry key="rs.security.signature.algorithm" value="RS256" />
+       </jaxrs:properties>
+   </jaxrs:server>
+   
+
+</beans>
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jcache.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jcache.xml
new file mode 100644
index 0000000..7f85b27
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jcache.xml
@@ -0,0 +1,131 @@
+<?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:util="http://www.springframework.org/schema/util"
+    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://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-4.2.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">
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+        <cxf:properties> 
+          <entry key="org.apache.cxf.jaxrs.bus.providers" value-ref="busProviders"/> 
+        </cxf:properties>
+    </cxf:bus>
+    <!-- providers -->
+    <util:list id="busProviders"> 
+        <ref bean="oauthJson"/> 
+    </util:list> 
+    <bean id="oauthJson" class="org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider"/>
+    
+    <httpj:engine-factory id="tls-config">
+        <httpj:engine port="${testutil.ports.jaxrs-oauth2-dynamic-reg-jcache}">
+            <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>
+    
+   <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JCacheOAuthDataProviderImpl">
+       <constructor-arg><value>${testutil.ports.jaxrs-oauth2-dynamic-reg2-jcache}</value></constructor-arg>
+   </bean>
+   
+   <bean id="authorizationService" class="org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="refreshGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandlerLoginHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CallbackHandlerLoginHandler">
+      <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <bean id="passwordGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="loginHandler" ref="callbackHandlerLoginHandler"/>
+   </bean>
+   
+   <bean id="clientCredsGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.clientcred.ClientCredentialsGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="tokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="grantHandlers">
+         <list>
+             <ref bean="refreshGrantHandler"/>
+             <ref bean="passwordGrantHandler"/>
+             <ref bean="clientCredsGrantHandler"/>
+         </list>
+      </property>
+   </bean>
+   
+   <bean id="dynamicRegistrationService" class="org.apache.cxf.rs.security.oauth2.services.DynamicRegistrationService">
+       <property name="clientProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="tokenIntrospectionService" class="org.apache.cxf.rs.security.oauth2.services.TokenIntrospectionService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.CallbackHandlerImpl">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="basicAuthFilter" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.WSS4JBasicAuthFilter">
+       <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <jaxrs:server 
+       depends-on="tls-config" 
+       address="https://localhost:${testutil.ports.jaxrs-oauth2-dynamic-reg-jcache}/services">
+       <jaxrs:serviceBeans>
+           <ref bean="authorizationService"/>
+           <ref bean="tokenService"/>
+           <ref bean="dynamicRegistrationService"/>
+           <ref bean="tokenIntrospectionService"/>
+       </jaxrs:serviceBeans>
+       <jaxrs:providers>
+           <ref bean="basicAuthFilter"/>
+           <bean class="org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider"/>
+       </jaxrs:providers>
+   </jaxrs:server>
+   
+
+</beans>
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jpa.xml b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jpa.xml
new file mode 100644
index 0000000..096a14c
--- /dev/null
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/grants/dynamic-reg-server-jpa.xml
@@ -0,0 +1,144 @@
+<?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:util="http://www.springframework.org/schema/util"
+    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://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-4.2.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">
+    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
+    <cxf:bus>
+        <cxf:features>
+            <cxf:logging/>
+        </cxf:features>
+        <cxf:properties> 
+          <entry key="org.apache.cxf.jaxrs.bus.providers" value-ref="busProviders"/> 
+        </cxf:properties>
+    </cxf:bus>
+    <!-- providers -->
+    <util:list id="busProviders"> 
+        <ref bean="oauthJson"/> 
+    </util:list> 
+    <bean id="oauthJson" class="org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider"/>
+    
+    <httpj:engine-factory id="tls-config">
+        <httpj:engine port="${testutil.ports.jaxrs-oauth2-dynamic-reg-jpa}">
+            <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>
+    
+    <bean id="entityManagerFactory"
+		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+		<property name="persistenceUnitName"
+			value="test-hibernate-cxf-systests-rs-security" />
+		<property name="jpaPropertyMap">
+			<map>
+				<entry key="hibernate.jdbc.fetch_size" value="400" />
+				<entry key="hibernate.jdbc.batch_size" value="100" />
+			</map>
+		</property>
+	</bean>
+    
+   <bean id="oauthProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.JPAOAuthDataProviderImpl">
+       <constructor-arg><value>${testutil.ports.jaxrs-oauth2-dynamic-reg2-jpa}</value></constructor-arg>
+        <constructor-arg ref="entityManagerFactory"/>
+   </bean>
+   
+   <bean id="authorizationService" class="org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="refreshGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandlerLoginHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CallbackHandlerLoginHandler">
+      <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <bean id="passwordGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="loginHandler" ref="callbackHandlerLoginHandler"/>
+   </bean>
+   
+   <bean id="clientCredsGrantHandler" class="org.apache.cxf.rs.security.oauth2.grants.clientcred.ClientCredentialsGrantHandler">
+      <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="tokenService" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
+      <property name="dataProvider" ref="oauthProvider"/>
+      <property name="grantHandlers">
+         <list>
+             <ref bean="refreshGrantHandler"/>
+             <ref bean="passwordGrantHandler"/>
+             <ref bean="clientCredsGrantHandler"/>
+         </list>
+      </property>
+   </bean>
+   
+   <bean id="dynamicRegistrationService" class="org.apache.cxf.rs.security.oauth2.services.DynamicRegistrationService">
+       <property name="clientProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="tokenIntrospectionService" class="org.apache.cxf.rs.security.oauth2.services.TokenIntrospectionService">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   
+   <bean id="callbackHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.CallbackHandlerImpl">
+       <property name="dataProvider" ref="oauthProvider"/>
+   </bean>
+   <bean id="basicAuthFilter" class="org.apache.cxf.systest.jaxrs.security.oauth2.common.WSS4JBasicAuthFilter">
+       <property name="callbackHandler" ref="callbackHandler"/>
+   </bean>
+   
+   <jaxrs:server 
+       depends-on="tls-config" 
+       address="https://localhost:${testutil.ports.jaxrs-oauth2-dynamic-reg-jpa}/services">
+       <jaxrs:serviceBeans>
+           <ref bean="authorizationService"/>
+           <ref bean="tokenService"/>
+           <ref bean="dynamicRegistrationService"/>
+           <ref bean="tokenIntrospectionService"/>
+       </jaxrs:serviceBeans>
+       <jaxrs:providers>
+           <ref bean="basicAuthFilter"/>
+           <bean class="org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider"/>
+       </jaxrs:providers>
+   </jaxrs:server>
+   
+
+</beans>