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 2015/12/23 13:45:20 UTC

cxf git commit: Prototyping some token management code in default oAuth2 data providers

Repository: cxf
Updated Branches:
  refs/heads/master f0c825245 -> d887fef43


Prototyping some token management code in default oAuth2 data providers


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

Branch: refs/heads/master
Commit: d887fef43b750a26cd6691fae1aad671f2f1cd46
Parents: f0c8252
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Wed Dec 23 12:45:04 2015 +0000
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Wed Dec 23 12:45:04 2015 +0000

----------------------------------------------------------------------
 .../grants/code/AbstractCodeDataProvider.java   |  7 +-
 .../code/DefaultEHCacheCodeDataProvider.java    | 24 ++++-
 .../code/DefaultEncryptingCodeDataProvider.java | 18 ++++
 .../provider/AbstractOAuthDataProvider.java     | 97 +++++++++++---------
 .../DefaultEHCacheOAuthDataProvider.java        | 20 ++++
 .../DefaultEncryptingOAuthDataProvider.java     | 18 +++-
 .../oauth2/services/AbstractTokenService.java   |  4 +
 .../oauth2/services/TokenRevocationService.java |  9 +-
 8 files changed, 146 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java
index 1b63bb3..14858c1 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AbstractCodeDataProvider.java
@@ -18,6 +18,8 @@
  */
 package org.apache.cxf.rs.security.oauth2.grants.code;
 
+import java.util.List;
+
 import org.apache.cxf.rs.security.oauth2.provider.AbstractOAuthDataProvider;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
 
@@ -45,8 +47,6 @@ public abstract class AbstractCodeDataProvider extends AbstractOAuthDataProvider
         this.codeLifetime = codeLifetime;
     }
     
-    protected abstract void saveCodeGrant(ServerAuthorizationCodeGrant grant);
-    
     public static ServerAuthorizationCodeGrant initCodeGrant(AuthorizationCodeRegistration reg, long lifetime) {
         ServerAuthorizationCodeGrant grant = new ServerAuthorizationCodeGrant(reg.getClient(), lifetime);
         grant.setRedirectUri(reg.getRedirectUri());
@@ -58,5 +58,6 @@ public abstract class AbstractCodeDataProvider extends AbstractOAuthDataProvider
         grant.setNonce(reg.getNonce());
         return grant;
     }
-    
+    protected abstract void saveCodeGrant(ServerAuthorizationCodeGrant grant);
+    public abstract List<ServerAuthorizationCodeGrant> getCodeGrants();
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEHCacheCodeDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEHCacheCodeDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEHCacheCodeDataProvider.java
index 5834a2c..de86647 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEHCacheCodeDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEHCacheCodeDataProvider.java
@@ -18,10 +18,14 @@
  */
 package org.apache.cxf.rs.security.oauth2.grants.code;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import net.sf.ehcache.Ehcache;
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.BusFactory;
+import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.rs.security.oauth2.provider.DefaultEHCacheOAuthDataProvider;
 import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
 
@@ -64,16 +68,30 @@ public class DefaultEHCacheCodeDataProvider extends DefaultEHCacheOAuthDataProvi
         return AbstractCodeDataProvider.initCodeGrant(reg, codeLifetime);
     }
 
+    public List<ServerAuthorizationCodeGrant> getCodeGrants() {
+        List<String> keys = CastUtils.cast(codeGrantCache.getKeys());
+        List<ServerAuthorizationCodeGrant> grants = 
+            new ArrayList<ServerAuthorizationCodeGrant>(keys.size());
+        for (String key : keys) {
+            grants.add(getCodeGrant(key));
+        }
+        return grants;
+    }
+    
     @Override
     public ServerAuthorizationCodeGrant removeCodeGrant(String code) throws OAuthServiceException {
-        ServerAuthorizationCodeGrant grant = getCacheValue(codeGrantCache, 
-                                                                  code, 
-                                                                  ServerAuthorizationCodeGrant.class);
+        ServerAuthorizationCodeGrant grant = getCodeGrant(code);
         if (grant != null) {
             codeGrantCache.remove(code);
         }
         return grant;
     }
