Repository: cxf
Updated Branches:
  refs/heads/master ba9fa0e7c -> cbb8261fc


Prototyping the X509 client cert token binding validation cvode, tests to 
follow next


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

Branch: refs/heads/master
Commit: cbb8261fc8f7261b8ef91a5931a2b343a7177d33
Parents: ba9fa0e
Author: Sergey Beryozkin <sberyoz...@gmail.com>
Authored: Thu Apr 20 16:52:54 2017 +0100
Committer: Sergey Beryozkin <sberyoz...@gmail.com>
Committed: Thu Apr 20 16:52:54 2017 +0100

----------------------------------------------------------------------
 .../oauth2/filters/OAuthRequestFilter.java         | 15 +++++++++++++++
 .../oauth2/provider/AbstractOAuthDataProvider.java | 15 +++++----------
 .../cxf/rs/security/oauth2/utils/OAuthUtils.java   | 17 +++++++++++++++--
 3 files changed, 35 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/cbb8261f/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
index 02d238f..a485c1e 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/filters/OAuthRequestFilter.java
@@ -19,6 +19,7 @@
 package org.apache.cxf.rs.security.oauth2.filters;
 
 import java.security.Principal;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -46,6 +47,7 @@ import org.apache.cxf.jaxrs.utils.JAXRSUtils;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
 import org.apache.cxf.rs.security.oauth2.common.AccessTokenValidation;
 import org.apache.cxf.rs.security.oauth2.common.AuthenticationMethod;
 import org.apache.cxf.rs.security.oauth2.common.OAuthContext;
@@ -56,6 +58,7 @@ import 
org.apache.cxf.rs.security.oauth2.utils.AuthorizationUtils;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
 import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
 import org.apache.cxf.security.SecurityContext;
+import org.apache.cxf.security.transport.TLSSessionInfo;
 
 /**
  * JAX-RS OAuth2 filter which can be used to protect the end-user endpoints
@@ -154,6 +157,15 @@ public class OAuthRequestFilter extends 
AbstractAccessTokenValidator
             throw ExceptionUtils.toForbiddenException(null, null);
 
         }
+        // Check Client Certificate Binding if any
+        String certThumbprint = 
accessTokenV.getExtraProps().get(JoseConstants.HEADER_X509_THUMBPRINT_SHA256);
+        if (certThumbprint != null) {
+            TLSSessionInfo tlsInfo = getTlsSessionInfo();
+            X509Certificate cert = tlsInfo == null ? null : 
OAuthUtils.getRootTLSCertificate(tlsInfo);
+            if (!OAuthUtils.compareCertificateThumbprints(cert, 
certThumbprint)) { 
+                throw ExceptionUtils.toForbiddenException(null, null);
+            }
+        }
 
         // Create the security context and make it available on the message
         SecurityContext sc = createSecurityContext(req, accessTokenV);
@@ -346,4 +358,7 @@ public class OAuthRequestFilter extends 
AbstractAccessTokenValidator
         this.issuer = issuer;
     }
 
+    private TLSSessionInfo getTlsSessionInfo() {
+        return 
(TLSSessionInfo)getMessageContext().get(TLSSessionInfo.class.getName());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/cbb8261f/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 22568cb..75e24d4 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,7 +30,6 @@ 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;
@@ -89,22 +88,18 @@ public abstract class AbstractOAuthDataProvider implements 
OAuthDataProvider, Cl
         at.setGrantCode(atReg.getGrantCode());
         at.getExtraProperties().putAll(atReg.getExtraProperties());
 
-        String certCnf = null;
         if (messageContext != null) {
-            certCnf = 
(String)messageContext.get(JoseConstants.HEADER_X509_THUMBPRINT_SHA256);
+            String certCnf = 
(String)messageContext.get(JoseConstants.HEADER_X509_THUMBPRINT_SHA256);
+            if (certCnf != null) {
+                // At a later stage we will likely introduce a dedicate 
Confirmation bean (as it is used in POP etc)
+                
at.getExtraProperties().put(JoseConstants.HEADER_X509_THUMBPRINT_SHA256, 
certCnf);
+            }
         }
         
         if (isUseJwtFormatForAccessTokens()) {
             JwtClaims claims = createJwtAccessToken(at);
-            // At a later stage we will likely introduce a dedicate 
Confirmation bean (as it is used in POP etc) 
-            if (certCnf != null) {
-                claims.setClaim(JwtConstants.CLAIM_CONFIRMATION, 
-                            
Collections.singletonMap(JoseConstants.HEADER_X509_THUMBPRINT_SHA256, certCnf));
-            }
             String jose = processJwtAccessToken(claims);
             at.setTokenKey(jose);
-        } else if (certCnf != null) {
-            
at.getExtraProperties().put(JoseConstants.HEADER_X509_THUMBPRINT_SHA256, 
certCnf);
         }
 
         return at;

http://git-wip-us.apache.org/repos/asf/cxf/blob/cbb8261f/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java
----------------------------------------------------------------------
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 66eac5a..6e38944 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
@@ -19,6 +19,7 @@
 package org.apache.cxf.rs.security.oauth2.utils;
 
 import java.lang.reflect.Method;
+import java.security.MessageDigest;
 import java.security.Principal;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
@@ -74,11 +75,13 @@ public final class OAuthUtils {
     private OAuthUtils() {
     }
 
+    public static byte[] createCertificateThumbprint(X509Certificate cert) 
throws Exception {
+        return MessageDigestUtils.createDigest(cert.getEncoded(), 
MessageDigestUtils.ALGO_SHA_256);
+    }
 
     public static void setCertificateThumbprintConfirmation(MessageContext mc, 
X509Certificate cert) {
         try {
-            byte[] thumbprint = 
-                MessageDigestUtils.createDigest(cert.getEncoded(), 
MessageDigestUtils.ALGO_SHA_256);
+            byte[] thumbprint = createCertificateThumbprint(cert);
             String encodedThumbprint = Base64UrlUtility.encode(thumbprint);
             mc.put(JoseConstants.HEADER_X509_THUMBPRINT_SHA256, 
encodedThumbprint);
         } catch (Exception ex) {
@@ -86,6 +89,16 @@ public final class OAuthUtils {
         }
     }
     
+    public static boolean compareCertificateThumbprints(X509Certificate cert, 
String encodedThumbprint) {
+        try {
+            byte[] thumbprint = createCertificateThumbprint(cert);
+            byte[] currentThumbrint = 
Base64UrlUtility.decode(encodedThumbprint);
+            return MessageDigest.isEqual(thumbprint, currentThumbrint);
+        } catch (Exception ex) {
+            return false;
+        }
+    }
+    
 
     public static boolean compareTlsCertificates(TLSSessionInfo tlsInfo,
                                           List<String> base64EncodedCerts) {

Reply via email to