From 67ad723ed761554cb1c44332543ea72ca6e4238d Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Sun, 8 Jun 2025 10:44:51 +0500 Subject: [PATCH 01/13] Support custom role claim --- .../guard/jwt/config/JwtOptionsConfig.java | 3 + .../jwt/config/JwtOptionsConfigBuilder.java | 10 +++- .../guard/jwt/internal/JwtGuardHandler.java | 55 +++++++++++++++++-- .../config/JwtOptionsConfigAdapter.java | 11 ++++ .../jwt/internal/JwtGuardHandlerTest.java | 39 +++++++++++++ .../zilla/specs/guard/jwt/config/guard.yaml | 1 + .../guard/jwt/schema/jwt.schema.patch.json | 6 ++ 7 files changed, 118 insertions(+), 7 deletions(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java index a001825a1e..5923b33efd 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java @@ -27,6 +27,7 @@ public class JwtOptionsConfig extends OptionsConfig { public final String issuer; public final String audience; + public final String guarded; public final List keys; public final Optional challenge; public final String identity; @@ -46,6 +47,7 @@ public static JwtOptionsConfigBuilder builder( JwtOptionsConfig( String issuer, String audience, + String guarded, List keys, Duration challenge, String identity, @@ -53,6 +55,7 @@ public static JwtOptionsConfigBuilder builder( { this.issuer = issuer; this.audience = audience; + this.guarded = guarded; this.keys = keys; this.challenge = ofNullable(challenge); this.identity = identity; diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java index 093819db70..b4aba0a506 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java @@ -28,6 +28,7 @@ public class JwtOptionsConfigBuilder extends ConfigBuilder keys; private Duration challenge; private String identity; @@ -60,6 +61,13 @@ public JwtOptionsConfigBuilder audience( return this; } + public JwtOptionsConfigBuilder guarded( + String guarded) + { + this.guarded = guarded; + return this; + } + public JwtOptionsConfigBuilder challenge( Duration challenge) { @@ -107,6 +115,6 @@ public JwtOptionsConfigBuilder keysURL( @Override public T build() { - return mapper.apply(new JwtOptionsConfig(issuer, audience, keys, challenge, identity, keysURL)); + return mapper.apply(new JwtOptionsConfig(issuer, audience, guarded, keys, challenge, identity, keysURL)); } } diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index 6a4e82c8d8..b0ae8596f2 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -27,9 +27,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.function.Consumer; import java.util.function.LongSupplier; +import java.util.stream.Collectors; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; @@ -53,10 +53,13 @@ public class JwtGuardHandler implements GuardHandler { + private static final String SCOPE_PATTERN = "\\s+"; + private final JsonWebSignature signature = new JsonWebSignature(); private final String issuer; private final String audience; + private final String guarded; private final Duration challenge; private final String identity; private final Map keys; @@ -72,6 +75,7 @@ public JwtGuardHandler( { this.issuer = options.issuer; this.audience = options.audience; + this.guarded = options.guarded; this.challenge = options.challenge.orElse(null); this.identity = options.identity; @@ -179,11 +183,23 @@ public long reauthorize( break authorize; } - List roles = Optional.ofNullable(claims.getClaimValue("scope")) - .map(s -> s.toString().intern()) - .map(s -> s.split("\\s+")) - .map(Arrays::asList) - .orElse(null); + List roles = null; + String path = (guarded != null && !guarded.isEmpty()) ? guarded : "scope"; + Object claimObj = claimValue(claims, path); + + if (claimObj instanceof List) + { + List listClaim = (List) claimObj; + roles = listClaim.stream() + .map(Object::toString) + .map(String::intern) + .collect(Collectors.toList()); + } + else if (claimObj != null) + { + roles = Arrays.asList(claimObj.toString().split(SCOPE_PATTERN)); + roles.replaceAll(String::intern); + } JwtSessionStore sessionStore = supplySessionStore(contextId); session = sessionStore.supplySession(identity, roles); @@ -407,6 +423,33 @@ private void unshareIfNecessary() } } + private static Object claimValue( + Object node, + String path) + { + Object current = node; + for (String part : path.split("\\.")) + { + if (current == null) + { + break; + } + if (current instanceof JwtClaims) + { + current = ((JwtClaims) current).getClaimValue(part); + } + else if (current instanceof Map) + { + current = ((Map) current).get(part); + } + else + { + current = null; + } + } + return current; + } + private static String readKeys( Path keysPath) { diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java index 628e18d047..78ed59b70c 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java @@ -38,6 +38,7 @@ public final class JwtOptionsConfigAdapter implements OptionsConfigAdapterSpi, J { private static final String ISSUER_NAME = "issuer"; private static final String AUDIENCE_NAME = "audience"; + private static final String GUARDED = "guarded"; private static final String KEYS_NAME = "keys"; private static final String CHALLENGE_NAME = "challenge"; private static final String IDENTITY_NAME = "identity"; @@ -76,6 +77,11 @@ public JsonObject adaptToJson( object.add(AUDIENCE_NAME, jwtOptions.audience); } + if (jwtOptions.guarded != null) + { + object.add(GUARDED, jwtOptions.guarded); + } + if (jwtOptions.keys != null) { JsonArrayBuilder newKeys = Json.createArrayBuilder(); @@ -118,6 +124,11 @@ public OptionsConfig adaptFromJson( jwtOptions.audience(object.getString(AUDIENCE_NAME)); } + if (object.containsKey(GUARDED)) + { + jwtOptions.guarded(object.getString(GUARDED)); + } + if (object.containsKey(KEYS_NAME)) { JsonValue keysValue = object.getValue(String.format("/%s", KEYS_NAME)); diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java index 199a7ae5b9..c4127c3fca 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java @@ -32,6 +32,9 @@ import java.time.Duration; import java.time.Instant; +import java.util.HashMap; +import java.util.Map; + import org.agrona.collections.MutableLong; import org.jose4j.jws.JsonWebSignature; import org.jose4j.jwt.JwtClaims; @@ -650,6 +653,42 @@ public void shouldDeauthorize() throws Exception guard.deauthorize(sessionId); } + @Test + public void shouldAuthorizeWithCustomRole() throws Exception + { + Duration challenge = ofSeconds(3L); + JwtOptionsConfig options = JwtOptionsConfig.builder() + .inject(identity()) + .issuer("test issuer") + .audience("testAudience") + .guarded("realm_access.roles") + .key(RFC7515_RS256_CONFIG) + .challenge(challenge) + .build(); + JwtGuardHandler guard = new JwtGuardHandler(options, context, new MutableLong(1L)::getAndIncrement); + + Instant now = Instant.now(); + + JwtClaims claims = new JwtClaims(); + claims.setClaim("iss", "test issuer"); + claims.setClaim("aud", "testAudience"); + claims.setClaim("sub", "testSubject"); + claims.setClaim("exp", now.getEpochSecond() + 10L); + Map realmAccess = new HashMap<>(); + realmAccess.put("roles", asList("default-roles-backend", "offline_access", "uma_authorization")); + claims.setClaim("realm_access", realmAccess); + + String token = sign(claims.toJson(), "test", RFC7515_RS256, "RS256"); + + long sessionId = guard.reauthorize(0L, 0L, 101L, token); + + assertThat(sessionId, not(equalTo(0L))); + assertThat(guard.identity(sessionId), equalTo("testSubject")); + assertThat(guard.expiresAt(sessionId), equalTo(ofSeconds(now.getEpochSecond() + 10L).toMillis())); + assertThat(guard.expiringAt(sessionId), equalTo(ofSeconds(now.getEpochSecond() + 10L).minus(challenge).toMillis())); + assertTrue(guard.verify(sessionId, asList("default-roles-backend", "offline_access", "uma_authorization"))); + } + static String sign( String payload, String kid, diff --git a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml index cfc2a9d4ff..77ca51760d 100644 --- a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml +++ b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml @@ -21,6 +21,7 @@ guards: options: issuer: https://auth.example.com audience: https://api.example.com + guarded: "realm_access.roles" keys: - kty: EC crv: P-256 diff --git a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json index e88157673e..b9e05e08be 100644 --- a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json +++ b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json @@ -41,6 +41,12 @@ "title": "Audience", "type": "string" }, + "guarded": + { + "title": "Guarded", + "type": "string", + "default": "scope" + }, "keys": { "title": "Keys", From c33e64b8429e5f76d29d9d99aadbad5a3ff29e35 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Sun, 8 Jun 2025 10:46:35 +0500 Subject: [PATCH 02/13] Add negative assertion --- .../zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java index c4127c3fca..dd50175738 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java @@ -687,6 +687,7 @@ public void shouldAuthorizeWithCustomRole() throws Exception assertThat(guard.expiresAt(sessionId), equalTo(ofSeconds(now.getEpochSecond() + 10L).toMillis())); assertThat(guard.expiringAt(sessionId), equalTo(ofSeconds(now.getEpochSecond() + 10L).minus(challenge).toMillis())); assertTrue(guard.verify(sessionId, asList("default-roles-backend", "offline_access", "uma_authorization"))); + assertFalse(guard.verify(sessionId, asList("admin"))); } static String sign( From d05d6809ee688b63f3bb97332ee2500293e01e03 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Sun, 8 Jun 2025 11:20:45 +0500 Subject: [PATCH 03/13] Refactored code --- .../zilla/runtime/guard/jwt/internal/JwtGuardHandler.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index b0ae8596f2..c5b085f0d1 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -53,7 +53,8 @@ public class JwtGuardHandler implements GuardHandler { - private static final String SCOPE_PATTERN = "\\s+"; + private static final String SCOPE_VALUE_PATTERN = "\\s+"; + private static final String SCOPE_PATH_PATTERN = "\\."; private final JsonWebSignature signature = new JsonWebSignature(); @@ -197,7 +198,7 @@ public long reauthorize( } else if (claimObj != null) { - roles = Arrays.asList(claimObj.toString().split(SCOPE_PATTERN)); + roles = Arrays.asList(claimObj.toString().split(SCOPE_VALUE_PATTERN)); roles.replaceAll(String::intern); } @@ -428,7 +429,7 @@ private static Object claimValue( String path) { Object current = node; - for (String part : path.split("\\.")) + for (String part : path.split(SCOPE_PATH_PATTERN)) { if (current == null) { From e52a7c395ab86b66a99008e5ecbb1c3bffeca6c9 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Mon, 9 Jun 2025 20:17:07 +0500 Subject: [PATCH 04/13] Change guarded to roles --- .../runtime/guard/jwt/config/JwtOptionsConfig.java | 6 +++--- .../guard/jwt/config/JwtOptionsConfigBuilder.java | 10 +++++----- .../runtime/guard/jwt/internal/JwtGuardHandler.java | 2 +- .../jwt/internal/config/JwtOptionsConfigAdapter.java | 10 +++++----- .../guard/jwt/internal/JwtGuardHandlerTest.java | 3 +-- .../aklivity/zilla/specs/guard/jwt/config/guard.yaml | 2 +- .../zilla/specs/guard/jwt/schema/jwt.schema.patch.json | 4 ++-- 7 files changed, 18 insertions(+), 19 deletions(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java index 5923b33efd..9ce40b714a 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfig.java @@ -27,7 +27,7 @@ public class JwtOptionsConfig extends OptionsConfig { public final String issuer; public final String audience; - public final String guarded; + public final String roles; public final List keys; public final Optional challenge; public final String identity; @@ -47,7 +47,7 @@ public static JwtOptionsConfigBuilder builder( JwtOptionsConfig( String issuer, String audience, - String guarded, + String roles, List keys, Duration challenge, String identity, @@ -55,7 +55,7 @@ public static JwtOptionsConfigBuilder builder( { this.issuer = issuer; this.audience = audience; - this.guarded = guarded; + this.roles = roles; this.keys = keys; this.challenge = ofNullable(challenge); this.identity = identity; diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java index b4aba0a506..4a5d46c8fc 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java @@ -28,7 +28,7 @@ public class JwtOptionsConfigBuilder extends ConfigBuilder keys; private Duration challenge; private String identity; @@ -61,10 +61,10 @@ public JwtOptionsConfigBuilder audience( return this; } - public JwtOptionsConfigBuilder guarded( - String guarded) + public JwtOptionsConfigBuilder roles( + String roles) { - this.guarded = guarded; + this.roles = roles; return this; } @@ -115,6 +115,6 @@ public JwtOptionsConfigBuilder keysURL( @Override public T build() { - return mapper.apply(new JwtOptionsConfig(issuer, audience, guarded, keys, challenge, identity, keysURL)); + return mapper.apply(new JwtOptionsConfig(issuer, audience, roles, keys, challenge, identity, keysURL)); } } diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index c5b085f0d1..633ab1d1b4 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -76,7 +76,7 @@ public JwtGuardHandler( { this.issuer = options.issuer; this.audience = options.audience; - this.guarded = options.guarded; + this.guarded = options.roles; this.challenge = options.challenge.orElse(null); this.identity = options.identity; diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java index 78ed59b70c..f56869335f 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java @@ -38,7 +38,7 @@ public final class JwtOptionsConfigAdapter implements OptionsConfigAdapterSpi, J { private static final String ISSUER_NAME = "issuer"; private static final String AUDIENCE_NAME = "audience"; - private static final String GUARDED = "guarded"; + private static final String ROLES = "roles"; private static final String KEYS_NAME = "keys"; private static final String CHALLENGE_NAME = "challenge"; private static final String IDENTITY_NAME = "identity"; @@ -77,9 +77,9 @@ public JsonObject adaptToJson( object.add(AUDIENCE_NAME, jwtOptions.audience); } - if (jwtOptions.guarded != null) + if (jwtOptions.roles != null) { - object.add(GUARDED, jwtOptions.guarded); + object.add(ROLES, jwtOptions.roles); } if (jwtOptions.keys != null) @@ -124,9 +124,9 @@ public OptionsConfig adaptFromJson( jwtOptions.audience(object.getString(AUDIENCE_NAME)); } - if (object.containsKey(GUARDED)) + if (object.containsKey(ROLES)) { - jwtOptions.guarded(object.getString(GUARDED)); + jwtOptions.roles(object.getString(ROLES)); } if (object.containsKey(KEYS_NAME)) diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java index dd50175738..840e26a80a 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java @@ -31,7 +31,6 @@ import java.time.Clock; import java.time.Duration; import java.time.Instant; - import java.util.HashMap; import java.util.Map; @@ -661,7 +660,7 @@ public void shouldAuthorizeWithCustomRole() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .guarded("realm_access.roles") + .roles("realm_access.roles") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); diff --git a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml index 77ca51760d..13f5a7a9d9 100644 --- a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml +++ b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/guard.yaml @@ -21,7 +21,7 @@ guards: options: issuer: https://auth.example.com audience: https://api.example.com - guarded: "realm_access.roles" + roles: "realm_access.roles" keys: - kty: EC crv: P-256 diff --git a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json index b9e05e08be..5c304f76d2 100644 --- a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json +++ b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/schema/jwt.schema.patch.json @@ -41,9 +41,9 @@ "title": "Audience", "type": "string" }, - "guarded": + "roles": { - "title": "Guarded", + "title": "Roles", "type": "string", "default": "scope" }, From 71c411ed5beda50934e096baca2df403b01c4321 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Mon, 9 Jun 2025 20:24:55 +0500 Subject: [PATCH 05/13] Fix typo --- .../zilla/runtime/guard/jwt/internal/JwtGuardHandler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index 633ab1d1b4..8f1b0ca3a5 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -60,7 +60,7 @@ public class JwtGuardHandler implements GuardHandler private final String issuer; private final String audience; - private final String guarded; + private final String roles; private final Duration challenge; private final String identity; private final Map keys; @@ -76,7 +76,7 @@ public JwtGuardHandler( { this.issuer = options.issuer; this.audience = options.audience; - this.guarded = options.roles; + this.roles = options.roles; this.challenge = options.challenge.orElse(null); this.identity = options.identity; @@ -185,7 +185,7 @@ public long reauthorize( } List roles = null; - String path = (guarded != null && !guarded.isEmpty()) ? guarded : "scope"; + String path = (this.roles != null && !this.roles.isEmpty()) ? this.roles : "scope"; Object claimObj = claimValue(claims, path); if (claimObj instanceof List) From 2039307ff869a9f1c5ccc3b76d42bb4005294a19 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Tue, 10 Jun 2025 10:16:49 +0500 Subject: [PATCH 06/13] Apply feedback from PR --- .../guard/jwt/internal/JwtGuardHandler.java | 35 +++++++++---------- .../jwt/internal/JwtGuardHandlerTest.java | 23 +++++++++--- .../guard/jwt/internal/JwtGuardTest.java | 7 ++++ 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index 8f1b0ca3a5..5ab4be2940 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -27,9 +27,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.function.Consumer; import java.util.function.LongSupplier; -import java.util.stream.Collectors; import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; @@ -184,23 +184,22 @@ public long reauthorize( break authorize; } - List roles = null; - String path = (this.roles != null && !this.roles.isEmpty()) ? this.roles : "scope"; - Object claimObj = claimValue(claims, path); - - if (claimObj instanceof List) - { - List listClaim = (List) claimObj; - roles = listClaim.stream() - .map(Object::toString) - .map(String::intern) - .collect(Collectors.toList()); - } - else if (claimObj != null) - { - roles = Arrays.asList(claimObj.toString().split(SCOPE_VALUE_PATTERN)); - roles.replaceAll(String::intern); - } + Object rolesValue = claimValue(claims, this.roles); + @SuppressWarnings("unchecked") + List rolesValueAsList = (rolesValue instanceof List) + ? (List) rolesValue + : Optional.ofNullable(rolesValue) + .map(Object::toString) + .map(s -> s.split(SCOPE_VALUE_PATTERN)) + .map(Arrays::asList) + .orElse(null); + + List roles = rolesValueAsList != null + ? rolesValueAsList.stream() + .map(Object::toString) + .map(String::intern) + .toList() + : null; JwtSessionStore sessionStore = supplySessionStore(contextId); session = sessionStore.supplySession(identity, roles); diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java index 840e26a80a..ca58786ba8 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java @@ -31,7 +31,7 @@ import java.time.Clock; import java.time.Duration; import java.time.Instant; -import java.util.HashMap; +import java.util.List; import java.util.Map; import org.agrona.collections.MutableLong; @@ -65,6 +65,7 @@ public void shouldAuthorize() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -98,6 +99,7 @@ public void shouldAuthorizeWithCustomIdentity() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .identity("username") @@ -132,6 +134,7 @@ public void shouldChallengeDuringChallengeWindow() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -161,6 +164,7 @@ public void shouldNotChallengeDuringWindowWithoutSubject() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -189,6 +193,7 @@ public void shouldNotChallengeBeforeChallengeWindow() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -218,6 +223,7 @@ public void shouldNotChallengeAgainDuringChallengeWindow() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -389,6 +395,7 @@ public void shouldNotVerifyAuthorizedWhenRolesInsufficient() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -415,6 +422,7 @@ public void shouldReauthorizeWhenExpirationLater() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -450,6 +458,7 @@ public void shouldReauthorizeWhenScopeBroader() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -486,6 +495,7 @@ public void shouldNotReauthorizeWhenExpirationEarlier() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -521,6 +531,7 @@ public void shouldNotReauthorizeWhenScopeNarrower() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -558,6 +569,7 @@ public void shouldNotReauthorizeWhenSubjectDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -595,6 +607,7 @@ public void shouldNotReauthorizeWhenContextDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -631,6 +644,7 @@ public void shouldDeauthorize() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -652,6 +666,7 @@ public void shouldDeauthorize() throws Exception guard.deauthorize(sessionId); } + @SuppressWarnings("checkstyle:Indentation") @Test public void shouldAuthorizeWithCustomRole() throws Exception { @@ -673,10 +688,8 @@ public void shouldAuthorizeWithCustomRole() throws Exception claims.setClaim("aud", "testAudience"); claims.setClaim("sub", "testSubject"); claims.setClaim("exp", now.getEpochSecond() + 10L); - Map realmAccess = new HashMap<>(); - realmAccess.put("roles", asList("default-roles-backend", "offline_access", "uma_authorization")); - claims.setClaim("realm_access", realmAccess); - + claims.setClaim("realm_access", + Map.of("roles", List.of("default-roles-backend", "offline_access", "uma_authorization"))); String token = sign(claims.toJson(), "test", RFC7515_RS256, "RS256"); long sessionId = guard.reauthorize(0L, 0L, 101L, token); diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java index 0e12950a39..6ae9cfb90b 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java @@ -150,6 +150,7 @@ public void shouldNotVerifyRolesWhenInsufficient() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -203,6 +204,7 @@ public void shouldVerifyRolesWhenExact() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -255,6 +257,7 @@ public void shouldVerifyRolesWhenSuperset() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -306,6 +309,7 @@ public void shouldVerifyRolesWhenEmpty() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -351,6 +355,7 @@ public void shouldVerifyWhenIndexDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -408,6 +413,7 @@ public void shouldIdentify() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -454,6 +460,7 @@ public void shouldIdentifyWhenIndexDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") + .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build() From e96205fb2ab0956dbcd9c53f517de0f0db0a95d6 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Tue, 10 Jun 2025 10:17:48 +0500 Subject: [PATCH 07/13] Fix checkstyle --- .../zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java index ca58786ba8..b5dbf482a7 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java @@ -666,7 +666,6 @@ public void shouldDeauthorize() throws Exception guard.deauthorize(sessionId); } - @SuppressWarnings("checkstyle:Indentation") @Test public void shouldAuthorizeWithCustomRole() throws Exception { @@ -689,7 +688,7 @@ public void shouldAuthorizeWithCustomRole() throws Exception claims.setClaim("sub", "testSubject"); claims.setClaim("exp", now.getEpochSecond() + 10L); claims.setClaim("realm_access", - Map.of("roles", List.of("default-roles-backend", "offline_access", "uma_authorization"))); + Map.of("roles", List.of("default-roles-backend", "offline_access", "uma_authorization"))); String token = sign(claims.toJson(), "test", RFC7515_RS256, "RS256"); long sessionId = guard.reauthorize(0L, 0L, 101L, token); From ce77565fb59f815b56b37611d27cc06fc1e341ff Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Wed, 11 Jun 2025 16:34:31 +0500 Subject: [PATCH 08/13] Apply feedback from PR --- .../jwt/config/JwtOptionsConfigBuilder.java | 2 ++ .../guard/jwt/internal/JwtGuardHandler.java | 17 +++++------------ .../guard/jwt/internal/JwtGuardHandlerTest.java | 14 -------------- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java index 4a5d46c8fc..508b386fb9 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java @@ -115,6 +115,8 @@ public JwtOptionsConfigBuilder keysURL( @Override public T build() { + roles = roles != null ? roles : "scope"; + return mapper.apply(new JwtOptionsConfig(issuer, audience, roles, keys, challenge, identity, keysURL)); } } diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index 5ab4be2940..d79b858246 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -53,8 +53,8 @@ public class JwtGuardHandler implements GuardHandler { - private static final String SCOPE_VALUE_PATTERN = "\\s+"; - private static final String SCOPE_PATH_PATTERN = "\\."; + private static final String SPLIT_VALUE_PATTERN = "\\s+"; + private static final String SPLIT_PATH_PATTERN = "\\."; private final JsonWebSignature signature = new JsonWebSignature(); @@ -186,21 +186,14 @@ public long reauthorize( Object rolesValue = claimValue(claims, this.roles); @SuppressWarnings("unchecked") - List rolesValueAsList = (rolesValue instanceof List) + List roles = (rolesValue instanceof List) ? (List) rolesValue : Optional.ofNullable(rolesValue) .map(Object::toString) - .map(s -> s.split(SCOPE_VALUE_PATTERN)) + .map(s -> s.split(SPLIT_VALUE_PATTERN)) .map(Arrays::asList) .orElse(null); - List roles = rolesValueAsList != null - ? rolesValueAsList.stream() - .map(Object::toString) - .map(String::intern) - .toList() - : null; - JwtSessionStore sessionStore = supplySessionStore(contextId); session = sessionStore.supplySession(identity, roles); @@ -428,7 +421,7 @@ private static Object claimValue( String path) { Object current = node; - for (String part : path.split(SCOPE_PATH_PATTERN)) + for (String part : path.split(SPLIT_PATH_PATTERN)) { if (current == null) { diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java index b5dbf482a7..f69714d38a 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandlerTest.java @@ -65,7 +65,6 @@ public void shouldAuthorize() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -99,7 +98,6 @@ public void shouldAuthorizeWithCustomIdentity() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .identity("username") @@ -134,7 +132,6 @@ public void shouldChallengeDuringChallengeWindow() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -164,7 +161,6 @@ public void shouldNotChallengeDuringWindowWithoutSubject() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -193,7 +189,6 @@ public void shouldNotChallengeBeforeChallengeWindow() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -223,7 +218,6 @@ public void shouldNotChallengeAgainDuringChallengeWindow() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -395,7 +389,6 @@ public void shouldNotVerifyAuthorizedWhenRolesInsufficient() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -422,7 +415,6 @@ public void shouldReauthorizeWhenExpirationLater() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -458,7 +450,6 @@ public void shouldReauthorizeWhenScopeBroader() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -495,7 +486,6 @@ public void shouldNotReauthorizeWhenExpirationEarlier() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -531,7 +521,6 @@ public void shouldNotReauthorizeWhenScopeNarrower() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -569,7 +558,6 @@ public void shouldNotReauthorizeWhenSubjectDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -607,7 +595,6 @@ public void shouldNotReauthorizeWhenContextDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); @@ -644,7 +631,6 @@ public void shouldDeauthorize() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build(); From 8432e4534d4a1fb4f9ffab8528ad5a34ee74a426 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Wed, 11 Jun 2025 16:35:56 +0500 Subject: [PATCH 09/13] Remove remaining default roles --- .../zilla/runtime/guard/jwt/internal/JwtGuardTest.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java index 6ae9cfb90b..0e12950a39 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardTest.java @@ -150,7 +150,6 @@ public void shouldNotVerifyRolesWhenInsufficient() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -204,7 +203,6 @@ public void shouldVerifyRolesWhenExact() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -257,7 +255,6 @@ public void shouldVerifyRolesWhenSuperset() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -309,7 +306,6 @@ public void shouldVerifyRolesWhenEmpty() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -355,7 +351,6 @@ public void shouldVerifyWhenIndexDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -413,7 +408,6 @@ public void shouldIdentify() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(ofSeconds(3L)) .build() @@ -460,7 +454,6 @@ public void shouldIdentifyWhenIndexDiffers() throws Exception .inject(identity()) .issuer("test issuer") .audience("testAudience") - .roles("scope") .key(RFC7515_RS256_CONFIG) .challenge(challenge) .build() From c5f0817d671b62c7a58c8ae9eacd37dbba221978 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Wed, 11 Jun 2025 18:31:49 +0500 Subject: [PATCH 10/13] Fix checkstyle --- .../zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java index 508b386fb9..1d60f76894 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java @@ -116,7 +116,7 @@ public JwtOptionsConfigBuilder keysURL( public T build() { roles = roles != null ? roles : "scope"; - + return mapper.apply(new JwtOptionsConfig(issuer, audience, roles, keys, challenge, identity, keysURL)); } } From d1f235185f94a890bc75df6b0f0008326d5d52f5 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Wed, 11 Jun 2025 20:37:23 +0500 Subject: [PATCH 11/13] Fix testware issue --- .../guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java index 392c516efd..f1856c2e2c 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java @@ -137,6 +137,7 @@ public void shouldWriteOptions() "{" + "\"issuer\":\"https://auth.example.com\"," + "\"audience\":\"https://api.example.com\"," + + "\"roles\":\"scope\"," + "\"keys\":" + "[" + "{" + From 51fd51c9e1bf19b969b8120bda5e455214a09cc8 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Wed, 11 Jun 2025 22:14:45 +0500 Subject: [PATCH 12/13] Don't print default value for roles field --- .../runtime/guard/jwt/config/JwtOptionsConfigBuilder.java | 4 +++- .../guard/jwt/internal/config/JwtOptionsConfigAdapter.java | 3 ++- .../jwt/internal/config/JwtOptionsConfigAdapterTest.java | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java index 1d60f76894..67612ebcf8 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java @@ -24,6 +24,8 @@ public class JwtOptionsConfigBuilder extends ConfigBuilder> { + public static final String ROLES_DEFAULT = "scope"; + private final Function mapper; private String issuer; @@ -115,7 +117,7 @@ public JwtOptionsConfigBuilder keysURL( @Override public T build() { - roles = roles != null ? roles : "scope"; + roles = roles != null ? roles : ROLES_DEFAULT; return mapper.apply(new JwtOptionsConfig(issuer, audience, roles, keys, challenge, identity, keysURL)); } diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java index f56869335f..8d1dd6c19c 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapter.java @@ -14,6 +14,7 @@ */ package io.aklivity.zilla.runtime.guard.jwt.internal.config; +import static io.aklivity.zilla.runtime.guard.jwt.config.JwtOptionsConfigBuilder.ROLES_DEFAULT; import static java.util.Collections.emptyList; import java.time.Duration; @@ -77,7 +78,7 @@ public JsonObject adaptToJson( object.add(AUDIENCE_NAME, jwtOptions.audience); } - if (jwtOptions.roles != null) + if (jwtOptions.roles != null && !ROLES_DEFAULT.equals(jwtOptions.roles)) { object.add(ROLES, jwtOptions.roles); } diff --git a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java index f1856c2e2c..392c516efd 100644 --- a/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java +++ b/runtime/guard-jwt/src/test/java/io/aklivity/zilla/runtime/guard/jwt/internal/config/JwtOptionsConfigAdapterTest.java @@ -137,7 +137,6 @@ public void shouldWriteOptions() "{" + "\"issuer\":\"https://auth.example.com\"," + "\"audience\":\"https://api.example.com\"," + - "\"roles\":\"scope\"," + "\"keys\":" + "[" + "{" + From 5322f3eaa063df9ff21053e9d6583767de91abf6 Mon Sep 17 00:00:00 2001 From: Akram Yakubov Date: Wed, 11 Jun 2025 22:16:45 +0500 Subject: [PATCH 13/13] Refactor code --- .../zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java index 67612ebcf8..3bd386ba7b 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/config/JwtOptionsConfigBuilder.java @@ -117,7 +117,7 @@ public JwtOptionsConfigBuilder keysURL( @Override public T build() { - roles = roles != null ? roles : ROLES_DEFAULT; + String roles = this.roles != null ? this.roles : ROLES_DEFAULT; return mapper.apply(new JwtOptionsConfig(issuer, audience, roles, keys, challenge, identity, keysURL)); }