Repository: cxf Updated Branches: refs/heads/master 63a1088a9 -> fd1d0afe8
Making sure a device code verifier is linked to the access token via a code grant Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/fd1d0afe Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/fd1d0afe Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/fd1d0afe Branch: refs/heads/master Commit: fd1d0afe8cf2f3d05772b63f1e8c13736acc0592 Parents: 63a1088 Author: Sergey Beryozkin <[email protected]> Authored: Tue Nov 17 17:00:11 2015 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Tue Nov 17 17:00:11 2015 +0000 ---------------------------------------------------------------------- .../oauth2/common/AccessTokenRegistration.java | 9 ++++++ .../oauth2/common/AccessTokenValidation.java | 9 ++++++ .../oauth2/common/ServerAccessToken.java | 9 ++++++ .../oauth2/grants/AbstractGrantHandler.java | 13 +++++--- .../code/AuthorizationCodeGrantHandler.java | 34 +++++++++++++------- .../provider/AbstractOAuthDataProvider.java | 2 ++ .../utils/crypto/ModelEncryptionSupport.java | 11 +++++-- 7 files changed, 67 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/fd1d0afe/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java index 8f844a0..b2641fc 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenRegistration.java @@ -31,6 +31,7 @@ public class AccessTokenRegistration { private String grantType; private UserSubject subject; private String audience; + private String clientCodeVerifier; /** * Sets the {@link Client} instance @@ -120,5 +121,13 @@ public class AccessTokenRegistration { public void setAudience(String audience) { this.audience = audience; } + + public String getClientCodeVerifier() { + return clientCodeVerifier; + } + + public void setClientCodeVerifier(String clientCodeVerifier) { + this.clientCodeVerifier = clientCodeVerifier; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/fd1d0afe/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenValidation.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenValidation.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenValidation.java index 3455a21..f25f286 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenValidation.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/AccessTokenValidation.java @@ -48,6 +48,7 @@ public class AccessTokenValidation { private UserSubject tokenSubject; private List<OAuthPermission> tokenScopes = new LinkedList<OAuthPermission>(); private String audience; + private String clientCodeVerifier; private Map<String, String> extraProps = new HashMap<String, String>(); public AccessTokenValidation() { @@ -68,6 +69,7 @@ public class AccessTokenValidation { this.tokenSubject = token.getSubject(); this.tokenScopes = token.getScopes(); this.audience = token.getAudience(); + this.clientCodeVerifier = token.getClientCodeVerifier(); } public String getClientId() { @@ -158,5 +160,12 @@ public class AccessTokenValidation { public void setClientConfidential(boolean isConfidential) { this.isClientConfidential = isConfidential; } + public String getClientCodeVerifier() { + return clientCodeVerifier; + } + + public void setClientCodeVerifier(String clientCodeVerifier) { + this.clientCodeVerifier = clientCodeVerifier; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/fd1d0afe/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java index 965b758..d5cc449 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/ServerAccessToken.java @@ -36,6 +36,7 @@ public abstract class ServerAccessToken extends AccessToken { private List<OAuthPermission> scopes = new LinkedList<OAuthPermission>(); private UserSubject subject; private String audience; + private String clientCodeVerifier; protected ServerAccessToken() { @@ -149,4 +150,12 @@ public abstract class ServerAccessToken extends AccessToken { } return token; } + + public String getClientCodeVerifier() { + return clientCodeVerifier; + } + + public void setClientCodeVerifier(String clientCodeVerifier) { + this.clientCodeVerifier = clientCodeVerifier; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/fd1d0afe/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java index dd17dd1..b855af0 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/AbstractGrantHandler.java @@ -84,7 +84,7 @@ public abstract class AbstractGrantHandler implements AccessTokenGrantHandler { } } - private String getSingleGrantType() { + protected String getSingleGrantType() { if (supportedGrants.size() > 1) { String errorMessage = "Request grant type must be specified"; LOG.warning(errorMessage); @@ -109,7 +109,7 @@ public abstract class AbstractGrantHandler implements AccessTokenGrantHandler { List<String> requestedScope) { return doCreateAccessToken(client, subject, getSingleGrantType(), requestedScope, - null, null); + null, null, null); } protected ServerAccessToken doCreateAccessToken(Client client, @@ -118,14 +118,15 @@ public abstract class AbstractGrantHandler implements AccessTokenGrantHandler { List<String> approvedScope, String audience) { - return doCreateAccessToken(client, subject, getSingleGrantType(), requestedScope, approvedScope, audience); + return doCreateAccessToken(client, subject, getSingleGrantType(), requestedScope, + approvedScope, audience, null); } protected ServerAccessToken doCreateAccessToken(Client client, UserSubject subject, String requestedGrant, List<String> requestedScope) { - return doCreateAccessToken(client, subject, requestedGrant, requestedScope, null, null); + return doCreateAccessToken(client, subject, requestedGrant, requestedScope, null, null, null); } protected ServerAccessToken doCreateAccessToken(Client client, @@ -133,7 +134,8 @@ public abstract class AbstractGrantHandler implements AccessTokenGrantHandler { String requestedGrant, List<String> requestedScope, List<String> approvedScope, - String audience) { + String audience, + String codeVerifier) { if (!OAuthUtils.validateScopes(requestedScope, client.getRegisteredScopes(), partialMatchScopeValidation)) { throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_SCOPE)); @@ -160,6 +162,7 @@ public abstract class AbstractGrantHandler implements AccessTokenGrantHandler { } reg.setApprovedScope(approvedScope); reg.setAudience(audience); + reg.setClientCodeVerifier(codeVerifier); return dataProvider.createAccessToken(reg); } http://git-wip-us.apache.org/repos/asf/cxf/blob/fd1d0afe/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java index 76fcbec..9a6888a 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/AuthorizationCodeGrantHandler.java @@ -35,6 +35,7 @@ import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; public class AuthorizationCodeGrantHandler extends AbstractGrantHandler { private CodeVerifierTransformer codeVerifierTransformer; + private boolean expectCodeVerifierForPublicClients; public AuthorizationCodeGrantHandler() { super(OAuthConstants.AUTHORIZATION_CODE_GRANT); @@ -71,32 +72,41 @@ public class AuthorizationCodeGrantHandler extends AbstractGrantHandler { throw new OAuthServiceException(OAuthConstants.INVALID_REQUEST); } + String clientCodeVerifier = params.getFirst(OAuthConstants.AUTHORIZATION_CODE_VERIFIER); String clientCodeChallenge = grant.getClientCodeChallenge(); - if (clientCodeChallenge != null) { - String clientCodeVerifier = params.getFirst(OAuthConstants.AUTHORIZATION_CODE_VERIFIER); - if (!compareCodeVerifierWithChallenge(clientCodeVerifier, clientCodeChallenge)) { - throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); - } + if (!compareCodeVerifierWithChallenge(client, clientCodeVerifier, clientCodeChallenge)) { + throw new OAuthServiceException(OAuthConstants.INVALID_GRANT); } return doCreateAccessToken(client, grant.getSubject(), + getSingleGrantType(), grant.getRequestedScopes(), grant.getApprovedScopes(), - grant.getAudience()); + grant.getAudience(), + clientCodeVerifier); } - private boolean compareCodeVerifierWithChallenge(String clientCodeVerifier, String clientCodeChallenge) { - if (clientCodeChallenge == null) { + private boolean compareCodeVerifierWithChallenge(Client c, String clientCodeVerifier, + String clientCodeChallenge) { + if (clientCodeChallenge == null && clientCodeChallenge == null + && (c.isConfidential() || !expectCodeVerifierForPublicClients)) { + return true; + } else if (clientCodeChallenge != null && clientCodeChallenge == null + || clientCodeChallenge == null && clientCodeChallenge != null) { return false; + } else { + String transformedCodeVerifier = codeVerifierTransformer == null + ? clientCodeVerifier : codeVerifierTransformer.transformCodeVerifier(clientCodeVerifier); + return clientCodeChallenge.equals(transformedCodeVerifier); } - String transformedCodeVerifier = codeVerifierTransformer == null - ? clientCodeVerifier : codeVerifierTransformer.transformCodeVerifier(clientCodeVerifier); - return clientCodeChallenge.equals(transformedCodeVerifier); - } public void setCodeVerifierTransformer(CodeVerifierTransformer codeVerifier) { this.codeVerifierTransformer = codeVerifier; } + + public void setExpectCodeVerifierForPublicClients(boolean expectCodeVerifierForPublicClients) { + this.expectCodeVerifierForPublicClients = expectCodeVerifierForPublicClients; + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/fd1d0afe/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 accd4af..8eba936 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 @@ -103,6 +103,7 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { convertScopeToPermissions(accessToken.getClient(), theScopes); at.setScopes(thePermissions); at.setSubject(accessToken.getSubject()); + at.setClientCodeVerifier(accessToken.getClientCodeVerifier()); saveAccessToken(at); if (isRefreshTokenSupported(theScopes)) { createNewRefreshToken(at); @@ -124,6 +125,7 @@ public abstract class AbstractOAuthDataProvider implements OAuthDataProvider { 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); http://git-wip-us.apache.org/repos/asf/cxf/blob/fd1d0afe/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/ModelEncryptionSupport.java ---------------------------------------------------------------------- diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/ModelEncryptionSupport.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/ModelEncryptionSupport.java index 5eb8990..2b3a798 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/ModelEncryptionSupport.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/crypto/ModelEncryptionSupport.java @@ -252,8 +252,10 @@ public final class ModelEncryptionSupport { } newToken.setScopes(perms); } + //Client verifier: + newToken.setClientCodeVerifier(parts[10]); //UserSubject: - newToken.setSubject(recreateUserSubject(parts[10])); + newToken.setSubject(recreateUserSubject(parts[11])); return newToken; } @@ -315,7 +317,10 @@ public final class ModelEncryptionSupport { } } state.append(SEP); - // 10: user subject + // 10: code verifier + state.append(tokenizeString(token.getClientCodeVerifier())); + state.append(SEP); + // 11: user subject tokenizeUserSubject(state, token.getSubject()); return state.toString(); @@ -419,7 +424,7 @@ public final class ModelEncryptionSupport { // 5: audience state.append(tokenizeString(grant.getAudience())); state.append(SEP); - // 6: code verifier + // 6: code challenge state.append(tokenizeString(grant.getClientCodeChallenge())); state.append(SEP); // 7: approved scopes
