This is an automated email from the ASF dual-hosted git repository.
yuqi4733 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new e462bb3c0 [#4056] improvement(server-common): Support multiple
authentication at the same time on the server side (#4160)
e462bb3c0 is described below
commit e462bb3c01376112744163b2f90f77550106b16c
Author: lwyang <[email protected]>
AuthorDate: Wed Jul 31 11:56:37 2024 +0800
[#4056] improvement(server-common): Support multiple authentication at the
same time on the server side (#4160)
### What changes were proposed in this pull request?
Support multiple authentication at the same time on the server side
### Why are the changes needed?
Fix: #4056
### Does this PR introduce _any_ user-facing change?
`gravitino.authenticator` support configuring multiple authenticators
### How was this patch tested?
IT,UT
---------
Co-authored-by: Qi Yu <[email protected]>
---
.../test/HadoopUserAuthenticationIT.java | 3 +-
.../integration/test/HiveUserAuthenticationIT.java | 3 +-
.../hive/integration/test/ProxyCatalogHiveIT.java | 2 +-
.../integration/test/AuditCatalogMysqlIT.java | 2 +-
.../test/CatalogIcebergKerberosHiveIT.java | 3 +-
.../test/CatalogPaimonKerberosFilesystemIT.java | 3 +-
.../filesystem/hadoop/TestOauth2Client.java | 7 +-
.../src/main/java/org/apache/gravitino/Config.java | 2 +
.../main/java/org/apache/gravitino/Configs.java | 20 +++-
.../gravitino/integration/test/MiniGravitino.java | 21 ++--
.../integration/test/util/AbstractIT.java | 27 ++---
.../gravitino/integration/test/client/AuditIT.java | 2 +-
.../test/web/rest/KerberosOperationsIT.java | 2 +-
...perationsIT.java => MultiAuthOperationsIT.java} | 111 ++++++++++++++++-----
.../test/web/rest/OAuth2OperationsIT.java | 2 +-
.../authentication/AuthenticationFilter.java | 34 +++++--
.../server/authentication/Authenticator.java | 15 +++
.../authentication/AuthenticatorFactory.java | 24 +++--
.../authentication/KerberosAuthenticator.java | 7 ++
.../authentication/OAuth2TokenAuthenticator.java | 7 ++
.../server/authentication/ServerAuthenticator.java | 13 ++-
.../server/authentication/SimpleAuthenticator.java | 7 ++
.../authentication/TestAuthenticationFilter.java | 54 +++++++++-
.../apache/gravitino/server/web/ConfigServlet.java | 7 +-
web/src/lib/store/auth/index.js | 4 +-
25 files changed, 294 insertions(+), 88 deletions(-)
diff --git
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopUserAuthenticationIT.java
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopUserAuthenticationIT.java
index ba495ef6e..9ca01edd8 100644
---
a/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopUserAuthenticationIT.java
+++
b/catalogs/catalog-hadoop/src/test/java/org/apache/gravitino/catalog/hadoop/integration/test/HadoopUserAuthenticationIT.java
@@ -36,6 +36,7 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.gravitino.Catalog;
+import org.apache.gravitino.Configs;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.SchemaChange;
import org.apache.gravitino.client.GravitinoAdminClient;
@@ -221,7 +222,7 @@ public class HadoopUserAuthenticationIT extends AbstractIT {
}
private static void addKerberosConfig() {
- AbstractIT.customConfigs.put("gravitino.authenticator", "kerberos");
+ AbstractIT.customConfigs.put(Configs.AUTHENTICATORS.getKey(), "kerberos");
AbstractIT.customConfigs.put(
"gravitino.authenticator.kerberos.principal",
GRAVITINO_SERVER_PRINCIPAL);
AbstractIT.customConfigs.put(
diff --git
a/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/HiveUserAuthenticationIT.java
b/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/HiveUserAuthenticationIT.java
index c236c2de2..9aa6d2aa1 100644
---
a/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/HiveUserAuthenticationIT.java
+++
b/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/HiveUserAuthenticationIT.java
@@ -36,6 +36,7 @@ import java.nio.file.Files;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.gravitino.Catalog;
+import org.apache.gravitino.Configs;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.client.GravitinoAdminClient;
import org.apache.gravitino.client.GravitinoMetalake;
@@ -188,7 +189,7 @@ public class HiveUserAuthenticationIT extends AbstractIT {
}
private static void addKerberosConfig() {
- AbstractIT.customConfigs.put("gravitino.authenticator", "kerberos");
+ AbstractIT.customConfigs.put(Configs.AUTHENTICATORS.getKey(), "kerberos");
AbstractIT.customConfigs.put(
"gravitino.authenticator.kerberos.principal",
GRAVITINO_SERVER_PRINCIPAL);
AbstractIT.customConfigs.put(
diff --git
a/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/ProxyCatalogHiveIT.java
b/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/ProxyCatalogHiveIT.java
index 0538a59c3..0bdb1ad3f 100644
---
a/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/ProxyCatalogHiveIT.java
+++
b/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/integration/test/ProxyCatalogHiveIT.java
@@ -94,7 +94,7 @@ public class ProxyCatalogHiveIT extends AbstractIT {
System.setProperty("user.name", "datastrato");
Map<String, String> configs = Maps.newHashMap();
- configs.put(Configs.AUTHENTICATOR.getKey(),
AuthenticatorType.SIMPLE.name().toLowerCase());
+ configs.put(Configs.AUTHENTICATORS.getKey(),
AuthenticatorType.SIMPLE.name().toLowerCase());
registerCustomConfigs(configs);
AbstractIT.startIntegrationTest();
containerSuite.startHiveContainer();
diff --git
a/catalogs/catalog-jdbc-mysql/src/test/java/org/apache/gravitino/catalog/mysql/integration/test/AuditCatalogMysqlIT.java
b/catalogs/catalog-jdbc-mysql/src/test/java/org/apache/gravitino/catalog/mysql/integration/test/AuditCatalogMysqlIT.java
index e5503b0f1..b2cf57147 100644
---
a/catalogs/catalog-jdbc-mysql/src/test/java/org/apache/gravitino/catalog/mysql/integration/test/AuditCatalogMysqlIT.java
+++
b/catalogs/catalog-jdbc-mysql/src/test/java/org/apache/gravitino/catalog/mysql/integration/test/AuditCatalogMysqlIT.java
@@ -64,7 +64,7 @@ public class AuditCatalogMysqlIT extends AbstractIT {
@BeforeAll
public static void startIntegrationTest() throws Exception {
Map<String, String> configs = Maps.newHashMap();
- configs.put(Configs.AUTHENTICATOR.getKey(),
AuthenticatorType.SIMPLE.name().toLowerCase());
+ configs.put(Configs.AUTHENTICATORS.getKey(),
AuthenticatorType.SIMPLE.name().toLowerCase());
registerCustomConfigs(configs);
AbstractIT.startIntegrationTest();
diff --git
a/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/integration/test/CatalogIcebergKerberosHiveIT.java
b/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/integration/test/CatalogIcebergKerberosHiveIT.java
index e20cc97f7..ebd8737f5 100644
---
a/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/integration/test/CatalogIcebergKerberosHiveIT.java
+++
b/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/integration/test/CatalogIcebergKerberosHiveIT.java
@@ -35,6 +35,7 @@ import java.nio.file.Files;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.gravitino.Catalog;
+import org.apache.gravitino.Configs;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.client.GravitinoAdminClient;
import org.apache.gravitino.client.GravitinoMetalake;
@@ -201,7 +202,7 @@ public class CatalogIcebergKerberosHiveIT extends
AbstractIT {
}
private static void addKerberosConfig() {
- AbstractIT.customConfigs.put("gravitino.authenticator", "kerberos");
+ AbstractIT.customConfigs.put(Configs.AUTHENTICATORS.getKey(), "kerberos");
AbstractIT.customConfigs.put(
"gravitino.authenticator.kerberos.principal",
GRAVITINO_SERVER_PRINCIPAL);
AbstractIT.customConfigs.put(
diff --git
a/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/integration/test/CatalogPaimonKerberosFilesystemIT.java
b/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/integration/test/CatalogPaimonKerberosFilesystemIT.java
index 009ea39bf..233c8aff7 100644
---
a/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/integration/test/CatalogPaimonKerberosFilesystemIT.java
+++
b/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/integration/test/CatalogPaimonKerberosFilesystemIT.java
@@ -32,6 +32,7 @@ import java.nio.file.Files;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.gravitino.Catalog;
+import org.apache.gravitino.Configs;
import org.apache.gravitino.NameIdentifier;
import
org.apache.gravitino.catalog.lakehouse.paimon.PaimonCatalogPropertiesMetadata;
import org.apache.gravitino.client.GravitinoAdminClient;
@@ -194,7 +195,7 @@ public class CatalogPaimonKerberosFilesystemIT extends
AbstractIT {
}
private static void addKerberosConfig() {
- AbstractIT.customConfigs.put("gravitino.authenticator", "kerberos");
+ AbstractIT.customConfigs.put(Configs.AUTHENTICATORS.getKey(), "kerberos");
AbstractIT.customConfigs.put(
"gravitino.authenticator.kerberos.principal",
GRAVITINO_SERVER_PRINCIPAL);
AbstractIT.customConfigs.put(
diff --git
a/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestOauth2Client.java
b/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestOauth2Client.java
index 81b9da66e..374d5993d 100644
---
a/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestOauth2Client.java
+++
b/clients/filesystem-hadoop3/src/test/java/org/apache/gravitino/filesystem/hadoop/TestOauth2Client.java
@@ -40,6 +40,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.gravitino.Config;
+import org.apache.gravitino.Configs;
import org.apache.gravitino.client.DefaultOAuth2TokenProvider;
import org.apache.gravitino.client.ErrorHandlers;
import org.apache.gravitino.client.HTTPClient;
@@ -256,7 +257,7 @@ public class TestOauth2Client extends TestGvfsBase {
// 3. test expired token
Config config = new Config(false) {};
config.set(
- new
ConfigBuilder("gravitino.authenticator").stringConf().createWithDefault("simple"),
+ new
ConfigBuilder(Configs.AUTHENTICATORS.getKey()).stringConf().createWithDefault("simple"),
"oauth");
config.set(OAuthConfig.SERVICE_AUDIENCE, "service1");
config.set(OAuthConfig.DEFAULT_SIGN_KEY, publicKey);
@@ -310,7 +311,9 @@ public class TestOauth2Client extends TestGvfsBase {
header.getValues().get(0).getValue().getBytes(StandardCharsets.UTF_8);
// should throw an UnauthorizedException here
try {
-
authenticator.authenticator().authenticateToken(tokenValue);
+ authenticator.authenticators().stream()
+ .filter(i -> i.supportsToken(tokenValue))
+ .forEach(i -> i.authenticateToken(tokenValue));
} catch (UnauthorizedException e) {
assertTrue(e.getMessage().contains("JWT parse error"));
throw e;
diff --git a/core/src/main/java/org/apache/gravitino/Config.java
b/core/src/main/java/org/apache/gravitino/Config.java
index 44813a052..de61a44d1 100644
--- a/core/src/main/java/org/apache/gravitino/Config.java
+++ b/core/src/main/java/org/apache/gravitino/Config.java
@@ -53,6 +53,8 @@ public abstract class Config {
"gravitino.entity.store.kv.deleteAfterTimeMs",
"0.5.0",
"Please use gravitino.entity.store.deleteAfterTimeMs instead."),
+ new DeprecatedConfig(
+ "gravitino.authenticator", "0.6.0", "Please use
gravitino.authenticators instead.")
};
/**
diff --git a/core/src/main/java/org/apache/gravitino/Configs.java
b/core/src/main/java/org/apache/gravitino/Configs.java
index 83021922f..4cbfebe01 100644
--- a/core/src/main/java/org/apache/gravitino/Configs.java
+++ b/core/src/main/java/org/apache/gravitino/Configs.java
@@ -199,11 +199,29 @@ public class Configs {
public static final ConfigEntry<String> AUTHENTICATOR =
new ConfigBuilder("gravitino.authenticator")
- .doc("The authenticator which Gravitino uses")
+ .doc(
+ "The authenticator which Gravitino uses. Multiple authenticators
"
+ + "separated by commas")
.version(ConfigConstants.VERSION_0_3_0)
+ .deprecated()
.stringConf()
.createWithDefault("simple");
+ public static final ConfigEntry<List<String>> AUTHENTICATORS =
+ new ConfigBuilder("gravitino.authenticators")
+ .doc(
+ "The authenticators which Gravitino uses. Multiple
authenticators "
+ + "separated by commas")
+ .version(ConfigConstants.VERSION_0_6_0)
+ .alternatives(Lists.newArrayList("gravitino.authenticator"))
+ .stringConf()
+ .toSequence()
+ .checkValue(
+ valueList ->
+ valueList != null &&
valueList.stream().allMatch(StringUtils::isNotBlank),
+ ConfigConstants.NOT_BLANK_ERROR_MSG)
+ .createWithDefault(Lists.newArrayList("simple"));
+
public static final ConfigEntry<Long> STORE_TRANSACTION_MAX_SKEW_TIME =
new ConfigBuilder("gravitino.entity.store.maxTransactionSkewTimeMs")
.doc("The maximum skew time of transactions in milliseconds")
diff --git
a/integration-test-common/src/test/java/org/apache/gravitino/integration/test/MiniGravitino.java
b/integration-test-common/src/test/java/org/apache/gravitino/integration/test/MiniGravitino.java
index 8dcf3bf34..e20681c40 100644
---
a/integration-test-common/src/test/java/org/apache/gravitino/integration/test/MiniGravitino.java
+++
b/integration-test-common/src/test/java/org/apache/gravitino/integration/test/MiniGravitino.java
@@ -21,12 +21,15 @@ package org.apache.gravitino.integration.test;
import static
com.google.common.util.concurrent.Uninterruptibles.sleepUninterruptibly;
import static org.apache.gravitino.Configs.ENTITY_KV_ROCKSDB_BACKEND_PATH;
+import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
@@ -59,6 +62,7 @@ import org.slf4j.LoggerFactory;
public class MiniGravitino {
private static final Logger LOG =
LoggerFactory.getLogger(MiniGravitino.class);
+ private static final Splitter COMMA =
Splitter.on(",").omitEmptyStrings().trimResults();
private MiniGravitinoContext context;
private RESTClient restClient;
private final File mockConfDir;
@@ -116,19 +120,20 @@ public class MiniGravitino {
this.host = jettyServerConfig.getHost();
this.port = jettyServerConfig.getHttpPort();
String URI = String.format("http://%s:%d", host, port);
- if (AuthenticatorType.OAUTH
- .name()
- .toLowerCase()
- .equals(context.customConfig.get(Configs.AUTHENTICATOR.getKey()))) {
+
+ List<String> authenticators = new ArrayList<>();
+ String authenticatorStr =
context.customConfig.get(Configs.AUTHENTICATORS.getKey());
+ if (authenticatorStr != null) {
+ authenticators = COMMA.splitToList(authenticatorStr);
+ }
+
+ if (authenticators.contains(AuthenticatorType.OAUTH.name().toLowerCase()))
{
restClient =
HTTPClient.builder(ImmutableMap.of())
.uri(URI)
.withAuthDataProvider(OAuthMockDataProvider.getInstance())
.build();
- } else if (AuthenticatorType.KERBEROS
- .name()
- .toLowerCase()
- .equals(context.customConfig.get(Configs.AUTHENTICATOR.getKey()))) {
+ } else if
(authenticators.contains(AuthenticatorType.KERBEROS.name().toLowerCase())) {
restClient =
HTTPClient.builder(ImmutableMap.of())
.uri(URI)
diff --git
a/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/AbstractIT.java
b/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/AbstractIT.java
index 1eabe7f58..968eeeef8 100644
---
a/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/AbstractIT.java
+++
b/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/AbstractIT.java
@@ -21,6 +21,7 @@ package org.apache.gravitino.integration.test.util;
import static org.apache.gravitino.Configs.ENTITY_RELATIONAL_JDBC_BACKEND_PATH;
import static
org.apache.gravitino.server.GravitinoServer.WEBSERVER_CONF_PREFIX;
+import com.google.common.base.Splitter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -30,8 +31,10 @@ import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
@@ -63,6 +66,8 @@ public class AbstractIT {
protected static final ContainerSuite containerSuite =
ContainerSuite.getInstance();
private static final Logger LOG = LoggerFactory.getLogger(AbstractIT.class);
+ private static final Splitter COMMA =
Splitter.on(",").omitEmptyStrings().trimResults();
+
protected static GravitinoAdminClient client;
private static final OAuthMockDataProvider mockDataProvider =
OAuthMockDataProvider.getInstance();
@@ -256,20 +261,18 @@ public class AbstractIT {
JettyServerConfig.fromConfig(serverConfig, WEBSERVER_CONF_PREFIX);
serverUri = "http://" + jettyServerConfig.getHost() + ":" +
jettyServerConfig.getHttpPort();
- if (AuthenticatorType.OAUTH
- .name()
- .toLowerCase()
- .equals(customConfigs.get(Configs.AUTHENTICATOR.getKey()))) {
+
+ List<String> authenticators = new ArrayList<>();
+ String authenticatorStr =
customConfigs.get(Configs.AUTHENTICATORS.getKey());
+ if (authenticatorStr != null) {
+ authenticators = COMMA.splitToList(authenticatorStr);
+ }
+
+ if (authenticators.contains(AuthenticatorType.OAUTH.name().toLowerCase()))
{
client =
GravitinoAdminClient.builder(serverUri).withOAuth(mockDataProvider).build();
- } else if (AuthenticatorType.SIMPLE
- .name()
- .toLowerCase()
- .equals(customConfigs.get(Configs.AUTHENTICATOR.getKey()))) {
+ } else if
(authenticators.contains(AuthenticatorType.SIMPLE.name().toLowerCase())) {
client =
GravitinoAdminClient.builder(serverUri).withSimpleAuth().build();
- } else if (AuthenticatorType.KERBEROS
- .name()
- .toLowerCase()
- .equals(customConfigs.get(Configs.AUTHENTICATOR.getKey()))) {
+ } else if
(authenticators.contains(AuthenticatorType.KERBEROS.name().toLowerCase())) {
serverUri = "http://localhost:" + jettyServerConfig.getHttpPort();
client = null;
} else {
diff --git
a/integration-test/src/test/java/org/apache/gravitino/integration/test/client/AuditIT.java
b/integration-test/src/test/java/org/apache/gravitino/integration/test/client/AuditIT.java
index 8541e3ebe..b635dc1f9 100644
---
a/integration-test/src/test/java/org/apache/gravitino/integration/test/client/AuditIT.java
+++
b/integration-test/src/test/java/org/apache/gravitino/integration/test/client/AuditIT.java
@@ -41,7 +41,7 @@ public class AuditIT extends AbstractIT {
@BeforeAll
public static void startIntegrationTest() throws Exception {
Map<String, String> configs = Maps.newHashMap();
- configs.put(Configs.AUTHENTICATOR.getKey(),
AuthenticatorType.SIMPLE.name().toLowerCase());
+ configs.put(Configs.AUTHENTICATORS.getKey(),
AuthenticatorType.SIMPLE.name().toLowerCase());
registerCustomConfigs(configs);
AbstractIT.startIntegrationTest();
}
diff --git
a/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/KerberosOperationsIT.java
b/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/KerberosOperationsIT.java
index 4f00de993..16de7b06e 100644
---
a/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/KerberosOperationsIT.java
+++
b/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/KerberosOperationsIT.java
@@ -72,7 +72,7 @@ public class KerberosOperationsIT extends AbstractIT {
initKeyTab();
Map<String, String> configs = Maps.newHashMap();
- configs.put(Configs.AUTHENTICATOR.getKey(),
AuthenticatorType.KERBEROS.name().toLowerCase());
+ configs.put(Configs.AUTHENTICATORS.getKey(),
AuthenticatorType.KERBEROS.name().toLowerCase());
configs.put(PRINCIPAL.getKey(), serverPrincipal);
configs.put(KEYTAB.getKey(), keytabFile);
configs.put("client.kerberos.principal", clientPrincipal);
diff --git
a/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/KerberosOperationsIT.java
b/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/MultiAuthOperationsIT.java
similarity index 55%
copy from
integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/KerberosOperationsIT.java
copy to
integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/MultiAuthOperationsIT.java
index 4f00de993..55fbf1ed8 100644
---
a/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/KerberosOperationsIT.java
+++
b/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/MultiAuthOperationsIT.java
@@ -16,16 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.gravitino.integration.test.web.rest;
+import static
org.apache.gravitino.server.GravitinoServer.WEBSERVER_CONF_PREFIX;
import static org.apache.gravitino.server.authentication.KerberosConfig.KEYTAB;
import static
org.apache.gravitino.server.authentication.KerberosConfig.PRINCIPAL;
import static org.apache.hadoop.minikdc.MiniKdc.MAX_TICKET_LIFETIME;
import com.google.common.collect.Maps;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.security.Keys;
import java.io.File;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyPair;
+import java.util.Base64;
+import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@@ -36,6 +43,9 @@ import org.apache.gravitino.client.GravitinoVersion;
import org.apache.gravitino.client.KerberosTokenProvider;
import org.apache.gravitino.integration.test.util.AbstractIT;
import org.apache.gravitino.integration.test.util.ITUtils;
+import org.apache.gravitino.integration.test.util.OAuthMockDataProvider;
+import org.apache.gravitino.server.authentication.OAuthConfig;
+import org.apache.gravitino.server.web.JettyServerConfig;
import org.apache.hadoop.minikdc.KerberosSecurityTestcase;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
@@ -45,8 +55,7 @@ import org.junit.jupiter.api.Test;
import
org.testcontainers.shaded.com.google.common.util.concurrent.Uninterruptibles;
@Tag("gravitino-docker-test")
-public class KerberosOperationsIT extends AbstractIT {
-
+public class MultiAuthOperationsIT extends AbstractIT {
private static final KerberosSecurityTestcase kdc =
new KerberosSecurityTestcase() {
@Override
@@ -55,34 +64,39 @@ public class KerberosOperationsIT extends AbstractIT {
getConf().setProperty(MAX_TICKET_LIFETIME, "5");
}
};
-
+ private static final String clientPrincipal = "[email protected]";
private static final String keytabFile =
new File(System.getProperty("test.dir", "target"),
UUID.randomUUID().toString())
.getAbsolutePath();
- // The following two keytab are needed both.
- private static final String serverPrincipal = "HTTP/[email protected]";
- private static final String serverPrincipalWithAll =
"HTTP/[email protected]";
-
- private static final String clientPrincipal = "[email protected]";
+ private static GravitinoAdminClient oauthClient;
+ private static GravitinoAdminClient kerberosClient;
@BeforeAll
public static void startIntegrationTest() throws Exception {
- kdc.startMiniKdc();
- initKeyTab();
-
Map<String, String> configs = Maps.newHashMap();
- configs.put(Configs.AUTHENTICATOR.getKey(),
AuthenticatorType.KERBEROS.name().toLowerCase());
- configs.put(PRINCIPAL.getKey(), serverPrincipal);
- configs.put(KEYTAB.getKey(), keytabFile);
- configs.put("client.kerberos.principal", clientPrincipal);
- configs.put("client.kerberos.keytab", keytabFile);
+ configs.put(
+ Configs.AUTHENTICATORS.getKey(),
+ String.join(
+ ",",
+ AuthenticatorType.KERBEROS.name().toLowerCase(),
+ AuthenticatorType.OAUTH.name().toLowerCase()));
- registerCustomConfigs(configs);
+ configOAuth(configs);
+ configKerberos(configs);
+ registerCustomConfigs(configs);
AbstractIT.startIntegrationTest();
- client =
+ oauthClient =
+ GravitinoAdminClient.builder(serverUri)
+ .withOAuth(OAuthMockDataProvider.getInstance())
+ .build();
+
+ JettyServerConfig jettyServerConfig =
+ JettyServerConfig.fromConfig(serverConfig, WEBSERVER_CONF_PREFIX);
+ serverUri = "http://localhost:" + jettyServerConfig.getHttpPort();
+ kerberosClient =
GravitinoAdminClient.builder(serverUri)
.withKerberosAuth(
KerberosTokenProvider.builder()
@@ -99,23 +113,61 @@ public class KerberosOperationsIT extends AbstractIT {
}
@Test
- public void testAuthenticationApi() throws Exception {
- GravitinoVersion gravitinoVersion = client.serverVersion();
- Assertions.assertEquals(System.getenv("PROJECT_VERSION"),
gravitinoVersion.version());
- Assertions.assertFalse(gravitinoVersion.compileDate().isEmpty());
+ public void testMultiAuthenticationSuccess() throws Exception {
+ GravitinoVersion gravitinoVersion1 = oauthClient.serverVersion();
+ Assertions.assertEquals(System.getenv("PROJECT_VERSION"),
gravitinoVersion1.version());
+ Assertions.assertFalse(gravitinoVersion1.compileDate().isEmpty());
+ if (testMode.equals(ITUtils.EMBEDDED_TEST_MODE)) {
+ final String gitCommitId = readGitCommitIdFromGitFile();
+ Assertions.assertEquals(gitCommitId, gravitinoVersion1.gitCommit());
+ }
+ new KerberosOperationsIT().testAuthenticationApi();
+
+ GravitinoVersion gravitinoVersion2 = kerberosClient.serverVersion();
+ Assertions.assertEquals(System.getenv("PROJECT_VERSION"),
gravitinoVersion2.version());
+ Assertions.assertFalse(gravitinoVersion2.compileDate().isEmpty());
if (testMode.equals(ITUtils.EMBEDDED_TEST_MODE)) {
final String gitCommitId = readGitCommitIdFromGitFile();
- Assertions.assertEquals(gitCommitId, gravitinoVersion.gitCommit());
+ Assertions.assertEquals(gitCommitId, gravitinoVersion2.gitCommit());
}
// Test to re-login with the keytab
Uninterruptibles.sleepUninterruptibly(6, TimeUnit.SECONDS);
- Assertions.assertEquals(System.getenv("PROJECT_VERSION"),
gravitinoVersion.version());
- Assertions.assertFalse(gravitinoVersion.compileDate().isEmpty());
+ Assertions.assertEquals(System.getenv("PROJECT_VERSION"),
gravitinoVersion2.version());
+ Assertions.assertFalse(gravitinoVersion2.compileDate().isEmpty());
+ }
+
+ @SuppressWarnings("JavaUtilDate")
+ private static void configOAuth(Map<String, String> configs) {
+ KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256);
+ String publicKey =
+ new String(
+ Base64.getEncoder().encode(keyPair.getPublic().getEncoded()),
StandardCharsets.UTF_8);
+
+ configs.put(OAuthConfig.SERVICE_AUDIENCE.getKey(), "service1");
+ configs.put(OAuthConfig.DEFAULT_SIGN_KEY.getKey(), publicKey);
+ configs.put(OAuthConfig.ALLOW_SKEW_SECONDS.getKey(), "6");
+ configs.put(OAuthConfig.DEFAULT_SERVER_URI.getKey(), "test");
+ configs.put(OAuthConfig.DEFAULT_TOKEN_PATH.getKey(), "test");
+
+ String token =
+ Jwts.builder()
+ .setSubject("gravitino")
+ .setExpiration(new Date(System.currentTimeMillis() + 1000 * 1000))
+ .setAudience("service1")
+ .signWith(keyPair.getPrivate(), SignatureAlgorithm.RS256)
+ .compact();
+ OAuthMockDataProvider mockDataProvider =
OAuthMockDataProvider.getInstance();
+ mockDataProvider.setTokenData(token.getBytes(StandardCharsets.UTF_8));
}
- private static void initKeyTab() throws Exception {
+ private static void configKerberos(Map<String, String> configs) throws
Exception {
+ kdc.startMiniKdc();
+
+ final String serverPrincipal = "HTTP/[email protected]";
+ final String serverPrincipalWithAll = "HTTP/[email protected]";
+
File newKeytabFile = new File(keytabFile);
String newClientPrincipal = removeRealm(clientPrincipal);
String newServerPrincipal = removeRealm(serverPrincipal);
@@ -123,6 +175,11 @@ public class KerberosOperationsIT extends AbstractIT {
kdc.getKdc()
.createPrincipal(
newKeytabFile, newClientPrincipal, newServerPrincipal,
newServerPrincipalAll);
+
+ configs.put(PRINCIPAL.getKey(), serverPrincipal);
+ configs.put(KEYTAB.getKey(), keytabFile);
+ configs.put("client.kerberos.principal", clientPrincipal);
+ configs.put("client.kerberos.keytab", keytabFile);
}
private static String removeRealm(String principal) {
diff --git
a/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/OAuth2OperationsIT.java
b/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/OAuth2OperationsIT.java
index 13a2887d4..e4f10769b 100644
---
a/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/OAuth2OperationsIT.java
+++
b/integration-test/src/test/java/org/apache/gravitino/integration/test/web/rest/OAuth2OperationsIT.java
@@ -60,7 +60,7 @@ public class OAuth2OperationsIT extends AbstractIT {
.setAudience("service1")
.signWith(keyPair.getPrivate(), SignatureAlgorithm.RS256)
.compact();
- configs.put(Configs.AUTHENTICATOR.getKey(),
AuthenticatorType.OAUTH.name().toLowerCase());
+ configs.put(Configs.AUTHENTICATORS.getKey(),
AuthenticatorType.OAUTH.name().toLowerCase());
configs.put(OAuthConfig.SERVICE_AUDIENCE.getKey(), "service1");
configs.put(OAuthConfig.DEFAULT_SIGN_KEY.getKey(), publicKey);
configs.put(OAuthConfig.ALLOW_SKEW_SECONDS.getKey(), "6");
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticationFilter.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticationFilter.java
index 2f031444a..3479503d4 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticationFilter.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticationFilter.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.Enumeration;
+import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -36,15 +37,15 @@ import
org.apache.gravitino.exceptions.UnauthorizedException;
public class AuthenticationFilter implements Filter {
- private final Authenticator filterAuthenticator;
+ private final List<Authenticator> filterAuthenticators;
public AuthenticationFilter() {
- filterAuthenticator = null;
+ filterAuthenticators = null;
}
@VisibleForTesting
- AuthenticationFilter(Authenticator authenticator) {
- this.filterAuthenticator = authenticator;
+ AuthenticationFilter(List<Authenticator> authenticators) {
+ this.filterAuthenticators = authenticators;
}
@Override
@@ -54,11 +55,11 @@ public class AuthenticationFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
try {
- Authenticator authenticator;
- if (filterAuthenticator == null) {
- authenticator = ServerAuthenticator.getInstance().authenticator();
+ List<Authenticator> authenticators;
+ if (filterAuthenticators == null || filterAuthenticators.isEmpty()) {
+ authenticators = ServerAuthenticator.getInstance().authenticators();
} else {
- authenticator = filterAuthenticator;
+ authenticators = filterAuthenticators;
}
HttpServletRequest req = (HttpServletRequest) request;
Enumeration<String> headerData =
req.getHeaders(AuthConstants.HTTP_HEADER_AUTHORIZATION);
@@ -66,10 +67,21 @@ public class AuthenticationFilter implements Filter {
if (headerData.hasMoreElements()) {
authData = headerData.nextElement().getBytes(StandardCharsets.UTF_8);
}
- if (authenticator.isDataFromToken()) {
- Principal principal = authenticator.authenticateToken(authData);
-
request.setAttribute(AuthConstants.AUTHENTICATED_PRINCIPAL_ATTRIBUTE_NAME,
principal);
+
+ Principal principal = null;
+ for (Authenticator authenticator : authenticators) {
+ if (authenticator.supportsToken(authData) &&
authenticator.isDataFromToken()) {
+ principal = authenticator.authenticateToken(authData);
+ if (principal != null) {
+
request.setAttribute(AuthConstants.AUTHENTICATED_PRINCIPAL_ATTRIBUTE_NAME,
principal);
+ break;
+ }
+ }
}
+ if (principal == null) {
+ throw new UnauthorizedException("The provided credentials did not
support");
+ }
+
chain.doFilter(request, response);
} catch (UnauthorizedException ue) {
HttpServletResponse resp = (HttpServletResponse) response;
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/Authenticator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/Authenticator.java
index 57e91b07e..dff4805d4 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/Authenticator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/Authenticator.java
@@ -55,4 +55,19 @@ public interface Authenticator {
* @throws RuntimeException if the initialization fails
*/
void initialize(Config config) throws RuntimeException;
+
+ /**
+ * Determines if the provided token data is supported by this authenticator
+ *
+ * <p>This method checks if the given token data can be processed by this
authenticator.
+ * Implementations should override this method to provide specific logic for
determining if the
+ * token data format or content is recognized and can be authenticated.
+ *
+ * @param tokenData The byte array containing the token data to be checked.
+ * @return true if the token data is supported and can be authenticated by
this authenticator;
+ * false otherwise.
+ */
+ default boolean supportsToken(byte[] tokenData) {
+ return false;
+ }
}
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticatorFactory.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticatorFactory.java
index 3eef4831d..31d67cfac 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticatorFactory.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/AuthenticatorFactory.java
@@ -20,6 +20,8 @@
package org.apache.gravitino.server.authentication;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import java.util.List;
import org.apache.gravitino.Config;
import org.apache.gravitino.Configs;
import org.apache.gravitino.auth.AuthenticatorType;
@@ -42,15 +44,21 @@ public class AuthenticatorFactory {
private AuthenticatorFactory() {}
- public static Authenticator createAuthenticator(Config config) {
- String name = config.get(Configs.AUTHENTICATOR);
- String className = AUTHENTICATORS.getOrDefault(name, name);
+ public static List<Authenticator> createAuthenticators(Config config) {
+ List<String> authenticatorNames = config.get(Configs.AUTHENTICATORS);
- try {
- return (Authenticator)
Class.forName(className).getDeclaredConstructor().newInstance();
- } catch (Exception e) {
- LOG.error("Failed to create and initialize Authenticator by name {}.",
name, e);
- throw new RuntimeException("Failed to create and initialize
Authenticator: " + name, e);
+ List<Authenticator> authenticators = Lists.newArrayList();
+ for (String name : authenticatorNames) {
+ String className = AUTHENTICATORS.getOrDefault(name, name);
+ try {
+ Authenticator authenticator =
+ (Authenticator)
Class.forName(className).getDeclaredConstructor().newInstance();
+ authenticators.add(authenticator);
+ } catch (Exception e) {
+ LOG.error("Failed to create and initialize Authenticator by name {}.",
name, e);
+ throw new RuntimeException("Failed to create and initialize
Authenticator: " + name, e);
+ }
}
+ return authenticators;
}
}
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
index 47507bee2..c5aff415c 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/KerberosAuthenticator.java
@@ -133,6 +133,13 @@ public class KerberosAuthenticator implements
Authenticator {
}
}
+ @Override
+ public boolean supportsToken(byte[] tokenData) {
+ return tokenData != null
+ && new String(tokenData, StandardCharsets.UTF_8)
+ .startsWith(AuthConstants.AUTHORIZATION_NEGOTIATE_HEADER);
+ }
+
private Principal retrievePrincipalFromToken(String serverPrincipal, byte[]
clientToken)
throws GSSException {
GSSContext gssContext = null;
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/OAuth2TokenAuthenticator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/OAuth2TokenAuthenticator.java
index ea457bc9a..c3433cf58 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/OAuth2TokenAuthenticator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/OAuth2TokenAuthenticator.java
@@ -126,6 +126,13 @@ class OAuth2TokenAuthenticator implements Authenticator {
this.defaultSigningKey =
decodeSignKey(Base64.getDecoder().decode(configuredSignKey), algType);
}
+ @Override
+ public boolean supportsToken(byte[] tokenData) {
+ return tokenData != null
+ && new String(tokenData, StandardCharsets.UTF_8)
+ .startsWith(AuthConstants.AUTHORIZATION_BEARER_HEADER);
+ }
+
private static Key decodeSignKey(byte[] key, String algType) {
try {
SignatureAlgorithmFamilyType algFamilyType =
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/ServerAuthenticator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/ServerAuthenticator.java
index 170cc566a..ce112b63a 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/ServerAuthenticator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/ServerAuthenticator.java
@@ -19,11 +19,12 @@
package org.apache.gravitino.server.authentication;
+import java.util.List;
import org.apache.gravitino.Config;
public class ServerAuthenticator {
- private Authenticator authenticator;
+ private List<Authenticator> authenticators;
private ServerAuthenticator() {}
@@ -47,11 +48,13 @@ public class ServerAuthenticator {
*/
public void initialize(Config config) {
// Create and initialize Authenticator related modules
- this.authenticator = AuthenticatorFactory.createAuthenticator(config);
- this.authenticator.initialize(config);
+ this.authenticators = AuthenticatorFactory.createAuthenticators(config);
+ for (Authenticator authenticator : authenticators) {
+ authenticator.initialize(config);
+ }
}
- public Authenticator authenticator() {
- return authenticator;
+ public List<Authenticator> authenticators() {
+ return authenticators;
}
}
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/SimpleAuthenticator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/SimpleAuthenticator.java
index 8763381e4..88ecebd91 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/SimpleAuthenticator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/SimpleAuthenticator.java
@@ -72,4 +72,11 @@ class SimpleAuthenticator implements Authenticator {
public void initialize(Config config) throws RuntimeException {
// no op
}
+
+ @Override
+ public boolean supportsToken(byte[] tokenData) {
+ return tokenData == null
+ || new String(tokenData, StandardCharsets.UTF_8)
+ .startsWith(AuthConstants.AUTHORIZATION_BASIC_HEADER);
+ }
}
diff --git
a/server-common/src/test/java/org/apache/gravitino/server/authentication/TestAuthenticationFilter.java
b/server-common/src/test/java/org/apache/gravitino/server/authentication/TestAuthenticationFilter.java
index a3540d8bc..0ef48c922 100644
---
a/server-common/src/test/java/org/apache/gravitino/server/authentication/TestAuthenticationFilter.java
+++
b/server-common/src/test/java/org/apache/gravitino/server/authentication/TestAuthenticationFilter.java
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.Collections;
import java.util.Vector;
@@ -45,12 +46,13 @@ public class TestAuthenticationFilter {
public void testDoFilterNormal() throws ServletException, IOException {
Authenticator authenticator = mock(Authenticator.class);
- AuthenticationFilter filter = new AuthenticationFilter(authenticator);
+ AuthenticationFilter filter = new
AuthenticationFilter(Lists.newArrayList(authenticator));
FilterChain mockChain = mock(FilterChain.class);
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
HttpServletResponse mockResponse = mock(HttpServletResponse.class);
when(mockRequest.getHeaders(AuthConstants.HTTP_HEADER_AUTHORIZATION))
.thenReturn(new
Vector<>(Collections.singletonList("user")).elements());
+ when(authenticator.supportsToken(any())).thenReturn(true);
when(authenticator.isDataFromToken()).thenReturn(true);
when(authenticator.authenticateToken(any())).thenReturn(new
UserPrincipal("user"));
filter.doFilter(mockRequest, mockResponse, mockChain);
@@ -60,16 +62,64 @@ public class TestAuthenticationFilter {
@Test
public void testDoFilterWithException() throws ServletException, IOException
{
Authenticator authenticator = mock(Authenticator.class);
- AuthenticationFilter filter = new AuthenticationFilter(authenticator);
+ AuthenticationFilter filter = new
AuthenticationFilter(Lists.newArrayList(authenticator));
FilterChain mockChain = mock(FilterChain.class);
HttpServletRequest mockRequest = mock(HttpServletRequest.class);
HttpServletResponse mockResponse = mock(HttpServletResponse.class);
when(mockRequest.getHeaders(AuthConstants.HTTP_HEADER_AUTHORIZATION))
.thenReturn(new
Vector<>(Collections.singletonList("user")).elements());
+ when(authenticator.supportsToken(any())).thenReturn(true);
when(authenticator.isDataFromToken()).thenReturn(true);
when(authenticator.authenticateToken(any()))
.thenThrow(new UnauthorizedException("UNAUTHORIZED"));
filter.doFilter(mockRequest, mockResponse, mockChain);
verify(mockResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED,
"UNAUTHORIZED");
}
+
+ @Test
+ public void testMultiFilterNormal() throws ServletException, IOException {
+
+ Authenticator authenticator1 = mock(Authenticator.class);
+ Authenticator authenticator2 = mock(Authenticator.class);
+ AuthenticationFilter filter =
+ new AuthenticationFilter(Lists.newArrayList(authenticator1,
authenticator2));
+ FilterChain mockChain = mock(FilterChain.class);
+ HttpServletRequest mockRequest = mock(HttpServletRequest.class);
+ HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ when(mockRequest.getHeaders(AuthConstants.HTTP_HEADER_AUTHORIZATION))
+ .thenReturn(new
Vector<>(Collections.singletonList("user")).elements());
+ when(authenticator1.supportsToken(any())).thenReturn(false);
+ when(authenticator1.isDataFromToken()).thenReturn(true);
+ when(authenticator1.authenticateToken(any())).thenReturn(new
UserPrincipal("user"));
+ when(authenticator2.supportsToken(any())).thenReturn(true);
+ when(authenticator2.isDataFromToken()).thenReturn(true);
+ when(authenticator2.authenticateToken(any())).thenReturn(new
UserPrincipal("user"));
+
+ filter.doFilter(mockRequest, mockResponse, mockChain);
+ verify(mockResponse, never()).sendError(anyInt(), anyString());
+ }
+
+ @Test
+ public void testMultiFilterWithException() throws ServletException,
IOException {
+
+ Authenticator authenticator1 = mock(Authenticator.class);
+ Authenticator authenticator2 = mock(Authenticator.class);
+ AuthenticationFilter filter =
+ new AuthenticationFilter(Lists.newArrayList(authenticator1,
authenticator2));
+ FilterChain mockChain = mock(FilterChain.class);
+ HttpServletRequest mockRequest = mock(HttpServletRequest.class);
+ HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ when(mockRequest.getHeaders(AuthConstants.HTTP_HEADER_AUTHORIZATION))
+ .thenReturn(new
Vector<>(Collections.singletonList("user")).elements());
+ when(authenticator1.supportsToken(any())).thenReturn(false);
+ when(authenticator1.isDataFromToken()).thenReturn(true);
+ when(authenticator1.authenticateToken(any())).thenReturn(new
UserPrincipal("user"));
+ when(authenticator2.supportsToken(any())).thenReturn(true);
+ when(authenticator2.isDataFromToken()).thenReturn(true);
+ when(authenticator2.authenticateToken(any()))
+ .thenThrow(new UnauthorizedException("UNAUTHORIZED"));
+
+ filter.doFilter(mockRequest, mockResponse, mockChain);
+ verify(mockResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED,
"UNAUTHORIZED");
+ }
}
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
b/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
index c040a301f..cdce0a0b1 100644
--- a/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
+++ b/server/src/main/java/org/apache/gravitino/server/web/ConfigServlet.java
@@ -42,7 +42,7 @@ public class ConfigServlet extends HttpServlet {
ImmutableSet.of(OAuthConfig.DEFAULT_SERVER_URI,
OAuthConfig.DEFAULT_TOKEN_PATH);
private static final ImmutableSet<ConfigEntry<?>> basicConfigEntries =
- ImmutableSet.of(Configs.AUTHENTICATOR);
+ ImmutableSet.of(Configs.AUTHENTICATORS);
private final Map<String, String> configs = Maps.newHashMap();
@@ -51,7 +51,10 @@ public class ConfigServlet extends HttpServlet {
String config = String.valueOf(serverConfig.get(key));
configs.put(key.getKey(), config);
}
- if
(serverConfig.get(Configs.AUTHENTICATOR).equalsIgnoreCase(AuthenticatorType.OAUTH.name()))
{
+
+ if (serverConfig
+ .get(Configs.AUTHENTICATORS)
+ .contains(AuthenticatorType.OAUTH.name().toLowerCase())) {
for (ConfigEntry<?> key : oauthConfigEntries) {
String config = String.valueOf(serverConfig.get(key));
configs.put(key.getKey(), config);
diff --git a/web/src/lib/store/auth/index.js b/web/src/lib/store/auth/index.js
index c8d77dbb9..83d58394c 100644
--- a/web/src/lib/store/auth/index.js
+++ b/web/src/lib/store/auth/index.js
@@ -38,7 +38,9 @@ export const getAuthConfigs =
createAsyncThunk('auth/getAuthConfigs', async () =
}
oauthUrl =
`${res['gravitino.authenticator.oauth.serverUri']}${res['gravitino.authenticator.oauth.tokenPath']}`
- authType = res['gravitino.authenticator']
+
+ // ** get the first authenticator from the response. response example:
"[simple, oauth]"
+ authType = res['gravitino.authenticators'].slice(1, -1).split(',')[0].trim()
localStorage.setItem('oauthUrl', oauthUrl)