You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by te...@apache.org on 2022/08/09 11:47:34 UTC
[pulsar] branch branch-2.9 updated: [improve][authentication] Support for get token from HTTP params (#16987)
This is an automated email from the ASF dual-hosted git repository.
technoboy 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 2c6db60abee [improve][authentication] Support for get token from HTTP params (#16987)
2c6db60abee is described below
commit 2c6db60abeec33f1e37fdd906f9994e267ad180b
Author: Zixuan Liu <no...@gmail.com>
AuthorDate: Tue Aug 9 19:47:26 2022 +0800
[improve][authentication] Support for get token from HTTP params (#16987)
---
.../authentication/AuthenticationDataHttps.java | 3 +-
.../AuthenticationProviderToken.java | 50 ++++++++++------
.../AuthenticationProviderTokenTest.java | 66 +++++++++++++++++++---
3 files changed, 93 insertions(+), 26 deletions(-)
diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationDataHttps.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationDataHttps.java
index 4e1d33b5ec5..0c262f5c620 100644
--- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationDataHttps.java
+++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationDataHttps.java
@@ -19,7 +19,6 @@
package org.apache.pulsar.broker.authentication;
import java.security.cert.X509Certificate;
-
import javax.servlet.http.HttpServletRequest;
public class AuthenticationDataHttps extends AuthenticationDataHttp {
@@ -27,7 +26,7 @@ public class AuthenticationDataHttps extends AuthenticationDataHttp {
protected final X509Certificate[] certificates;
public AuthenticationDataHttps(HttpServletRequest request) {
- super(request);
+ super(new AuthenticationProviderToken.HttpServletRequestWrapper(request));
certificates = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
}
diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderToken.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderToken.java
index 21bda4c97bf..dccd7bbb2b7 100644
--- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderToken.java
+++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderToken.java
@@ -19,35 +19,32 @@
package org.apache.pulsar.broker.authentication;
import static java.nio.charset.StandardCharsets.UTF_8;
-
+import com.google.common.annotations.VisibleForTesting;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jwt;
+import io.jsonwebtoken.JwtException;
+import io.jsonwebtoken.JwtParser;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.RequiredTypeException;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.security.SignatureException;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Histogram;
import java.io.IOException;
import java.net.SocketAddress;
import java.security.Key;
-
import java.util.Date;
import java.util.List;
import javax.naming.AuthenticationException;
import javax.net.ssl.SSLSession;
-
-import com.google.common.annotations.VisibleForTesting;
-import io.jsonwebtoken.ExpiredJwtException;
-import io.jsonwebtoken.RequiredTypeException;
-import io.jsonwebtoken.JwtParser;
-import io.prometheus.client.Counter;
-import io.prometheus.client.Histogram;
+import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.pulsar.broker.ServiceConfiguration;
import org.apache.pulsar.broker.authentication.metrics.AuthenticationMetrics;
import org.apache.pulsar.broker.authentication.utils.AuthTokenUtils;
import org.apache.pulsar.common.api.AuthData;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Jwt;
-import io.jsonwebtoken.JwtException;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.SignatureAlgorithm;
-import io.jsonwebtoken.security.SignatureException;
-
public class AuthenticationProviderToken implements AuthenticationProvider {
static final String HTTP_HEADER_NAME = "Authorization";
@@ -368,4 +365,25 @@ public class AuthenticationProviderToken implements AuthenticationProvider {
return expiration < System.currentTimeMillis();
}
}
+ public static final class HttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {
+ private final HttpServletRequest request;
+
+ public HttpServletRequestWrapper(HttpServletRequest request) {
+ super(request);
+ this.request = request;
+ }
+
+ @Override
+ public String getHeader(String name) {
+ // The browser javascript WebSocket client couldn't add the auth param to the request header, use the
+ // query param `token` to transport the auth token for the browser javascript WebSocket client.
+ if (name.equals(HTTP_HEADER_NAME) && request.getHeader(HTTP_HEADER_NAME) == null) {
+ String token = request.getParameter(TOKEN);
+ if (token != null) {
+ return !token.startsWith(HTTP_HEADER_VALUE_PREFIX) ? HTTP_HEADER_VALUE_PREFIX + token : token;
+ }
+ }
+ return super.getHeader(name);
+ }
+ }
}
diff --git a/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTokenTest.java b/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTokenTest.java
index b05ad4ca483..7d6404c3a32 100644
--- a/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTokenTest.java
+++ b/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/authentication/AuthenticationProviderTokenTest.java
@@ -18,12 +18,13 @@
*/
package org.apache.pulsar.broker.authentication;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-
import com.google.common.collect.Lists;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
@@ -32,26 +33,24 @@ import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
-import java.security.Key;
-import java.util.Arrays;
-import java.util.List;
-import lombok.Cleanup;
-
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.security.Key;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.sql.Date;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
-
import javax.crypto.SecretKey;
import javax.naming.AuthenticationException;
-
+import javax.servlet.http.HttpServletRequest;
+import lombok.Cleanup;
import org.apache.pulsar.broker.ServiceConfiguration;
import org.apache.pulsar.broker.authentication.utils.AuthTokenUtils;
import org.apache.pulsar.common.api.AuthData;
@@ -848,4 +847,55 @@ public class AuthenticationProviderTokenTest {
assertEquals(subject, SUBJECT);
provider.close();
}
+
+ @Test
+ public void testTokenFromHttpParams() throws Exception {
+ SecretKey secretKey = AuthTokenUtils.createSecretKey(SignatureAlgorithm.HS256);
+
+ @Cleanup
+ AuthenticationProviderToken provider = new AuthenticationProviderToken();
+
+ Properties properties = new Properties();
+ properties.setProperty(AuthenticationProviderToken.CONF_TOKEN_SECRET_KEY,
+ AuthTokenUtils.encodeKeyBase64(secretKey));
+
+ ServiceConfiguration conf = new ServiceConfiguration();
+ conf.setProperties(properties);
+ provider.initialize(conf);
+
+ String token = AuthTokenUtils.createToken(secretKey, SUBJECT, Optional.empty());
+ HttpServletRequest servletRequest = mock(HttpServletRequest.class);
+ doReturn(token).when(servletRequest).getParameter("token");
+ doReturn(null).when(servletRequest).getHeader("Authorization");
+ doReturn("127.0.0.1").when(servletRequest).getRemoteAddr();
+ doReturn(0).when(servletRequest).getRemotePort();
+
+ AuthenticationDataHttps authenticationDataHttps = new AuthenticationDataHttps(servletRequest);
+ provider.authenticate(authenticationDataHttps);
+ }
+
+ @Test
+ public void testTokenFromHttpHeaders() throws Exception {
+ SecretKey secretKey = AuthTokenUtils.createSecretKey(SignatureAlgorithm.HS256);
+
+ @Cleanup
+ AuthenticationProviderToken provider = new AuthenticationProviderToken();
+
+ Properties properties = new Properties();
+ properties.setProperty(AuthenticationProviderToken.CONF_TOKEN_SECRET_KEY,
+ AuthTokenUtils.encodeKeyBase64(secretKey));
+
+ ServiceConfiguration conf = new ServiceConfiguration();
+ conf.setProperties(properties);
+ provider.initialize(conf);
+
+ String token = AuthTokenUtils.createToken(secretKey, SUBJECT, Optional.empty());
+ HttpServletRequest servletRequest = mock(HttpServletRequest.class);
+ doReturn("Bearer " + token).when(servletRequest).getHeader("Authorization");
+ doReturn("127.0.0.1").when(servletRequest).getRemoteAddr();
+ doReturn(0).when(servletRequest).getRemotePort();
+
+ AuthenticationDataHttps authenticationDataHttps = new AuthenticationDataHttps(servletRequest);
+ provider.authenticate(authenticationDataHttps);
+ }
}