Repository: cxf
Updated Branches:
  refs/heads/master 7bf10fc3f -> 6cd954781


Optional support for using OAuth2 client secret or certs for JWS/JWE


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

Branch: refs/heads/master
Commit: 6cd954781734df6645867ca5208a7032c103c1e4
Parents: 7bf10fc
Author: Sergey Beryozkin <sberyoz...@talend.com>
Authored: Fri Dec 5 14:20:23 2014 +0000
Committer: Sergey Beryozkin <sberyoz...@talend.com>
Committed: Fri Dec 5 14:20:23 2014 +0000

----------------------------------------------------------------------
 .../cxf/rs/security/jose/jws/JwsUtils.java      |  25 +++--
 .../grants/code/JwtRequestCodeFilter.java       |  47 +++++++-
 .../oauth2/grants/code/JwtRequestCodeGrant.java |  45 ++++++--
 .../oidc/idp/AbstractJwsJweProducer.java        |  97 +++++++++++++++++
 .../oidc/idp/UserInfoCodeResponseFilter.java    |  60 +++++++++++
 .../rs/security/oidc/idp/UserInfoProvider.java  |  31 ++++++
 .../rs/security/oidc/idp/UserInfoService.java   |  80 ++++++++++++++
 .../oidc/rp/AbstractTokenValidator.java         |  15 +--
 .../oidc/rp/idp/UserInfoCodeResponseFilter.java |  83 --------------
 .../security/oidc/rp/idp/UserInfoProvider.java  |  31 ------
 .../security/oidc/rp/idp/UserInfoService.java   | 108 -------------------
 11 files changed, 374 insertions(+), 248 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
 
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
index aef782a..20058ad 100644
--- 
a/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
+++ 
b/rt/rs/security/jose/src/main/java/org/apache/cxf/rs/security/jose/jws/JwsUtils.java
@@ -207,11 +207,11 @@ public final class JwsUtils {
         if 
(JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE)))
 {
             JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, 
JsonWebKey.KEY_OPER_SIGN);
             if (jwk != null) {
-                rsaSignatureAlgo = getSignatureAlgo(m, props, 
jwk.getAlgorithm());
+                rsaSignatureAlgo = getSignatureAlgo(m, props, 
jwk.getAlgorithm(), getDefaultKeyAlgo(jwk));
                 theSigProvider = JwsUtils.getSignatureProvider(jwk, 
rsaSignatureAlgo);
             }
         } else {
-            rsaSignatureAlgo = getSignatureAlgo(m, props, null);
+            rsaSignatureAlgo = getSignatureAlgo(m, props, null, null);
             RSAPrivateKey pk = 
(RSAPrivateKey)KeyManagementUtils.loadPrivateKey(m, props, 
                 JsonWebKey.KEY_OPER_SIGN);
             theSigProvider = getRSAKeySignatureProvider(pk, rsaSignatureAlgo);
@@ -228,12 +228,12 @@ public final class JwsUtils {
         if 
(JwkUtils.JWK_KEY_STORE_TYPE.equals(props.get(KeyManagementUtils.RSSEC_KEY_STORE_TYPE)))
 {
             JsonWebKey jwk = JwkUtils.loadJsonWebKey(m, props, 
JsonWebKey.KEY_OPER_VERIFY);
             if (jwk != null) {
-                rsaSignatureAlgo = getSignatureAlgo(m, props, 
jwk.getAlgorithm());
+                rsaSignatureAlgo = getSignatureAlgo(m, props, 
jwk.getAlgorithm(), getDefaultKeyAlgo(jwk));
                 theVerifier = JwsUtils.getSignatureVerifier(jwk, 
rsaSignatureAlgo);
             }
             
         } else {
-            rsaSignatureAlgo = getSignatureAlgo(m, props, null);
+            rsaSignatureAlgo = getSignatureAlgo(m, props, null, null);
             theVerifier = getRSAKeySignatureVerifier(
                               
(RSAPublicKey)KeyManagementUtils.loadPublicKey(m, props), rsaSignatureAlgo);
         }
@@ -249,13 +249,24 @@ public final class JwsUtils {
             throw new SecurityException(ex);
         }
     }
-    private static String getSignatureAlgo(Message m, Properties props, String 
algo) {
+    private static String getSignatureAlgo(Message m, Properties props, String 
algo, String defaultAlgo) {
         if (algo == null) {
-            return KeyManagementUtils.getKeyAlgorithm(m, props, 
-                                               JSON_WEB_SIGNATURE_ALGO_PROP, 
JoseConstants.RS_SHA_256_ALGO);
+            if (defaultAlgo == null) {
+                defaultAlgo = JoseConstants.RS_SHA_256_ALGO;
+            }
+            return KeyManagementUtils.getKeyAlgorithm(m, props, 
JSON_WEB_SIGNATURE_ALGO_PROP, defaultAlgo);
         }
         return algo;
     }
+    private static String getDefaultKeyAlgo(JsonWebKey jwk) {
+        if (JsonWebKey.KEY_TYPE_OCTET.equals(jwk.getKeyType())) {
+            return JoseConstants.HMAC_SHA_256_ALGO;
+        } else if (JsonWebKey.KEY_TYPE_ELLIPTIC.equals(jwk.getKeyType())) {
+            return JoseConstants.ES_SHA_256_ALGO;
+        } else {
+            return JoseConstants.RS_SHA_256_ALGO;
+        }
+    }
     private static JwsCompactConsumer verify(JwsSignatureVerifier v, String 
content) {
         JwsCompactConsumer jws = new JwsCompactConsumer(content);
         if (!jws.verifySignatureWith(v)) {

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeFilter.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeFilter.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeFilter.java
index 3e43cf9..73f0022 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeFilter.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeFilter.java
@@ -18,11 +18,16 @@
  */
 package org.apache.cxf.rs.security.oauth2.grants.code;
 
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
 import java.util.Map;
 
+import javax.crypto.SecretKey;
 import javax.ws.rs.core.MultivaluedMap;
 
+import org.apache.cxf.common.util.crypto.CryptoUtils;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.rs.security.jose.JoseConstants;
 import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
 import org.apache.cxf.rs.security.jose.jwe.JweUtils;
 import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
@@ -38,6 +43,9 @@ public class JwtRequestCodeFilter implements 
AuthorizationCodeRequestFilter {
     private static final String REQUEST_PARAM = "request";
     private JweDecryptionProvider jweDecryptor;
     private JwsSignatureVerifier jwsVerifier;
+    private boolean verifyWithClientCertificates;
+    private boolean verifyWithClientSecret;
+    private boolean decryptWithClientSecret;
     private String issuer;
     @Override
     public MultivaluedMap<String, String> process(MultivaluedMap<String, 
String> params, 
@@ -45,11 +53,11 @@ public class JwtRequestCodeFilter implements 
AuthorizationCodeRequestFilter {
                                                   Client client) {
         String requestToken = params.getFirst(REQUEST_PARAM);
         if (requestToken != null) {
-            JweDecryptionProvider theJweDecryptor = 
getInitializedDecryptionProvider();
+            JweDecryptionProvider theJweDecryptor = 
getInitializedDecryptionProvider(client);
             if (theJweDecryptor != null) {
                 requestToken = 
theJweDecryptor.decrypt(requestToken).getContentText();
             }
-            JwsSignatureVerifier theSigVerifier = getInitializedSigVerifier();
+            JwsSignatureVerifier theSigVerifier = 
getInitializedSigVerifier(client);
             JwsJwtCompactConsumer consumer = new 
JwsJwtCompactConsumer(requestToken);
             if (!consumer.verifySignatureWith(theSigVerifier)) {
                 throw new SecurityException("Invalid Signature");
@@ -79,19 +87,50 @@ public class JwtRequestCodeFilter implements 
AuthorizationCodeRequestFilter {
         this.jwsVerifier = theJwsVerifier;
     }
     
-    protected JweDecryptionProvider getInitializedDecryptionProvider() {
+    protected JweDecryptionProvider getInitializedDecryptionProvider(Client c) 
{
         if (jweDecryptor != null) {
             return jweDecryptor;    
         } 
+        if (decryptWithClientSecret) {
+            SecretKey key = CryptoUtils.decodeSecretKey(c.getClientSecret());
+            return JweUtils.getDirectKeyJweDecryption(key, 
JoseConstants.A128GCM_ALGO);
+        }
         return JweUtils.loadDecryptionProvider(false);
     }
-    protected JwsSignatureVerifier getInitializedSigVerifier() {
+    protected JwsSignatureVerifier getInitializedSigVerifier(Client c) {
         if (jwsVerifier != null) {
             return jwsVerifier;    
         } 
+        if (verifyWithClientSecret) {
+            byte[] hmac = CryptoUtils.decodeSequence(c.getClientSecret());
+            return JwsUtils.getHmacSignatureVerifier(hmac, 
JoseConstants.HMAC_SHA_256_ALGO);
+        } else if (verifyWithClientCertificates) {
+            X509Certificate cert = 
+                
(X509Certificate)CryptoUtils.decodeCertificate(c.getApplicationCertificates().get(0));
+            return 
JwsUtils.getRSAKeySignatureVerifier((RSAPublicKey)cert.getPublicKey(), 
+                                                       
JoseConstants.RS_SHA_256_ALGO);
+        } 
         return JwsUtils.loadSignatureVerifier(true);
     }
     public void setIssuer(String issuer) {
         this.issuer = issuer;
     }
+    public void setVerifyWithClientCertificates(boolean 
verifyWithClientCertificates) {
+        if (verifyWithClientSecret) {
+            throw new SecurityException();          
+        }
+        this.verifyWithClientCertificates = verifyWithClientCertificates;
+    }
+    public void setVerifyWithClientSecret(boolean verifyWithClientSecret) {
+        if (decryptWithClientSecret || verifyWithClientCertificates) {
+            throw new SecurityException();          
+        }
+        this.verifyWithClientSecret = verifyWithClientSecret;
+    }
+    public void setDecryptWithClientSecret(boolean decryptWithClientSecret) {
+        if (verifyWithClientSecret) {
+            throw new SecurityException();          
+        }
+        this.decryptWithClientSecret = decryptWithClientSecret;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeGrant.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeGrant.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeGrant.java
index 5b2f8b9..7bfea42 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeGrant.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JwtRequestCodeGrant.java
@@ -20,11 +20,13 @@ package org.apache.cxf.rs.security.oauth2.grants.code;
 
 import java.net.URI;
 
+import javax.crypto.SecretKey;
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.common.util.crypto.CryptoUtils;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
-import org.apache.cxf.rs.security.jose.JoseHeaders;
+import org.apache.cxf.rs.security.jose.JoseConstants;
 import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
 import org.apache.cxf.rs.security.jose.jwe.JweUtils;
 import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
@@ -42,6 +44,9 @@ public class JwtRequestCodeGrant extends 
AuthorizationCodeGrant {
     private static final long serialVersionUID = -3738825769770411453L;
     private JwsSignatureProvider sigProvider;
     private JweEncryptionProvider encryptionProvider;
+    private String clientSecret;
+    private boolean encryptWithClientSecret;
+    private boolean signWithClientSecret;
     // can be a client id
     private String issuer;
     public JwtRequestCodeGrant() {
@@ -64,13 +69,16 @@ public class JwtRequestCodeGrant extends 
AuthorizationCodeGrant {
         this.sigProvider = signatureProvider;
     }
     
-    protected JwsSignatureProvider getInitializedSigProvider(JoseHeaders 
headers) {
+    protected JwsSignatureProvider getInitializedSigProvider() {
         if (sigProvider != null) {
             return sigProvider;    
         } 
-        JwsSignatureProvider theSigProvider = 
JwsUtils.loadSignatureProvider(true); 
-        headers.setAlgorithm(theSigProvider.getAlgorithm());
-        return theSigProvider;
+        if (signWithClientSecret) {
+            byte[] hmac = CryptoUtils.decodeSequence(clientSecret);
+            return JwsUtils.getHmacSignatureProvider(hmac, 
JoseConstants.HMAC_SHA_256_ALGO);
+        } else {
+            return JwsUtils.loadSignatureProvider(true);
+        }
     }
     public MultivaluedMap<String, String> toMap() {
         String request = getRequest();
@@ -87,8 +95,7 @@ public class JwtRequestCodeGrant extends 
AuthorizationCodeGrant {
             claims.setClaim(key, map.getFirst(key));
         }
         JwsJwtCompactProducer producer = new JwsJwtCompactProducer(claims);
-        JoseHeaders headers = new JoseHeaders();
-        JwsSignatureProvider theSigProvider = 
getInitializedSigProvider(headers);
+        JwsSignatureProvider theSigProvider = getInitializedSigProvider();
         String request = producer.signWith(theSigProvider);
         
         JweEncryptionProvider theEncryptionProvider = 
getInitializedEncryptionProvider();
@@ -101,11 +108,31 @@ public class JwtRequestCodeGrant extends 
AuthorizationCodeGrant {
         if (encryptionProvider != null) {
             return encryptionProvider;    
         } 
-        return JweUtils.loadEncryptionProvider(false);
+        if (encryptWithClientSecret) {
+            SecretKey key = CryptoUtils.decodeSecretKey(clientSecret);
+            return JweUtils.getDirectKeyJweEncryption(key, 
JoseConstants.A128GCM_ALGO);
+        } else {
+            return JweUtils.loadEncryptionProvider(false);
+        }
     }
 
     public void setIssuer(String issuer) {
         this.issuer = issuer;
     }
-    
+
+    public void setClientSecret(String clientSecret) {
+        this.clientSecret = clientSecret;
+    }
+    public void setEncryptWithClientSecret(boolean encryptWithClientSecret) {
+        if (signWithClientSecret) {
+            throw new SecurityException();
+        }
+        this.encryptWithClientSecret = encryptWithClientSecret;
+    }
+    public void setSignWithClientSecret(boolean signWithClientSecret) {
+        if (encryptWithClientSecret) {
+            throw new SecurityException();
+        }
+        this.signWithClientSecret = signWithClientSecret;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/AbstractJwsJweProducer.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/AbstractJwsJweProducer.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/AbstractJwsJweProducer.java
new file mode 100644
index 0000000..dfbf8b6
--- /dev/null
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/AbstractJwsJweProducer.java
@@ -0,0 +1,97 @@
+/**
+ * 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.oidc.idp;
+
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+
+import javax.crypto.SecretKey;
+
+import org.apache.cxf.common.util.crypto.CryptoUtils;
+import org.apache.cxf.rs.security.jose.JoseConstants;
+import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweUtils;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
+import org.apache.cxf.rs.security.jose.jws.JwsUtils;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+
+public abstract class AbstractJwsJweProducer {
+    private JwsSignatureProvider sigProvider;
+    private JweEncryptionProvider encryptionProvider;
+    private boolean encryptWithClientCertificates;
+    private boolean encryptWithClientSecret;
+    private boolean signWithClientSecret;
+    public void setSignatureProvider(JwsSignatureProvider signatureProvider) {
+        this.sigProvider = signatureProvider;
+    }
+    
+    protected JwsSignatureProvider getInitializedSigProvider(Client c, boolean 
required) {
+        if (sigProvider != null) {
+            return sigProvider;    
+        } 
+        
+        if (signWithClientSecret) {
+            byte[] hmac = CryptoUtils.decodeSequence(c.getClientSecret());
+            return JwsUtils.getHmacSignatureProvider(hmac, 
JoseConstants.HMAC_SHA_256_ALGO);
+        } else {
+            return JwsUtils.loadSignatureProvider(required);
+        }
+    }
+    protected JweEncryptionProvider getInitializedEncryptionProvider(Client c, 
boolean required) {
+        if (encryptionProvider != null) {
+            return encryptionProvider;    
+        }
+        JweEncryptionProvider theEncryptionProvider = null;
+        if (encryptWithClientSecret) {
+            SecretKey key = CryptoUtils.decodeSecretKey(c.getClientSecret());
+            theEncryptionProvider = JweUtils.getDirectKeyJweEncryption(key, 
JoseConstants.A128GCM_ALGO);
+        } else if (encryptWithClientCertificates) {
+            X509Certificate cert = 
+                
(X509Certificate)CryptoUtils.decodeCertificate(c.getApplicationCertificates().get(0));
+            theEncryptionProvider = 
JweUtils.createJweEncryptionProvider((RSAPublicKey)cert.getPublicKey(), 
+                                                                         
JoseConstants.RSA_OAEP_ALGO, 
+                                                                         
JoseConstants.A128GCM_ALGO, 
+                                                                         null);
+        }
+        if (theEncryptionProvider == null) {
+            theEncryptionProvider = JweUtils.loadEncryptionProvider(required);
+        }
+        return theEncryptionProvider;
+        
+    }
+
+    public void setEncryptWithClientCertificates(boolean 
encryptWithClientCertificates) {
+        if (encryptWithClientSecret) {
+            throw new SecurityException();
+        }
+        this.encryptWithClientCertificates = encryptWithClientCertificates;
+    }
+    public void setEncryptWithClientSecret(boolean encryptWithClientSecret) {
+        if (signWithClientSecret || encryptWithClientCertificates) {
+            throw new SecurityException();
+        }
+        this.encryptWithClientSecret = encryptWithClientSecret;
+    }
+    public void setSignWithClientSecret(boolean signWithClientSecret) {
+        if (encryptWithClientSecret) {
+            throw new SecurityException();
+        }
+        this.signWithClientSecret = signWithClientSecret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoCodeResponseFilter.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoCodeResponseFilter.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoCodeResponseFilter.java
new file mode 100644
index 0000000..e0b5a3e
--- /dev/null
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoCodeResponseFilter.java
@@ -0,0 +1,60 @@
+/**
+ * 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.oidc.idp;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.provider.AccessTokenResponseFilter;
+import org.apache.cxf.rs.security.oidc.common.UserToken;
+import org.apache.cxf.rs.security.oidc.utils.OidcUtils;
+
+public class UserInfoCodeResponseFilter extends AbstractJwsJweProducer 
implements AccessTokenResponseFilter {
+    private UserInfoProvider userInfoProvider;
+    private String issuer;
+    @Override
+    public void process(ClientAccessToken ct, ServerAccessToken st) {
+        UserToken token = 
+            userInfoProvider.getUserToken(st.getClient().getClientId(), 
st.getSubject(), st.getScopes());
+        token.setIssuer(issuer);
+        token.setAudience(st.getClient().getClientId());
+        
+        JwsJwtCompactProducer producer = new JwsJwtCompactProducer(token);
+        JwsSignatureProvider theSigProvider = 
getInitializedSigProvider(st.getClient(), true);
+        String idToken = producer.signWith(theSigProvider);
+        
+        JweEncryptionProvider theEncryptionProvider = 
getInitializedEncryptionProvider(st.getClient(), false);
+        if (theEncryptionProvider != null) {
+            idToken = 
theEncryptionProvider.encrypt(StringUtils.toBytesUTF8(idToken), null);
+        }
+        ct.getParameters().put(OidcUtils.ID_TOKEN, idToken);
+        
+    }
+    
+    public void setIssuer(String issuer) {
+        this.issuer = issuer;
+    }
+    public void setUserInfoProvider(UserInfoProvider userInfoProvider) {
+        this.userInfoProvider = userInfoProvider;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoProvider.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoProvider.java
new file mode 100644
index 0000000..0fa9c22
--- /dev/null
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoProvider.java
@@ -0,0 +1,31 @@
+/**
+ * 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.oidc.idp;
+
+import java.util.List;
+
+import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oidc.common.UserInfo;
+import org.apache.cxf.rs.security.oidc.common.UserToken;
+
+public interface UserInfoProvider {
+    UserToken getUserToken(String clientId, UserSubject authenticatedUser, 
List<OAuthPermission> scopes);
+    UserInfo getUserInfo(String clientId, UserSubject authenticatedUser, 
List<OAuthPermission> scopes);
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
new file mode 100644
index 0000000..7896678
--- /dev/null
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/idp/UserInfoService.java
@@ -0,0 +1,80 @@
+/**
+ * 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.oidc.idp;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.ext.MessageContext;
+import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweJwtCompactProducer;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
+import org.apache.cxf.rs.security.oauth2.common.OAuthContext;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthContextUtils;
+import org.apache.cxf.rs.security.oidc.common.UserInfo;
+
+@Path("/userinfo")
+public class UserInfoService extends AbstractJwsJweProducer {
+    private UserInfoProvider userInfoProvider;
+    private String issuer;
+    
+    @Context
+    private MessageContext mc;
+    @GET
+    @Produces({"application/json", "application/jwt" })
+    public Response getUserInfo() {
+        OAuthContext oauth = OAuthContextUtils.getContext(mc);
+        UserInfo userInfo = 
+            userInfoProvider.getUserInfo(oauth.getClientId(), 
oauth.getSubject(), oauth.getPermissions());
+        if (userInfo != null) {
+            userInfo.setIssuer(issuer);
+        }
+        userInfo.setAudience(oauth.getClientId());
+        
+        Object responseEntity = userInfo;
+        
+        JwsJwtCompactProducer producer = new JwsJwtCompactProducer(userInfo);
+        JwsSignatureProvider theSigProvider = getInitializedSigProvider(null, 
false);
+        JweEncryptionProvider theEncryptionProvider = 
getInitializedEncryptionProvider(null, false);
+        if (theSigProvider != null) {
+            String userInfoString = producer.signWith(theSigProvider);
+            if (theEncryptionProvider != null) {
+                userInfoString = 
theEncryptionProvider.encrypt(StringUtils.toBytesUTF8(userInfoString), null);
+            }
+            responseEntity = userInfoString;
+        } else if (theEncryptionProvider != null) {
+            JweJwtCompactProducer jwe = new JweJwtCompactProducer(userInfo);
+            responseEntity = jwe.encryptWith(theEncryptionProvider);
+        }
+        return Response.ok(responseEntity).build();
+        
+    }
+    
+    public void setIssuer(String issuer) {
+        this.issuer = issuer;
+    }
+    public void setUserInfoProvider(UserInfoProvider userInfoProvider) {
+        this.userInfoProvider = userInfoProvider;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
index 9c26804..69c54a4 100644
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
+++ 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/AbstractTokenValidator.java
@@ -41,7 +41,9 @@ public abstract class AbstractTokenValidator {
     private WebClient jwkSetClient;
     private ConcurrentHashMap<String, JsonWebKey> keyMap = new 
ConcurrentHashMap<String, JsonWebKey>(); 
     
-    protected JwtToken getJwtToken(String wrappedJwtToken, String clientId, 
String idTokenKid, 
+    protected JwtToken getJwtToken(String wrappedJwtToken, 
+                                   String clientId,
+                                   String idTokenKid, 
                                    boolean jweOnly) {
         if (wrappedJwtToken == null) {
             throw new SecurityException("ID Token is missing");
@@ -89,13 +91,14 @@ public abstract class AbstractTokenValidator {
             throw new SecurityException("Provider Jwk Set Client is not 
available");
         }
         String keyId = idTokenKid != null ? idTokenKid : 
jwtConsumer.getJwtToken().getHeaders().getKeyId();
-        if (keyId == null) {
-            throw new SecurityException("Provider JWK key id is null");
-        }
-        JsonWebKey key = keyMap.get(keyId);
+        JsonWebKey key = keyId != null ? keyMap.get(keyId) : null;
         if (key == null) {
             JsonWebKeys keys = jwkSetClient.get(JsonWebKeys.class);
-            key = keys.getKey(keyId);
+            if (keyId != null) {
+                key = keys.getKey(keyId);
+            } else if (keys.getKeys().size() == 1) {
+                key = keys.getKeys().get(0);
+            }
             keyMap.putAll(keys.getKeyIdMap());
         }
         if (key == null) {

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoCodeResponseFilter.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoCodeResponseFilter.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoCodeResponseFilter.java
deleted file mode 100644
index 0a1375a..0000000
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoCodeResponseFilter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * 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.oidc.rp.idp;
-
-import org.apache.cxf.common.util.StringUtils;
-import org.apache.cxf.rs.security.jose.JoseHeaders;
-import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
-import org.apache.cxf.rs.security.jose.jwe.JweUtils;
-import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
-import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
-import org.apache.cxf.rs.security.jose.jws.JwsUtils;
-import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
-import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
-import org.apache.cxf.rs.security.oauth2.provider.AccessTokenResponseFilter;
-import org.apache.cxf.rs.security.oidc.common.UserToken;
-import org.apache.cxf.rs.security.oidc.utils.OidcUtils;
-
-public class UserInfoCodeResponseFilter implements AccessTokenResponseFilter {
-    private JwsSignatureProvider sigProvider;
-    private JweEncryptionProvider encryptionProvider;
-    private UserInfoProvider userInfoProvider;
-    private String issuer;
-    @Override
-    public void process(ClientAccessToken ct, ServerAccessToken st) {
-        UserToken token = 
-            userInfoProvider.getUserToken(st.getClient().getClientId(), 
st.getSubject(), st.getScopes());
-        token.setIssuer(issuer);
-        token.setAudience(st.getClient().getClientId());
-        
-        JwsJwtCompactProducer producer = new JwsJwtCompactProducer(token);
-        JoseHeaders headers = new JoseHeaders();
-        JwsSignatureProvider theSigProvider = 
getInitializedSigProvider(headers);
-        String idToken = producer.signWith(theSigProvider);
-        
-        JweEncryptionProvider theEncryptionProvider = 
getInitializedEncryptionProvider();
-        if (theEncryptionProvider != null) {
-            idToken = 
theEncryptionProvider.encrypt(StringUtils.toBytesUTF8(idToken), null);
-        }
-        ct.getParameters().put(OidcUtils.ID_TOKEN, idToken);
-        
-    }
-    public void setSignatureProvider(JwsSignatureProvider signatureProvider) {
-        this.sigProvider = signatureProvider;
-    }
-    
-    protected JwsSignatureProvider getInitializedSigProvider(JoseHeaders 
headers) {
-        if (sigProvider != null) {
-            return sigProvider;    
-        } 
-        JwsSignatureProvider theSigProvider = 
JwsUtils.loadSignatureProvider(true); 
-        headers.setAlgorithm(theSigProvider.getAlgorithm());
-        return theSigProvider;
-    }
-    protected JweEncryptionProvider getInitializedEncryptionProvider() {
-        if (encryptionProvider != null) {
-            return encryptionProvider;    
-        } 
-        return JweUtils.loadEncryptionProvider(false);
-    }
-
-    public void setIssuer(String issuer) {
-        this.issuer = issuer;
-    }
-    public void setUserInfoProvider(UserInfoProvider userInfoProvider) {
-        this.userInfoProvider = userInfoProvider;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoProvider.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoProvider.java
deleted file mode 100644
index db58214..0000000
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoProvider.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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.oidc.rp.idp;
-
-import java.util.List;
-
-import org.apache.cxf.rs.security.oauth2.common.OAuthPermission;
-import org.apache.cxf.rs.security.oauth2.common.UserSubject;
-import org.apache.cxf.rs.security.oidc.common.UserInfo;
-import org.apache.cxf.rs.security.oidc.common.UserToken;
-
-public interface UserInfoProvider {
-    UserToken getUserToken(String clientId, UserSubject authenticatedUser, 
List<OAuthPermission> scopes);
-    UserInfo getUserInfo(String clientId, UserSubject authenticatedUser, 
List<OAuthPermission> scopes);
-}

http://git-wip-us.apache.org/repos/asf/cxf/blob/6cd95478/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoService.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoService.java
 
b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoService.java
deleted file mode 100644
index dbe20f9..0000000
--- 
a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/idp/UserInfoService.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * 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.oidc.rp.idp;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-
-import org.apache.cxf.common.util.StringUtils;
-import org.apache.cxf.jaxrs.ext.MessageContext;
-import org.apache.cxf.rs.security.jose.JoseHeaders;
-import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
-import org.apache.cxf.rs.security.jose.jwe.JweJwtCompactProducer;
-import org.apache.cxf.rs.security.jose.jwe.JweUtils;
-import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactProducer;
-import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
-import org.apache.cxf.rs.security.jose.jws.JwsUtils;
-import org.apache.cxf.rs.security.oauth2.common.OAuthContext;
-import org.apache.cxf.rs.security.oauth2.utils.OAuthContextUtils;
-import org.apache.cxf.rs.security.oidc.common.UserInfo;
-
-@Path("/userinfo")
-public class UserInfoService {
-    // TODO: review if it makes sense to do JWE and JWS at the out filter 
level instead
-    private JwsSignatureProvider sigProvider;
-    private JweEncryptionProvider encryptionProvider;
-    private UserInfoProvider userInfoProvider;
-    private String issuer;
-    
-    @Context
-    private MessageContext mc;
-    @GET
-    @Produces({"application/json", "application/jwt" })
-    public Response getUserInfo() {
-        OAuthContext oauth = OAuthContextUtils.getContext(mc);
-        UserInfo userInfo = 
-            userInfoProvider.getUserInfo(oauth.getClientId(), 
oauth.getSubject(), oauth.getPermissions());
-        if (userInfo != null) {
-            userInfo.setIssuer(issuer);
-        }
-        userInfo.setAudience(oauth.getClientId());
-        
-        Object responseEntity = userInfo;
-        
-        JwsJwtCompactProducer producer = new JwsJwtCompactProducer(userInfo);
-        JoseHeaders headers = new JoseHeaders();
-        JwsSignatureProvider theSigProvider = 
getInitializedSigProvider(headers);
-        JweEncryptionProvider theEncryptionProvider = 
getInitializedEncryptionProvider();
-        if (theSigProvider != null) {
-            String userInfoString = producer.signWith(theSigProvider);
-            if (theEncryptionProvider != null) {
-                userInfoString = 
theEncryptionProvider.encrypt(StringUtils.toBytesUTF8(userInfoString), null);
-            }
-            responseEntity = userInfoString;
-        } else if (theEncryptionProvider != null) {
-            JweJwtCompactProducer jwe = new JweJwtCompactProducer(userInfo);
-            responseEntity = jwe.encryptWith(theEncryptionProvider);
-        }
-        return Response.ok(responseEntity).build();
-        
-    }
-    public void setSignatureProvider(JwsSignatureProvider signatureProvider) {
-        this.sigProvider = signatureProvider;
-    }
-    
-    protected JwsSignatureProvider getInitializedSigProvider(JoseHeaders 
headers) {
-        if (sigProvider != null) {
-            return sigProvider;    
-        } 
-        JwsSignatureProvider theSigProvider = 
JwsUtils.loadSignatureProvider(false); 
-        headers.setAlgorithm(theSigProvider.getAlgorithm());
-        return theSigProvider;
-    }
-    protected JweEncryptionProvider getInitializedEncryptionProvider() {
-        if (encryptionProvider != null) {
-            return encryptionProvider;    
-        } 
-        return JweUtils.loadEncryptionProvider(false);
-    }
-
-    public void setIssuer(String issuer) {
-        this.issuer = issuer;
-    }
-    public UserInfoProvider getUserInfoProvider() {
-        return userInfoProvider;
-    }
-    public void setUserInfoProvider(UserInfoProvider userInfoProvider) {
-        this.userInfoProvider = userInfoProvider;
-    }
-}

Reply via email to