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

collado pushed a commit to branch mcollado-support-tokenexchange
in repository https://gitbox.apache.org/repos/asf/polaris.git

commit 5cc5c1e431d5592b7f71ad4bb73eca237e257f2e
Author: Michael Collado <[email protected]>
AuthorDate: Fri Feb 7 11:41:10 2025 -0800

    Update TokenBroker interface to accept requestedTokenType
---
 .../service/quarkus/auth/JWTRSAKeyPairTest.java    |  7 ++-
 .../quarkus/auth/JWTSymmetricKeyGeneratorTest.java |  7 ++-
 .../service/auth/DefaultOAuth2ApiService.java      | 10 ++--
 .../org/apache/polaris/service/auth/JWTBroker.java | 14 ++++-
 .../service/auth/NoneTokenBrokerFactory.java       | 12 +++-
 .../apache/polaris/service/auth/TokenBroker.java   | 70 +++++++++++++++++++++-
 .../service/auth/DefaultOAuth2ApiServiceTest.java  | 22 ++++---
 7 files changed, 122 insertions(+), 20 deletions(-)

diff --git 
a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java
 
b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java
index 6627fbf9..8eb89fb4 100644
--- 
a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java
+++ 
b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTRSAKeyPairTest.java
@@ -41,6 +41,7 @@ import org.apache.polaris.service.auth.PemUtils;
 import org.apache.polaris.service.auth.TokenBroker;
 import org.apache.polaris.service.auth.TokenRequestValidator;
 import org.apache.polaris.service.auth.TokenResponse;
+import org.apache.polaris.service.types.TokenType;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
@@ -76,7 +77,11 @@ public class JWTRSAKeyPairTest {
         new JWTRSAKeyPair(metastoreManager, session, 420, publicFileLocation, 
privateFileLocation);
     TokenResponse token =
         tokenBroker.generateFromClientSecrets(
-            clientId, mainSecret, TokenRequestValidator.CLIENT_CREDENTIALS, 
scope);
+            clientId,
+            mainSecret,
+            TokenRequestValidator.CLIENT_CREDENTIALS,
+            scope,
+            TokenType.ACCESS_TOKEN);
     assertThat(token).isNotNull();
     assertThat(token.getExpiresIn()).isEqualTo(420);
 
diff --git 
a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTSymmetricKeyGeneratorTest.java
 
b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTSymmetricKeyGeneratorTest.java
index 039e575c..787e329e 100644
--- 
a/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTSymmetricKeyGeneratorTest.java
+++ 
b/quarkus/service/src/test/java/org/apache/polaris/service/quarkus/auth/JWTSymmetricKeyGeneratorTest.java
@@ -34,6 +34,7 @@ import org.apache.polaris.service.auth.JWTSymmetricKeyBroker;
 import org.apache.polaris.service.auth.TokenBroker;
 import org.apache.polaris.service.auth.TokenRequestValidator;
 import org.apache.polaris.service.auth.TokenResponse;
+import org.apache.polaris.service.types.TokenType;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
@@ -64,7 +65,11 @@ public class JWTSymmetricKeyGeneratorTest {
         new JWTSymmetricKeyBroker(metastoreManager, metaStoreSession, 666, () 
-> "polaris");
     TokenResponse token =
         generator.generateFromClientSecrets(
-            clientId, mainSecret, TokenRequestValidator.CLIENT_CREDENTIALS, 
"PRINCIPAL_ROLE:TEST");
+            clientId,
+            mainSecret,
+            TokenRequestValidator.CLIENT_CREDENTIALS,
+            "PRINCIPAL_ROLE:TEST",
+            TokenType.ACCESS_TOKEN);
     assertThat(token).isNotNull();
 
     JWTVerifier verifier = 
JWT.require(Algorithm.HMAC256("polaris")).withIssuer("polaris").build();
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/auth/DefaultOAuth2ApiService.java
 
b/service/common/src/main/java/org/apache/polaris/service/auth/DefaultOAuth2ApiService.java
index 5855e36a..4055d6e5 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/auth/DefaultOAuth2ApiService.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/auth/DefaultOAuth2ApiService.java
@@ -96,12 +96,14 @@ public class DefaultOAuth2ApiService implements 
IcebergRestOAuth2ApiService {
       }
     }
     TokenResponse tokenResponse;
