You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2020/07/09 09:25:34 UTC

[cxf] 01/02: CXF-8311 - OAuth 2.0: Refresh token redemption unexpectedly fails with invalid_grant error

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 <co...@apache.org>
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());