You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2016/02/05 15:20:53 UTC

cxf git commit: Adding the renamed resources

Repository: cxf
Updated Branches:
  refs/heads/master 5c8c5f5b0 -> dcf440746


Adding the renamed resources


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

Branch: refs/heads/master
Commit: dcf4407466d5c307feb5f3be387ed8667dba6e32
Parents: 5c8c5f5
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Fri Feb 5 14:20:40 2016 +0000
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Fri Feb 5 14:20:40 2016 +0000

----------------------------------------------------------------------
 .../rs/security/jose/jwt/JoseJwtConsumer.java   | 107 +++++++++++
 .../rs/security/jose/jwt/JoseJwtProducer.java   |  91 +++++++++
 .../oauth2/provider/OAuthJoseJwtConsumer.java   |  60 ++++++
 .../oauth2/provider/OAuthJoseJwtProducer.java   |  71 +++++++
 .../provider/OAuthServerJoseJwtProducer.java    |  65 +++++++
 .../security/oidc/rp/OidcClaimsValidator.java   | 192 +++++++++++++++++++
 6 files changed, 586 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/dcf44074/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtConsumer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtConsumer.java
new file mode 100644
index 0000000..35a6eee
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtConsumer.java
@@ -0,0 +1,107 @@
+/**
+ * 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.jose.jwt;
+
+import org.apache.cxf.rs.security.jose.common.AbstractJoseConsumer;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionOutput;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
+import org.apache.cxf.rs.security.jose.jwe.JweHeaders;
+import org.apache.cxf.rs.security.jose.jwe.JweJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+
+public class JoseJwtConsumer extends AbstractJoseConsumer {
+    private boolean jwsRequired = true;
+    private boolean jweRequired;
+    
+    public JwtToken getJwtToken(String wrappedJwtToken) {
+        return getJwtToken(wrappedJwtToken, null, null);
+    }
+    public JwtToken getJwtToken(String wrappedJwtToken,
+                                   JweDecryptionProvider theDecryptor,
+                                   JwsSignatureVerifier theSigVerifier) {
+        if (!isJwsRequired() && !isJweRequired()) {
+            throw new JwtException("Unable to process JWT");
+        }
+        
+        JweHeaders jweHeaders = new JweHeaders();
+        if (isJweRequired()) {
+            JweJwtCompactConsumer jwtConsumer = new JweJwtCompactConsumer(wrappedJwtToken);
+            
+            if (theDecryptor == null) {
+                theDecryptor = getInitializedDecryptionProvider(jwtConsumer.getHeaders());
+            }
+            if (theDecryptor == null) {
+                throw new JwtException("Unable to decrypt JWT");
+            }
+            
+            if (!isJwsRequired()) {
+                return jwtConsumer.decryptWith(theDecryptor);    
+            }
+            
+            JweDecryptionOutput decOutput = theDecryptor.decrypt(wrappedJwtToken);
+            wrappedJwtToken = decOutput.getContentText();
+            jweHeaders = decOutput.getHeaders();
+        }
+        
+        JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(wrappedJwtToken);
+        JwtToken jwt = jwtConsumer.getJwtToken();
+        // Store the encryption headers as well
+        jwt = new JwtToken(jwt.getJwsHeaders(), jweHeaders, jwt.getClaims());
+        
+        if (isJwsRequired()) {
+            if (theSigVerifier == null) {
+                theSigVerifier = getInitializedSignatureVerifier(jwt);
+            }
+            if (theSigVerifier == null) {
+                throw new JwtException("Unable to validate JWT");
+            }
+            
+            if (!jwtConsumer.verifySignatureWith(theSigVerifier)) {
+                throw new JwtException("Invalid Signature");
+            }
+        }
+        
+        validateToken(jwt);
+        return jwt; 
+    }
+    
+    protected JwsSignatureVerifier getInitializedSignatureVerifier(JwtToken jwt) {
+        return super.getInitializedSignatureVerifier(jwt.getJwsHeaders());
+    }
+    
+    protected void validateToken(JwtToken jwt) {
+    }
+    public boolean isJwsRequired() {
+        return jwsRequired;
+    }
+
+    public void setJwsRequired(boolean jwsRequired) {
+        this.jwsRequired = jwsRequired;
+    }
+
+    public boolean isJweRequired() {
+        return jweRequired;
+    }
+
+    public void setJweRequired(boolean jweRequired) {
+        this.jweRequired = jweRequired;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/dcf44074/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtProducer.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtProducer.java
new file mode 100644
index 0000000..c729cbe
--- /dev/null
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JoseJwtProducer.java
@@ -0,0 +1,91 @@
+/**
+ * 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.jose.jwt;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.common.AbstractJoseProducer;
+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;
+
+public class JoseJwtProducer extends AbstractJoseProducer {
+    private boolean jwsRequired = true;
+    private boolean jweRequired;
+    
+    public String processJwt(JwtToken jwt) {
+        return processJwt(jwt, null, null);
+    }
+    public String processJwt(JwtToken jwt,
+                                JweEncryptionProvider theEncProvider,
+                                JwsSignatureProvider theSigProvider) {
+        if (!isJwsRequired() && !isJweRequired()) {
+            throw new JwtException("Unable to secure JWT");
+        }
+        String data = null;
+        
+        if (isJweRequired() && theEncProvider == null) {
+            theEncProvider = getInitializedEncryptionProvider(jwt.getJweHeaders());
+            if (theEncProvider == null) {
+                throw new JwtException("Unable to encrypt JWT");
+            }
+        }
+        
+        if (isJwsRequired()) {
+            JwsJwtCompactProducer jws = new JwsJwtCompactProducer(jwt);
+            if (jws.isPlainText()) {
+                data = jws.getSignedEncodedJws();
+            } else {
+                if (theSigProvider == null) {
+                    theSigProvider = getInitializedSignatureProvider(jwt.getJwsHeaders());
+                }
+                
+                if (theSigProvider == null) {
+                    throw new JwtException("Unable to sign JWT");
+                }
+                
+                data = jws.signWith(theSigProvider);
+            }
+            if (theEncProvider != null) {
+                data = theEncProvider.encrypt(StringUtils.toBytesUTF8(data), null);
+            }
+        } else {
+            JweJwtCompactProducer jwe = new JweJwtCompactProducer(jwt);
+            data = jwe.encryptWith(theEncProvider);
+        }
+        return data;
+    }
+
+    public boolean isJwsRequired() {
+        return jwsRequired;
+    }
+
+    public void setJwsRequired(boolean jwsRequired) {
+        this.jwsRequired = jwsRequired;
+    }
+
+    public boolean isJweRequired() {
+        return jweRequired;
+    }
+
+    public void setJweRequired(boolean jweRequired) {
+        this.jweRequired = jweRequired;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/dcf44074/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtConsumer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtConsumer.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtConsumer.java
new file mode 100644
index 0000000..a6e4541
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtConsumer.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.oauth2.provider;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwe.JweDecryptionProvider;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+import org.apache.cxf.rs.security.jose.jwt.JoseJwtConsumer;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
+
+public class OAuthJoseJwtConsumer extends JoseJwtConsumer {
+   
+    private boolean decryptWithClientSecret;
+    private boolean verifyWithClientSecret;
+    
+    public JwtToken getJwtToken(String wrappedJwtToken, String clientSecret) {
+        return getJwtToken(wrappedJwtToken, 
+                           getInitializedDecryptionProvider(clientSecret),
+                           getInitializedSignatureVerifier(clientSecret));
+    }
+    
+    protected JwsSignatureVerifier getInitializedSignatureVerifier(String clientSecret) {
+        if (verifyWithClientSecret && !StringUtils.isEmpty(clientSecret)) {
+            return OAuthUtils.getClientSecretSignatureVerifier(clientSecret);
+        } else {
+            return null;
+        }
+    }
+    protected JweDecryptionProvider getInitializedDecryptionProvider(String clientSecret) {
+        if (decryptWithClientSecret && !StringUtils.isEmpty(clientSecret)) {
+            return OAuthUtils.getClientSecretDecryptionProvider(clientSecret);
+        } else {
+            return null;
+        }
+    }
+
+    public void setDecryptWithClientSecret(boolean decryptWithClientSecret) {
+        this.decryptWithClientSecret = verifyWithClientSecret;
+    }
+    public void setVerifyWithClientSecret(boolean verifyWithClientSecret) {
+        this.verifyWithClientSecret = verifyWithClientSecret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/dcf44074/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtProducer.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtProducer.java
new file mode 100644
index 0000000..506e826
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthJoseJwtProducer.java
@@ -0,0 +1,71 @@
+/**
+ * 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.common.util.StringUtils;
+import org.apache.cxf.rs.security.jose.jwe.JweEncryptionProvider;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider;
+import org.apache.cxf.rs.security.jose.jwt.JoseJwtProducer;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils;
+
+public class OAuthJoseJwtProducer extends JoseJwtProducer {
+    private boolean encryptWithClientSecret;
+    private boolean signWithClientSecret;
+    
+    public String processJwt(JwtToken jwt, String clientSecret) {
+        return processJwt(jwt, 
+                         getInitializedEncryptionProvider(clientSecret),
+                         getInitializedSignatureProvider(clientSecret));
+    }
+    
+    protected JwsSignatureProvider getInitializedSignatureProvider(String clientSecret) {
+        if (signWithClientSecret && !StringUtils.isEmpty(clientSecret)) {
+            return OAuthUtils.getClientSecretSignatureProvider(clientSecret);
+        } else {
+            return null;
+        }
+    }
+    protected JweEncryptionProvider getInitializedEncryptionProvider(String clientSecret) {
+        if (encryptWithClientSecret && !StringUtils.isEmpty(clientSecret)) {
+            return OAuthUtils.getClientSecretEncryptionProvider(clientSecret);
+        } else {
+            return null;
+        }
+    }
+
+    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;
+    }
+    public boolean isSignWithClientSecret() {
+        return signWithClientSecret;
+    }
+    public boolean isEncryptWithClientSecret() {
+        return encryptWithClientSecret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/dcf44074/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthServerJoseJwtProducer.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthServerJoseJwtProducer.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthServerJoseJwtProducer.java
new file mode 100644
index 0000000..24e6a16
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/OAuthServerJoseJwtProducer.java
@@ -0,0 +1,65 @@
+/**
+ * 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 java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+
+import org.apache.cxf.rs.security.jose.jwa.ContentAlgorithm;
+import org.apache.cxf.rs.security.jose.jwa.KeyAlgorithm;
+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.jwt.JwtToken;
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rt.security.crypto.CryptoUtils;
+
+public class OAuthServerJoseJwtProducer extends OAuthJoseJwtProducer {
+    private boolean encryptWithClientCertificates;
+   
+    public String processJwt(JwtToken jwt, Client client) {
+        return processJwt(jwt, 
+                         getInitializedEncryptionProvider(client),
+                         getInitializedSignatureProvider(client.getClientSecret()));
+    }
+    
+    protected JweEncryptionProvider getInitializedEncryptionProvider(Client c) {
+        JweEncryptionProvider theEncryptionProvider = null;
+        if (encryptWithClientCertificates) {
+            X509Certificate cert = 
+                (X509Certificate)CryptoUtils.decodeCertificate(c.getApplicationCertificates().get(0));
+            theEncryptionProvider = JweUtils.createJweEncryptionProvider((RSAPublicKey)cert.getPublicKey(), 
+                                                                         KeyAlgorithm.RSA_OAEP, 
+                                                                         ContentAlgorithm.A128GCM, 
+                                                                         null);
+        }
+        if (theEncryptionProvider == null) {
+            theEncryptionProvider = super.getInitializedEncryptionProvider(c.getClientSecret());
+        }
+        return theEncryptionProvider;
+        
+    }
+
+    public void setEncryptWithClientCertificates(boolean encryptWithClientCertificates) {
+        if (isEncryptWithClientSecret()) {
+            throw new SecurityException();
+        }
+        this.encryptWithClientCertificates = encryptWithClientCertificates;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/dcf44074/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/OidcClaimsValidator.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/OidcClaimsValidator.java b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/OidcClaimsValidator.java
new file mode 100644
index 0000000..31a3111
--- /dev/null
+++ b/rt/rs/security/sso/oidc/src/main/java/org/apache/cxf/rs/security/oidc/rp/OidcClaimsValidator.java
@@ -0,0 +1,192 @@
+/**
+ * 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;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.cxf.common.util.StringUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+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.jwk.JwkUtils;
+import org.apache.cxf.rs.security.jose.jws.JwsSignatureVerifier;
+import org.apache.cxf.rs.security.jose.jws.JwsUtils;
+import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
+import org.apache.cxf.rs.security.jose.jwt.JwtException;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
+import org.apache.cxf.rs.security.jose.jwt.JwtUtils;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthJoseJwtConsumer;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+import org.apache.cxf.rs.security.oidc.common.IdToken;
+
+public class OidcClaimsValidator extends OAuthJoseJwtConsumer {
+    private static final String SELF_ISSUED_ISSUER = "https://self-issued.me";
+    private String issuerId;
+    private int clockOffset;
+    private int ttl;
+    private WebClient jwkSetClient;
+    private boolean supportSelfIssuedProvider;
+    private boolean strictTimeValidation;
+    private ConcurrentHashMap<String, JsonWebKey> keyMap = new ConcurrentHashMap<String, JsonWebKey>(); 
+
+    /**
+     * Validate core JWT claims
+     * @param claims the claims
+     * @param clientId OAuth2 client id
+     * @param validateClaimsAlways if set to true then enforce that the claims 
+     *                             to be validated must be set
+     */
+    public void validateJwtClaims(JwtClaims claims, String clientId, boolean validateClaimsAlways) {
+        // validate the issuer
+        String issuer = claims.getIssuer();
+        if (issuer == null && validateClaimsAlways) {
+            throw new OAuthServiceException("Invalid issuer");
+        }
+        if (supportSelfIssuedProvider && issuerId == null 
+            && issuer != null && SELF_ISSUED_ISSUER.equals(issuer)) {
+            validateSelfIssuedProvider(claims, clientId, validateClaimsAlways);
+        } else {
+            if (issuer != null && !issuer.equals(issuerId)) {
+                throw new OAuthServiceException("Invalid issuer");
+            }
+            // validate subject
+            if (claims.getSubject() == null) {
+                throw new OAuthServiceException("Invalid subject");
+            }
+            
+            // validate authorized party
+            String authorizedParty = (String)claims.getClaim(IdToken.AZP_CLAIM);
+            if (authorizedParty != null && !authorizedParty.equals(clientId)) {
+                throw new OAuthServiceException("Invalid authorized party");
+            }
+            // validate audience
+            List<String> audiences = claims.getAudiences();
+            if (StringUtils.isEmpty(audiences) && validateClaimsAlways 
+                || !StringUtils.isEmpty(audiences) && !audiences.contains(clientId)) {
+                throw new OAuthServiceException("Invalid audience");
+            }
+    
+            // If strict time validation: if no issuedTime claim is set then an expiresAt claim must be set
+            // Otherwise: validate only if expiresAt claim is set
+            boolean expiredRequired = 
+                validateClaimsAlways || strictTimeValidation && claims.getIssuedAt() == null;
+            try {
+                JwtUtils.validateJwtExpiry(claims, clockOffset, expiredRequired);
+            } catch (JwtException ex) {
+                throw new OAuthServiceException("ID Token has expired", ex);
+            }
+            
+            // If strict time validation: If no expiresAt claim is set then an issuedAt claim must be set
+            // Otherwise: validate only if issuedAt claim is set
+            boolean issuedAtRequired = 
+                validateClaimsAlways || strictTimeValidation && claims.getExpiryTime() == null;
+            try {
+                JwtUtils.validateJwtIssuedAt(claims, ttl, clockOffset, issuedAtRequired);
+            } catch (JwtException ex) {
+                throw new OAuthServiceException("Invalid issuedAt claim", ex);
+            }
+            if (strictTimeValidation) {
+                try {
+                    JwtUtils.validateJwtNotBefore(claims, clockOffset, strictTimeValidation);
+                } catch (JwtException ex) {
+                    throw new OAuthServiceException("ID Token can not be used yet", ex);
+                }    
+            }
+        }
+    }
+    
+    private void validateSelfIssuedProvider(JwtClaims claims, String clientId, boolean validateClaimsAlways) {
+    }
+
+    public void setIssuerId(String issuerId) {
+        this.issuerId = issuerId;
+    }
+
+    public void setJwkSetClient(WebClient jwkSetClient) {
+        this.jwkSetClient = jwkSetClient;
+    }
+
+    @Override
+    protected JwsSignatureVerifier getInitializedSignatureVerifier(JwtToken jwt) {
+        JsonWebKey key = null;
+        if (supportSelfIssuedProvider && SELF_ISSUED_ISSUER.equals(jwt.getClaim("issuer"))) {
+            String publicKeyJson = (String)jwt.getClaim("sub_jwk");
+            if (publicKeyJson != null) {
+                JsonWebKey publicKey = JwkUtils.readJwkKey(publicKeyJson);
+                String thumbprint = JwkUtils.getThumbprint(publicKey);
+                if (thumbprint.equals(jwt.getClaim("sub"))) {
+                    key = publicKey;
+                }
+            }
+            if (key == null) {
+                throw new SecurityException("Self-issued JWK key is invalid or not available");
+            }
+        } else {
+            String keyId = jwt.getJwsHeaders().getKeyId();
+            key = keyId != null ? keyMap.get(keyId) : null;
+            if (key == null && jwkSetClient != null) {
+                JsonWebKeys keys = jwkSetClient.get(JsonWebKeys.class);
+                if (keyId != null) {
+                    key = keys.getKey(keyId);
+                } else if (keys.getKeys().size() == 1) {
+                    key = keys.getKeys().get(0);
+                }
+                //jwkSetClient returns the most up-to-date keys
+                keyMap.clear();
+                keyMap.putAll(keys.getKeyIdMap());
+            }
+        }
+        JwsSignatureVerifier theJwsVerifier = null;
+        if (key != null) {
+            theJwsVerifier = JwsUtils.getSignatureVerifier(key);
+        } else {
+            theJwsVerifier = super.getInitializedSignatureVerifier(jwt.getJwsHeaders());
+        }
+        if (theJwsVerifier == null) {
+            throw new SecurityException("JWS Verifier is not available");
+        }
+        
+        return theJwsVerifier;
+    }
+
+    public void setSupportSelfIssuedProvider(boolean supportSelfIssuedProvider) {
+        this.supportSelfIssuedProvider = supportSelfIssuedProvider;
+    }
+
+    public int getClockOffset() {
+        return clockOffset;
+    }
+
+    public void setClockOffset(int clockOffset) {
+        this.clockOffset = clockOffset;
+    }
+
+    public void setStrictTimeValidation(boolean strictTimeValidation) {
+        this.strictTimeValidation = strictTimeValidation;
+    }
+
+    public int getTtl() {
+        return ttl;
+    }
+
+    public void setTtl(int ttl) {
+        this.ttl = ttl;
+    }
+}