+    
+    public ServerAuthorizationCodeGrant getCodeGrant(String code) throws OAuthServiceException {
+        return getCacheValue(codeGrantCache, 
+                             code, 
+                             ServerAuthorizationCodeGrant.class);
+    }
         
     protected void saveCodeGrant(ServerAuthorizationCodeGrant grant) { 
         putCacheValue(codeGrantCache, grant.getCode(), grant, grant.getExpiresIn());

http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEncryptingCodeDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEncryptingCodeDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEncryptingCodeDataProvider.java
index a7f58c9..a96659b 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEncryptingCodeDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/DefaultEncryptingCodeDataProvider.java
@@ -18,6 +18,7 @@
  */
 package org.apache.cxf.rs.security.oauth2.grants.code;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -52,11 +53,28 @@ public class DefaultEncryptingCodeDataProvider extends DefaultEncryptingOAuthDat
         return grant;
     }
 
+    public List<ServerAuthorizationCodeGrant> getCodeGrants() {
+        List<ServerAuthorizationCodeGrant> list = 
+            new ArrayList<ServerAuthorizationCodeGrant>(grants.size());
+        for (String grant : grants) {
+            list.add(getCodeGrant(grant));
+        }
+        return list;
+    }
+    
     @Override
     public ServerAuthorizationCodeGrant removeCodeGrant(String code) throws OAuthServiceException {
         grants.remove(code);
         return ModelEncryptionSupport.decryptCodeGrant(this, code, key);
     }