-    if (subjectToken != null) {
+    if (clientSecret != null) {
       tokenResponse =
-          tokenBroker.generateFromToken(subjectTokenType, subjectToken, 
grantType, scope);
-    } else if (clientSecret != null) {
+          tokenBroker.generateFromClientSecrets(
+              clientId, clientSecret, grantType, scope, requestedTokenType);
+    } else if (subjectToken != null) {
       tokenResponse =
-          tokenBroker.generateFromClientSecrets(clientId, clientSecret, 
grantType, scope);
+          tokenBroker.generateFromToken(
+              subjectTokenType, subjectToken, grantType, scope, 
requestedTokenType);
     } else {
       return 
OAuthUtils.getResponseFromError(OAuthTokenErrorResponse.Error.invalid_request);
     }
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/auth/JWTBroker.java 
b/service/common/src/main/java/org/apache/polaris/service/auth/JWTBroker.java
index cd4b24d1..ef7151ff 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/auth/JWTBroker.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/auth/JWTBroker.java
@@ -98,8 +98,12 @@ public abstract class JWTBroker implements TokenBroker {
 
   @Override
   public TokenResponse generateFromToken(
-      TokenType tokenType, String subjectToken, String grantType, String 
scope) {
-    if (!TokenType.ACCESS_TOKEN.equals(tokenType)) {
+      TokenType subjectTokenType,
+      String subjectToken,
+      String grantType,
+      String scope,
+      TokenType requestedTokenType) {
+    if (!TokenType.ACCESS_TOKEN.equals(subjectTokenType)) {
       return new TokenResponse(OAuthTokenErrorResponse.Error.invalid_request);
     }
     if (StringUtils.isBlank(subjectToken)) {
@@ -121,7 +125,11 @@ public abstract class JWTBroker implements TokenBroker {
 
   @Override
   public TokenResponse generateFromClientSecrets(
-      String clientId, String clientSecret, String grantType, String scope) {
+      String clientId,
+      String clientSecret,
+      String grantType,
+      String scope,
+      TokenType requestedTokenType) {
     // Initial sanity checks
     TokenRequestValidator validator = new TokenRequestValidator();
     Optional<OAuthTokenErrorResponse.Error> initialValidationResponse =
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/auth/NoneTokenBrokerFactory.java
 
b/service/common/src/main/java/org/apache/polaris/service/auth/NoneTokenBrokerFactory.java
index 9f642a2b..175c2afa 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/auth/NoneTokenBrokerFactory.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/auth/NoneTokenBrokerFactory.java
@@ -42,13 +42,21 @@ public class NoneTokenBrokerFactory implements 
TokenBrokerFactory {
 
         @Override
         public TokenResponse generateFromClientSecrets(
-            String clientId, String clientSecret, String grantType, String 
scope) {
+            String clientId,
+            String clientSecret,
+            String grantType,
+            String scope,
+            TokenType requestedTokenType) {
           return null;
         }
 
         @Override
         public TokenResponse generateFromToken(
-            TokenType tokenType, String subjectToken, String grantType, String 
scope) {
+            TokenType subjectTokenType,
+            String subjectToken,
+            String grantType,
+            String scope,
+            TokenType requestedTokenType) {
           return null;
         }
 
diff --git 
a/service/common/src/main/java/org/apache/polaris/service/auth/TokenBroker.java 
b/service/common/src/main/java/org/apache/polaris/service/auth/TokenBroker.java
index 31b6c400..62969938 100644
--- 
a/service/common/src/main/java/org/apache/polaris/service/auth/TokenBroker.java
+++ 
b/service/common/src/main/java/org/apache/polaris/service/auth/TokenBroker.java
@@ -34,11 +34,77 @@ public interface TokenBroker {
 
   boolean supportsRequestedTokenType(TokenType tokenType);
 
+  /**
+   * Generate a token from client secrets without specifying the requested 
token type
+   *
+   * @param clientId
+   * @param clientSecret
+   * @param grantType
+   * @param scope
+   * @return the response indicating an error or the requested token
+   * @deprecated - use the method with the requested token type
+   */
+  @Deprecated
+  default TokenResponse generateFromClientSecrets(
+      final String clientId,
+      final String clientSecret,
+      final String grantType,
+      final String scope) {
+    return generateFromClientSecrets(
+        clientId, clientSecret, grantType, scope, TokenType.ACCESS_TOKEN);
+  }
+
+  /**
+   * Generate a token from client secrets
+   *
+   * @param clientId
+   * @param clientSecret
+   * @param grantType
+   * @param scope
+   * @param requestedTokenType
+   * @return the response indicating an error or the requested token
+   */
   TokenResponse generateFromClientSecrets(
-      final String clientId, final String clientSecret, final String 
grantType, final String scope);
+      final String clientId,
+      final String clientSecret,
+      final String grantType,
+      final String scope,
+      TokenType requestedTokenType);
+
+  /**
+   * Generate a token from an existing token of a specified type without 
specifying the requested
+   * token type
+   *
+   * @param subjectTokenType
+   * @param subjectToken
+   * @param grantType
+   * @param scope
+   * @return the response indicating an error or the requested token
+   * @deprecated - use the method with the requested token type
+   */
+  @Deprecated
+  default TokenResponse generateFromToken(
+      TokenType subjectTokenType, String subjectToken, final String grantType, 
final String scope) {
+    return generateFromToken(
+        subjectTokenType, subjectToken, grantType, scope, 
TokenType.ACCESS_TOKEN);
+  }
 
+  /**
+   * Generate a token from an existing token of a specified type
+   *
+   * @param subjectTokenType
+   * @param subjectToken
+   * @param grantType
+   * @param scope
+   * @param requestedTokenType
+   * @return the response indicating an error or the requested token
+   */
   TokenResponse generateFromToken(
-      TokenType tokenType, String subjectToken, final String grantType, final 
String scope);
+      TokenType subjectTokenType,
+      String subjectToken,
+      final String grantType,
+      final String scope,
+      TokenType requestedTokenType);
 
   DecodedToken verify(String token);
 
diff --git 
a/service/common/src/test/java/org/apache/polaris/service/auth/DefaultOAuth2ApiServiceTest.java
 
b/service/common/src/test/java/org/apache/polaris/service/auth/DefaultOAuth2ApiServiceTest.java
index 097f99e9..ea119e5c 100644
--- 
a/service/common/src/test/java/org/apache/polaris/service/auth/DefaultOAuth2ApiServiceTest.java
+++ 
b/service/common/src/test/java/org/apache/polaris/service/auth/DefaultOAuth2ApiServiceTest.java
@@ -43,7 +43,8 @@ class DefaultOAuth2ApiServiceTest {
     when(tokenBrokerFactory.apply(realmContext)).thenReturn(tokenBroker);
     when(tokenBroker.supportsGrantType(CLIENT_CREDENTIALS)).thenReturn(false);
     
when(tokenBroker.supportsRequestedTokenType(TokenType.ACCESS_TOKEN)).thenReturn(true);
-    when(tokenBroker.generateFromClientSecrets("client", "secret", 
CLIENT_CREDENTIALS, "scope"))
+    when(tokenBroker.generateFromClientSecrets(
+            "client", "secret", CLIENT_CREDENTIALS, "scope", 
TokenType.ACCESS_TOKEN))
         .thenReturn(new TokenResponse("token", 
TokenType.ACCESS_TOKEN.getValue(), 3600));
     Response response =
         new InvocationBuilder()
@@ -70,7 +71,8 @@ class DefaultOAuth2ApiServiceTest {
     when(tokenBrokerFactory.apply(realmContext)).thenReturn(tokenBroker);
     when(tokenBroker.supportsGrantType(CLIENT_CREDENTIALS)).thenReturn(true);
     
when(tokenBroker.supportsRequestedTokenType(TokenType.ACCESS_TOKEN)).thenReturn(false);
-    when(tokenBroker.generateFromClientSecrets("client", "secret", 
CLIENT_CREDENTIALS, "scope"))
+    when(tokenBroker.generateFromClientSecrets(
+            "client", "secret", CLIENT_CREDENTIALS, "scope", 
TokenType.ACCESS_TOKEN))
         .thenReturn(new TokenResponse("token", 
TokenType.ACCESS_TOKEN.getValue(), 3600));
     Response response =
         new InvocationBuilder()
@@ -97,7 +99,8 @@ class DefaultOAuth2ApiServiceTest {
     when(tokenBrokerFactory.apply(realmContext)).thenReturn(tokenBroker);
     when(tokenBroker.supportsGrantType(CLIENT_CREDENTIALS)).thenReturn(true);
     
when(tokenBroker.supportsRequestedTokenType(TokenType.ACCESS_TOKEN)).thenReturn(true);
-    when(tokenBroker.generateFromClientSecrets(null, "secret", 
CLIENT_CREDENTIALS, "scope"))
+    when(tokenBroker.generateFromClientSecrets(
+            null, "secret", CLIENT_CREDENTIALS, "scope", 
TokenType.ACCESS_TOKEN))
         .thenReturn(new TokenResponse("token", 
TokenType.ACCESS_TOKEN.getValue(), 3600));
     Response response =
         new InvocationBuilder()
@@ -121,7 +124,8 @@ class DefaultOAuth2ApiServiceTest {
     when(tokenBrokerFactory.apply(realmContext)).thenReturn(tokenBroker);
     when(tokenBroker.supportsGrantType(CLIENT_CREDENTIALS)).thenReturn(true);
     
when(tokenBroker.supportsRequestedTokenType(TokenType.ACCESS_TOKEN)).thenReturn(true);
-    when(tokenBroker.generateFromClientSecrets("client", "secret", 
CLIENT_CREDENTIALS, "scope"))
+    when(tokenBroker.generateFromClientSecrets(
+            "client", "secret", CLIENT_CREDENTIALS, "scope", 
TokenType.ACCESS_TOKEN))
         .thenReturn(new TokenResponse("token", 
TokenType.ACCESS_TOKEN.getValue(), 3600));
     Response response =
         new InvocationBuilder()
@@ -147,7 +151,11 @@ class DefaultOAuth2ApiServiceTest {
     
when(tokenBroker.supportsGrantType(TokenRequestValidator.TOKEN_EXCHANGE)).thenReturn(true);
     
when(tokenBroker.supportsRequestedTokenType(TokenType.ACCESS_TOKEN)).thenReturn(true);
     when(tokenBroker.generateFromClientSecrets(
-            "client", "secret", TokenRequestValidator.TOKEN_EXCHANGE, "scope"))
+            "client",
+            "secret",
+            TokenRequestValidator.TOKEN_EXCHANGE,
+            "scope",
+            TokenType.ACCESS_TOKEN))
         .thenReturn(new TokenResponse("token", 
TokenType.ACCESS_TOKEN.getValue(), 3600));
     Response response =
         new InvocationBuilder()
@@ -175,7 +183,7 @@ class DefaultOAuth2ApiServiceTest {
     
when(tokenBroker.supportsGrantType(TokenRequestValidator.TOKEN_EXCHANGE)).thenReturn(true);
     
when(tokenBroker.supportsRequestedTokenType(TokenType.ACCESS_TOKEN)).thenReturn(true);
     when(tokenBroker.generateFromClientSecrets(
-            null, "secret", TokenRequestValidator.TOKEN_EXCHANGE, "scope"))
+            null, "secret", TokenRequestValidator.TOKEN_EXCHANGE, "scope", 
TokenType.ACCESS_TOKEN))
         .thenReturn(new TokenResponse("token", 
TokenType.ACCESS_TOKEN.getValue(), 3600));
     Response response =
         new InvocationBuilder()
@@ -206,7 +214,7 @@ class DefaultOAuth2ApiServiceTest {
     
when(tokenBroker.supportsRequestedTokenType(TokenType.ACCESS_TOKEN)).thenReturn(true);
 
     when(tokenBroker.generateFromClientSecrets(
-            "", "secret", TokenRequestValidator.TOKEN_EXCHANGE, "scope"))
+            "", "secret", TokenRequestValidator.TOKEN_EXCHANGE, "scope", 
TokenType.ACCESS_TOKEN))
         .thenReturn(new TokenResponse("token", 
TokenType.ACCESS_TOKEN.getValue(), 3600));
     Response response =
         new InvocationBuilder()

Reply via email to