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 <sberyoz...@gmail.com> Authored: Wed Dec 23 12:45:04 2015 +0000 Committer: Sergey Beryozkin <sberyoz...@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(); }