+    public ServerAuthorizationCodeGrant getCodeGrant(String code) throws OAuthServiceException {
+        
+        ServerAuthorizationCodeGrant grant = ModelEncryptionSupport.decryptCodeGrant(this, code, key);
+        if (grant != null) {
+            grants.remove(code);
+        }
+        return grant;
+    }
     
     protected ServerAuthorizationCodeGrant doCreateCodeGrant(AuthorizationCodeRegistration reg)
         throws OAuthServiceException {

http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
index 9bb52ed..df3cb31 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/AbstractOAuthDataProvider.java
@@ -79,7 +79,16 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl
     @Override
     public ServerAccessToken refreshAccessToken(Client client, String refreshTokenKey,
                                                 List<String> restrictedScopes) throws OAuthServiceException {
-        RefreshToken currentRefreshToken = revokeRefreshAndAccessTokens(client, refreshTokenKey);
+        RefreshToken currentRefreshToken = recycleRefreshTokens 
+            ? revokeRefreshToken(client, refreshTokenKey) : getRefreshToken(client, refreshTokenKey);
+        if (currentRefreshToken == null 
+            || OAuthUtils.isExpired(currentRefreshToken.getIssuedAt(), currentRefreshToken.getExpiresIn())) {
+            throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED);
+        }
+        if (recycleRefreshTokens) {
+            revokeAccessTokens(currentRefreshToken);
+        }
+        
         ServerAccessToken at = doRefreshAccessToken(client, currentRefreshToken, restrictedScopes);
         saveAccessToken(at);
         if (recycleRefreshTokens) {
@@ -92,27 +101,42 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl
     
     @Override
     public void revokeToken(Client client, String tokenKey, String tokenTypeHint) throws OAuthServiceException {
-        ServerAccessToken accessToken = revokeAccessToken(tokenKey);
-        if (accessToken == null) {
-            // Revoke refresh token            
-            doRevokeRefreshAndAccessTokens(client, tokenKey, true);
-        } else {
-            // Revoke access token
-            if (accessToken.getRefreshToken() != null) {
-                RefreshToken rt = getRefreshToken(client, accessToken.getRefreshToken());
-                if (rt == null) {
-                    return;
-                }
-                
-                unlinkRefreshAccessToken(rt, accessToken.getTokenKey());
-                if (rt.getAccessTokens().isEmpty()) {
-                    revokeRefreshToken(client, rt.getTokenKey());
-                } else {
-                    saveRefreshToken(null, rt);
-                }
+        ServerAccessToken accessToken = null;
+        if (!OAuthConstants.REFRESH_TOKEN.equals(tokenTypeHint)) { 
+            accessToken = revokeAccessToken(tokenKey);
+        }
+        if (accessToken != null) {
+            handleLinkedRefreshToken(accessToken);
+        } else if (!OAuthConstants.ACCESS_TOKEN.equals(tokenTypeHint)) {
+            RefreshToken currentRefreshToken = revokeRefreshToken(client, tokenKey);
+            revokeAccessTokens(currentRefreshToken);
+        }
+    }
+    protected void handleLinkedRefreshToken(ServerAccessToken accessToken) {
+        if (accessToken != null && accessToken.getRefreshToken() != null) {
+            RefreshToken rt = getRefreshToken(accessToken.getClient(), accessToken.getRefreshToken());
+            if (rt == null) {
+                return;
+            }
+            
+            unlinkRefreshAccessToken(rt, accessToken.getTokenKey());
+            if (rt.getAccessTokens().isEmpty()) {
+                revokeRefreshToken(accessToken.getClient(), rt.getTokenKey());
+            } else {
+                saveRefreshToken(null, rt);
             }
         }
+        
     }
+
+    protected void revokeAccessTokens(RefreshToken currentRefreshToken) {
+        if (currentRefreshToken != null) {
+            for (String accessTokenKey : currentRefreshToken.getAccessTokens()) {
+                revokeAccessToken(accessTokenKey);
+            }
+        }
+    }
+
     protected void unlinkRefreshAccessToken(RefreshToken rt, String tokenKey) {
         List<String> accessTokenKeys = rt.getAccessTokens();
         for (int i = 0; i < accessTokenKeys.size(); i++) {
@@ -123,24 +147,8 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl
         }
     }
 
-    protected RefreshToken revokeRefreshAndAccessTokens(Client client, String tokenKey) {
-        return doRevokeRefreshAndAccessTokens(client, tokenKey, recycleRefreshTokens);
-    }
-    protected RefreshToken doRevokeRefreshAndAccessTokens(Client client, String tokenKey, boolean recycle) {
-        RefreshToken currentRefreshToken = recycle ? revokeRefreshToken(client, tokenKey)
-            : getRefreshToken(client, tokenKey);
-        if (currentRefreshToken == null 
-            || OAuthUtils.isExpired(currentRefreshToken.getIssuedAt(), currentRefreshToken.getExpiresIn())) {
-            throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED);
-        }
-        if (recycle) {
-            for (String accessTokenKey : currentRefreshToken.getAccessTokens()) {
-                revokeAccessToken(accessTokenKey);
-            }
-        }
-        return currentRefreshToken;
-    }
-
+        
+    
     @Override
     public List<OAuthPermission> convertScopeToPermissions(Client client, List<String> requestedScopes) {
         if (requestedScopes.isEmpty()) {
@@ -239,12 +247,6 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl
     public void close() {
     }
     
-    protected abstract void saveAccessToken(ServerAccessToken serverToken);
-    protected abstract void saveRefreshToken(ServerAccessToken at, RefreshToken refreshToken);
-    protected abstract ServerAccessToken revokeAccessToken(String accessTokenKey);
-    protected abstract RefreshToken revokeRefreshToken(Client client, String refreshTokenKey);
-    protected abstract RefreshToken getRefreshToken(Client client, String refreshTokenKey);
-
     public Map<String, OAuthPermission> getPermissionMap() {
         return permissionMap;
     }
@@ -267,4 +269,13 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider, Cl
     public void setMessageContext(MessageContext messageContext) {
         this.messageContext = messageContext;
     }
+    
+    protected abstract void saveAccessToken(ServerAccessToken serverToken);
+    protected abstract void saveRefreshToken(ServerAccessToken at, RefreshToken refreshToken);
+    protected abstract ServerAccessToken revokeAccessToken(String accessTokenKey);
+    protected abstract List<ServerAccessToken> getAccessTokens();
+    protected abstract List<RefreshToken> getRefreshTokens();
+    protected abstract RefreshToken revokeRefreshToken(Client client, String refreshTokenKey);
+    protected abstract RefreshToken getRefreshToken(Client client, String refreshTokenKey);
+
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/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 8a3b514..5d78d87 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
@@ -95,6 +95,26 @@ public class DefaultEHCacheOAuthDataProvider extends AbstractOAuthDataProvider {
         }
         return clients;
     }
+
+    @Override
+    protected List<ServerAccessToken> getAccessTokens() {
+        List<String> keys = CastUtils.cast(accessTokenCache.getKeys());
+        List<ServerAccessToken> tokens = new ArrayList<ServerAccessToken>(keys.size());
+        for (String key : keys) {
+            tokens.add(getAccessToken(key));
+        }
+        return tokens;
+    }
+
+    @Override
+    protected List<RefreshToken> getRefreshTokens() {
+        List<String> keys = CastUtils.cast(refreshTokenCache.getKeys());
+        List<RefreshToken> tokens = new ArrayList<RefreshToken>(keys.size());
+        for (String key : keys) {
+            tokens.add(getRefreshToken(null, key));
+        }
+        return tokens;
+    }
     
     @Override
     public ServerAccessToken getAccessToken(String accessToken) throws OAuthServiceException {

http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEncryptingOAuthDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEncryptingOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEncryptingOAuthDataProvider.java
index 7d9e4d2..bdb63a2 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEncryptingOAuthDataProvider.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/DefaultEncryptingOAuthDataProvider.java
@@ -74,7 +74,22 @@ public class DefaultEncryptingOAuthDataProvider extends AbstractOAuthDataProvide
         }
         return clients;
     }
-    
+    @Override
+    protected List<ServerAccessToken> getAccessTokens() {
+        List<ServerAccessToken> list = new ArrayList<ServerAccessToken>(tokens.size());
+        for (String tokenKey : tokens) {
+            list.add(getAccessToken(tokenKey));
+        }
+        return list;
+    }
+    @Override
+    protected List<RefreshToken> getRefreshTokens() {
+        List<RefreshToken> list = new ArrayList<RefreshToken>(refreshTokens.size());
+        for (String tokenKey : tokens) {
+            list.add(getRefreshToken(null, tokenKey));
+        }
+        return list;
+    }
     @Override
     public ServerAccessToken getAccessToken(String accessToken) throws OAuthServiceException {
         try {
@@ -127,4 +142,5 @@ public class DefaultEncryptingOAuthDataProvider extends AbstractOAuthDataProvide
             throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED, ex);
         }
     }
+    
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
index a31fb5d..adbeebd 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/AbstractTokenService.java
@@ -205,6 +205,10 @@ public class AbstractTokenService extends AbstractOAuthService {
         return createErrorResponseFromBean(new OAuthError(error));
     }
     
+    protected Response createErrorResponseFromErrorCode(String error) {
+        return createErrorResponseFromBean(new OAuthError(error));
+    }
+    
     protected Response createErrorResponseFromBean(OAuthError errorBean) {
         return JAXRSUtils.toResponseBuilder(400).entity(errorBean).build();
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/d887fef4/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenRevocationService.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenRevocationService.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenRevocationService.java
index 092b9ec..26be81f 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenRevocationService.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/services/TokenRevocationService.java
@@ -53,10 +53,17 @@ public class TokenRevocationService extends AbstractTokenService {
             return createErrorResponse(params, OAuthConstants.UNSUPPORTED_TOKEN_TYPE);
         }
         String tokenTypeHint = params.getFirst(OAuthConstants.REVOKED_TOKEN_TYPE_HINT);
+        if (tokenTypeHint != null 
+            && !OAuthConstants.ACCESS_TOKEN.equals(tokenTypeHint)
+            && !OAuthConstants.REFRESH_TOKEN.equals(tokenTypeHint)) {
+            return createErrorResponseFromErrorCode(OAuthConstants.UNSUPPORTED_TOKEN_TYPE);
+        }
         try {
             getDataProvider().revokeToken(client, token, tokenTypeHint);
         } catch (OAuthServiceException ex) {
-            return handleException(ex, OAuthConstants.UNSUPPORTED_TOKEN_TYPE);
+            // Spec: The authorization server responds with HTTP status code 200 if the
+            // token has been revoked successfully or if the client submitted an
+            // invalid token
         }
         return Response.ok().build();
     }