[CXF-6692] Updating JCache provider to support storing jose token 
representations only


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

Branch: refs/heads/master-jaxrs-2.1
Commit: 0eeeccd94afc7c7a0ace1872584ebc23b43235d7
Parents: b69f76c
Author: Sergey Beryozkin <[email protected]>
Authored: Fri Aug 12 15:50:59 2016 +0100
Committer: Sergey Beryozkin <[email protected]>
Committed: Fri Aug 12 15:50:59 2016 +0100

----------------------------------------------------------------------
 .../DefaultEHCacheOAuthDataProvider.java        |   6 +-
 .../provider/JCacheOAuthDataProvider.java       | 113 ++++++++++++++++---
 .../src/test/resources/cxf-oauth2-ehcache3.xml  |  27 -----
 .../src/test/resources/cxf-oauth2-jcache.xml    |  27 +++++
 4 files changed, 130 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/0eeeccd9/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
index c49e2ef..bb055a1 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEHCacheOAuthDataProvider.java
@@ -68,9 +68,9 @@ public class DefaultEHCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
     public DefaultEHCacheOAuthDataProvider(String configFileURL, 
                                                Bus bus,
                                                String clientCacheKey, 
-                                               String accessTokenKey,
-                                               String refreshTokenKey) {
-        createCaches(configFileURL, bus, clientCacheKey, accessTokenKey, 
refreshTokenKey);
+                                               String accessTokenCacheKey,
+                                               String refreshTokenCacheKey) {
+        createCaches(configFileURL, bus, clientCacheKey, accessTokenCacheKey, 
refreshTokenCacheKey);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/cxf/blob/0eeeccd9/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JCacheOAuthDataProvider.java
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JCacheOAuthDataProvider.java
 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JCacheOAuthDataProvider.java
index 3a2bbb8..fa16612 100644
--- 
a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JCacheOAuthDataProvider.java
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JCacheOAuthDataProvider.java
@@ -24,6 +24,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+
 import javax.cache.Cache;
 import javax.cache.CacheManager;
 import javax.cache.Caching;
@@ -32,10 +33,12 @@ import javax.cache.spi.CachingProvider;
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.BusFactory;
+import org.apache.cxf.rs.security.jose.jwt.JoseJwtConsumer;
 import org.apache.cxf.rs.security.oauth2.common.Client;
 import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
 import org.apache.cxf.rs.security.oauth2.common.UserSubject;
 import org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken;
+import org.apache.cxf.rs.security.oauth2.utils.JwtAccessTokenUtils;
 
 import static org.apache.cxf.jaxrs.utils.ResourceUtils.getClasspathResourceURL;
 
@@ -47,27 +50,53 @@ public class JCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
 
     protected final CacheManager cacheManager;
     private final Cache<String, Client> clientCache;
-    private final Cache<String, ServerAccessToken> accessTokenCache;
+    private Cache<String, ServerAccessToken> accessTokenCache;
+    private Cache<String, String> jwtAccessTokenCache;
     private final Cache<String, RefreshToken> refreshTokenCache;
+    private boolean storeJwtTokenKeyOnly;
+    private JoseJwtConsumer jwtTokenConsumer;
 
     public JCacheOAuthDataProvider() throws Exception {
+        this(false);
+    }
+    public JCacheOAuthDataProvider(boolean storeJwtTokenKeyOnly) throws 
Exception {
         this(DEFAULT_CONFIG_URL, BusFactory.getThreadDefaultBus(true));
     }
 
     public JCacheOAuthDataProvider(String configFileURL, Bus bus) throws 
Exception {
-        this(configFileURL, bus, CLIENT_CACHE_KEY, ACCESS_TOKEN_CACHE_KEY, 
REFRESH_TOKEN_CACHE_KEY);
+        this(configFileURL, bus, false);
+    }
+    
+    public JCacheOAuthDataProvider(String configFileURL, Bus bus, boolean 
storeJwtTokenKeyOnly) throws Exception {
+        this(configFileURL, bus, CLIENT_CACHE_KEY, ACCESS_TOKEN_CACHE_KEY, 
REFRESH_TOKEN_CACHE_KEY,
+             storeJwtTokenKeyOnly);
     }
 
     public JCacheOAuthDataProvider(String configFileURL,
-                                          Bus bus,
-                                          String clientCacheKey,
-                                          String accessTokenKey,
-                                          String refreshTokenKey) throws 
Exception {
+                                   Bus bus,
+                                   String clientCacheKey,
+                                   String accessTokenCacheKey,
+                                   String refreshTokenCacheKey) throws 
Exception {
+        this(configFileURL, bus, clientCacheKey, accessTokenCacheKey, 
refreshTokenCacheKey, false);
+    }
+    public JCacheOAuthDataProvider(String configFileURL,
+                                   Bus bus,
+                                   String clientCacheKey,
+                                   String accessTokenCacheKey,
+                                   String refreshTokenCacheKey,
+                                   boolean storeJwtTokenKeyOnly) throws 
Exception {    
 
         cacheManager = createCacheManager(configFileURL, bus);
         clientCache = createCache(cacheManager, clientCacheKey, String.class, 
Client.class);
-        accessTokenCache = createCache(cacheManager, accessTokenKey, 
String.class, ServerAccessToken.class);
-        refreshTokenCache = createCache(cacheManager, refreshTokenKey, 
String.class, RefreshToken.class);
+        
+        this.storeJwtTokenKeyOnly = storeJwtTokenKeyOnly;
+        if (storeJwtTokenKeyOnly) {
+            jwtAccessTokenCache = createCache(cacheManager, 
accessTokenCacheKey, String.class, String.class);
+        } else {
+            accessTokenCache = createCache(cacheManager, accessTokenCacheKey, 
String.class, ServerAccessToken.class);
+        }
+        
+        refreshTokenCache = createCache(cacheManager, refreshTokenCacheKey, 
String.class, RefreshToken.class);
     }
     
     @Override
@@ -101,7 +130,11 @@ public class JCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
 
     @Override
     public List<ServerAccessToken> getAccessTokens(Client c, UserSubject sub) {
-        return getTokens(accessTokenCache, c, sub);
+        if (isUseJwtFormatForAccessTokens() && isStoreJwtTokenKeyOnly()) {
+            return getJwtAccessTokens(c, sub);
+        } else {
+            return getTokens(accessTokenCache, c, sub);
+        }
     }
 
     @Override
@@ -111,7 +144,11 @@ public class JCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
     
     @Override
     public ServerAccessToken getAccessToken(String accessTokenKey) throws 
OAuthServiceException {
-        return getToken(accessTokenCache, accessTokenKey);
+        if (isUseJwtFormatForAccessTokens() && isStoreJwtTokenKeyOnly()) {
+            return getJwtAccessToken(accessTokenKey);
+        } else {
+            return getToken(accessTokenCache, accessTokenKey);
+        }
     }
 
     @Override
@@ -131,7 +168,12 @@ public class JCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
 
     @Override
     protected void saveAccessToken(ServerAccessToken serverToken) {
-        accessTokenCache.put(serverToken.getTokenKey(), serverToken);
+        if (isUseJwtFormatForAccessTokens() && isStoreJwtTokenKeyOnly()) {
+            jwtAccessTokenCache.put(serverToken.getTokenKey(), 
serverToken.getTokenKey());
+        } else {
+            accessTokenCache.put(serverToken.getTokenKey(), serverToken);
+        }
+        
     }
 
     @Override
@@ -144,15 +186,28 @@ public class JCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
         cacheManager.close();
     }
 
