You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by ma...@apache.org on 2022/05/25 06:52:35 UTC

[pulsar] branch branch-2.9 updated: Support handling single role and non-jwt-token in MultiRolesTokenAuthorizationProvider (#14857)

This is an automated email from the ASF dual-hosted git repository.

mattisonchao pushed a commit to branch branch-2.9
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/branch-2.9 by this push:
     new a861242dc57 Support handling single role and non-jwt-token in MultiRolesTokenAuthorizationProvider (#14857)
a861242dc57 is described below

commit a861242dc57439be30def69d5a9a1821510ce7dd
Author: Zike Yang <zi...@apache.org>
AuthorDate: Sun May 8 23:08:45 2022 +0800

    Support handling single role and non-jwt-token in MultiRolesTokenAuthorizationProvider (#14857)
    
    ### Motivation
    
    Currently, `MultiRolesTokenAuthorizationProvider` doesn't support handling the single string type role. It will return the empty role in that case. This PR adds support for handling the string-type role. This PR also adds support for handling the non-jwt-token.
    
    ### Modifications
    
    * Add support for handling the string-type role
    * Add support for handling the non-jwt-token
    
    ### Verifying this change
    
    This change is already covered by existing tests, such as *testMultiRolesAuthzWithSingleRole*.
    
    (cherry picked from commit 8bf6785c0803d314465b2d9156df6ca5bbb3c644)
---
 .../MultiRolesTokenAuthorizationProvider.java      |   8 +-
 .../MultiRolesTokenAuthorizationProviderTest.java  | 101 +++++++++++++++++++++
 2 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProvider.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProvider.java
index 8a91d7f6971..c508ccbd5b4 100644
--- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProvider.java
+++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProvider.java
@@ -59,7 +59,7 @@ public class MultiRolesTokenAuthorizationProvider extends PulsarAuthorizationPro
     // The token's claim that corresponds to the "role" string
     static final String CONF_TOKEN_AUTH_CLAIM = "tokenAuthClaim";
 
-    private JwtParser parser;
+    private final JwtParser parser;
     private String roleClaim;
 
     public MultiRolesTokenAuthorizationProvider() {
@@ -107,11 +107,15 @@ public class MultiRolesTokenAuthorizationProvider extends PulsarAuthorizationPro
             return Collections.emptyList();
 
         String[] splitToken = token.split("\\.");
+        if (splitToken.length < 2) {
+            log.warn("Unable to extract additional roles from JWT token");
+            return Collections.emptyList();
+        }
         String unsignedToken = splitToken[0] + "." + splitToken[1] + ".";
 
         Jwt<?, Claims> jwt = parser.parseClaimsJwt(unsignedToken);
         try {
-            Collections.singletonList(jwt.getBody().get(roleClaim, String.class));
+            return Collections.singletonList(jwt.getBody().get(roleClaim, String.class));
         } catch (RequiredTypeException requiredTypeException) {
             try {
                 List list = jwt.getBody().get(roleClaim, List.class);
diff --git a/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProviderTest.java b/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProviderTest.java
index edd0baa42ae..078e2aad07a 100644
--- a/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProviderTest.java
+++ b/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authorization/MultiRolesTokenAuthorizationProviderTest.java
@@ -18,10 +18,14 @@
  */
 package org.apache.pulsar.broker.authorization;
 
+import static org.mockito.Mockito.mock;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
+import java.util.Properties;
+import org.apache.pulsar.broker.ServiceConfiguration;
 import org.apache.pulsar.broker.authentication.AuthenticationDataSource;
 import org.apache.pulsar.broker.authentication.utils.AuthTokenUtils;
+import org.apache.pulsar.broker.resources.PulsarResources;
 import org.junit.Assert;
 import org.testng.annotations.Test;
 
@@ -96,4 +100,101 @@ public class MultiRolesTokenAuthorizationProviderTest {
 
         Assert.assertFalse(provider.authorize(ads, role -> CompletableFuture.completedFuture(false)).get());
     }
+
+    @Test
+    public void testMultiRolesAuthzWithSingleRole() throws Exception {
+        SecretKey secretKey = AuthTokenUtils.createSecretKey(SignatureAlgorithm.HS256);
+        String testRole = "test-role";
+        String token = Jwts.builder().claim("sub", testRole).signWith(secretKey).compact();
+
+        MultiRolesTokenAuthorizationProvider provider = new MultiRolesTokenAuthorizationProvider();
+
+        AuthenticationDataSource ads = new AuthenticationDataSource() {
+            @Override
+            public boolean hasDataFromHttp() {
+                return true;
+            }
+
+            @Override
+            public String getHttpHeader(String name) {
+                if (name.equals("Authorization")) {
+                    return "Bearer " + token;
+                } else {
+                    throw new IllegalArgumentException("Wrong HTTP header");
+                }
+            }
+        };
+
+        Assert.assertTrue(provider.authorize(ads, role -> {
+            if (role.equals(testRole)) {
+                return CompletableFuture.completedFuture(true);
+            }
+            return CompletableFuture.completedFuture(false);
+        }).get());
+    }
+
+    @Test
+    public void testMultiRolesNotFailNonJWT() throws Exception {
+        String token = "a-non-jwt-token";
+
+        MultiRolesTokenAuthorizationProvider provider = new MultiRolesTokenAuthorizationProvider();
+
+        AuthenticationDataSource ads = new AuthenticationDataSource() {
+            @Override
+            public boolean hasDataFromHttp() {
+                return true;
+            }
+
+            @Override
+            public String getHttpHeader(String name) {
+                if (name.equals("Authorization")) {
+                    return "Bearer " + token;
+                } else {
+                    throw new IllegalArgumentException("Wrong HTTP header");
+                }
+            }
+        };
+
+        Assert.assertFalse(provider.authorize(ads, role -> CompletableFuture.completedFuture(false)).get());
+    }
+
+    @Test
+    public void testMultiRolesAuthzWithCustomRolesClaims() throws Exception {
+        SecretKey secretKey = AuthTokenUtils.createSecretKey(SignatureAlgorithm.HS256);
+        String testRole = "test-role";
+        String customRolesClaims = "role";
+        String token = Jwts.builder().claim(customRolesClaims, new String[]{testRole}).signWith(secretKey).compact();
+
+        Properties properties = new Properties();
+        properties.setProperty("tokenSettingPrefix", "prefix_");
+        properties.setProperty("prefix_tokenAuthClaim", customRolesClaims);
+        ServiceConfiguration conf = new ServiceConfiguration();
+        conf.setProperties(properties);
+
+        MultiRolesTokenAuthorizationProvider provider = new MultiRolesTokenAuthorizationProvider();
+        provider.initialize(conf, mock(PulsarResources.class));
+
+        AuthenticationDataSource ads = new AuthenticationDataSource() {
+            @Override
+            public boolean hasDataFromHttp() {
+                return true;
+            }
+
+            @Override
+            public String getHttpHeader(String name) {
+                if (name.equals("Authorization")) {
+                    return "Bearer " + token;
+                } else {
+                    throw new IllegalArgumentException("Wrong HTTP header");
+                }
+            }
+        };
+
+        Assert.assertTrue(provider.authorize(ads, role -> {
+            if (role.equals(testRole)) {
+                return CompletableFuture.completedFuture(true);
+            }
+            return CompletableFuture.completedFuture(false);
+        }).get());
+    }
 }