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

smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git


The following commit(s) were added to refs/heads/master by this push:
     new 716ed152c KNOX-3266: Support JWKS verification in SSOCookieProvider 
(#1168)
716ed152c is described below

commit 716ed152c119b7bf1c01fc821bc3c8e40f6234f4
Author: Sandor Molnar <[email protected]>
AuthorDate: Mon Mar 2 21:31:46 2026 +0100

    KNOX-3266: Support JWKS verification in SSOCookieProvider (#1168)
---
 .../federation/jwt/filter/AbstractJWTFilter.java   | 45 ++++++++++++++++--
 .../federation/jwt/filter/JWTFederationFilter.java | 53 ++--------------------
 .../jwt/filter/SSOCookieFederationFilter.java      |  6 +++
 .../provider/federation/AbstractJWTFilterTest.java |  7 +--
 .../token/impl/DefaultTokenAuthorityService.java   | 34 ++++++--------
 .../token/impl/TokenAuthorityServiceMessages.java  |  3 +-
 .../services/token/impl/JWKSourceBuilderTest.java  |  9 ++--
 .../gateway/service/knoxsso/WebSSOResource.java    |  6 +++
 .../service/knoxsso/WebSSOResourceTest.java        |  7 +--
 .../knoxtoken/TokenServiceResourceTest.java        |  7 +--
 .../services/security/token/JWTokenAuthority.java  |  8 ++--
 11 files changed, 94 insertions(+), 91 deletions(-)

diff --git 
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
 
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
index b5eaf69da..cc420bfb0 100644
--- 
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
+++ 
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
@@ -21,6 +21,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.IOException;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.security.Principal;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
@@ -36,6 +37,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.security.auth.Subject;
 import javax.servlet.Filter;
@@ -48,6 +50,9 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import com.nimbusds.jose.proc.DefaultJOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.JOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.SecurityContext;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.knox.gateway.audit.api.Action;
@@ -122,8 +127,8 @@ public abstract class AbstractJWTFilter implements Filter {
   private List<String> expectedIssuers;
   private String expectedSigAlg;
   protected String expectedPrincipalClaim;
-  protected Set<URI> expectedJWKSUrls = new LinkedHashSet();
-  protected Set<JOSEObjectType> allowedJwsTypes;
+  protected Set<URI> jwksUrls = new LinkedHashSet<>();
+  private JOSEObjectTypeVerifier<SecurityContext> typeVerifier;
 
   private TokenStateService tokenStateService;
   private TokenMAC tokenMAC;
@@ -209,6 +214,38 @@ public abstract class AbstractJWTFilter implements Filter {
     return audList;
   }
 
+  /**
+   * @param configuredJwksUrls configured JWKS URLs in the form of 
http(s)://url:port/contxt/.wellknown, http(s)://url2:port/contxt/.wellknown
+   */
+  protected Set<URI> parseJwksUrlsFromConfig(final String configuredJwksUrls) {
+    final Set<URI> jwksUrls = new HashSet<>();
+    if (configuredJwksUrls != null) {
+      Arrays.stream(configuredJwksUrls.split(","))
+              .map(String::trim)
+              .collect(Collectors.toSet())
+              .forEach(jwksUrl -> {
+                try {
+                  jwksUrls.add(new URI(jwksUrl));
+                } catch (URISyntaxException e) {
+                  /* Not valid JWKS url, log and move on */
+                  log.invalidJwksUrl(jwksUrl);
+                }
+              });
+    }
+    return jwksUrls;
+  }
+
+  protected void setJwsTypeVerifier(final FilterConfig filterConfig, final 
String configName) {
+    final Set<JOSEObjectType> allowedJwsTypes = new HashSet<>();
+    final String allowedTypes = filterConfig.getInitParameter(configName);
+    if (allowedTypes != null) {
+      Stream.of(allowedTypes.trim().split(",")).forEach(allowedType -> 
allowedJwsTypes.add(new JOSEObjectType(allowedType.trim())));
+    } else {
+      allowedJwsTypes.add(JOSEObjectType.JWT);
+    }
+    typeVerifier = new DefaultJOSEObjectTypeVerifier<>(allowedJwsTypes);
+  }
+
   protected boolean tokenIsStillValid(final JWT jwtToken) throws 
UnknownTokenException {
     Date expires = 
getServerManagedStateExpiration(TokenUtils.getTokenId(jwtToken));
     if (expires == null) {
@@ -573,9 +610,9 @@ public abstract class AbstractJWTFilter implements Filter {
           log.pemVerificationResultMessage(verified);
         }
 
-        if (!verified && expectedJWKSUrls != null && 
!expectedJWKSUrls.isEmpty()) {
+        if (!verified && jwksUrls != null && !jwksUrls.isEmpty()) {
           attemptedJWKSVerification = true;
-          verified = authority.verifyToken(token, expectedJWKSUrls, 
expectedSigAlg, allowedJwsTypes);
+          verified = authority.verifyToken(token, jwksUrls, expectedSigAlg, 
typeVerifier);
           log.jwksVerificationResultMessage(verified);
         }
 
diff --git 
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
 
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
index ab339a50a..5795d9a0e 100644
--- 
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
+++ 
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
@@ -17,7 +17,6 @@
  */
 package org.apache.knox.gateway.provider.federation.jwt.filter;
 
-import com.nimbusds.jose.JOSEObjectType;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
@@ -40,17 +39,12 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
 import java.text.ParseException;
-import java.util.Arrays;
 import java.util.Base64;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static 
org.apache.knox.gateway.util.AuthFilterUtils.DEFAULT_AUTH_UNAUTHENTICATED_PATHS_PARAM;
@@ -111,25 +105,10 @@ public class JWTFederationFilter extends 
AbstractJWTFilter {
       paramName = queryParamName;
     }
 
-    //  JWKSUrl
-    String oidcjwksurl = filterConfig.getInitParameter(JWKS_URL);
-    if (oidcjwksurl != null) {
-      expectedJWKSUrls = parseJwksUrlsFromConfig(oidcjwksurl);
-    }
-
-    /* in case knox.token.jwks.urls property is defined use it */
-    final String oidcjwksurls = filterConfig.getInitParameter(JWKS_URLS);
-    if (oidcjwksurls != null) {
-      expectedJWKSUrls.addAll(parseJwksUrlsFromConfig(oidcjwksurls));
-    }
-
-    allowedJwsTypes = new HashSet<>();
-    final String allowedTypes = 
filterConfig.getInitParameter(ALLOWED_JWS_TYPES);
-    if (allowedTypes != null) {
-      Stream.of(allowedTypes.trim().split(",")).forEach(allowedType -> 
allowedJwsTypes.add(new JOSEObjectType(allowedType.trim())));
-    } else {
-      allowedJwsTypes.add(JOSEObjectType.JWT);
-    }
+    //  JWKSUrl(s) and allowed JWS types
+    jwksUrls = 
parseJwksUrlsFromConfig(filterConfig.getInitParameter(JWKS_URL));
+    
jwksUrls.addAll(parseJwksUrlsFromConfig(filterConfig.getInitParameter(JWKS_URLS)));
+    setJwsTypeVerifier(filterConfig, ALLOWED_JWS_TYPES);
 
     //cookie auth support
     final String useCookieParam = 
filterConfig.getInitParameter(KNOX_TOKEN_USE_COOKIE);
@@ -159,30 +138,6 @@ public class JWTFederationFilter extends AbstractJWTFilter 
{
     configureExpectedParameters(filterConfig);
   }
 
-  /**
-   * Helper function to extract URLs from given string
-   * in the form of https://url:port/contxt/.wellknown, 
https://url2:port/contxt/.wellknown
-   * into expectedJWKSUrl URL set.
-   * @param oidcjwksurls
-   */
-  private Set<URI> parseJwksUrlsFromConfig(final String oidcjwksurls) {
-    final Set<URI> jwksUrlSet = new HashSet<>();
-    final Set<String> jwksurls = Arrays.stream(
-            oidcjwksurls.split(","))
-            .map(String::trim)
-            .collect(Collectors.toSet());
-
-    for (final String jwksurl : jwksurls) {
-        try {
-          jwksUrlSet.add(new URI(jwksurl));
-        } catch (URISyntaxException e) {
-          /* Not valid JWKS url, log and move on */
-          log.invalidJwksUrl(jwksurl);
-        }
-    }
-    return jwksUrlSet;
-  }
-
   @Override
   public void destroy() {
   }
diff --git 
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
 
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
index 7f3af11d3..a8e7b8f8d 100644
--- 
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
+++ 
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
@@ -63,6 +63,8 @@ public class SSOCookieFederationFilter extends 
AbstractJWTFilter {
   public static final String SSO_EXPECTED_AUDIENCES = "sso.expected.audiences";
   public static final String SSO_AUTHENTICATION_PROVIDER_URL = 
"sso.authentication.provider.url";
   public static final String SSO_VERIFICATION_PEM = 
"sso.token.verification.pem";
+  public static final String SSO_VERIFICATION_JWKS_URLS = 
"sso.token.verification.jwks.urls";
+  public static final String SSO_VERIFICATION_ALLOWED_JWS_TYPES = 
"sso.token.verification.allowed.jws.types";
   public static final String SSO_IDLE_TIMEOUT_SECONDS = 
"sso.idle.timeout.seconds";
   public static final String X_FORWARDED_HOST = "X-Forwarded-Host";
   public static final String X_FORWARDED_PORT = "X-Forwarded-Port";
@@ -132,6 +134,10 @@ public class SSOCookieFederationFilter extends 
AbstractJWTFilter {
       publicKey = CertificateUtils.parseRSAPublicKey(verificationPEM);
     }
 
+    //Token verification: JWKS URL(s) and allowed JWS types
+    jwksUrls = 
parseJwksUrlsFromConfig(filterConfig.getInitParameter(SSO_VERIFICATION_JWKS_URLS));
+    setJwsTypeVerifier(filterConfig, SSO_VERIFICATION_ALLOWED_JWS_TYPES);
+
     final String unAuthPathString = filterConfig
         .getInitParameter(SSO_UNAUTHENTICATED_PATHS_PARAM);
     /* prepare a list of allowed unauthenticated paths */
diff --git 
a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
 
b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
index 84eb5144b..f025aa277 100644
--- 
a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
+++ 
b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
@@ -17,13 +17,14 @@
  */
 package org.apache.knox.gateway.provider.federation;
 
-import com.nimbusds.jose.JOSEObjectType;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSHeader;
 import com.nimbusds.jose.JWSSigner;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.crypto.RSASSASigner;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.proc.JOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.SecurityContext;
 import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.SignedJWT;
 import org.apache.commons.codec.binary.Base64;
@@ -1462,12 +1463,12 @@ public abstract class AbstractJWTFilterTest  {
     }
 
     @Override
-    public boolean verifyToken(JWT token, String jwksurl, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) {
+    public boolean verifyToken(JWT token, String jwksurl, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) {
      return false;
     }
 
     @Override
-    public boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) throws TokenServiceException {
+    public boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) throws 
TokenServiceException {
       return false;
     }
   }
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
index 5ca067614..034b27ce5 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityService.java
@@ -39,7 +39,6 @@ import java.util.Optional;
 import java.util.Set;
 
 import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JOSEObjectType;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSSigner;
 import com.nimbusds.jose.JWSVerifier;
@@ -51,7 +50,6 @@ import com.nimbusds.jose.crypto.RSASSAVerifier;
 import com.nimbusds.jose.jwk.source.JWKSource;
 import com.nimbusds.jose.jwk.source.JWKSourceBuilder;
 import com.nimbusds.jose.proc.BadJOSEException;
-import com.nimbusds.jose.proc.DefaultJOSEObjectTypeVerifier;
 import com.nimbusds.jose.proc.JOSEObjectTypeVerifier;
 import com.nimbusds.jose.proc.JWSKeySelector;
 import com.nimbusds.jose.proc.JWSVerificationKeySelector;
@@ -59,7 +57,6 @@ import com.nimbusds.jose.proc.SecurityContext;
 import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
 import com.nimbusds.jwt.proc.DefaultJWTClaimsVerifier;
 import com.nimbusds.jwt.proc.DefaultJWTProcessor;
-import com.nimbusds.jwt.proc.JWTClaimsSetVerifier;
 import org.apache.knox.gateway.GatewayResources;
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
@@ -226,26 +223,26 @@ public class DefaultTokenAuthorityService implements 
JWTokenAuthority, Service {
   }
 
   @Override
-  public boolean verifyToken(JWT token, String jwksurl, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) throws TokenServiceException {
+  public boolean verifyToken(JWT token, String jwksUrl, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) throws 
TokenServiceException {
     boolean verified = false;
     try {
-      if (algorithm != null && jwksurl != null) {
+      if (algorithm != null && jwksUrl != null) {
         JWSAlgorithm expectedJWSAlg = JWSAlgorithm.parse(algorithm);
         /* Retry one time in case of failure and cache JWKS in case there is 
outage, TTL is OUTAGE_TTL */
         long outageTTL = config.getJwksOutageCacheTTL();
         long cacheTTL = config.getJwksCacheTimeToLive();
         long cacheTimeOut = config.getJwksCacheRefreshTimeout();
 
-        JWKSource<SecurityContext> jwksSource = cachedJwkSources.get(jwksurl);
+        JWKSource<SecurityContext> jwksSource = cachedJwkSources.get(jwksUrl);
 
         if(jwksSource == null) {
-          jwksSource = JWKSourceBuilder.create(new URL(jwksurl))
+          jwksSource = JWKSourceBuilder.create(new URL(jwksUrl))
                   .cache(cacheTTL, cacheTimeOut)
                   .refreshAheadCache(true)
                   .retrying(true)
                   .outageTolerant(outageTTL)
                   .build();
-            cachedJwkSources.put(jwksurl, jwksSource);
+            cachedJwkSources.put(jwksUrl, jwksSource);
         }
 
         JWSKeySelector<SecurityContext> keySelector = new 
JWSVerificationKeySelector<>(expectedJWSAlg, jwksSource);
@@ -253,15 +250,12 @@ public class DefaultTokenAuthorityService implements 
JWTokenAuthority, Service {
         // Create a JWT processor for the access tokens
         ConfigurableJWTProcessor<SecurityContext> jwtProcessor = new 
DefaultJWTProcessor<>();
         jwtProcessor.setJWSKeySelector(keySelector);
-        JWTClaimsSetVerifier<SecurityContext> claimsVerifier = new 
DefaultJWTClaimsVerifier<>();
-        jwtProcessor.setJWTClaimsSetVerifier(claimsVerifier);
-        final JOSEObjectTypeVerifier<SecurityContext> objectTypeVerifier = new 
DefaultJOSEObjectTypeVerifier<>(allowedJwsTypes);
-        /* See if we have a issuer for which we want to ignore type validation 
*/
-        
if(!config.getIssuersWithIgnoredTypeHeader().contains(token.getIssuer())) {
-          jwtProcessor.setJWSTypeVerifier(objectTypeVerifier);
-        } else {
-          /* no typ claim found in token, log and move on */
+        jwtProcessor.setJWTClaimsSetVerifier(new 
DefaultJWTClaimsVerifier<>(null, null));
+        /* See if we have an issuer for which we want to ignore type 
validation */
+        if 
(config.getIssuersWithIgnoredTypeHeader().contains(token.getIssuer())) {
           LOG.ignoreTypeHeaderVerification();
+        } else {
+          jwtProcessor.setJWSTypeVerifier(typeVerifier);
         }
 
         // Process the token
@@ -276,18 +270,18 @@ public class DefaultTokenAuthorityService implements 
JWTokenAuthority, Service {
   }
 
   @Override
-  public boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) throws TokenServiceException {
+  public boolean verifyToken(JWT token, Set<URI> jwksUrls, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) throws 
TokenServiceException {
     boolean verified = false;
-    for(final URI url : jwksurls) {
+    for(final URI url : jwksUrls) {
       try {
-        verified = this.verifyToken(token, url.toString(), algorithm, 
allowedJwsTypes);
+        verified = this.verifyToken(token, url.toString(), algorithm, 
typeVerifier);
         /* if token is verified no need to check further return result */
         if(verified) {
           return verified;
         }
       } catch (TokenServiceException e) {
         /* failed to verify token, log and move on */
-        LOG.jwksVerificationFailed(url.toString(), e.toString());
+        LOG.jwksVerificationFailed(url.toString(), e.toString(), e);
       }
     }
     return verified;
diff --git 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenAuthorityServiceMessages.java
 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenAuthorityServiceMessages.java
index 6ccc83b09..d31ecc0af 100644
--- 
a/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenAuthorityServiceMessages.java
+++ 
b/gateway-server/src/main/java/org/apache/knox/gateway/services/token/impl/TokenAuthorityServiceMessages.java
@@ -20,6 +20,7 @@ package org.apache.knox.gateway.services.token.impl;
 import org.apache.knox.gateway.i18n.messages.Message;
 import org.apache.knox.gateway.i18n.messages.MessageLevel;
 import org.apache.knox.gateway.i18n.messages.Messages;
+import org.apache.knox.gateway.i18n.messages.StackTrace;
 
 @Messages(logger = "org.apache.knox.gateway.services.token.state")
 public interface TokenAuthorityServiceMessages {
@@ -27,7 +28,7 @@ public interface TokenAuthorityServiceMessages {
   void errorGettingKid(String message);
 
   @Message(level = MessageLevel.ERROR, text = "Failed to verify token using 
JWKS endpoint {0}, reason: {1}")
-  void jwksVerificationFailed(String jwksUrl, String reason);
+  void jwksVerificationFailed(String jwksUrl, String reason, @StackTrace( 
level = MessageLevel.ERROR) Exception e);
 
   @Message(level = MessageLevel.WARN, text = "Ignoring typ header verification 
for token")
   void ignoreTypeHeaderVerification();
diff --git 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JWKSourceBuilderTest.java
 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JWKSourceBuilderTest.java
index 01dc6ca41..8dfe3b6b5 100644
--- 
a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JWKSourceBuilderTest.java
+++ 
b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/JWKSourceBuilderTest.java
@@ -18,6 +18,9 @@
 package org.apache.knox.gateway.services.token.impl;
 
 import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jose.proc.DefaultJOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.JOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.SecurityContext;
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.KeystoreService;
@@ -28,7 +31,6 @@ import org.junit.Test;
 
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Set;
 
 import static org.junit.Assert.assertTrue;
@@ -74,12 +76,11 @@ public class JWKSourceBuilderTest {
         // Define the JWK URL and algorithm
         String jwksUrl = "https://example.com/.well-known/jwks.json";;
         String algorithm = "RS256";
-        Set<JOSEObjectType> allowedJwsTypes = new HashSet<>();
-        allowedJwsTypes.add(JOSEObjectType.JWT);
+        final JOSEObjectTypeVerifier<SecurityContext> typeVerifier = new 
DefaultJOSEObjectTypeVerifier<>(Set.of(JOSEObjectType.JWT));
         try {
             // This will throw an exception because the URL doesn't exist, but 
we're only
             // interested in verifying that the correct parameters are passed 
to JWKSourceBuilder
-            service.verifyToken(token, jwksUrl, algorithm, allowedJwsTypes);
+            service.verifyToken(token, jwksUrl, algorithm, typeVerifier);
             fail("Expected TokenServiceException");
         } catch (TokenServiceException e) {
             // Expected exception because the URL doesn't exist
diff --git 
a/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java
 
b/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java
index 6856120a2..16e676240 100644
--- 
a/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java
+++ 
b/gateway-service-knoxsso/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOResource.java
@@ -46,6 +46,7 @@ import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.Response;
 
+import com.nimbusds.jose.JOSEObjectType;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.knox.gateway.audit.log4j.audit.Log4jAuditor;
 import org.apache.knox.gateway.config.GatewayConfig;
@@ -80,6 +81,7 @@ public class WebSSOResource {
   private static final String SSO_COOKIE_DOMAIN_SUFFIX_PARAM = 
"knoxsso.cookie.domain.suffix";
   private static final String SSO_COOKIE_SAMESITE_PARAM = 
"knoxsso.cookie.samesite";
   private static final String SSO_COOKIE_TOKEN_TTL_PARAM = "knoxsso.token.ttl";
+  private static final String SSO_COOKIE_TOKEN_TYPE_PARAM = 
"knoxsso.token.type";
   private static final String SSO_COOKIE_TOKEN_AUDIENCES_PARAM = 
"knoxsso.token.audiences";
   private static final String SSO_COOKIE_TOKEN_SIG_ALG = 
"knoxsso.token.sigalg";
   private static final String SSO_COOKIE_TOKEN_WHITELIST_PARAM = 
"knoxsso.redirect.whitelist.regex";
@@ -103,6 +105,7 @@ public class WebSSOResource {
   private boolean secureOnly = true;
   private int maxAge = -1;
   private long tokenTTL = TOKEN_TTL_DEFAULT;
+  private String tokenType;
   private String whitelist;
   private String domainSuffix;
   private List<String> targetAudiences = new ArrayList<>();
@@ -219,6 +222,8 @@ public class WebSSOResource {
         LOGGER.invalidTokenTTLEncountered(ttl);
       }
     }
+    final String configuredTokenType = 
context.getInitParameter(SSO_COOKIE_TOKEN_TYPE_PARAM);
+    tokenType = StringUtils.isBlank(configuredTokenType) ? 
JOSEObjectType.JWT.getType() : configuredTokenType;
   }
 
   @GET
@@ -308,6 +313,7 @@ public class WebSSOResource {
               .setSigningKeystoreAlias(signingKeystoreAlias)
               .setSigningKeystorePassphrase(signingKeystorePassphrase)
               .setManaged(tokenStateService != null)
+              .setType(tokenType)
               .build();
       JWT token = tokenAuthority.issueToken(jwtAttributes);
 
diff --git 
a/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java
 
b/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java
index 5cee80579..f0e119478 100644
--- 
a/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java
+++ 
b/gateway-service-knoxsso/src/test/java/org/apache/knox/gateway/service/knoxsso/WebSSOResourceTest.java
@@ -53,6 +53,8 @@ import javax.servlet.http.HttpServletResponseWrapper;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
 
+import com.nimbusds.jose.proc.JOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.SecurityContext;
 import org.apache.http.HttpStatus;
 import org.apache.knox.gateway.audit.log4j.audit.Log4jAuditor;
 import org.apache.knox.gateway.config.GatewayConfig;
@@ -72,7 +74,6 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JOSEObjectType;
 import com.nimbusds.jose.JWSSigner;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.KeyLengthException;
@@ -931,12 +932,12 @@ public class WebSSOResourceTest {
     }
 
     @Override
-    public boolean verifyToken(JWT token, String jwksurl, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) {
+    public boolean verifyToken(JWT token, String jwksurl, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) {
      return false;
     }
 
     @Override
-    public boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) throws TokenServiceException {
+    public boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) {
       return false;
     }
   }
diff --git 
a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
 
b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
index 66e89580f..9687eed06 100644
--- 
a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
+++ 
b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/TokenServiceResourceTest.java
@@ -76,13 +76,14 @@ import javax.ws.rs.core.UriInfo;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.nimbusds.jose.JOSEObjectType;
 import com.nimbusds.jose.JWSAlgorithm;
 import com.nimbusds.jose.JWSSigner;
 import com.nimbusds.jose.JWSVerifier;
 import com.nimbusds.jose.KeyLengthException;
 import com.nimbusds.jose.crypto.RSASSASigner;
 import com.nimbusds.jose.crypto.RSASSAVerifier;
+import com.nimbusds.jose.proc.JOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.SecurityContext;
 import de.thetaphi.forbiddenapis.SuppressForbidden;
 import org.apache.commons.codec.digest.HmacAlgorithms;
 import org.apache.commons.lang3.StringUtils;
@@ -2025,12 +2026,12 @@ public class TokenServiceResourceTest {
     }
 
     @Override
-    public boolean verifyToken(JWT token, String jwksurl, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) {
+    public boolean verifyToken(JWT token, String jwksurl, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) {
      return false;
     }
 
     @Override
-    public boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) throws TokenServiceException {
+    public boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) throws 
TokenServiceException {
       return false;
     }
   }
diff --git 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAuthority.java
 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAuthority.java
index 7c1e503c6..71d9a1321 100644
--- 
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAuthority.java
+++ 
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAuthority.java
@@ -21,10 +21,10 @@ import java.net.URI;
 import java.security.interfaces.RSAPublicKey;
 import java.util.Set;
 
+import com.nimbusds.jose.proc.JOSEObjectTypeVerifier;
+import com.nimbusds.jose.proc.SecurityContext;
 import org.apache.knox.gateway.services.security.token.impl.JWT;
 
-import com.nimbusds.jose.JOSEObjectType;
-
 public interface JWTokenAuthority {
 
   JWT issueToken(JWTokenAttributes jwtAttributes) throws TokenServiceException;
@@ -33,8 +33,8 @@ public interface JWTokenAuthority {
 
   boolean verifyToken(JWT token, RSAPublicKey publicKey) throws 
TokenServiceException;
 
-  boolean verifyToken(JWT token, String jwksurl, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) throws TokenServiceException;
+  boolean verifyToken(JWT token, String jwksUrl, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) throws 
TokenServiceException;
 
-  boolean verifyToken(JWT token, Set<URI> jwksurls, String algorithm, 
Set<JOSEObjectType> allowedJwsTypes) throws TokenServiceException;
+  boolean verifyToken(JWT token, Set<URI> jwksUrls, String algorithm, 
JOSEObjectTypeVerifier<SecurityContext> typeVerifier) throws 
TokenServiceException;
 
 }

Reply via email to