cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From serg...@apache.org
Subject git commit: [CXF-5705] Better support for the client authentication, including 2-way TLS
Date Tue, 29 Apr 2014 16:10:22 GMT
Repository: cxf
Updated Branches:
  refs/heads/master e2eacb217 -> 5f1a556bd


[CXF-5705] Better support for the client authentication, including 2-way TLS


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

Branch: refs/heads/master
Commit: 5f1a556bda9d4eb50c3dae1de2b0408ae461ea99
Parents: e2eacb2
Author: Sergey Beryozkin <sberyozkin@talend.com>
Authored: Tue Apr 29 17:10:01 2014 +0100
Committer: Sergey Beryozkin <sberyozkin@talend.com>
Committed: Tue Apr 29 17:10:01 2014 +0100

----------------------------------------------------------------------
 .../cxf/rs/security/oauth2/common/Client.java   |  49 +++++--
 .../oauth2/common/ClientCredentialType.java     |  25 ++++
 .../oauth2/provider/ClientIdProvider.java       |  37 +++++
 .../oauth2/services/AbstractTokenService.java   | 138 +++++++++++++++----
 .../services/AuthorizationCodeGrantService.java |   2 +-
 .../oauth2/utils/ModelEncryptionSupport.java    |  27 ++--
 .../oauth2/utils/EncryptionUtilsTest.java       |   2 +-
 .../jaxrs/security/oauth2/JAXRSOAuth2Test.java  |   9 ++
 .../security/oauth2/OAuthDataProviderImpl.java  |  24 +++-
 9 files changed, 263 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
