This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch 3.3.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 8fade1b4eca6f2b38d520ce68c16651ae9ff9575 Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Thu Jul 9 10:07:40 2020 +0100 CXF-8311 - OAuth 2.0: Refresh token redemption unexpectedly fails with invalid_grant error (cherry picked from commit a0f76d634d9b58a2644bc01532d7dd87b66081de) # Conflicts: # rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java --- .../grants/refresh/RefreshTokenGrantHandler.java | 2 +- .../cxf/rs/security/oauth2/utils/OAuthUtils.java | 12 +++++- .../grants/AuthorizationGrantNegativeTest.java | 46 ++++++++++++++++++++++ .../oauth2/grants/AuthorizationGrantTest.java | 45 +++++++++++++++++++++ 4 files changed, 103 insertions(+), 2 deletions(-) diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java index ac6714d..7da2135 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/refresh/RefreshTokenGrantHandler.java @@ -51,7 +51,7 @@ public class RefreshTokenGrantHandler implements AccessTokenGrantHandler { List<String> requestedScopes = OAuthUtils.getRequestedScopes(client, params.getFirst(OAuthConstants.SCOPE), useAllClientScopes, - partialMatchScopeValidation); + partialMatchScopeValidation, false); final ServerAccessToken st = dataProvider.refreshAccessToken(client, refreshToken, requestedScopes); st.setGrantType(OAuthConstants.REFRESH_TOKEN_GRANT); return st; diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java index f311661..2683122 100644 --- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java +++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/utils/OAuthUtils.java @@ -329,10 +329,20 @@ public final class OAuthUtils { String scopeParameter, boolean useAllClientScopes, boolean partialMatchScopeValidation) { + return getRequestedScopes(client, scopeParameter, useAllClientScopes, partialMatchScopeValidation, true); + } + + public static List<String> getRequestedScopes(Client client, + String scopeParameter, + boolean useAllClientScopes, + boolean partialMatchScopeValidation, + boolean defaultToRegisteredScopes) { List<String> requestScopes = parseScope(scopeParameter); List<String> registeredScopes = client.getRegisteredScopes(); if (requestScopes.isEmpty()) { - requestScopes.addAll(registeredScopes); + if (defaultToRegisteredScopes) { + return registeredScopes; + } return requestScopes; } if (!validateScopes(requestScopes, registeredScopes, partialMatchScopeValidation)) { diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java index 10eee52..5baa313 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantNegativeTest.java @@ -416,6 +416,52 @@ public class AuthorizationGrantNegativeTest extends AbstractBusClientServerTestB } } + // Try to refresh the access token specifying an additional scope + @org.junit.Test + public void testRefreshWithScopeUpgrade() throws Exception { + URL busFile = AuthorizationGrantTest.class.getResource("client.xml"); + + String address = "https://localhost:" + port + "/services/"; + WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(), + "alice", "security", busFile.toString()); + // Save the Cookie for the second request... + WebClient.getConfig(client).getRequestContext().put( + org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE); + + // Get Authorization Code + String code = OAuth2TestUtils.getAuthorizationCode(client, "read_balance"); + assertNotNull(code); + + // Now get the access token + client = WebClient.create(address, OAuth2TestUtils.setupProviders(), + "consumer-id", "this-is-a-secret", busFile.toString()); + // Save the Cookie for the second request... + WebClient.getConfig(client).getRequestContext().put( + org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE); + + ClientAccessToken accessToken = + OAuth2TestUtils.getAccessTokenWithAuthorizationCode(client, code); + assertNotNull(accessToken.getTokenKey()); + assertNotNull(accessToken.getRefreshToken()); + + // Refresh the access token + client.type("application/x-www-form-urlencoded").accept("application/json"); + + Form form = new Form(); + form.param("grant_type", "refresh_token"); + form.param("refresh_token", accessToken.getRefreshToken()); + form.param("client_id", "consumer-id"); + form.param("scope", "read_balance create_balance"); + + try { + Response response = client.post(form); + response.readEntity(ClientAccessToken.class); + fail("Failure expected on trying to upgrade scopes"); + } catch (ResponseProcessingException ex) { + //expected + } + } + @org.junit.Test public void testAccessTokenBadCode() throws Exception { URL busFile = AuthorizationGrantTest.class.getResource("client.xml"); diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java index 161da2f..f6b11e3 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/grants/AuthorizationGrantTest.java @@ -272,6 +272,51 @@ public class AuthorizationGrantTest extends AbstractBusClientServerTestBase { accessToken = response.readEntity(ClientAccessToken.class); assertNotNull(accessToken.getTokenKey()); assertNotNull(accessToken.getRefreshToken()); + assertEquals("read_balance", accessToken.getApprovedScope()); + + if (isAccessTokenInJWTFormat()) { + validateAccessToken(accessToken.getTokenKey()); + } + } + + // Here we don't specify a scope in the refresh token call + @org.junit.Test + public void testAuthorizationCodeGrantRefreshWithoutScope() throws Exception { + String address = "https://localhost:" + port + "/services/"; + WebClient client = WebClient.create(address, OAuth2TestUtils.setupProviders(), + "alice", "security", null); + // Save the Cookie for the second request... + WebClient.getConfig(client).getRequestContext().put( + org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE); + + // Get Authorization Code + String code = OAuth2TestUtils.getAuthorizationCode(client, "read_balance"); + assertNotNull(code); + + // Now get the access token + client = WebClient.create(address, OAuth2TestUtils.setupProviders(), + "consumer-id", "this-is-a-secret", null); + // Save the Cookie for the second request... + WebClient.getConfig(client).getRequestContext().put( + org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE); + + ClientAccessToken accessToken = + OAuth2TestUtils.getAccessTokenWithAuthorizationCode(client, code); + assertNotNull(accessToken.getTokenKey()); + assertNotNull(accessToken.getRefreshToken()); + + // Refresh the access token + client.type("application/x-www-form-urlencoded").accept("application/json"); + + Form form = new Form(); + form.param("grant_type", "refresh_token"); + form.param("refresh_token", accessToken.getRefreshToken()); + form.param("client_id", "consumer-id"); + + accessToken = client.post(form, ClientAccessToken.class); + assertNotNull(accessToken.getTokenKey()); + assertNotNull(accessToken.getRefreshToken()); +// assertEquals("read_balance", accessToken.getApprovedScope()); if (isAccessTokenInJWTFormat()) { validateAccessToken(accessToken.getTokenKey());