-    protected static <K, V extends ServerAccessToken> V getToken(Cache<K, V> 
cache, K key) {
+    protected static <V extends ServerAccessToken> V getToken(Cache<String, V> 
cache, String key) {
         V token = cache.get(key);
         if (token != null && isExpired(token)) {
             cache.remove(key);
             token = null;
         }
-
         return token;
     }
+    protected ServerAccessToken getJwtAccessToken(String key) {
+        String jose = jwtAccessTokenCache.get(key);
+        ServerAccessToken token = null;
+        if (jose != null) {
+            JoseJwtConsumer theConsumer = jwtTokenConsumer == null ? new 
JoseJwtConsumer() : jwtTokenConsumer;
+            token = JwtAccessTokenUtils.createAccessTokenFromJwt(theConsumer, 
jose, this);
+            if (isExpired(token)) {
+                jwtAccessTokenCache.remove(key);
+                token = null;
+            }
+        }
+        return token;
+    }
+    
 
     protected static <K, V extends ServerAccessToken> List<V> 
getTokens(Cache<K, V> cache,
                                                                       Client 
client, UserSubject sub) {
@@ -174,6 +229,29 @@ public class JCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
 
         return tokens;
     }
+    
+    protected List<ServerAccessToken> getJwtAccessTokens(Client client, 
UserSubject sub) {
+        final Set<String> toRemove = new HashSet<>();
+        final List<ServerAccessToken> tokens = new ArrayList<>();
+
+        for (Iterator<Cache.Entry<String, String>> it = 
jwtAccessTokenCache.iterator(); it.hasNext();) {
+            Cache.Entry<String, String> entry = it.next();
+            String jose = entry.getValue();
+
+            JoseJwtConsumer theConsumer = jwtTokenConsumer == null ? new 
JoseJwtConsumer() : jwtTokenConsumer;
+            ServerAccessToken token = 
JwtAccessTokenUtils.createAccessTokenFromJwt(theConsumer, jose, this);
+          
+            if (!isExpired(token)) {
+                toRemove.add(entry.getKey());
+            } else if (isTokenMatched(token, client, sub)) {
+                tokens.add(token);
+            }
+        }
+
+        jwtAccessTokenCache.removeAll(toRemove);
+
+        return tokens;
+    }
 
     protected static boolean isExpired(ServerAccessToken token) {
         return System.currentTimeMillis() < (token.getIssuedAt() + 
token.getExpiresIn());
@@ -212,4 +290,13 @@ public class JCacheOAuthDataProvider extends 
AbstractOAuthDataProvider {
 
         return cache;
     }
+
+    public boolean isStoreJwtTokenKeyOnly() {
+        return storeJwtTokenKeyOnly;
+    }
+
+    public void setJwtTokenConsumer(JoseJwtConsumer jwtTokenConsumer) {
+        this.jwtTokenConsumer = jwtTokenConsumer;
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/0eeeccd9/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-ehcache3.xml
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-ehcache3.xml 
b/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-ehcache3.xml
deleted file mode 100644
index 50ebfae..0000000
--- 
a/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-ehcache3.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<config
-    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
-    xmlns='http://www.ehcache.org/v3'
-    xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
-    xsi:schemaLocation="
-        http://www.ehcache.org/v3 
http://www.ehcache.org/schema/ehcache-core-3.0.xsd";>
-
-  <cache alias="cxf.oauth2.client.cache">
-    <key-type>java.lang.String</key-type>
-    <value-type>org.apache.cxf.rs.security.oauth2.common.Client</value-type>
-    <heap unit="entries">100</heap>
-    <jsr107:mbeans enable-management="false" enable-statistics="false"/>
-  </cache>
-  <cache alias="cxf.oauth2.accesstoken.cache">
-    <key-type>java.lang.String</key-type>
-    
<value-type>org.apache.cxf.rs.security.oauth2.common.ServerAccessToken</value-type>
-    <heap unit="entries">100</heap>
-    <jsr107:mbeans enable-management="false" enable-statistics="false"/>
-  </cache>
-  <cache alias="cxf.oauth2.refreshtoken.cache">
-    <key-type>java.lang.String</key-type>
-    
<value-type>org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken</value-type>
-    <heap unit="entries">100</heap>
-    <jsr107:mbeans enable-management="false" enable-statistics="false"/>
-  </cache>
-
-</config>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/0eeeccd9/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-jcache.xml
----------------------------------------------------------------------
diff --git 
a/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-jcache.xml 
b/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-jcache.xml
new file mode 100644
index 0000000..50ebfae
--- /dev/null
+++ 
b/rt/rs/security/oauth-parent/oauth2/src/test/resources/cxf-oauth2-jcache.xml
@@ -0,0 +1,27 @@
+<config
+    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+    xmlns='http://www.ehcache.org/v3'
+    xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
+    xsi:schemaLocation="
+        http://www.ehcache.org/v3 
http://www.ehcache.org/schema/ehcache-core-3.0.xsd";>
+
+  <cache alias="cxf.oauth2.client.cache">
+    <key-type>java.lang.String</key-type>
+    <value-type>org.apache.cxf.rs.security.oauth2.common.Client</value-type>
+    <heap unit="entries">100</heap>
+    <jsr107:mbeans enable-management="false" enable-statistics="false"/>
+  </cache>
+  <cache alias="cxf.oauth2.accesstoken.cache">
+    <key-type>java.lang.String</key-type>
+    
<value-type>org.apache.cxf.rs.security.oauth2.common.ServerAccessToken</value-type>
+    <heap unit="entries">100</heap>
+    <jsr107:mbeans enable-management="false" enable-statistics="false"/>
+  </cache>
+  <cache alias="cxf.oauth2.refreshtoken.cache">
+    <key-type>java.lang.String</key-type>
+    
<value-type>org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken</value-type>
+    <heap unit="entries">100</heap>
+    <jsr107:mbeans enable-management="false" enable-statistics="false"/>
+  </cache>
+
+</config>
\ No newline at end of file

Reply via email to