index ba0e20b..6ac8145 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
@@ -32,9 +32,8 @@ public class Client implements Serializable {
     private static final long serialVersionUID = -5550840247125850922L;
     
     private String clientId;
-    // TODO: Consider introducing ClientCredentials instead
-    // so that a secret, public key, etc can be kept
-    private String clientSecret;
+    private String clientCred;
+    private ClientCredentialType clientCredentialType = ClientCredentialType.PASSWORD;
     
     private String applicationName;
     private String applicationDescription;
@@ -54,23 +53,33 @@ public class Client implements Serializable {
         
     }
     
-    public Client(String clientId, String clientSecret, boolean isConfidential) {
+    public Client(String clientId, String clientCred, boolean isConfidential) {
         this.clientId = clientId;
-        this.clientSecret = clientSecret;
+        this.clientCred = clientCred;
         this.isConfidential = isConfidential;
     }
 
     public Client(String clientId, 
-                  String clientSecret,
+                  String clientCred,
                   boolean isConfidential,
                   String applicationName,
                   String applicationWebUri) {
-        this(clientId, clientSecret, isConfidential);
+        this(clientId, clientCred, isConfidential);
         this.applicationName = applicationName;
         this.applicationWebUri = applicationWebUri;
         
     }
     
+    public Client(String clientId, 
+                  String clientCred,
+                  ClientCredentialType clientCredType,
+                  boolean isConfidential,
+                  String applicationName,
+                  String applicationWebUri) {
+        this(clientId, clientCred, isConfidential, applicationName, applicationWebUri);
+        this.clientCredentialType = clientCredType;
+    }
+    
     /**
      * Gets the client registration id
      * @return the consumer key
@@ -87,12 +96,26 @@ public class Client implements Serializable {
      * Gets the client secret
      * @return the secret
      */
+    @Deprecated
     public String getClientSecret() {
-        return clientSecret;
+        return clientCred;
     }
 
+    @Deprecated
     public void setClientSecret(String secret) {
-        this.clientSecret = secret;
+        this.clientCred = secret;
+    }
+    
+    /**
+     * Gets the client credential
+     * @return the secret
+     */
+    public String getClientCredential() {
+        return clientCred;
+    }
+
+    public void setClientCredential(String cred) {
+        this.clientCred = cred;
     }
     
     /**
@@ -279,4 +302,12 @@ public class Client implements Serializable {
     public void setRegisteredAudiences(List<String> registeredAudiences) {
         this.registeredAudiences = registeredAudiences;
     }
+
+    public ClientCredentialType getClientCredentialType() {
+        return clientCredentialType;
+    }
+
+    public void setClientCredentialType(ClientCredentialType clientCredentialType) {
+        this.clientCredentialType = clientCredentialType;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ClientCredentialType.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ClientCredentialType.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ClientCredentialType.java
new file mode 100644
index 0000000..367b612
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ClientCredentialType.java
@@ -0,0 +1,25 @@
+/**
+ * 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.rs.security.oauth2.common;
+
+public enum ClientCredentialType {
+    PASSWORD,
+    X509CERTIFICATE,
+    PUBLIC_KEY
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/ClientIdProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/ClientIdProvider.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/ClientIdProvider.java
new file mode 100644
index 0000000..f0b9a7a
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/ClientIdProvider.java
@@ -0,0 +1,37 @@
+/**
+ * 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.rs.security.oauth2.provider;
+
+import org.apache.cxf.jaxrs.ext.MessageContext;
+
+/**
+ * ClientIdProvider responsible for providing a mapping between
+ * the authenticated client and its id  
+ */
+public interface ClientIdProvider {
+
+    /**
+     * Get a client id
+     * 
+     * @param mc the {@link MessageContext} of this request
+     * @return the client id
+     */
+    String getClientId(MessageContext mc);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
----------------------------------------------------------------------
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 0ef9008..f3068bf 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
@@ -20,24 +20,34 @@
 package org.apache.cxf.rs.security.oauth2.services;
 
 import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
 
+import javax.security.auth.x500.X500Principal;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.SecurityContext;
 
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.common.util.StringUtils;
 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.ClientCredentialType;
 import org.apache.cxf.rs.security.oauth2.common.OAuthError;
+import org.apache.cxf.rs.security.oauth2.provider.ClientIdProvider;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
 import org.apache.cxf.rs.security.oauth2.utils.AuthorizationUtils;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
+import org.apache.cxf.security.transport.TLSSessionInfo;
 
 public class AbstractTokenService extends AbstractOAuthService {
     private boolean canSupportPublicClients;
     private boolean writeCustomErrors;
+    private ClientIdProvider clientIdProvider;
     
     /**
      * Make sure the client is authenticated
@@ -47,36 +57,36 @@ public class AbstractTokenService extends AbstractOAuthService {
         SecurityContext sc = getMessageContext().getSecurityContext();
         
         if (params.containsKey(OAuthConstants.CLIENT_ID)) {
-            // both client_id and client_secret are expected in the form payload
+            // Both client_id and client_secret are expected in the form payload
             client = getAndValidateClient(params.getFirst(OAuthConstants.CLIENT_ID),
                                           params.getFirst(OAuthConstants.CLIENT_SECRET));
         } else if (sc.getUserPrincipal() != null) {
-            // client has already authenticated
+            // Client has already been authenticated
             Principal p = sc.getUserPrincipal();
-            String scheme = sc.getAuthenticationScheme();
-            if (OAuthConstants.BASIC_SCHEME.equalsIgnoreCase(scheme)) {
-                // section 2.3.1
+            if (p.getName() != null) {
                 client = getClient(p.getName());
             } else {
-                // section 2.3.2
-                // the client has authenticated itself using some other scheme
-                // in which case the mapping between the scheme and the client_id
-                // should've been done and the client_id is expected
-                // on the current message
-                Object clientIdProp = getMessageContext().get(OAuthConstants.CLIENT_ID);
-                if (clientIdProp != null) {
-                    client = getClient(clientIdProp.toString());
-                    // TODO: consider matching client.getUserSubject().getLoginName() 
-                    // against principal.getName() ?
+                // Most likely a container-level authentication, possibly 2-way TLS, 
+                // Check if the mapping between Principal and Client Id has been done in
a filter
+                String clientId = (String)getMessageContext().get(OAuthConstants.CLIENT_ID);
+                if (StringUtils.isEmpty(clientId) && clientIdProvider != null) {
+                    // Check Custom ClientIdProvider
+                    clientId = clientIdProvider.getClientId(getMessageContext());
                 }
+                if (!StringUtils.isEmpty(clientId)) {
+                    client = getClient(clientId);
+                } 
             }
-        } else {
-            // the client id and secret are expected to be in the Basic scheme data
-            String[] parts = 
-                AuthorizationUtils.getAuthorizationParts(getMessageContext());
-            if (OAuthConstants.BASIC_SCHEME.equalsIgnoreCase(parts[0])) {
-                String[] authInfo = AuthorizationUtils.getBasicAuthParts(parts[1]);
-                client = getAndValidateClient(authInfo[0], authInfo[1]);
+        } 
+        
+        if (client == null) {
+            TLSSessionInfo tlsSessionInfo = 
+                (TLSSessionInfo)getMessageContext().get(TLSSessionInfo.class.getName());
+            if (tlsSessionInfo != null) {
+                client = getClientFromTLSCertificates(sc, tlsSessionInfo);
+            } else {
+                // Basic Authentication is expected by default
+                client = getClientFromBasicAuthScheme();
             }
         }
         
@@ -89,20 +99,94 @@ public class AbstractTokenService extends AbstractOAuthService {
     // Get the Client and check the id and secret
     protected Client getAndValidateClient(String clientId, String clientSecret) {
         Client client = getClient(clientId);
+        if (clientSecret != null 
+            && (client.getClientCredentialType() == null 
+            || !ClientCredentialType.PASSWORD.equals(client.getClientCredentialType())))
{
+            throw ExceptionUtils.toNotAuthorizedException(null, null);
+        }
         if (canSupportPublicClients 
             && !client.isConfidential() 
-            && client.getClientSecret() == null 
+            && client.getClientCredential() == null 
             && clientSecret == null) {
             return client;
         }
-        if (clientSecret == null || client.getClientSecret() == null 
+        if (clientSecret == null || client.getClientCredential() == null 
             || !client.getClientId().equals(clientId) 
-            || !client.getClientSecret().equals(clientSecret)) {
+            || !client.getClientCredential().equals(clientSecret)) {
             throw ExceptionUtils.toNotAuthorizedException(null, null);
         }
         return client;
     }
     
+    protected Client getClientFromBasicAuthScheme() {
+        String[] parts = AuthorizationUtils.getAuthorizationParts(getMessageContext());
+        if (OAuthConstants.BASIC_SCHEME.equalsIgnoreCase(parts[0])) {
+            String[] authInfo = AuthorizationUtils.getBasicAuthParts(parts[1]);
+            return getAndValidateClient(authInfo[0], authInfo[1]);
+        } else {
+            return null;
+        }
+    }
+    
+    protected Client getClientFromTLSCertificates(SecurityContext sc, TLSSessionInfo tlsSessionInfo)
{
+        Client client = null;
+        if (tlsSessionInfo != null) {
+            String authScheme = sc.getAuthenticationScheme();
+            if (StringUtils.isEmpty(authScheme)) {
+                // Pure 2-way TLS authentication
+                String clientId = getClientIdFromTLSCertificates(sc, tlsSessionInfo);
+                if (!StringUtils.isEmpty(clientId)) {
+                    client = getClient(clientId);
+                    // Validate the client identified from certificates
+                    validateTwoWayTlsClient(sc, tlsSessionInfo, client);
+                }
+            } else if (OAuthConstants.BASIC_SCHEME.equalsIgnoreCase(authScheme)) {
+                // Basic Authentication on top of 2-way TLS
+                client = getClientFromBasicAuthScheme();    
+            }
+        }
+        return client;
+    }
+    
+    protected String getClientIdFromTLSCertificates(SecurityContext sc, TLSSessionInfo tlsInfo)
{
+        Certificate[] clientCerts = tlsInfo.getPeerCertificates();
+        if (clientCerts != null && clientCerts.length > 0) {
+            X500Principal x509Principal = ((X509Certificate)clientCerts[0]).getSubjectX500Principal();
+            return x509Principal.getName();    
+        }
+        return null;
+    }
+    
+    protected void validateTwoWayTlsClient(SecurityContext sc, TLSSessionInfo tlsSessionInfo,
Client client) {
+        ClientCredentialType credType = client.getClientCredentialType();
+        if (credType != ClientCredentialType.X509CERTIFICATE && credType != ClientCredentialType.PUBLIC_KEY)
{
+            reportInvalidClient();
+        } else if (client.getClientCredential() != null) {
+            // Client has a Base64 encoded representation of the certificate loaded
+            // so lets validate the TLS certificates
+            compareCertificates(tlsSessionInfo, client.getClientCredential(), credType);
+        }
+    }
+    
+    protected void compareCertificates(TLSSessionInfo tlsInfo, 
+                                       String base64EncodedCert,
+                                       ClientCredentialType type) {
+        Certificate[] clientCerts = tlsInfo.getPeerCertificates();
+        try {
+            X509Certificate cert = (X509Certificate)clientCerts[0];
+            byte[] encodedKey = type == ClientCredentialType.PUBLIC_KEY 
+                ? cert.getPublicKey().getEncoded() : cert.getEncoded();
+            byte[] clientKey = Base64Utility.decode(base64EncodedCert);
+            if (Arrays.equals(encodedKey, clientKey)) {
+                return;
+            }
+        } catch (Exception ex) {
+            reportInvalidClient();
+        }
+    }
+    
+    
+    
     protected Response handleException(OAuthServiceException ex, String error) {
         OAuthError customError = ex.getError();
         if (writeCustomErrors && customError != null) {
@@ -168,4 +252,8 @@ public class AbstractTokenService extends AbstractOAuthService {
     public void setWriteCustomErrors(boolean writeCustomErrors) {
         this.writeCustomErrors = writeCustomErrors;
     }
+
+    public void setClientIdProvider(ClientIdProvider clientIdProvider) {
+        this.clientIdProvider = clientIdProvider;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
index a4b48ce..a345204 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AuthorizationCodeGrantService.java
@@ -126,7 +126,7 @@ public class AuthorizationCodeGrantService extends RedirectionBasedGrantService
 
     @Override
     protected boolean canSupportPublicClient(Client c) {
-        return canSupportPublicClients && !c.isConfidential() && c.getClientSecret()
== null;
+        return canSupportPublicClients && !c.isConfidential() && c.getClientCredential()
== null;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/ModelEncryptionSupport.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/ModelEncryptionSupport.java
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/ModelEncryptionSupport.java
index 6f7872c..a6dd2bb 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/ModelEncryptionSupport.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/ModelEncryptionSupport.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import javax.crypto.SecretKey;
 
 import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.ClientCredentialType;
 import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
 import org.apache.cxf.rs.security.oauth2.common.UserSubject;
@@ -322,16 +323,17 @@ public final class ModelEncryptionSupport {
 
     private static Client recreateClientInternal(String sequence) {
         String[] parts = getParts(sequence);
-        Client c = new Client(parts[0], parts[1], Boolean.valueOf(parts[2]), 
-                              getStringPart(parts[3]), getStringPart(parts[4]));
-        c.setApplicationDescription(getStringPart(parts[5]));
-        c.setApplicationLogoUri(getStringPart(parts[6]));
-        c.setAllowedGrantTypes(parseSimpleList(parts[7]));
-        c.setRegisteredScopes(parseSimpleList(parts[8]));
-        c.setRedirectUris(parseSimpleList(parts[9]));
-        c.setRegisteredAudiences(parseSimpleList(parts[10]));
-        c.setProperties(parseSimpleMap(parts[11]));
-        c.setSubject(recreateUserSubject(parts[12]));
+        Client c = new Client(parts[0], parts[1], ClientCredentialType.valueOf(parts[2]),

+                              Boolean.valueOf(parts[3]), 
+                              getStringPart(parts[4]), getStringPart(parts[5]));
+        c.setApplicationDescription(getStringPart(parts[6]));
+        c.setApplicationLogoUri(getStringPart(parts[7]));
+        c.setAllowedGrantTypes(parseSimpleList(parts[8]));
+        c.setRegisteredScopes(parseSimpleList(parts[9]));
+        c.setRedirectUris(parseSimpleList(parts[10]));
+        c.setRegisteredAudiences(parseSimpleList(parts[11]));
+        c.setProperties(parseSimpleMap(parts[12]));
+        c.setSubject(recreateUserSubject(parts[13]));
         return c; 
     }
     private static String tokenizeClient(Client client) {
@@ -340,7 +342,10 @@ public final class ModelEncryptionSupport {
         state.append(tokenizeString(client.getClientId()));
         state.append(SEP);
         // 1: secret
-        state.append(tokenizeString(client.getClientSecret()));
+        state.append(tokenizeString(client.getClientCredential()));
+        state.append(SEP);
+        // 1.1: secret type
+        state.append(tokenizeString(client.getClientCredentialType().toString()));
         state.append(SEP);
         // 2: confidentiality
         state.append(client.isConfidential());

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/EncryptionUtilsTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/EncryptionUtilsTest.java
b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/EncryptionUtilsTest.java
index 30d2d45..47a2f80 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/EncryptionUtilsTest.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/utils/EncryptionUtilsTest.java
@@ -179,7 +179,7 @@ public class EncryptionUtilsTest extends Assert {
                                                   new ByteArrayInputStream(decrypted.getBytes()));
         
         assertEquals(c.getClientId(), c2.getClientId());
-        assertEquals(c.getClientSecret(), c2.getClientSecret());
+        assertEquals(c.getClientCredential(), c2.getClientCredential());
         assertTrue(c2.isConfidential());
         assertEquals("subject", c2.getSubject().getLogin());
         assertEquals("id", c2.getSubject().getId());

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java
index 10db4a9..500037e 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java
@@ -101,6 +101,15 @@ public class JAXRSOAuth2Test extends AbstractBusClientServerTestBase
{
     }
     
     @Test
+    public void testTwoWayTLSAuthentication() throws Exception {
+        String address = "https://localhost:" + PORT + "/oauth2/token";
+        WebClient wc = createWebClient(address);
+        
+        ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, new CustomGrant());
+        assertNotNull(at.getTokenKey());
+    }
+    
+    @Test
     public void testSAML2BearerAuthenticationInterceptor() throws Exception {
         String address = "https://localhost:" + PORT + "/oauth2-auth/token";
         WebClient wc = createWebClientWithProps(address);

http://git-wip-us.apache.org/repos/asf/cxf/blob/5f1a556b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/OAuthDataProviderImpl.java
----------------------------------------------------------------------
diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/OAuthDataProviderImpl.java
b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/OAuthDataProviderImpl.java
index d811e07..460129a 100644
--- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/OAuthDataProviderImpl.java
+++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/OAuthDataProviderImpl.java
@@ -18,10 +18,13 @@
  */
 package org.apache.cxf.systest.jaxrs.security.oauth2;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.cxf.rs.security.oauth2.common.AccessTokenRegistration;
 import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.ClientCredentialType;
 import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
 import org.apache.cxf.rs.security.oauth2.common.UserSubject;
@@ -33,12 +36,27 @@ import org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken;
 
 public class OAuthDataProviderImpl implements OAuthDataProvider {
 
-    @Override
-    public Client getClient(String clientId) throws OAuthServiceException {
+    private Map<String, Client> clients = new HashMap<String, Client>();
+    
+    public OAuthDataProviderImpl() {
         Client client = new Client("alice", "alice", true);
         client.getAllowedGrantTypes().add(Constants.SAML2_BEARER_GRANT);
         client.getAllowedGrantTypes().add("custom_grant");
-        return client;
+        clients.put(client.getClientId(), client);
+        
+        Client client2 = new Client("CN=whateverhost.com,OU=Morpit,O=ApacheTest,L=Syracuse,C=US",

+                                    null,
+                                    ClientCredentialType.X509CERTIFICATE,
+                                    true,
+                                    null,
+                                    null);
+        client.getAllowedGrantTypes().add("custom_grant");
+        clients.put(client2.getClientId(), client2);
+    }
+    
+    @Override
+    public Client getClient(String clientId) throws OAuthServiceException {
+        return clients.get(clientId);
     }
 
     @Override


Mime
View raw message