cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject cxf git commit: Testing cert token binding when JWT is used
Date Wed, 26 Apr 2017 13:13:22 GMT
Repository: cxf
Updated Branches:
  refs/heads/3.1.x-fixes 11fc8b3ca -> 0487b301a


Testing cert token binding when JWT is used


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/0487b301
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/0487b301
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/0487b301

Branch: refs/heads/3.1.x-fixes
Commit: 0487b301a878e37178776af9a5aacf7934a674ca
Parents: 11fc8b3
Author: Sergey Beryozkin <sberyozkin@gmail.com>
Authored: Wed Apr 26 14:10:06 2017 +0100
Committer: Sergey Beryozkin <sberyozkin@gmail.com>
Committed: Wed Apr 26 14:13:05 2017 +0100

----------------------------------------------------------------------
 .../oauth2/filters/JwtAccessTokenValidator.java | 11 ++-
 .../provider/AbstractOAuthDataProvider.java     | 13 +++-
 .../rs/security/oauth2/utils/JwtTokenUtils.java | 11 ++-
 .../security/oauth2/tls/JAXRSOAuth2TlsTest.java | 47 +++++++++++--
 .../oauth2/tls/OAuthDataProviderImplJwt.java    | 44 ++++++++++++
 .../jaxrs/security/oauth2/tls/serverTls.xml     | 70 ++++++++++++++++++++
 6 files changed, 186 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/0487b301/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwtAccessTokenValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwtAccessTokenValidator.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwtAccessTokenValidator.java
index 7581cf7..b139db9 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwtAccessTokenValidator.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/JwtAccessTokenValidator.java
@@ -29,8 +29,10 @@ import javax.ws.rs.core.MultivaluedMap;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
 import org.apache.cxf.rs.security.jose.jwt.JoseJwtConsumer;
 import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
 import org.apache.cxf.rs.security.jose.jwt.JwtToken;
 import org.apache.cxf.rs.security.oauth2.common.AccessTokenValidation;
 import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
@@ -110,10 +112,17 @@ public class JwtAccessTokenValidator extends JoseJwtConsumer implements
AccessTo
         } else if (claims.getSubject() != null) {
             atv.setTokenSubject(new UserSubject(claims.getSubject()));
         }
-        Map<String, String> extraProperties = CastUtils.cast((Map<?, ?>)claims.getClaim("extra_propertirs"));
+        Map<String, String> extraProperties = CastUtils.cast((Map<?, ?>)claims.getClaim("extra_properties"));
         if (extraProperties != null) {
             atv.getExtraProps().putAll(extraProperties);
         }
+        Map<String, Object> cnfClaim = CastUtils.cast((Map<?, ?>)claims.getClaim(JwtConstants.CLAIM_CONFIRMATION));
+        if (cnfClaim != null) {
+            Object certCnf = cnfClaim.get(JoseConstants.HEADER_X509_THUMBPRINT_SHA256);
+            if (certCnf != null) {
+                atv.getExtraProps().put(JoseConstants.HEADER_X509_THUMBPRINT_SHA256, certCnf.toString());
+            }
+        }
         
         return atv;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/0487b301/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
index 8e44e48..1fb2b67 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
@@ -30,6 +30,7 @@ import javax.ws.rs.core.MultivaluedMap;
 import org.apache.cxf.jaxrs.ext.MessageContext;
 import org.apache.cxf.rs.security.jose.common.JoseConstants;
 import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
 import org.apache.cxf.rs.security.jose.jwt.JwtToken;
 import org.apache.cxf.rs.security.oauth2.common.AccessTokenRegistration;
 import org.apache.cxf.rs.security.oauth2.common.Client;
