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 2016/02/29 18:15:35 UTC

cxf-fediz git commit: Get keys from a remote URI to validate IdTokens

Repository: cxf-fediz
Updated Branches:
  refs/heads/master 2dd2567fe -> c1d860563


Get keys from a remote URI to validate IdTokens


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

Branch: refs/heads/master
Commit: c1d860563a1a8c0b6128f523db7a57884d278044
Parents: 2dd2567
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Feb 29 17:15:14 2016 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Feb 29 17:15:14 2016 +0000

----------------------------------------------------------------------
 .../TrustedIdpOIDCProtocolHandler.java          | 75 ++++++++++++++++----
 1 file changed, 62 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/c1d86056/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java
----------------------------------------------------------------------
diff --git a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java
index 0a25c54..9075012 100644
--- a/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java
+++ b/services/idp/src/main/java/org/apache/cxf/fediz/service/idp/protocols/TrustedIdpOIDCProtocolHandler.java
@@ -55,7 +55,11 @@ import org.apache.cxf.interceptor.LoggingInInterceptor;
 import org.apache.cxf.interceptor.LoggingOutInterceptor;
 import org.apache.cxf.jaxrs.client.ClientConfiguration;
 import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.jose.common.JoseConstants;
+import org.apache.cxf.rs.security.jose.jaxrs.JsonWebKeysProvider;
 import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKey;
+import org.apache.cxf.rs.security.jose.jwk.JsonWebKeys;
 import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
 import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
 import org.apache.cxf.rs.security.jose.jwt.JwtToken;
@@ -116,6 +120,11 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler
      */
     public static final String SCOPE = "scope";
     
+    /**
+     * The URI from which to retrieve the JSON Web Keys to validate the signed IdToken.
+     */
+    public static final String JWKS_URI = "jwks.uri";
+    
     public static final String PROTOCOL = "openid-connect-1.0";
 
     private static final Logger LOG = LoggerFactory.getLogger(TrustedIdpOIDCProtocolHandler.class);
@@ -143,7 +152,7 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler
         String scope = getProperty(trustedIdp, SCOPE);
         if (scope != null) {
             scope = scope.trim();
-            if (!scope.startsWith("openid")) {
+            if (!scope.contains("openid")) {
                 scope = "openid " + scope;
             }
         }
@@ -234,12 +243,6 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler
             }
             
             try {
-                X509Certificate validatingCert = getCertificate(trustedIdp.getCertificate());
-                if (validatingCert == null) {
-                    LOG.warn("No X.509 Certificate configured for signature validation");
-                    return null;
-                }
-                
                 String whr = (String) WebUtils.getAttributeFromFlowScope(context,
                                                                          FederationConstants.PARAM_HOME_REALM);
                 if (whr == null) {
@@ -265,12 +268,7 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler
                     }
                 }
                 
-                // Validate the Signature
-                String sigAlgo = getProperty(trustedIdp, SIGNATURE_ALGORITHM);
-                if (sigAlgo == null || sigAlgo.isEmpty()) {
-                    sigAlgo = "RS256";
-                }
-                if (!jwtConsumer.verifySignatureWith(validatingCert, SignatureAlgorithm.getAlgorithm(sigAlgo))) {
+                if (!validateSignature(trustedIdp, jwtConsumer)) {
                     LOG.warn("Signature does not validate");
                     return null;
                 }
@@ -335,6 +333,57 @@ public class TrustedIdpOIDCProtocolHandler implements TrustedIdpProtocolHandler
         JwtUtils.validateTokenClaims(jwt.getClaims(), 300, 0, false);
     }
     
+    private boolean validateSignature(TrustedIdp trustedIdp, JwsJwtCompactConsumer jwtConsumer) 
+        throws CertificateException, WSSecurityException, Base64DecodingException, 
+            ProcessingException, IOException {
+        
+        // Validate the Signature
+        String sigAlgo = getProperty(trustedIdp, SIGNATURE_ALGORITHM);
+        if (sigAlgo == null || sigAlgo.isEmpty()) {
+            sigAlgo = "RS256";
+        }
+        
+        JwtToken jwt = jwtConsumer.getJwtToken();
+        String jwksUri = getProperty(trustedIdp, JWKS_URI);
+        JsonWebKey verifyingKey = null;
+        
+        if (jwksUri != null && jwt.getJwsHeaders() != null 
+            && jwt.getJwsHeaders().containsHeader(JoseConstants.HEADER_KEY_ID)) {
+            String kid = (String)jwt.getJwsHeaders().getHeader(JoseConstants.HEADER_KEY_ID);
+            LOG.debug("Attemping to retrieve key id {} from uri {}", kid, jwksUri);
+            List<Object> jsonKeyProviders = new ArrayList<Object>();
+            jsonKeyProviders.add(new JsonWebKeysProvider());
+            
+            WebClient client = 
+                WebClient.create(jwksUri, jsonKeyProviders, "cxf-tls.xml");
+            client.accept("application/json");
+            
+            ClientConfiguration config = WebClient.getConfig(client);
+            if (LOG.isDebugEnabled()) {
+                config.getOutInterceptors().add(new LoggingOutInterceptor());
+                config.getInInterceptors().add(new LoggingInInterceptor());
+            }
+            
+            Response response = client.get();
+            JsonWebKeys jsonWebKeys = response.readEntity(JsonWebKeys.class);
+            if (jsonWebKeys != null) {
+                verifyingKey = jsonWebKeys.getKey(kid);
+            }
+        }
+        
+        if (verifyingKey != null) {
+            return jwtConsumer.verifySignatureWith(verifyingKey, SignatureAlgorithm.getAlgorithm(sigAlgo));
+        }
+        
+        X509Certificate validatingCert = getCertificate(trustedIdp.getCertificate());
+        if (validatingCert != null) {
+            return jwtConsumer.verifySignatureWith(validatingCert, SignatureAlgorithm.getAlgorithm(sigAlgo));
+        }
+        
+        LOG.warn("No key supplied to verify the signature of the IdToken");
+        return false;
+    }
+    
     private Crypto getCrypto(String certificate) throws ProcessingException {
         if (certificate == null) {
             return null;