Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public AuthenticationState newAuthState(AuthData authData, SocketAddress remoteA

@Override
public AuthenticationState newHttpAuthState(HttpServletRequest request) throws AuthenticationException {
return new TokenAuthenticationState(this, request);
return new TokenAuthenticationState(this, new HttpServletRequestWrapper(request));
}

public static String getToken(AuthenticationDataSource authData) throws AuthenticationException {
Expand Down Expand Up @@ -387,4 +387,26 @@ public boolean isExpired() {
return expiration < System.currentTimeMillis();
}
}

private 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
package org.apache.pulsar.broker.authentication;

import static org.mockito.ArgumentMatchers.anyString;
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;
Expand All @@ -33,26 +34,24 @@
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;
Expand Down Expand Up @@ -837,7 +836,7 @@ public void testTokenSettingPrefix() throws Exception {
ServiceConfiguration conf = new ServiceConfiguration();
conf.setProperties(properties);

ServiceConfiguration mockConf = Mockito.mock(ServiceConfiguration.class);
ServiceConfiguration mockConf = mock(ServiceConfiguration.class);
String prefix = "test";

Mockito.when(mockConf.getProperty(anyString()))
Expand All @@ -864,6 +863,57 @@ public void testTokenSettingPrefix() throws Exception {
.getProperty(prefix + AuthenticationProviderToken.CONF_TOKEN_AUDIENCE);
}

@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();

AuthenticationState authState = provider.newHttpAuthState(servletRequest);
provider.authenticate(authState.getAuthDataSource());
}

@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();

AuthenticationState authState = provider.newHttpAuthState(servletRequest);
provider.authenticate(authState.getAuthDataSource());
}

private static String createTokenWithAudience(Key signingKey, String audienceClaim, List<String> audience) {
JwtBuilder builder = Jwts.builder()
.setSubject(SUBJECT)
Expand Down