This is an automated email from the ASF dual-hosted git repository.
roryqi pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new 3de4b5a92a [Cherry-pick to branch-1.3] [#13971] fix(auth): preserve
UnauthorizedException from PrincipalMapper in JWKS validation (#13972) (#14025)
3de4b5a92a is described below
commit 3de4b5a92a3dfcb50e0bd4a42494e8fcc852f7f2
Author: MaSai <[email protected]>
AuthorDate: Wed Oct 21 14:33:19 2026 +0800
[Cherry-pick to branch-1.3] [#13971] fix(auth): preserve
UnauthorizedException from PrincipalMapper in JWKS validation (#13972) (#14025)
**Cherry-pick Information:**
- Original commit: 25bfe375f152a91dfd9ad01d789f929be6e645ef
- Target branch: `branch-1.3`
- Status: ✅ Clean cherry-pick (no conflicts)
Co-authored-by: Cursor <[email protected]>
---
.../server/authentication/JwksTokenValidator.java | 2 +
.../authentication/TestJwksTokenValidator.java | 55 ++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git
a/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
b/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
index 32e47b84e1..3605f016c9 100644
---
a/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
+++
b/server-common/src/main/java/org/apache/gravitino/server/authentication/JwksTokenValidator.java
@@ -170,6 +170,8 @@ public class JwksTokenValidator implements
OAuthTokenValidator {
} catch (ExpiredJWTException e) {
throw new TokenExpiredException(e, "Authentication token is expired");
+ } catch (UnauthorizedException e) {
+ throw e;
} catch (Exception e) {
LOG.warn(
"JWKS JWT validation failed for principal [{}]: {}",
diff --git
a/server-common/src/test/java/org/apache/gravitino/server/authentication/TestJwksTokenValidator.java
b/server-common/src/test/java/org/apache/gravitino/server/authentication/TestJwksTokenValidator.java
index 2fb1c1f2f7..db0b56eea5 100644
---
a/server-common/src/test/java/org/apache/gravitino/server/authentication/TestJwksTokenValidator.java
+++
b/server-common/src/test/java/org/apache/gravitino/server/authentication/TestJwksTokenValidator.java
@@ -46,8 +46,10 @@ import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.gravitino.Config;
import org.apache.gravitino.UserPrincipal;
+import org.apache.gravitino.auth.PrincipalMapper;
import org.apache.gravitino.exceptions.TokenExpiredException;
import org.apache.gravitino.exceptions.UnauthorizedException;
import org.junit.jupiter.api.BeforeEach;
@@ -771,4 +773,57 @@ public class TestJwksTokenValidator {
assertTrue(exception.getMessage().contains("expired"));
}
}
+
+ @Test
+ public void
testValidateTokenPreservesUnauthorizedExceptionFromPrincipalMapper()
+ throws Exception {
+ RSAKey rsaKey =
+ new
RSAKeyGenerator(2048).keyID("test-key-id").algorithm(JWSAlgorithm.RS256).generate();
+
+ JWTClaimsSet claimsSet =
+ new JWTClaimsSet.Builder()
+ .subject("disabled-user")
+ .audience("test-service")
+ .issuer("https://test-issuer.com")
+ .expirationTime(Date.from(Instant.now().plusSeconds(3600)))
+ .issueTime(Date.from(Instant.now()))
+ .build();
+
+ SignedJWT signedJWT =
+ new SignedJWT(
+ new
JWSHeader.Builder(JWSAlgorithm.RS256).keyID("test-key-id").build(), claimsSet);
+ signedJWT.sign(new RSASSASigner(rsaKey));
+ String tokenString = signedJWT.serialize();
+
+ try (MockedStatic<JWKSourceBuilder> mockedBuilder =
mockStatic(JWKSourceBuilder.class)) {
+ @SuppressWarnings("unchecked")
+ JWKSource<SecurityContext> mockJwkSource = mock(JWKSource.class);
+ @SuppressWarnings("unchecked")
+ JWKSourceBuilder<SecurityContext> mockBuilder =
mock(JWKSourceBuilder.class);
+
+ mockedBuilder.when(() ->
JWKSourceBuilder.create(any(URL.class))).thenReturn(mockBuilder);
+ when(mockBuilder.build()).thenReturn(mockJwkSource);
+ when(mockJwkSource.get(any(), any())).thenReturn(Arrays.asList(rsaKey));
+
+ Map<String, String> config = new HashMap<>();
+ config.put(
+ "gravitino.authenticator.oauth.jwksUri",
"https://test-jwks.com/.well-known/jwks.json");
+ config.put("gravitino.authenticator.oauth.authority",
"https://test-issuer.com");
+ config.put("gravitino.authenticator.oauth.principalMapper", "regex");
+
config.put("gravitino.authenticator.oauth.principalMapper.regex.pattern",
"(.*)");
+ config.put("gravitino.authenticator.oauth.allowSkewSecs", "120");
+
+ validator.initialize(createConfig(config));
+
+ PrincipalMapper rejectingMapper = mock(PrincipalMapper.class);
+ when(rejectingMapper.map(any())).thenThrow(new
UnauthorizedException("Invalid access token"));
+ FieldUtils.writeField(validator, "principalMapper", rejectingMapper,
true);
+
+ UnauthorizedException exception =
+ assertThrows(
+ UnauthorizedException.class,
+ () -> validator.validateToken(tokenString, "test-service"));
+ assertEquals("Invalid access token", exception.getMessage());
+ }
+ }
}