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

oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 39133b1ada37 CAMEL-23504: camel-keycloak - include IS_ACTIVE check in 
parseAndVerifyAccessToken (#23197)
39133b1ada37 is described below

commit 39133b1ada37c60dea53f3b7db720dbd2ae73fa6
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu May 14 09:19:03 2026 +0200

    CAMEL-23504: camel-keycloak - include IS_ACTIVE check in 
parseAndVerifyAccessToken (#23197)
    
    KeycloakSecurityHelper.parseAndVerifyAccessToken built its TokenVerifier
    with only SUBJECT_EXISTS_CHECK and a RealmUrlCheck. The Keycloak
    TokenVerifier starts with an empty internal check list and withChecks(...)
    appends rather than replacing a default set, so the built-in IS_ACTIVE
    predicate (which validates the exp and nbf claims) was not part of the
    verification chain.
    
    Add IS_ACTIVE to the withChecks(...) invocation so the helper enforces
    the token's validity window in addition to signature, subject and issuer.
    
    Two unit tests are added in KeycloakSecurityHelperTest:
    * testParseAndVerifyAccessTokenRejectsExpiredToken signs a token whose
      exp claim is in the past and asserts that parseAndVerifyAccessToken
      throws VerificationException.
    * testParseAndVerifyAccessTokenAcceptsValidToken signs an unexpired
      token and asserts that verification returns the parsed claims.
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../keycloak/security/KeycloakSecurityHelper.java  |  1 +
 .../security/KeycloakSecurityHelperTest.java       | 47 ++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
index c3ec59574f04..fa8408d05bbf 100644
--- 
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
+++ 
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelper.java
@@ -63,6 +63,7 @@ public final class KeycloakSecurityHelper {
                 .publicKey(publicKey)
                 .withChecks(
                         TokenVerifier.SUBJECT_EXISTS_CHECK,
+                        TokenVerifier.IS_ACTIVE,
                         new TokenVerifier.RealmUrlCheck(expectedIssuer));
 
         AccessToken token = verifier.verify().getToken();
diff --git 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
index 34e6041de9ac..92d31b94f260 100644
--- 
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
+++ 
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/security/KeycloakSecurityHelperTest.java
@@ -26,6 +26,7 @@ import java.util.Set;
 
 import org.junit.jupiter.api.Test;
 import org.keycloak.common.VerificationException;
+import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.representations.AccessToken;
 import org.mockito.Mockito;
 
@@ -176,6 +177,52 @@ public class KeycloakSecurityHelperTest {
         });
     }
 
+    @Test
+    void testParseAndVerifyAccessTokenRejectsExpiredToken() throws Exception {
+        String expectedIssuer = "http://localhost:8080/realms/test";;
+
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+        keyGen.initialize(2048);
+        KeyPair keyPair = keyGen.generateKeyPair();
+
+        AccessToken token = new AccessToken();
+        token.issuer(expectedIssuer);
+        token.subject("user-123");
+        token.exp(System.currentTimeMillis() / 1000 - 3600);
+
+        String signed = new JWSBuilder()
+                .type("JWT")
+                .jsonContent(token)
+                .rsa256(keyPair.getPrivate());
+
+        assertThrows(VerificationException.class,
+                () -> KeycloakSecurityHelper.parseAndVerifyAccessToken(signed, 
keyPair.getPublic(), expectedIssuer));
+    }
+
+    @Test
+    void testParseAndVerifyAccessTokenAcceptsValidToken() throws Exception {
+        String expectedIssuer = "http://localhost:8080/realms/test";;
+
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+        keyGen.initialize(2048);
+        KeyPair keyPair = keyGen.generateKeyPair();
+
+        AccessToken token = new AccessToken();
+        token.issuer(expectedIssuer);
+        token.subject("user-123");
+        token.exp(System.currentTimeMillis() / 1000 + 3600);
+
+        String signed = new JWSBuilder()
+                .type("JWT")
+                .jsonContent(token)
+                .rsa256(keyPair.getPrivate());
+
+        AccessToken verified
+                = KeycloakSecurityHelper.parseAndVerifyAccessToken(signed, 
keyPair.getPublic(), expectedIssuer);
+        assertEquals("user-123", verified.getSubject());
+        assertEquals(expectedIssuer, verified.getIssuer());
+    }
+
     @Test
     void testExtractPermissions() {
         AccessToken token = Mockito.mock(AccessToken.class);

Reply via email to