Return-Path: X-Original-To: apmail-cxf-commits-archive@www.apache.org Delivered-To: apmail-cxf-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 823851892B for ; Fri, 27 Nov 2015 13:45:05 +0000 (UTC) Received: (qmail 92631 invoked by uid 500); 27 Nov 2015 13:45:05 -0000 Delivered-To: apmail-cxf-commits-archive@cxf.apache.org Received: (qmail 92564 invoked by uid 500); 27 Nov 2015 13:45:05 -0000 Mailing-List: contact commits-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list commits@cxf.apache.org Received: (qmail 92555 invoked by uid 99); 27 Nov 2015 13:45:05 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 27 Nov 2015 13:45:05 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id CB331E027F; Fri, 27 Nov 2015 13:45:04 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sergeyb@apache.org To: commits@cxf.apache.org Message-Id: <97767df443cd40548f7d90e7ae3119b3@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: cxf git commit: Supporting overriding OAuth data providers in a more fine grained fashion and non-recycled refresh tokens Date: Fri, 27 Nov 2015 13:45:04 +0000 (UTC) Repository: cxf Updated Branches: refs/heads/3.1.x-fixes 6b355293a -> 9ef24a17c Supporting overriding OAuth data providers in a more fine grained fashion and non-recycled refresh tokens Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/9ef24a17 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/9ef24a17 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/9ef24a17 Branch: refs/heads/3.1.x-fixes Commit: 9ef24a17c0085974c129d1739934eaca84b05e88 Parents: 6b35529 Author: Sergey Beryozkin Authored: Fri Nov 27 13:41:56 2015 +0000 Committer: Sergey Beryozkin Committed: Fri Nov 27 13:42:52 2015 +0000 ---------------------------------------------------------------------- .../grants/code/AbstractCodeDataProvider.java | 7 +- .../code/DefaultEHCacheCodeDataProvider.java | 7 +- .../provider/AbstractOAuthDataProvider.java | 130 +++++++++++++------ .../DefaultEHCacheOAuthDataProvider.java | 17 ++- .../DefaultEncryptingOAuthDataProvider.java | 30 +++-- 5 files changed, 129 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/9ef24a17/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 fff16fa..6bed976 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 @@ -31,11 +31,16 @@ public abstract class AbstractCodeDataProvider extends AbstractOAuthDataProvider @Override public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg) throws OAuthServiceException { - ServerAuthorizationCodeGrant grant = initCodeGrant(reg, codeLifetime); + ServerAuthorizationCodeGrant grant = doCreateCodeGrant(reg); saveCodeGrant(grant); return grant; } + protected ServerAuthorizationCodeGrant doCreateCodeGrant(AuthorizationCodeRegistration reg) + throws OAuthServiceException { + return AbstractCodeDataProvider.initCodeGrant(reg, codeLifetime); + } + public void setCodeLifetime(long codeLifetime) { this.codeLifetime = codeLifetime; } http://git-wip-us.apache.org/repos/asf/cxf/blob/9ef24a17/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 ceb4ba0..5834a2c 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 @@ -54,10 +54,15 @@ public class DefaultEHCacheCodeDataProvider extends DefaultEHCacheOAuthDataProvi @Override public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg) throws OAuthServiceException { - ServerAuthorizationCodeGrant grant = AbstractCodeDataProvider.initCodeGrant(reg, codeLifetime); + ServerAuthorizationCodeGrant grant = doCreateCodeGrant(reg); saveCodeGrant(grant); return grant; } + + protected ServerAuthorizationCodeGrant doCreateCodeGrant(AuthorizationCodeRegistration reg) + throws OAuthServiceException { + return AbstractCodeDataProvider.initCodeGrant(reg, codeLifetime); + } @Override public ServerAuthorizationCodeGrant removeCodeGrant(String code) throws OAuthServiceException { http://git-wip-us.apache.org/repos/asf/cxf/blob/9ef24a17/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 0346c09..c951c6e 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 @@ -34,14 +34,33 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { private long accessTokenLifetime = 3600L; private long refreshTokenLifetime; // refresh tokens are eternal by default + private boolean recycleRefreshTokens = true; protected AbstractOAuthDataProvider() { } @Override - public ServerAccessToken createAccessToken(AccessTokenRegistration accessToken) + public ServerAccessToken createAccessToken(AccessTokenRegistration reg) throws OAuthServiceException { - return doCreateAccessToken(accessToken); + ServerAccessToken at = doCreateAccessToken(reg); + saveAccessToken(at); + if (isRefreshTokenSupported(reg.getApprovedScope())) { + createNewRefreshToken(at); + } + return at; + } + + protected ServerAccessToken doCreateAccessToken(AccessTokenRegistration accessToken) { + ServerAccessToken at = createNewAccessToken(accessToken.getClient()); + at.setAudience(accessToken.getAudience()); + at.setGrantType(accessToken.getGrantType()); + List theScopes = accessToken.getApprovedScope(); + List thePermissions = + convertScopeToPermissions(accessToken.getClient(), theScopes); + at.setScopes(thePermissions); + at.setSubject(accessToken.getSubject()); + at.setClientCodeVerifier(accessToken.getClientCodeVerifier()); + return at; } @Override @@ -52,30 +71,61 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { @Override public ServerAccessToken refreshAccessToken(Client client, String refreshTokenKey, List restrictedScopes) throws OAuthServiceException { - RefreshToken oldRefreshToken = revokeRefreshAndAccessTokens(client, refreshTokenKey); - if (oldRefreshToken == null - || OAuthUtils.isExpired(oldRefreshToken.getIssuedAt(), oldRefreshToken.getExpiresIn())) { - throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED); + RefreshToken currentRefreshToken = revokeRefreshAndAccessTokens(client, refreshTokenKey); + ServerAccessToken at = doRefreshAccessToken(client, currentRefreshToken, restrictedScopes); + saveAccessToken(at); + if (recycleRefreshTokens) { + createNewRefreshToken(at); + } else { + updateRefreshToken(currentRefreshToken, at); } - return doRefreshAccessToken(client, oldRefreshToken, restrictedScopes); - + return at; } @Override public void revokeToken(Client client, String tokenKey, String tokenTypeHint) throws OAuthServiceException { - if (revokeAccessToken(tokenKey)) { - return; + ServerAccessToken accessToken = revokeAccessToken(tokenKey); + if (accessToken == null) { + doRevokeRefreshAndAccessTokens(client, tokenKey, true); + } else { + if (accessToken.getRefreshToken() != null) { + RefreshToken rt = getRefreshToken(client, accessToken.getRefreshToken()); + if (rt == null) { + return; + } + + List accessTokenKeys = rt.getAccessTokens(); + for (int i = 0; i < accessTokenKeys.size(); i++) { + if (accessTokenKeys.get(i).equals(accessToken.getTokenKey())) { + accessTokenKeys.remove(i); + break; + } + } + if (rt.getAccessTokens().isEmpty()) { + revokeRefreshToken(client, rt.getTokenKey()); + } else { + saveRefreshToken(null, rt); + } + } } - revokeRefreshAndAccessTokens(client, tokenKey); } protected RefreshToken revokeRefreshAndAccessTokens(Client client, String tokenKey) { - RefreshToken oldRefreshToken = revokeRefreshToken(client, tokenKey); - if (oldRefreshToken != null) { - for (String accessTokenKey : oldRefreshToken.getAccessTokens()) { - revokeAccessToken(accessTokenKey); - } + 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); + } + for (String accessTokenKey : currentRefreshToken.getAccessTokens()) { + revokeAccessToken(accessTokenKey); } - return oldRefreshToken; + if (recycle) { + currentRefreshToken.getAccessTokens().clear(); + } + return currentRefreshToken; } @@ -96,23 +146,6 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { return null; } - protected ServerAccessToken doCreateAccessToken(AccessTokenRegistration accessToken) { - ServerAccessToken at = createNewAccessToken(accessToken.getClient()); - at.setAudience(accessToken.getAudience()); - at.setGrantType(accessToken.getGrantType()); - List theScopes = accessToken.getApprovedScope(); - List thePermissions = - convertScopeToPermissions(accessToken.getClient(), theScopes); - at.setScopes(thePermissions); - at.setSubject(accessToken.getSubject()); - at.setClientCodeVerifier(accessToken.getClientCodeVerifier()); - saveAccessToken(at); - if (isRefreshTokenSupported(theScopes)) { - createNewRefreshToken(at); - } - return at; - } - protected boolean isRefreshTokenSupported(List theScopes) { return theScopes.contains(OAuthConstants.REFRESH_TOKEN_SCOPE); } @@ -121,19 +154,32 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { return new BearerAccessToken(client, accessTokenLifetime); } + protected RefreshToken updateRefreshToken(RefreshToken rt, ServerAccessToken at) { + linkRefreshAccessTokens(rt, at); + saveRefreshToken(at, rt); + return rt; + } protected RefreshToken createNewRefreshToken(ServerAccessToken at) { + RefreshToken rt = doCreateNewRefreshToken(at); + saveRefreshToken(at, rt); + return rt; + } + protected RefreshToken doCreateNewRefreshToken(ServerAccessToken at) { RefreshToken rt = new RefreshToken(at.getClient(), refreshTokenLifetime); rt.setAudience(at.getAudience()); rt.setGrantType(at.getGrantType()); rt.setScopes(at.getScopes()); rt.setSubject(at.getSubject()); rt.setClientCodeVerifier(at.getClientCodeVerifier()); - rt.getAccessTokens().add(at.getTokenKey()); - at.setRefreshToken(rt.getTokenKey()); - saveRefreshToken(at, rt); + linkRefreshAccessTokens(rt, at); return rt; } + private void linkRefreshAccessTokens(RefreshToken rt, ServerAccessToken at) { + rt.getAccessTokens().add(at.getTokenKey()); + at.setRefreshToken(rt.getTokenKey()); + } + protected ServerAccessToken doRefreshAccessToken(Client client, RefreshToken oldRefreshToken, List restrictedScopes) { @@ -151,8 +197,6 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { throw new OAuthServiceException("Invalid scopes"); } } - saveAccessToken(at); - createNewRefreshToken(at); return at; } @@ -164,9 +208,13 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { this.refreshTokenLifetime = refreshTokenLifetime; } + public void setRecycleRefreshTokens(boolean recycleRefreshTokens) { + this.recycleRefreshTokens = recycleRefreshTokens; + } + protected abstract void saveAccessToken(ServerAccessToken serverToken); protected abstract void saveRefreshToken(ServerAccessToken at, RefreshToken refreshToken); - protected abstract boolean revokeAccessToken(String accessTokenKey); + protected abstract ServerAccessToken revokeAccessToken(String accessTokenKey); 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/9ef24a17/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 f78d012..3e9e800 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 @@ -102,17 +102,20 @@ public class DefaultEHCacheOAuthDataProvider extends AbstractOAuthDataProvider return getCacheValue(accessTokenCache, accessToken, ServerAccessToken.class); } - @Override - public void removeAccessToken(ServerAccessToken accessToken) throws OAuthServiceException { - revokeAccessToken(accessToken.getTokenKey()); + protected ServerAccessToken revokeAccessToken(String accessTokenKey) { + ServerAccessToken at = getAccessToken(accessTokenKey); + if (at != null) { + accessTokenCache.remove(accessTokenKey); + } + return at; } - - protected boolean revokeAccessToken(String accessTokenKey) { - return accessTokenCache.remove(accessTokenKey); + + protected RefreshToken getRefreshToken(Client client, String refreshTokenKey) { + return getCacheValue(refreshTokenCache, refreshTokenKey, RefreshToken.class); } protected RefreshToken revokeRefreshToken(Client client, String refreshTokenKey) { - RefreshToken refreshToken = getCacheValue(refreshTokenCache, refreshTokenKey, RefreshToken.class); + RefreshToken refreshToken = getRefreshToken(client, refreshTokenKey); if (refreshToken != null) { refreshTokenCache.remove(refreshTokenKey); } http://git-wip-us.apache.org/repos/asf/cxf/blob/9ef24a17/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 d033b1f..ed968ad 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 @@ -86,18 +86,15 @@ public class DefaultEncryptingOAuthDataProvider extends AbstractOAuthDataProvide } @Override - public void removeAccessToken(ServerAccessToken accessToken) throws OAuthServiceException { - revokeAccessToken(accessToken.getTokenKey()); - } - - @Override protected void saveAccessToken(ServerAccessToken serverToken) { encryptAccessToken(serverToken); } @Override - protected boolean revokeAccessToken(String accessTokenKey) { - return tokens.remove(accessTokenKey); + protected ServerAccessToken revokeAccessToken(String accessTokenKey) { + ServerAccessToken at = getAccessToken(accessTokenKey); + tokens.remove(accessTokenKey); + return at; } @Override @@ -108,12 +105,13 @@ public class DefaultEncryptingOAuthDataProvider extends AbstractOAuthDataProvide @Override protected RefreshToken revokeRefreshToken(Client client, String refreshTokenKey) { - refreshTokens.remove(refreshTokenKey); - try { - return ModelEncryptionSupport.decryptRefreshToken(this, refreshTokenKey, key); - } catch (SecurityException ex) { - throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED, ex); + RefreshToken rt = null; + if (refreshTokens.containsKey(refreshTokenKey)) { + rt = getRefreshToken(client, refreshTokenKey); + refreshTokens.remove(refreshTokenKey); } + return rt; + } private void encryptAccessToken(ServerAccessToken token) { @@ -122,4 +120,12 @@ public class DefaultEncryptingOAuthDataProvider extends AbstractOAuthDataProvide refreshTokens.put(token.getRefreshToken(), encryptedToken); token.setTokenKey(encryptedToken); } + @Override + protected RefreshToken getRefreshToken(Client client, String refreshTokenKey) { + try { + return ModelEncryptionSupport.decryptRefreshToken(this, refreshTokenKey, key); + } catch (SecurityException ex) { + throw new OAuthServiceException(OAuthConstants.ACCESS_DENIED, ex); + } + } }