You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by sm...@apache.org on 2022/04/13 19:39:35 UTC
[knox] branch master updated: KNOX-2731 Allow group membership information to be included in issued JWTs (#554)
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 c4699b994 KNOX-2731 Allow group membership information to be included in issued JWTs (#554)
c4699b994 is described below
commit c4699b994f5d020c6613970595f8b4048d892426
Author: Attila Magyar <m....@gmail.com>
AuthorDate: Wed Apr 13 21:39:31 2022 +0200
KNOX-2731 Allow group membership information to be included in issued JWTs (#554)
---
.../token/impl/DefaultTokenAuthorityService.java | 52 +++---
.../token/impl/DefaultTokenStateServiceTest.java | 12 +-
.../service/knoxsso/WebSSOResourceTest.java | 76 ++++-----
.../gateway/service/knoxtoken/TokenResource.java | 68 ++++++--
.../service/knoxtoken/JWKSResourceTest.java | 4 +-
.../knoxtoken/TokenServiceResourceTest.java | 187 +++++++++++++++------
.../services/security/token/JWTokenAttributes.java | 44 ++++-
.../security/token/JWTokenAttributesBuilder.java | 25 ++-
.../services/security/token/impl/JWTToken.java | 74 +++-----
.../services/security/token/impl/JWTTokenTest.java | 105 ++----------
10 files changed, 340 insertions(+), 307 deletions(-)
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 6ab734269..275e2ec97 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
@@ -36,23 +36,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import org.apache.knox.gateway.GatewayResources;
-import org.apache.knox.gateway.config.GatewayConfig;
-import org.apache.knox.gateway.i18n.messages.MessagesFactory;
-import org.apache.knox.gateway.i18n.resources.ResourcesFactory;
-import org.apache.knox.gateway.services.Service;
-import org.apache.knox.gateway.services.ServiceLifecycleException;
-import org.apache.knox.gateway.services.security.AliasService;
-import org.apache.knox.gateway.services.security.AliasServiceException;
-import org.apache.knox.gateway.services.security.KeystoreService;
-import org.apache.knox.gateway.services.security.KeystoreServiceException;
-import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
-import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
-import org.apache.knox.gateway.services.security.token.TokenServiceException;
-import org.apache.knox.gateway.services.security.token.TokenUtils;
-import org.apache.knox.gateway.services.security.token.impl.JWT;
-import org.apache.knox.gateway.services.security.token.impl.JWTToken;
-
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
@@ -75,6 +58,22 @@ 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;
+import org.apache.knox.gateway.i18n.resources.ResourcesFactory;
+import org.apache.knox.gateway.services.Service;
+import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.gateway.services.security.AliasServiceException;
+import org.apache.knox.gateway.services.security.KeystoreService;
+import org.apache.knox.gateway.services.security.KeystoreServiceException;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
+import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
+import org.apache.knox.gateway.services.security.token.TokenServiceException;
+import org.apache.knox.gateway.services.security.token.TokenUtils;
+import org.apache.knox.gateway.services.security.token.impl.JWT;
+import org.apache.knox.gateway.services.security.token.impl.JWTToken;
public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
private static final GatewayResources RESOURCES = ResourcesFactory.get(GatewayResources.class);
@@ -104,26 +103,15 @@ public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
@Override
public JWT issueToken(JWTokenAttributes jwtAttributes) throws TokenServiceException {
- String[] claimArray = new String[6];
- claimArray[0] = "KNOXSSO";
- claimArray[1] = jwtAttributes.getUserName();
- claimArray[2] = null;
- if (jwtAttributes.getExpires() == -1) {
- claimArray[3] = null;
- }
- else {
- claimArray[3] = String.valueOf(jwtAttributes.getExpires());
- }
final String algorithm = jwtAttributes.getAlgorithm();
if(SUPPORTED_HMAC_SIG_ALGS.contains(algorithm)) {
- claimArray[4] = null;
- claimArray[5] = null;
+ jwtAttributes.setKid(null);
+ jwtAttributes.setJku(null);
} else {
- claimArray[4] = cachedSigningKeyID.isPresent() ? cachedSigningKeyID.get() : null;
- claimArray[5] = jwtAttributes.getJku();
+ jwtAttributes.setKid(cachedSigningKeyID.isPresent() ? cachedSigningKeyID.get() : null);
}
final JWT token = SUPPORTED_PKI_SIG_ALGS.contains(algorithm) || SUPPORTED_HMAC_SIG_ALGS.contains(algorithm)
- ? new JWTToken(algorithm, claimArray, jwtAttributes.getAudiences(), jwtAttributes.isManaged(), jwtAttributes.getType())
+ ? new JWTToken(jwtAttributes)
: null;
if (token != null) {
if (SUPPORTED_HMAC_SIG_ALGS.contains(algorithm)) {
diff --git a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateServiceTest.java b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateServiceTest.java
index ab9103c52..419d077c6 100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateServiceTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenStateServiceTest.java
@@ -37,6 +37,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
import org.apache.knox.gateway.services.security.token.TokenMetadata;
import org.apache.knox.gateway.services.security.token.TokenStateService;
import org.apache.knox.gateway.services.security.token.TokenUtils;
@@ -369,16 +370,7 @@ public class DefaultTokenStateServiceTest {
/* create a test JWT token */
protected JWT getJWTToken(final long expiry) {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "https://login.example.com";
- if(expiry > 0) {
- claims[3] = Long.toString(expiry);
- }
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- JWT token = new JWTToken("RS256", claims);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setExpires(expiry).setAlgorithm("RS256").build());
// Sign the token
JWSSigner signer = new RSASSASigner(privateKey);
token.sign(signer);
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 be85e7648..407813a21 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
@@ -17,6 +17,37 @@
*/
package org.apache.knox.gateway.service.knoxsso;
+import static org.apache.knox.gateway.services.GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.net.HttpCookie;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Principal;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSSigner;
@@ -44,37 +75,6 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
-import java.lang.reflect.Field;
-import java.net.HttpCookie;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.Principal;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.knox.gateway.services.GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
/**
* Some tests for the Knox SSO service.
*/
@@ -770,19 +770,7 @@ public class WebSSOResourceTest {
@Override
public JWT issueToken(JWTokenAttributes jwtAttributes)
throws TokenServiceException {
- String[] claimArray = new String[6];
- claimArray[0] = "KNOXSSO";
- claimArray[1] = jwtAttributes.getUserName();
- claimArray[2] = null;
- if (jwtAttributes.getExpires() == -1) {
- claimArray[3] = null;
- } else {
- claimArray[3] = String.valueOf(jwtAttributes.getExpires());
- }
- claimArray[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claimArray[5] = null;
-
- JWT token = new JWTToken(jwtAttributes.getAlgorithm(), claimArray, jwtAttributes.getAudiences());
+ JWT token = new JWTToken(jwtAttributes);
try {
JWSSigner signer = useHMAC ? new MACSigner(HMAC_SECRET)
: new RSASSASigner(getPrivateKey(jwtAttributes.getSigningKeystoreName(), jwtAttributes.getSigningKeystoreAlias(), jwtAttributes.getSigningKeystorePassphrase()));
diff --git a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
index 2d227cd9a..375e12e8c 100644
--- a/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
+++ b/gateway-service-knoxtoken/src/main/java/org/apache/knox/gateway/service/knoxtoken/TokenResource.java
@@ -18,6 +18,7 @@
package org.apache.knox.gateway.service.knoxtoken;
import java.nio.charset.StandardCharsets;
+import java.security.AccessController;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
@@ -34,11 +35,14 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
+import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
+import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.inject.Singleton;
+import javax.security.auth.Subject;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
@@ -62,6 +66,7 @@ import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.security.GroupPrincipal;
import org.apache.knox.gateway.security.SubjectUtils;
import org.apache.knox.gateway.services.ServiceType;
import org.apache.knox.gateway.services.GatewayServices;
@@ -103,27 +108,29 @@ public class TokenResource {
private static final String TARGET_URL = "target_url";
private static final String ENDPOINT_PUBLIC_CERT = "endpoint_public_cert";
private static final String BEARER = "Bearer";
- private static final String TOKEN_TTL_PARAM = "knox.token.ttl";
- private static final String TOKEN_TYPE_PARAM = "knox.token.type";
- private static final String TOKEN_AUDIENCES_PARAM = "knox.token.audiences";
- private static final String TOKEN_TARGET_URL = "knox.token.target.url";
- static final String TOKEN_CLIENT_DATA = "knox.token.client.data";
- private static final String TOKEN_CLIENT_CERT_REQUIRED = "knox.token.client.cert.required";
- private static final String TOKEN_ALLOWED_PRINCIPALS = "knox.token.allowed.principals";
- private static final String TOKEN_SIG_ALG = "knox.token.sigalg";
- private static final String TOKEN_EXP_RENEWAL_INTERVAL = "knox.token.exp.renew-interval";
- private static final String TOKEN_EXP_RENEWAL_MAX_LIFETIME = "knox.token.exp.max-lifetime";
- private static final String TOKEN_EXP_TOKENGEN_ALLOWED_TSS_BACKENDS = "knox.token.exp.tokengen.allowed.tss.backends";
- private static final String TOKEN_RENEWER_WHITELIST = "knox.token.renewer.whitelist";
+ private static final String TOKEN_PARAM_PREFIX = "knox.token.";
+ private static final String TOKEN_TTL_PARAM = TOKEN_PARAM_PREFIX + "ttl";
+ private static final String TOKEN_TYPE_PARAM = TOKEN_PARAM_PREFIX + "type";
+ private static final String TOKEN_AUDIENCES_PARAM = TOKEN_PARAM_PREFIX + "audiences";
+ public static final String TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED = TOKEN_PARAM_PREFIX + "include.groups.allowed";
+ private static final String TOKEN_TARGET_URL = TOKEN_PARAM_PREFIX + "target.url";
+ static final String TOKEN_CLIENT_DATA = TOKEN_PARAM_PREFIX + "client.data";
+ private static final String TOKEN_CLIENT_CERT_REQUIRED = TOKEN_PARAM_PREFIX + "client.cert.required";
+ private static final String TOKEN_ALLOWED_PRINCIPALS = TOKEN_PARAM_PREFIX + "allowed.principals";
+ private static final String TOKEN_SIG_ALG = TOKEN_PARAM_PREFIX + "sigalg";
+ private static final String TOKEN_EXP_RENEWAL_INTERVAL = TOKEN_PARAM_PREFIX + "exp.renew-interval";
+ private static final String TOKEN_EXP_RENEWAL_MAX_LIFETIME = TOKEN_PARAM_PREFIX + "exp.max-lifetime";
+ private static final String TOKEN_EXP_TOKENGEN_ALLOWED_TSS_BACKENDS = TOKEN_PARAM_PREFIX + "exp.tokengen.allowed.tss.backends";
+ private static final String TOKEN_RENEWER_WHITELIST = TOKEN_PARAM_PREFIX + "renewer.whitelist";
private static final String TSS_STATUS_IS_MANAGEMENT_ENABLED = "tokenManagementEnabled";
private static final String TSS_STATUS_CONFIFURED_BACKEND = "configuredTssBackend";
private static final String TSS_STATUS_ACTUAL_BACKEND = "actualTssBackend";
private static final String TSS_ALLOWED_BACKEND_FOR_TOKENGEN = "allowedTssForTokengen";
private static final String TSS_MAXIMUM_LIFETIME_SECONDS = "maximumLifetimeSeconds";
private static final String TSS_MAXIMUM_LIFETIME_TEXT = "maximumLifetimeText";
- private static final String LIFESPAN_INPUT_ENABLED_PARAM = "knox.token.lifespan.input.enabled";
+ private static final String LIFESPAN_INPUT_ENABLED_PARAM = TOKEN_PARAM_PREFIX + "lifespan.input.enabled";
private static final String LIFESPAN_INPUT_ENABLED_TEXT = "lifespanInputEnabled";
- static final String KNOX_TOKEN_USER_LIMIT_EXCEEDED_ACTION = "knox.token.user.limit.exceeded.action";
+ static final String KNOX_TOKEN_USER_LIMIT_EXCEEDED_ACTION = TOKEN_PARAM_PREFIX + "user.limit.exceeded.action";
private static final String METADATA_QUERY_PARAM_PREFIX = "md_";
private static final long TOKEN_TTL_DEFAULT = 30000L;
static final String TOKEN_API_PATH = "knoxtoken/api/v1";
@@ -134,9 +141,10 @@ public class TokenResource {
static final String REVOKE_PATH = "/revoke";
static final String ENABLE_PATH = "/enable";
static final String DISABLE_PATH = "/disable";
- private static final String TARGET_ENDPOINT_PULIC_CERT_PEM = "knox.token.target.endpoint.cert.pem";
+ private static final String TARGET_ENDPOINT_PULIC_CERT_PEM = TOKEN_PARAM_PREFIX + "target.endpoint.cert.pem";
static final String QUERY_PARAMETER_DOAS = "doAs";
- static final String PROXYUSER_PREFIX = "knox.token.proxyuser";
+ static final String PROXYUSER_PREFIX = TOKEN_PARAM_PREFIX + "proxyuser";
+ public static final String KNOX_TOKEN_INCLUDE_GROUPS = TOKEN_PARAM_PREFIX + "include.groups";
private static TokenServiceMessages log = MessagesFactory.get(TokenServiceMessages.class);
private long tokenTTL = TOKEN_TTL_DEFAULT;
@@ -160,6 +168,7 @@ public class TokenResource {
private Optional<Long> maxTokenLifetime = Optional.empty();
private int tokenLimitPerUser;
+ private boolean includeGroupsInTokenAllowed;
enum UserLimitExceededAction {REMOVE_OLDEST, RETURN_ERROR};
private UserLimitExceededAction userLimitExceededAction = UserLimitExceededAction.RETURN_ERROR;
@@ -228,6 +237,11 @@ public class TokenResource {
}
}
+ String includeGroupsInTokenAllowedParam = context.getInitParameter(TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED);
+ includeGroupsInTokenAllowed = includeGroupsInTokenAllowedParam == null
+ ? true
+ : Boolean.parseBoolean(includeGroupsInTokenAllowedParam);
+
this.tokenType = context.getInitParameter(TOKEN_TYPE_PARAM);
tokenTTLAsText = getTokenTTLAsText();
@@ -756,6 +770,16 @@ public class TokenResource {
if (!targetAudiences.isEmpty()) {
jwtAttributesBuilder.setAudiences(targetAudiences);
}
+ if (shouldIncludeGroups()) {
+ if (includeGroupsInTokenAllowed) {
+ jwtAttributesBuilder.setGroups(groups());
+ } else {
+ return Response
+ .status(Response.Status.BAD_REQUEST)
+ .entity("{\n \"error\": \"Including group information in tokens is disabled\"\n}\n")
+ .build();
+ }
+ }
jwtAttributes = jwtAttributesBuilder.build();
token = ts.issueToken(jwtAttributes);
@@ -813,6 +837,18 @@ public class TokenResource {
return Response.ok().entity("{ \"Unable to acquire token.\" }").build();
}
+ private boolean shouldIncludeGroups() {
+ return Boolean.parseBoolean(request.getParameter(KNOX_TOKEN_INCLUDE_GROUPS));
+ }
+
+ protected Set<String> groups() {
+ Subject subject = Subject.getSubject(AccessController.getContext());
+ Set<String> groups = subject.getPrincipals(GroupPrincipal.class).stream()
+ .map(GroupPrincipal::getName)
+ .collect(Collectors.toSet());
+ return groups;
+ }
+
private void addArbitraryTokenMetadata(TokenMetadata tokenMetadata) {
final Enumeration<String> paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
diff --git a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java
index 27963ab24..966ca8554 100644
--- a/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java
+++ b/gateway-service-knoxtoken/src/test/java/org/apache/knox/gateway/service/knoxtoken/JWKSResourceTest.java
@@ -37,6 +37,7 @@ import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.ServiceType;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.KeystoreService;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
import org.apache.knox.gateway.services.security.token.impl.JWT;
import org.apache.knox.gateway.services.security.token.impl.JWTToken;
import org.easymock.EasyMock;
@@ -141,8 +142,7 @@ public class JWKSResourceTest {
claimArray[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
claimArray[5] = null;
- final JWT token = new JWTToken(algorithm, claimArray,
- Collections.singletonList("aud"), false);
+ final JWT token = new JWTToken(new JWTokenAttributesBuilder().setAlgorithm(algorithm).setAudiences(Collections.singletonList("aud")).setManaged(false).build());
final JWSSigner signer = new RSASSASigner(privateKey, true);
token.sign(signer);
return token;
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 a44310667..49b8772ae 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
@@ -20,6 +20,8 @@ package org.apache.knox.gateway.service.knoxtoken;
import static org.apache.knox.gateway.config.impl.GatewayConfigImpl.KNOX_TOKEN_USER_LIMIT;
import static org.apache.knox.gateway.config.impl.GatewayConfigImpl.KNOX_TOKEN_USER_LIMIT_DEFAULT;
import static org.apache.knox.gateway.service.knoxtoken.TokenResource.KNOX_TOKEN_USER_LIMIT_EXCEEDED_ACTION;
+import static org.apache.knox.gateway.service.knoxtoken.TokenResource.TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED;
+import static org.apache.knox.gateway.services.security.token.impl.JWTToken.KNOX_GROUPS_CLAIM;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -27,6 +29,44 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.function.Predicate;
+import javax.security.auth.Subject;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.JOSEObjectType;
@@ -36,14 +76,13 @@ import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.KeyLengthException;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
-
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.lang3.StringUtils;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.ServiceLifecycleException;
import org.apache.knox.gateway.services.ServiceType;
-import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
@@ -62,44 +101,6 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
-import javax.security.auth.Subject;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.MultivaluedHashMap;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import java.io.IOException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.TreeSet;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.function.Predicate;
-
/**
* Some tests for the token service
*/
@@ -159,6 +160,9 @@ public class TokenServiceResourceTest {
if (contextExpectations.containsKey(TokenResource.LIFESPAN)) {
EasyMock.expect(request.getParameter(TokenResource.LIFESPAN)).andReturn(contextExpectations.get(TokenResource.LIFESPAN)).anyTimes();
}
+ if (contextExpectations.containsKey(TokenResource.KNOX_TOKEN_INCLUDE_GROUPS)) {
+ EasyMock.expect(request.getParameter(TokenResource.KNOX_TOKEN_INCLUDE_GROUPS)).andReturn(contextExpectations.get(TokenResource.KNOX_TOKEN_INCLUDE_GROUPS)).anyTimes();
+ }
if (contextExpectations.containsKey(TokenResource.QUERY_PARAMETER_DOAS)) {
EasyMock.expect(request.getParameter(TokenResource.QUERY_PARAMETER_DOAS)).andReturn(contextExpectations.get(TokenResource.QUERY_PARAMETER_DOAS)).anyTimes();
}
@@ -653,8 +657,8 @@ public class TokenServiceResourceTest {
validateSuccessfulRenewalResponse(renewalResponse);
String responseContent = (String) renewalResponse.getEntity();
assertNotNull(responseContent);
- Map<String, String> json = parseJSONResponse(responseContent);
- assertTrue(Boolean.parseBoolean(json.get("renewed")));
+ Map<String, Object> json = parseJSONResponse(responseContent);
+ assertTrue(Boolean.parseBoolean((String)json.get("renewed")));
assertNotNull(json.get("expires")); // Should get back the original expiration from the token itself
}
@@ -670,8 +674,8 @@ public class TokenServiceResourceTest {
validateSuccessfulRenewalResponse(renewalResponse);
String responseContent = (String) renewalResponse.getEntity();
assertNotNull(responseContent);
- Map<String, String> json = parseJSONResponse(responseContent);
- assertTrue(Boolean.parseBoolean(json.get("renewed")));
+ Map<String, Object> json = parseJSONResponse(responseContent);
+ assertTrue(Boolean.parseBoolean((String)json.get("renewed")));
assertNotNull(json.get("expires")); // Should get back the original expiration from the token itself
}
@@ -687,8 +691,8 @@ public class TokenServiceResourceTest {
validateSuccessfulRenewalResponse(renewalResponse);
String responseContent = (String) renewalResponse.getEntity();
assertNotNull(responseContent);
- Map<String, String> json = parseJSONResponse(responseContent);
- assertTrue(Boolean.parseBoolean(json.get("renewed")));
+ Map<String, Object> json = parseJSONResponse(responseContent);
+ assertTrue(Boolean.parseBoolean((String)json.get("renewed")));
assertNotNull(json.get("expires")); // Should get back the original expiration from the token itself
}
@@ -1117,6 +1121,78 @@ public class TokenServiceResourceTest {
assertEquals(metadata.get("userName"), impersonatedUser);
}
+ @Test
+ public void testGroupsAddedToToken() throws Exception {
+ Set<String> groups = new HashSet<>(Arrays.asList("group1", "group2"));
+ Map<String, String> contextExpectations = new HashMap<>();
+ contextExpectations.put(TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED, "true");
+ contextExpectations.put(TokenResource.KNOX_TOKEN_INCLUDE_GROUPS, "true");
+ configureCommonExpectations(contextExpectations, Boolean.TRUE);
+
+ TokenResource tr = new TokenResource() {
+ @Override
+ protected Set<String> groups() {
+ return groups;
+ }
+ };
+ tr.request = request;
+ tr.context = context;
+ tr.init();
+
+ Response response = tr.doGet();
+ assertEquals(200, response.getStatus());
+
+ String accessToken = getTagValue(response.getEntity().toString(), "access_token");
+ Map<String, Object> payload = parseJSONResponse(JWTToken.parseToken(accessToken).getPayload());
+ assertEquals(new ArrayList<>(groups), payload.get(KNOX_GROUPS_CLAIM));
+ }
+
+ @Test
+ public void testNoGroupsAddedToTokenByDefault() throws Exception {
+ Map<String, String> contextExpectations = new HashMap<>();
+ contextExpectations.put(TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED, "true");
+ configureCommonExpectations(contextExpectations, Boolean.TRUE);
+
+ TokenResource tr = new TokenResource() {
+ @Override
+ protected Set<String> groups() {
+ return new HashSet<>(Arrays.asList("group1", "group2"));
+ }
+ };
+ tr.request = request;
+ tr.context = context;
+ tr.init();
+
+ Response response = tr.doGet();
+ assertEquals(200, response.getStatus());
+
+ String accessToken = getTagValue(response.getEntity().toString(), "access_token");
+ Map<String, Object> payload = parseJSONResponse(JWTToken.parseToken(accessToken).getPayload());
+ assertFalse(payload.containsKey(KNOX_GROUPS_CLAIM));
+ }
+
+ @Test
+ public void testBadRequestWhenGroupsAreRequestedToBeIncludedInTokenButItIsDisabledByServer() throws Exception {
+ Set<String> groups = new HashSet<>(Arrays.asList("group1", "group2"));
+ Map<String, String> contextExpectations = new HashMap<>();
+ contextExpectations.put(TOKEN_INCLUDE_GROUPS_IN_JWT_ALLOWED, "false");
+ contextExpectations.put(TokenResource.KNOX_TOKEN_INCLUDE_GROUPS, "true");
+ configureCommonExpectations(contextExpectations, Boolean.TRUE);
+
+ TokenResource tr = new TokenResource() {
+ @Override
+ protected Set<String> groups() {
+ return groups;
+ }
+ };
+ tr.request = request;
+ tr.context = context;
+ tr.init();
+
+ Response response = tr.doGet();
+ assertEquals(400, response.getStatus());
+ }
+
/**
*
* @param isTokenStateServerManaged true, if server-side token state management should be enabled; Otherwise, false or null.
@@ -1332,12 +1408,12 @@ public class TokenServiceResourceTest {
String responseContent = (String) response.getEntity();
assertNotNull(responseContent);
assertFalse(responseContent.isEmpty());
- Map<String, String> json = parseJSONResponse(responseContent);
- boolean result = Boolean.valueOf(json.get("renewed"));
+ Map<String, Object> json = parseJSONResponse(responseContent);
+ boolean result = Boolean.valueOf((String)json.get("renewed"));
assertEquals(expectedResult, result);
assertEquals(expectedMessage, json.get("error"));
if (expectedCode != null) {
- assertEquals(expectedCode.toInt(), Integer.parseInt(json.get("code")));
+ assertEquals(expectedCode.toInt(), json.get("code"));
}
}
@@ -1355,12 +1431,12 @@ public class TokenServiceResourceTest {
String responseContent = (String) response.getEntity();
assertNotNull(responseContent);
assertFalse(responseContent.isEmpty());
- Map<String, String> json = parseJSONResponse(responseContent);
- boolean result = Boolean.valueOf(json.get("revoked"));
+ Map<String, Object> json = parseJSONResponse(responseContent);
+ boolean result = Boolean.valueOf((String)json.get("revoked"));
assertEquals(expectedResult, result);
assertEquals(expectedMessage, json.get("error"));
if (expectedCode != null) {
- assertEquals(expectedCode.toInt(), Integer.parseInt(json.get("code")));
+ assertEquals(expectedCode.toInt(), json.get("code"));
}
}
@@ -1396,8 +1472,8 @@ public class TokenServiceResourceTest {
return s;
}
- private static Map<String, String> parseJSONResponse(final String response) throws IOException {
- return (new ObjectMapper()).readValue(response, new TypeReference<Map<String, String>>(){});
+ private static Map<String, Object> parseJSONResponse(final String response) throws IOException {
+ return (new ObjectMapper()).readValue(response, new TypeReference<Map<String, Object>>(){});
}
@@ -1583,7 +1659,8 @@ public class TokenServiceResourceTest {
claimArray[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
claimArray[5] = jwtAttributes.getJku();
- JWT token = new JWTToken(jwtAttributes.getAlgorithm(), claimArray, jwtAttributes.getAudiences());
+ jwtAttributes.setKid("E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA");
+ JWT token = new JWTToken(jwtAttributes);
JWSSigner signer = new RSASSASigner(privateKey);
token.sign(signer);
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributes.java b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributes.java
index b7e7a82aa..a644c0a1f 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributes.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributes.java
@@ -17,10 +17,13 @@
*/
package org.apache.knox.gateway.services.security.token;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
import java.util.List;
+import java.util.Set;
public class JWTokenAttributes {
-
private final String userName;
private final List<String> audiences;
private final String algorithm;
@@ -29,11 +32,14 @@ public class JWTokenAttributes {
private final String signingKeystoreAlias;
private final char[] signingKeystorePassphrase;
private final boolean managed;
- private final String jku;
+ private String jku;
private final String type;
+ private final Set<String> groups;
+ private final String issuer;
+ private String kid;
JWTokenAttributes(String userName, List<String> audiences, String algorithm, long expires, String signingKeystoreName, String signingKeystoreAlias,
- char[] signingKeystorePassphrase, boolean managed, String jku, String type) {
+ char[] signingKeystorePassphrase, boolean managed, String jku, String type, Set<String> groups, String kid, String issuer) {
this.userName = userName;
this.audiences = audiences;
this.algorithm = algorithm;
@@ -44,6 +50,9 @@ public class JWTokenAttributes {
this.managed = managed;
this.jku = jku;
this.type = type;
+ this.groups = groups;
+ this.kid = kid;
+ this.issuer = issuer;
}
public String getUserName() {
@@ -62,6 +71,10 @@ public class JWTokenAttributes {
return expires;
}
+ public Date getExpiresDate() {
+ return expires == -1 ? null : new Date(expires);
+ }
+
public String getSigningKeystoreName() {
return signingKeystoreName;
}
@@ -78,12 +91,35 @@ public class JWTokenAttributes {
return managed;
}
- public String getJku() {
+ public URI getJkuUri() throws URISyntaxException {
+ return jku != null ? new URI(jku) : null;
+ }
+
+ public String getJku(){
return jku;
}
+ public void setJku(String jku) {
+ this.jku = jku;
+ }
+
public String getType() {
return type;
}
+ public Set<String> getGroups() {
+ return groups;
+ }
+
+ public void setKid(String kid) {
+ this.kid = kid;
+ }
+
+ public String getKid() {
+ return kid;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
}
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributesBuilder.java b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributesBuilder.java
index faf4bf362..4d86ff48a 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributesBuilder.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributesBuilder.java
@@ -17,8 +17,10 @@
*/
package org.apache.knox.gateway.services.security.token;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
public class JWTokenAttributesBuilder {
@@ -32,6 +34,9 @@ public class JWTokenAttributesBuilder {
private boolean managed;
private String jku;
private String type;
+ private Set<String> groups;
+ private String kid;
+ private String issuer = "KNOXSSO";
public JWTokenAttributesBuilder setUserName(String userName) {
this.userName = userName;
@@ -87,9 +92,23 @@ public class JWTokenAttributesBuilder {
return this;
}
- public JWTokenAttributes build() {
- return new JWTokenAttributes(userName, (audiences == null ? Collections.emptyList() : audiences), algorithm, expires, signingKeystoreName, signingKeystoreAlias,
- signingKeystorePassphrase, managed, jku, type);
+ public JWTokenAttributesBuilder setGroups(Set<String> groups) {
+ this.groups = groups;
+ return this;
+ }
+
+ public JWTokenAttributesBuilder setKid(String kid) {
+ this.kid = kid;
+ return this;
}
+ public JWTokenAttributesBuilder setIssuer(String issuer) {
+ this.issuer = issuer;
+ return this;
+ }
+
+ public JWTokenAttributes build() {
+ return new JWTokenAttributes(userName, (audiences == null ? new ArrayList<>() : audiences), algorithm, expires, signingKeystoreName, signingKeystoreAlias,
+ signingKeystorePassphrase, managed, jku, type, groups, kid, issuer);
+ }
}
diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java
index 281bed24f..7920bfcf5 100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java
@@ -16,16 +16,11 @@
*/
package org.apache.knox.gateway.services.security.token.impl;
-import java.net.URI;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.Date;
-import java.util.ArrayList;
-import java.util.List;
import java.util.UUID;
-import org.apache.knox.gateway.i18n.messages.MessagesFactory;
-
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
@@ -36,6 +31,8 @@ import com.nimbusds.jose.Payload;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
public class JWTToken implements JWT {
private static JWTProviderMessages log = MessagesFactory.get( JWTProviderMessages.class );
@@ -44,6 +41,7 @@ public class JWTToken implements JWT {
public static final String MANAGED_TOKEN_CLAIM = "managed.token";
public static final String KNOX_KID_CLAIM = "kid";
public static final String KNOX_JKU_CLAIM = "jku";
+ public static final String KNOX_GROUPS_CLAIM = "knox.groups";
SignedJWT jwt;
@@ -60,79 +58,53 @@ public class JWTToken implements JWT {
}
}
- public JWTToken(String alg, String[] claimsArray) {
- this(alg, claimsArray, null);
- }
-
- public JWTToken(String alg, String[] claimsArray, List<String> audiences) {
- this(alg, claimsArray, audiences, false);
- }
-
- public JWTToken(String alg, String[] claimsArray, List<String> audiences, boolean managed) {
- this(alg, claimsArray, audiences, managed, null);
- }
-
- public JWTToken(String alg, String[] claimsArray, List<String> audiences, boolean managed, String type) {
- if(claimsArray == null) {
- log.missingClaims(-1);
- } else if (claimsArray.length < 6){
- log.missingClaims(claimsArray.length);
- }
-
+ public JWTToken(JWTokenAttributes jwtAttributes) {
JWSHeader header = null;
try {
- header = new JWSHeader(new JWSAlgorithm(alg),
- type == null ? null : new JOSEObjectType(type),
+ header = new JWSHeader(new JWSAlgorithm(jwtAttributes.getAlgorithm()),
+ jwtAttributes.getType() == null ? null : new JOSEObjectType(jwtAttributes.getType()),
null,
null,
- getClaimValue(claimsArray, 5) != null ? new URI(getClaimValue(claimsArray, 5)) : null, // JKU
+ jwtAttributes.getJkuUri(),
null,
null,
null,
null,
null,
- getClaimValue(claimsArray, 4) != null ? getClaimValue(claimsArray, 4) : null, // KID
+ jwtAttributes.getKid(),
null,
null);
} catch (URISyntaxException e) {
/* in event of bad URI exception fall back to using just algo in header */
- header = new JWSHeader(new JWSAlgorithm(alg));
- }
-
- if (getClaimValue(claimsArray, 2) != null) {
- if (audiences == null) {
- audiences = new ArrayList<>();
- }
- audiences.add(getClaimValue(claimsArray, 2));
+ header = new JWSHeader(new JWSAlgorithm(jwtAttributes.getAlgorithm()));
}
JWTClaimsSet claims;
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder()
- .issuer(getClaimValue(claimsArray, 0))
- .subject(getClaimValue(claimsArray, 1))
- .audience(audiences);
- if(getClaimValue(claimsArray, 3) != null) {
- builder = builder.expirationTime(new Date(Long.parseLong(claimsArray[3])));
+ .issuer(jwtAttributes.getIssuer())
+ .subject(jwtAttributes.getUserName())
+ .audience(jwtAttributes.getAudiences());
+ if(jwtAttributes.getExpiresDate() != null) {
+ builder = builder.expirationTime(jwtAttributes.getExpiresDate());
+ }
+ if(jwtAttributes.getKid() != null) {
+ builder.claim(KNOX_KID_CLAIM, jwtAttributes.getKid());
}
- if(getClaimValue(claimsArray, 4) != null) {
- builder.claim(KNOX_KID_CLAIM, getClaimValue(claimsArray, 4));
+ if(jwtAttributes.getJku() != null) {
+ builder.claim(KNOX_JKU_CLAIM, jwtAttributes.getJku());
}
- if(getClaimValue(claimsArray, 5) != null) {
- builder.claim(KNOX_JKU_CLAIM, getClaimValue(claimsArray, 5));
+ if (jwtAttributes.getGroups() != null) {
+ builder.claim(KNOX_GROUPS_CLAIM, jwtAttributes.getGroups());
}
// Add a private UUID claim for uniqueness
builder.claim(KNOX_ID_CLAIM, String.valueOf(UUID.randomUUID()));
- builder.claim(MANAGED_TOKEN_CLAIM, String.valueOf(managed));
+ builder.claim(MANAGED_TOKEN_CLAIM, String.valueOf(jwtAttributes.isManaged()));
claims = builder.build();
jwt = new SignedJWT(header, claims);
}
- private String getClaimValue(String[] claims, int index) {
- return claims == null || claims.length <= index ? null : claims[index];
- }
-
@Override
public String getHeader() {
JWSHeader header = jwt.getHeader();
@@ -245,7 +217,7 @@ public class JWTToken implements JWT {
@Override
public String getExpires() {
- Date expires = getExpiresDate();
+ Date expires = getExpiresDate();
if (expires != null) {
return String.valueOf(expires.getTime());
}
diff --git a/gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java b/gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java
index d022cb705..ff0df7af4 100644
--- a/gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java
+++ b/gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java
@@ -17,6 +17,8 @@
*/
package org.apache.knox.gateway.services.security.token.impl;
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -34,6 +36,7 @@ import java.util.Date;
import java.util.List;
import java.util.UUID;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -73,14 +76,7 @@ public class JWTTokenTest {
final String KID = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
final String JKU = "https://localhost:8443/gateway/token/knoxtoken/api/v1/jwks.json";
final String ALGO = "RS256";
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "https://login.example.com";
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = KID;
- claims[5] = JKU;
- JWT token = new JWTToken(ALGO, claims);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setAudiences(singletonList("https://login.example.com")).setKid(KID).setUserName("john.doe@example.com").setJku(JKU).setAlgorithm(ALGO).build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
@@ -93,14 +89,7 @@ public class JWTTokenTest {
@Test
public void testPrivateUUIDClaim() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "https://login.example.com";
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- JWT token = new JWTToken("RS256", claims);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setAudiences(singletonList("https://login.example.com")).setUserName("john.doe@example.com").setAlgorithm("RS256").build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
@@ -114,17 +103,10 @@ public class JWTTokenTest {
@Test
public void testTokenCreationWithAudienceListSingle() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = null;
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
List<String> audiences = new ArrayList<>();
audiences.add("https://login.example.com");
- JWT token = new JWTToken("RS256", claims, audiences);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setUserName("john.doe@example.com").setAudiences(audiences).setAlgorithm("RS256").setManaged(false).build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
@@ -134,18 +116,11 @@ public class JWTTokenTest {
@Test
public void testTokenCreationWithAudienceListMultiple() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = null;
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
List<String> audiences = new ArrayList<>();
audiences.add("https://login.example.com");
audiences.add("KNOXSSO");
- JWT token = new JWTToken("RS256", claims, audiences);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setUserName("john.doe@example.com").setAudiences(audiences).setManaged(false).setAlgorithm("RS256").build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
@@ -155,19 +130,7 @@ public class JWTTokenTest {
@Test
public void testTokenCreationWithAudienceListCombined() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "LJM";
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- ArrayList<String> audiences = new ArrayList<>();
- audiences.add("https://login.example.com");
- audiences.add("KNOXSSO");
-
- JWTToken token = new JWTToken("RS256", claims, audiences);
-
+ JWTToken token = new JWTToken(new JWTokenAttributesBuilder().setAudiences(asList("https://login.example.com", "KNOXSSO", "LJM")).setUserName("john.doe@example.com").setManaged(false).setAlgorithm("RS256").build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
assertEquals("https://login.example.com", token.getAudience());
@@ -176,17 +139,7 @@ public class JWTTokenTest {
@Test
public void testTokenCreationWithNullAudienceList() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = null;
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- List<String> audiences = null;
-
- JWT token = new JWTToken("RS256", claims, audiences);
-
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setUserName("john.doe@example.com").setAudiences((List<String>)null).setAlgorithm("RS256").setManaged(false).build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
assertNull(token.getAudience());
@@ -195,14 +148,7 @@ public class JWTTokenTest {
@Test
public void testTokenCreationRS512() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "https://login.example.com";
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- JWTToken token = new JWTToken(JWSAlgorithm.RS512.getName(), claims);
+ JWTToken token = new JWTToken(new JWTokenAttributesBuilder().setAudiences(singletonList("https://login.example.com")).setUserName("john.doe@example.com").setAlgorithm(JWSAlgorithm.RS512.getName()).build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
@@ -212,14 +158,7 @@ public class JWTTokenTest {
@Test
public void testTokenSignature() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "https://login.example.com";
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- JWT token = new JWTToken("RS256", claims);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setAudiences(singletonList("https://login.example.com")).setUserName("john.doe@example.com").setAlgorithm("RS256").build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
@@ -237,14 +176,7 @@ public class JWTTokenTest {
@Test
public void testTokenSignatureRS512() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "https://login.example.com";
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- JWT token = new JWTToken(JWSAlgorithm.RS512.getName(), claims);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setAudiences(singletonList("https://login.example.com")).setUserName("john.doe@example.com").setAlgorithm(JWSAlgorithm.RS512.getName()).build());
assertEquals("KNOXSSO", token.getIssuer());
assertEquals("john.doe@example.com", token.getSubject());
@@ -263,14 +195,7 @@ public class JWTTokenTest {
@Test
public void testTokenExpiry() throws Exception {
- String[] claims = new String[6];
- claims[0] = "KNOXSSO";
- claims[1] = "john.doe@example.com";
- claims[2] = "https://login.example.com";
- claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
- claims[4] = "E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA";
- claims[5] = null;
- JWT token = new JWTToken("RS256", claims);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setAlgorithm("RS256").build());
assertNotNull(token.getExpires());
assertNotNull(token.getExpiresDate());
@@ -294,11 +219,11 @@ public class JWTTokenTest {
@Test
public void testTokenType() throws Exception {
- JWT token = new JWTToken("RS256", null, null, false, null);
+ JWT token = new JWTToken(new JWTokenAttributesBuilder().setAlgorithm("RS256").build());
assertNull(token.getType());
final String tokenType = "at+jwt";
- token = new JWTToken("RS256", null, null, false, tokenType);
+ token = new JWTToken(new JWTokenAttributesBuilder().setAlgorithm("RS256").setType(tokenType).build());
assertEquals(token.getType(), new JOSEObjectType(tokenType));
}
}