This is an automated email from the ASF dual-hosted git repository.
janhoy pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new ce753aa415b SOLR-18073 JWT Authentication plugin now supports matching
non-string claims (#4049)
ce753aa415b is described below
commit ce753aa415ba63277e65a3db9a600f26eaaa0a63
Author: Jan Høydahl <[email protected]>
AuthorDate: Wed Feb 4 15:52:57 2026 +0100
SOLR-18073 JWT Authentication plugin now supports matching non-string
claims (#4049)
(cherry picked from commit 507859f3dae209dbe39a4609992cf738f9226e95)
---
.../unreleased/SOLR-18073-jwt-bool-claims.yml | 9 ++++++
.../apache/solr/security/jwt/JWTAuthPlugin.java | 6 ++--
.../solr/security/jwt/JWTAuthPluginTest.java | 34 ++++++++++++++++++++++
3 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/changelog/unreleased/SOLR-18073-jwt-bool-claims.yml
b/changelog/unreleased/SOLR-18073-jwt-bool-claims.yml
new file mode 100644
index 00000000000..0053d2c78de
--- /dev/null
+++ b/changelog/unreleased/SOLR-18073-jwt-bool-claims.yml
@@ -0,0 +1,9 @@
+title: JWT Authentication plugin now supports matching non-string claims such
as boolean
+type: fixed
+authors:
+ - name: Jan Høydahl
+ url: https://home.apache.org/phonebook.html?uid=janhoy
+ - name: Tony Panza
+links:
+ - name: SOLR-18073
+ url: https://issues.apache.org/jira/browse/SOLR-18073
diff --git
a/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java
b/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java
index 83d0e99303b..4c4c35eaabb 100644
---
a/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java
+++
b/solr/modules/jwt-auth/src/java/org/apache/solr/security/jwt/JWTAuthPlugin.java
@@ -576,13 +576,15 @@ public class JWTAuthPlugin extends AuthenticationPlugin
for (Map.Entry<String, Pattern> entry :
claimsMatchCompiled.entrySet()) {
String claim = entry.getKey();
if (jwtClaims.hasClaim(claim)) {
- if
(!entry.getValue().matcher(jwtClaims.getStringClaimValue(claim)).matches()) {
+ Object claimValue = jwtClaims.getClaimValue(claim);
+ String claimValueStr = (claimValue != null) ?
String.valueOf(claimValue) : "";
+ if (!entry.getValue().matcher(claimValueStr).matches()) {
return new JWTAuthenticationResponse(
AuthCode.CLAIM_MISMATCH,
"Claim "
+ claim
+ "="
- + jwtClaims.getStringClaimValue(claim)
+ + claimValueStr
+ " does not match required regular expression "
+ entry.getValue().pattern());
}
diff --git
a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java
b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java
index 0d6cc759cb2..7b9ace8084b 100644
---
a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java
+++
b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginTest.java
@@ -141,6 +141,8 @@ public class JWTAuthPluginTest extends SolrTestCaseJ4 {
claims.setClaim("claim1", "foo"); // additional claims/attributes about
the subject can be added
claims.setClaim("claim2", "bar"); // additional claims/attributes about
the subject can be added
claims.setClaim("claim3", "foo"); // additional claims/attributes about
the subject can be added
+ claims.setClaim("email_verified", true); // boolean claim as per OIDC spec
+ claims.setClaim("admin", false); // another boolean claim
List<String> roles = Arrays.asList("group-one", "other-group",
"group-three");
claims.setStringListClaim(
"roles", roles); // multi-valued claims work too and will end up as a
JSON array
@@ -336,6 +338,38 @@ public class JWTAuthPluginTest extends SolrTestCaseJ4 {
assertEquals(CLAIM_MISMATCH, resp.getAuthCode());
}
+ @Test
+ public void claimMatchWithBooleanClaim() {
+ // Test that boolean claims work correctly with claimsMatch
+ Map<String, String> shouldMatch = new HashMap<>();
+ shouldMatch.put("email_verified", "true");
+ testConfig.put("claimsMatch", shouldMatch);
+ plugin.init(testConfig);
+ JWTAuthPlugin.JWTAuthenticationResponse resp =
plugin.authenticate(testHeader);
+ assertTrue(resp.getErrorMessage(), resp.isAuthenticated());
+
+ // Test matching false boolean value
+ shouldMatch.clear();
+ shouldMatch.put("admin", "false");
+ plugin.init(testConfig);
+ resp = plugin.authenticate(testHeader);
+ assertTrue(resp.getErrorMessage(), resp.isAuthenticated());
+
+ // Test mismatch with boolean claim
+ shouldMatch.clear();
+ shouldMatch.put("email_verified", "false");
+ plugin.init(testConfig);
+ resp = plugin.authenticate(testHeader);
+ assertEquals(CLAIM_MISMATCH, resp.getAuthCode());
+
+ // Test regex pattern with boolean claim
+ shouldMatch.clear();
+ shouldMatch.put("email_verified", "true|false");
+ plugin.init(testConfig);
+ resp = plugin.authenticate(testHeader);
+ assertTrue(resp.getErrorMessage(), resp.isAuthenticated());
+ }
+
@Test
public void missingIssAudExp() {
testConfig.put("requireIss", "false");