@@ -146,7 +147,17 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider,
Cl
             }
         }
         if (!at.getExtraProperties().isEmpty()) {
-            claims.setClaim("extra_properties", at.getExtraProperties());
+            Map<String, String> actualExtraProps = new HashMap<String, String>();
+            for (Map.Entry<String, String> entry : at.getExtraProperties().entrySet())
{
+                if (JoseConstants.HEADER_X509_THUMBPRINT_SHA256.equals(entry.getKey())) {
+                    claims.setClaim(JwtConstants.CLAIM_CONFIRMATION, 
+                        Collections.singletonMap(JoseConstants.HEADER_X509_THUMBPRINT_SHA256,

+                                                 entry.getValue()));
+                } else {
+                    actualExtraProps.put(entry.getKey(), entry.getValue());
+                }
+            }
+            claims.setClaim("extra_properties", actualExtraProps);
         }
         // Can be used to check at RS/etc which grant was used to get this token issued
         if (at.getGrantType() != null) {

http://git-wip-us.apache.org/repos/asf/cxf/blob/0487b301/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/JwtTokenUtils.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/JwtTokenUtils.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/JwtTokenUtils.java
index a7b4494..baf7c58 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/JwtTokenUtils.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/JwtTokenUtils.java
@@ -24,8 +24,10 @@ import java.util.Map;
 
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
 import org.apache.cxf.rs.security.jose.jwt.JoseJwtConsumer;
 import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
 import org.apache.cxf.rs.security.oauth2.common.Client;
 import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
@@ -117,9 +119,16 @@ public final class JwtTokenUtils {
             at.setNonce(nonce);
         }
         
-        Map<String, String> extraProperties = CastUtils.cast((Map<?, ?>)claims.getClaim("extra_propertirs"));
+        Map<String, String> extraProperties = CastUtils.cast((Map<?, ?>)claims.getClaim("extra_properties"));
         if (extraProperties != null) {
             at.getExtraProperties().putAll(extraProperties);
+            Map<String, Object> cnfClaim = CastUtils.cast((Map<?, ?>)claims.getClaim(JwtConstants.CLAIM_CONFIRMATION));
+            if (cnfClaim != null) {
+                Object certCnf = cnfClaim.get(JoseConstants.HEADER_X509_THUMBPRINT_SHA256);
+                if (certCnf != null) {
+                    at.getExtraProperties().put(JoseConstants.HEADER_X509_THUMBPRINT_SHA256,
certCnf.toString());
+                }
+            }
         }
         
         return at;

http://git-wip-us.apache.org/repos/asf/cxf/blob/0487b301/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
index 0820364..2614dea 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/JAXRSOAuth2TlsTest.java
@@ -53,8 +53,8 @@ public class JAXRSOAuth2TlsTest extends AbstractBusClientServerTestBase
{
 
     @Test
     public void testTwoWayTLSClientIdIsSubjectDn() throws Exception {
-        String address = "https://localhost:" + PORT + "/oauth2/token";
-        WebClient wc = createOAuth2WebClient(address);
+        String atServiceAddress = "https://localhost:" + PORT + "/oauth2/token";
+        WebClient wc = createOAuth2WebClient(atServiceAddress);
 
         ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, new CustomGrant());
         assertNotNull(at.getTokenKey());
@@ -85,13 +85,46 @@ public class JAXRSOAuth2TlsTest extends AbstractBusClientServerTestBase
{
     
     @Test
     public void testTwoWayTLSClientIdBound() throws Exception {
-        String address = "https://localhost:" + PORT + "/oauth2/token";
-        WebClient wc = createOAuth2WebClient(address);
+        String atServiceAddress = "https://localhost:" + PORT + "/oauth2/token";
+        WebClient wc = createOAuth2WebClient(atServiceAddress);
+
+        ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, new Consumer("bound"),

+                                                               new CustomGrant());
+        assertNotNull(at.getTokenKey());
+        
+    }
+    
+    @Test
+    public void testTwoWayTLSClientIdBoundJwt() throws Exception {
+        String atServiceAddress = "https://localhost:" + PORT + "/oauth2Jwt/token";
+        WebClient wc = createOAuth2WebClient(atServiceAddress);
 
-        ClientAccessToken at = OAuthClientUtils.getAccessToken(wc,
-                                        new Consumer("bound"),
-                                        new CustomGrant());
+        ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, new Consumer("boundJwt"),

+                                                               new CustomGrant());
         assertNotNull(at.getTokenKey());
+        
+        String protectedRsAddress = "https://localhost:" + PORT + "/rsJwt/bookstore/books/123";
+        WebClient wcRs = createRsWebClient(protectedRsAddress, at, "client.xml");
+        Book book = wcRs.get(Book.class);
+        assertEquals(123L, book.getId());
+        
+        String protectedRsAddress2 = "https://localhost:" + PORT + "/rsJwt2/bookstore/books/123";
+        WebClient wcRs2 = createRsWebClient(protectedRsAddress2, at, "client.xml");
+        book = wcRs2.get(Book.class);
+        assertEquals(123L, book.getId());
+        
+        String unprotectedRsAddress = "https://localhost:" + PORT + "/rsUnprotected/bookstore/books/123";
+        WebClient wcRsDiffClientCert = createRsWebClient(unprotectedRsAddress, at, "client2.xml");
+        // Unprotected resource
+        book = wcRsDiffClientCert.get(Book.class);
+        assertEquals(123L, book.getId());
+        
+        // Protected resource, access token was created with Morphit.jks key, RS is accessed
with
+        // Bethal.jks key, thus 401 is expected
+        wcRsDiffClientCert = createRsWebClient(protectedRsAddress, at, "client2.xml");
+        assertEquals(401, wcRsDiffClientCert.get().getStatus());
+        wcRsDiffClientCert = createRsWebClient(protectedRsAddress2, at, "client2.xml");
+        assertEquals(401, wcRsDiffClientCert.get().getStatus());
     }
     
     @Test

http://git-wip-us.apache.org/repos/asf/cxf/blob/0487b301/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/OAuthDataProviderImplJwt.java
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/OAuthDataProviderImplJwt.java
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/OAuthDataProviderImplJwt.java
new file mode 100644
index 0000000..9443781
--- /dev/null
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/tls/OAuthDataProviderImplJwt.java
@@ -0,0 +1,44 @@
+/**
+ * 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.tls;
+
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.grants.code.DefaultEHCacheCodeDataProvider;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+
+/**
+ * Extend the DefaultEHCacheCodeDataProvider to allow refreshing of tokens
+ */
+public class OAuthDataProviderImplJwt extends DefaultEHCacheCodeDataProvider {
+    public OAuthDataProviderImplJwt() throws Exception {
+
+        Client client = new Client("boundJwt",
+                                   null,
+                                   true,
+                                   null,
+                                   null);
+        client.getProperties().put(OAuthConstants.TLS_CLIENT_AUTH_SUBJECT_DN, 
+                                    "CN=whateverhost.com,OU=Morpit,O=ApacheTest,L=Syracuse,C=US");
+        client.getAllowedGrantTypes().add("custom_grant");
+        this.setClient(client);
+        this.setUseJwtFormatForAccessTokens(true);
+        this.setStoreJwtTokenKeyOnly(true);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/0487b301/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
index a0db728..1d3d2e5 100644
--- a/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
+++ b/systests/rs-security/src/test/resources/org/apache/cxf/systest/jaxrs/security/oauth2/tls/serverTls.xml
@@ -63,9 +63,13 @@ under the License.
     <bean id="customGrantHandler" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CustomGrantHandler">
         <property name="dataProvider" ref="dataProvider"/>
     </bean>
+    <bean id="customGrantHandlerJwt" class="org.apache.cxf.systest.jaxrs.security.oauth2.grants.CustomGrantHandler">
+        <property name="dataProvider" ref="dataProviderJwt"/>
+    </bean>
     
     <bean id="oauthJson" class="org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider"/>
     <bean id="dataProvider" class="org.apache.cxf.systest.jaxrs.security.oauth2.tls.OAuthDataProviderImpl"/>
+    <bean id="dataProviderJwt" class="org.apache.cxf.systest.jaxrs.security.oauth2.tls.OAuthDataProviderImplJwt"/>
     <bean id="rsService" class="org.apache.cxf.systest.jaxrs.security.BookStore"/>
     
     <bean id="accessTokenService1" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
@@ -76,6 +80,15 @@ under the License.
             </list>
         </property>
     </bean>
+    <bean id="keyPasswordProvider" class="org.apache.cxf.systest.jaxrs.security.jose.jwejws.PrivateKeyPasswordProviderImpl"/>
+    <bean id="accessTokenServiceJwt" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenService">
+        <property name="dataProvider" ref="dataProviderJwt"/>
+        <property name="grantHandlers">
+            <list>
+                <ref bean="customGrantHandlerJwt"/>
+            </list>
+        </property>
+    </bean>
     
     <bean id="tokenValidatorService1" class="org.apache.cxf.rs.security.oauth2.services.AccessTokenValidatorService">
        <property name="dataProvider" ref="dataProvider"/>
@@ -86,6 +99,11 @@ under the License.
        <property name="blockUnauthorizedRequests" value="false"/>
     </bean>
     
+    <bean id="tokenIntrospectionServiceJwt" class="org.apache.cxf.rs.security.oauth2.services.TokenIntrospectionService">
+       <property name="dataProvider" ref="dataProviderJwt"/>
+       <property name="blockUnauthorizedRequests" value="false"/>
+    </bean>
+    
     <jaxrs:server id="tokenServer1" address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/oauth2">
         <jaxrs:serviceBeans>
             <ref bean="accessTokenService1"/>
@@ -94,6 +112,17 @@ under the License.
         </jaxrs:serviceBeans>
     </jaxrs:server>
     
+    <jaxrs:server id="tokenServerJwt" address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/oauth2Jwt">
+        <jaxrs:serviceBeans>
+            <ref bean="accessTokenServiceJwt"/>
+            <ref bean="tokenIntrospectionServiceJwt"/>
+        </jaxrs:serviceBeans>
+        <jaxrs:properties>
+            <entry key="rs.security.signature.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
+            <entry key="rs.security.signature.key.password.provider" value-ref="keyPasswordProvider"/>
+        </jaxrs:properties>
+    </jaxrs:server>
+    
     <jaxrs-client:client id="tokenValidatorClient1" 
         address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/oauth2/validate" 
         serviceClass="org.apache.cxf.jaxrs.client.WebClient">
@@ -128,6 +157,28 @@ under the License.
         <property name="tokenValidator" ref="tokenValidator2"/>
     </bean>
     
+    <jaxrs-client:client id="tokenValidatorClientJwt" 
+        address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/oauth2Jwt/introspect"

+        serviceClass="org.apache.cxf.jaxrs.client.WebClient">
+        <jaxrs-client:headers>
+            <entry key="Accept" value="application/json"/>
+            <entry key="Content-Type" value="application/x-www-form-urlencoded"/>
+         </jaxrs-client:headers>
+    </jaxrs-client:client>
+    
+    <bean id="tokenValidatorJwt" class="org.apache.cxf.rs.security.oauth2.filters.AccessTokenIntrospectionClient">
+       <property name="tokenValidatorClient" ref="tokenValidatorClientJwt"/>
+    </bean>
+    
+    <bean id="tokenValidatorJwtLocal" class="org.apache.cxf.rs.security.oauth2.filters.JwtAccessTokenValidator"/>
+    
+    <bean id="oauth2FilterJwt" class="org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter">
+        <property name="tokenValidator" ref="tokenValidatorJwt"/>
+    </bean>
+
+    <bean id="oauth2FilterJwtLocal" class="org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter">
+        <property name="tokenValidator" ref="tokenValidatorJwtLocal"/>
+    </bean>    
     
     <jaxrs:server id="rsServer1" address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/rs">
         <jaxrs:serviceBeans>
@@ -145,6 +196,25 @@ under the License.
             <ref bean="oauth2Filter2"/>
         </jaxrs:providers>
     </jaxrs:server>
+    <jaxrs:server id="rsServerJwt" address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/rsJwt">
+        <jaxrs:serviceBeans>
+            <ref bean="rsService"/>
+        </jaxrs:serviceBeans>
+        <jaxrs:providers>
+            <ref bean="oauth2FilterJwt"/>
+        </jaxrs:providers>
+    </jaxrs:server>
+    <jaxrs:server id="rsServerJwt2" address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/rsJwt2">
+        <jaxrs:serviceBeans>
+            <ref bean="rsService"/>
+        </jaxrs:serviceBeans>
+        <jaxrs:providers>
+            <ref bean="oauth2FilterJwtLocal"/>
+        </jaxrs:providers>
+        <jaxrs:properties>
+            <entry key="rs.security.signature.properties" value="org/apache/cxf/systest/jaxrs/security/alice.rs.properties"/>
+        </jaxrs:properties>
+    </jaxrs:server>
     <jaxrs:server id="rsServerUnprotected" address="https://localhost:${testutil.ports.jaxrs-oauth2-tls}/rsUnprotected">
         <jaxrs:serviceBeans>
             <ref bean="rsService"/>


Mime
View raw message