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;
}