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 2021/03/16 13:17:55 UTC

[knox] branch master updated: KNOX-2553 - Adding the 'managed_token' flag in the issued JWT as well as the JSON response of our KnoxToken service (#416)

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 2be0345  KNOX-2553 - Adding the 'managed_token' flag in the issued JWT as well as the JSON response of our KnoxToken service (#416)
2be0345 is described below

commit 2be034535c025daf71818f717bd784286e01dd65
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Tue Mar 16 14:17:47 2021 +0100

    KNOX-2553 - Adding the 'managed_token' flag in the issued JWT as well as the JSON response of our KnoxToken service (#416)
    
    In order to avoid adding new and confusing methods into JWTokenAuthority I introduced a model object to store possible JWT attributes and kept only one method to issue a token.
---
 .../jwt/filter/JWTAccessTokenAssertionFilter.java  |  5 +-
 .../jwt/filter/JWTAuthCodeAssertionFilter.java     |  3 +-
 .../provider/federation/AbstractJWTFilterTest.java | 36 +--------
 .../token/impl/DefaultTokenAuthorityService.java   | 60 ++-------------
 .../impl/DefaultTokenAuthorityServiceTest.java     | 20 +++--
 .../gateway/service/knoxsso/WebSSOResource.java    |  6 +-
 .../service/knoxsso/WebSSOResourceTest.java        | 59 ++------------
 .../gateway/service/knoxtoken/TokenResource.java   | 13 +++-
 .../knoxtoken/TokenServiceResourceTest.java        | 51 ++----------
 .../services/security/token/JWTokenAttributes.java | 79 +++++++++++++++++++
 .../security/token/JWTokenAttributesBuilder.java   | 90 ++++++++++++++++++++++
 .../services/security/token/JWTokenAuthority.java  | 27 +------
 .../services/security/token/impl/JWTToken.java     |  7 ++
 13 files changed, 239 insertions(+), 217 deletions(-)

diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java
index df4783a..37644d0 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java
@@ -38,6 +38,8 @@ import org.apache.knox.gateway.provider.federation.jwt.JWTMessages;
 import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.GatewayServices;
 import org.apache.knox.gateway.services.registry.ServiceRegistry;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
 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.impl.JWT;
@@ -146,7 +148,8 @@ public class JWTAccessTokenAssertionFilter extends AbstractIdentityAssertionFilt
     };
     JWT token;
     try {
-      token = authority.issueToken(p, serviceName, signatureAlgorithm, expires);
+      final JWTokenAttributes jwtAttributes = new JWTokenAttributesBuilder().setPrincipal(p).setAudiences(serviceName).setAlgorithm(signatureAlgorithm).setExpires(expires).build();
+      token = authority.issueToken(jwtAttributes);
       // Coverity CID 1327961
       if( token != null ) {
         accessToken = token.toString();
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java
index cda9f16..ab03f42 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java
@@ -32,6 +32,7 @@ import org.apache.knox.gateway.filter.security.AbstractIdentityAssertionFilter;
 import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.GatewayServices;
 import org.apache.knox.gateway.services.registry.ServiceRegistry;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
 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.impl.JWT;
@@ -64,7 +65,7 @@ public class JWTAuthCodeAssertionFilter extends AbstractIdentityAssertionFilter
     principalName = mapper.mapUserPrincipal(principalName);
     JWT authCode;
     try {
-      authCode = authority.issueToken(subject, signatureAlgorithm);
+      authCode = authority.issueToken(new JWTokenAttributesBuilder().setPrincipal(subject).setAlgorithm(signatureAlgorithm).build());
       // get the url for the token service
       String url = null;
       if (sr != null) {
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 20324d6..3f6bc98 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
@@ -30,6 +30,7 @@ import org.apache.commons.codec.binary.Base64;
 import org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter;
 import org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter;
 import org.apache.knox.gateway.security.PrimaryPrincipal;
+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.impl.JWT;
 import org.apache.knox.gateway.services.security.token.impl.JWTToken;
@@ -1246,46 +1247,13 @@ public abstract class AbstractJWTFilterTest  {
     }
 
     @Override
-    public JWT issueToken(Subject subject, String algorithm) {
-      return null;
-    }
-
-    @Override
-    public JWT issueToken(Principal p, String algorithm) {
-      return null;
-    }
-
-    @Override
-    public JWT issueToken(Principal p, String audience, String algorithm) {
-      return null;
-    }
-
-    @Override
     public boolean verifyToken(JWT token) {
       JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) verifyingKey);
       return token.verify(verifier);
     }
 
     @Override
-    public JWT issueToken(Principal p, String audience, String algorithm,
-        long expires) {
-      return null;
-    }
-
-    @Override
-    public JWT issueToken(Principal p, List<String> audiences, String algorithm,
-        long expires) {
-      return null;
-    }
-
-    @Override
-    public JWT issueToken(Principal p, List<String> audiences, String algorithm, long expires,
-                          String signingKeystoreName, String signingKeystoreAlias, char[] signingKeystorePassphrase) {
-      return null;
-    }
-
-    @Override
-    public JWT issueToken(Principal p, String algorithm, long expires) {
+    public JWT issueToken(JWTokenAttributes jwtAttributes) {
       return null;
     }
 
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 5b15825..76e65ab 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
@@ -24,22 +24,17 @@ import java.security.Key;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
 import java.security.PublicKey;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.Certificate;
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
 import java.text.ParseException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.security.auth.Subject;
-
 import org.apache.knox.gateway.GatewayResources;
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.i18n.resources.ResourcesFactory;
@@ -49,6 +44,7 @@ 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;
@@ -99,65 +95,25 @@ public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
   }
 
   @Override
-  public JWT issueToken(Subject subject, String algorithm) throws TokenServiceException {
-    Principal p = (Principal) subject.getPrincipals().toArray()[0];
-    return issueToken(p, algorithm);
-  }
-
-  @Override
-  public JWT issueToken(Principal p, String algorithm) throws TokenServiceException {
-    return issueToken(p, null, algorithm);
-  }
-
-  @Override
-  public JWT issueToken(Principal p, String algorithm, long expires) throws TokenServiceException {
-    return issueToken(p, (String)null, algorithm, expires);
-  }
-
-  @Override
-  public JWT issueToken(Principal p, String audience, String algorithm)
-      throws TokenServiceException {
-    return issueToken(p, audience, algorithm, -1);
-  }
-
-  @Override
-  public JWT issueToken(Principal p, String audience, String algorithm, long expires)
-      throws TokenServiceException {
-    List<String> audiences = null;
-    if (audience != null) {
-      audiences = new ArrayList<>();
-      audiences.add(audience);
-    }
-    return issueToken(p, audiences, algorithm, expires);
-  }
-
-  @Override
-  public JWT issueToken(Principal p, List<String> audiences, String algorithm, long expires)
-      throws TokenServiceException {
-    return issueToken(p, audiences, algorithm, expires, null, null, null);
-  }
-
-  @Override
-  public JWT issueToken(Principal p, List<String> audiences, String algorithm, long expires,
-                        String signingKeystoreName, String signingKeystoreAlias, char[] signingKeystorePassphrase)
-      throws TokenServiceException {
+  public JWT issueToken(JWTokenAttributes jwtAttributes) throws TokenServiceException {
     String[] claimArray = new String[4];
     claimArray[0] = "KNOXSSO";
-    claimArray[1] = p.getName();
+    claimArray[1] = jwtAttributes.getPrincipal().getName();
     claimArray[2] = null;
-    if (expires == -1) {
+    if (jwtAttributes.getExpires() == -1) {
       claimArray[3] = null;
     }
     else {
-      claimArray[3] = String.valueOf(expires);
+      claimArray[3] = String.valueOf(jwtAttributes.getExpires());
     }
 
-    final JWT token = SUPPORTED_PKI_SIG_ALGS.contains(algorithm) || SUPPORTED_HMAC_SIG_ALGS.contains(algorithm) ? new JWTToken(algorithm, claimArray, audiences) : null;
+    final String algorithm = jwtAttributes.getAlgorithm();
+    final JWT token = SUPPORTED_PKI_SIG_ALGS.contains(algorithm) || SUPPORTED_HMAC_SIG_ALGS.contains(algorithm) ? new JWTToken(algorithm, claimArray, jwtAttributes.getAudiences(), jwtAttributes.isManaged()) : null;
     if (token != null) {
       if (SUPPORTED_HMAC_SIG_ALGS.contains(algorithm)) {
         signTokenWithHMAC(token);
       } else {
-        signTokenWithRSA(token, signingKeystoreName, signingKeystoreAlias, signingKeystorePassphrase);
+        signTokenWithRSA(token, jwtAttributes.getSigningKeystoreName(), jwtAttributes.getSigningKeystoreAlias(), jwtAttributes.getSigningKeystorePassphrase());
       }
       return token;
     } else {
diff --git a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java
index 485f752..b3a62ed 100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/services/token/impl/DefaultTokenAuthorityServiceTest.java
@@ -29,6 +29,9 @@ import org.apache.knox.gateway.services.security.AliasService;
 import org.apache.knox.gateway.services.security.MasterService;
 import org.apache.knox.gateway.services.security.impl.DefaultKeystoreService;
 import org.apache.knox.gateway.services.security.token.impl.JWT;
+import org.apache.knox.gateway.services.security.token.impl.JWTToken;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
 import org.apache.knox.gateway.services.security.token.TokenServiceException;
 
 import org.easymock.EasyMock;
@@ -84,9 +87,10 @@ public class DefaultTokenAuthorityServiceTest {
     ta.init(config, new HashMap<>());
     ta.start();
 
-    JWT token = ta.issueToken(principal, "RS256");
+    JWT token = ta.issueToken(new JWTokenAttributesBuilder().setPrincipal(principal).setAlgorithm("RS256").setManaged(true).build());
     assertEquals("KNOXSSO", token.getIssuer());
     assertEquals("john.doe@example.com", token.getSubject());
+    assertTrue(Boolean.parseBoolean(token.getClaim(JWTToken.MANAGED_TOKEN_CLAIM)));
 
     assertTrue(ta.verifyToken(token));
   }
@@ -133,7 +137,8 @@ public class DefaultTokenAuthorityServiceTest {
     ta.init(config, new HashMap<>());
     ta.start();
 
-    JWT token = ta.issueToken(principal, "https://login.example.com", "RS256");
+    JWT token = ta
+        .issueToken(new JWTokenAttributesBuilder().setPrincipal(principal).setAudiences("https://login.example.com").setAlgorithm("RS256").build());
     assertEquals("KNOXSSO", token.getIssuer());
     assertEquals("john.doe@example.com", token.getSubject());
     assertEquals("https://login.example.com", token.getAudience());
@@ -183,7 +188,7 @@ public class DefaultTokenAuthorityServiceTest {
     ta.init(config, new HashMap<>());
     ta.start();
 
-    JWT token = ta.issueToken(principal, null, "RS256");
+    JWT token = ta.issueToken(new JWTokenAttributesBuilder().setPrincipal(principal).setAlgorithm("RS256").build());
     assertEquals("KNOXSSO", token.getIssuer());
     assertEquals("john.doe@example.com", token.getSubject());
 
@@ -232,7 +237,7 @@ public class DefaultTokenAuthorityServiceTest {
     ta.init(config, new HashMap<>());
     ta.start();
 
-    JWT token = ta.issueToken(principal, "RS512");
+    JWT token = ta.issueToken(new JWTokenAttributesBuilder().setPrincipal(principal).setAlgorithm("RS512").build());
     assertEquals("KNOXSSO", token.getIssuer());
     assertEquals("john.doe@example.com", token.getSubject());
     assertTrue(token.getHeader().contains("RS512"));
@@ -280,7 +285,7 @@ public class DefaultTokenAuthorityServiceTest {
     ta.setKeystoreService(ks);
 
     ta.init(config, new HashMap<>());
-    ta.issueToken(principal, "none");
+    ta.issueToken(new JWTokenAttributesBuilder().setPrincipal(principal).setAlgorithm("none").build());
   }
 
   @Test
@@ -333,8 +338,9 @@ public class DefaultTokenAuthorityServiceTest {
     ta.setKeystoreService(ks);
     ta.init(config, new HashMap<>());
 
-    JWT token = ta.issueToken(principal, Collections.emptyList(), "RS256", -1,
-        customSigningKeyName, customSigningKeyAlias, customSigningKeyPassphrase.toCharArray());
+    final JWTokenAttributes jwtAttributes = new JWTokenAttributesBuilder().setPrincipal(principal).setAudiences(Collections.emptyList()).setAlgorithm("RS256").setExpires(-1)
+        .setSigningKeystoreName(customSigningKeyName).setSigningKeystoreAlias(customSigningKeyAlias).setSigningKeystorePassphrase(customSigningKeyPassphrase.toCharArray()).build();
+    JWT token = ta.issueToken(jwtAttributes);
     assertEquals("KNOXSSO", token.getIssuer());
     assertEquals("john.doe@example.com", token.getSubject());
 
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 8f34fec..a902199 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
@@ -52,6 +52,8 @@ 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.AliasServiceException;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributes;
+import org.apache.knox.gateway.services.security.token.JWTokenAttributesBuilder;
 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;
@@ -260,7 +262,9 @@ public class WebSSOResource {
         signingKeystorePassphrase = as.getPasswordFromAliasForCluster(clusterName, signingKeystorePassphraseAlias);
       }
 
-      JWT token = tokenAuthority.issueToken(p, targetAudiences, signatureAlgorithm, getExpiry(), signingKeystoreName,  signingKeystoreAlias, signingKeystorePassphrase);
+      final JWTokenAttributes jwtAttributes = new JWTokenAttributesBuilder().setPrincipal(p).setAudiences(targetAudiences).setAlgorithm(signatureAlgorithm).setExpires(getExpiry())
+          .setSigningKeystoreName(signingKeystoreName).setSigningKeystoreAlias(signingKeystoreAlias).setSigningKeystorePassphrase(signingKeystorePassphrase).build();
+      JWT token = tokenAuthority.issueToken(jwtAttributes);
 
       // Coverity CID 1327959
       if( token != null ) {
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 23054e7..b6671ec 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
@@ -31,6 +31,7 @@ import org.apache.knox.gateway.config.GatewayConfig;
 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.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;
@@ -42,7 +43,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.ServletOutputStream;
 import javax.servlet.http.Cookie;
@@ -60,7 +60,6 @@ import java.security.KeyPairGenerator;
 import java.security.Principal;
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
@@ -762,63 +761,27 @@ public class WebSSOResourceTest {
     }
 
     @Override
-    public JWT issueToken(Subject subject, String algorithm)
-      throws TokenServiceException {
-      Principal p = (Principal) subject.getPrincipals().toArray()[0];
-      return issueToken(p, algorithm);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, String algorithm)
-      throws TokenServiceException {
-      return issueToken(p, null, algorithm);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, String audience, String algorithm)
-      throws TokenServiceException {
-      return issueToken(p, audience, algorithm, -1);
-    }
-
-    @Override
     public boolean verifyToken(JWT token) throws TokenServiceException {
       return verifyToken(token, this.publicKey);
     }
 
     @Override
-    public JWT issueToken(Principal p, String audience, String algorithm,
-                               long expires) throws TokenServiceException {
-      List<String> audiences = null;
-      if (audience != null) {
-        audiences = new ArrayList<>();
-        audiences.add(audience);
-      }
-      return issueToken(p, audiences, algorithm, expires);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, List<String> audiences, String algorithm,
-                          long expires) throws TokenServiceException {
-      return issueToken(p, audiences, algorithm, expires, null, null, null);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, List<String> audiences, String algorithm, long expires,
-                          String signingKeystoreName, String signingKeystoreAlias, char[] signingKeystorePassphrase)
+    public JWT issueToken(JWTokenAttributes jwtAttributes)
         throws TokenServiceException {
       String[] claimArray = new String[4];
       claimArray[0] = "KNOXSSO";
-      claimArray[1] = p.getName();
+      claimArray[1] = jwtAttributes.getPrincipal().getName();
       claimArray[2] = null;
-      if (expires == -1) {
+      if (jwtAttributes.getExpires() == -1) {
         claimArray[3] = null;
       } else {
-        claimArray[3] = String.valueOf(expires);
+        claimArray[3] = String.valueOf(jwtAttributes.getExpires());
       }
 
-      JWT token = new JWTToken(algorithm, claimArray, audiences);
+      JWT token = new JWTToken(jwtAttributes.getAlgorithm(), claimArray, jwtAttributes.getAudiences());
       try {
-        JWSSigner signer = useHMAC ? new MACSigner(HMAC_SECRET) :  new RSASSASigner(getPrivateKey(signingKeystoreName, signingKeystoreAlias, signingKeystorePassphrase));
+        JWSSigner signer = useHMAC ? new MACSigner(HMAC_SECRET)
+            : new RSASSASigner(getPrivateKey(jwtAttributes.getSigningKeystoreName(), jwtAttributes.getSigningKeystoreAlias(), jwtAttributes.getSigningKeystorePassphrase()));
         token.sign(signer);
       } catch (KeyLengthException e) {
         throw new TokenServiceException(e);
@@ -841,12 +804,6 @@ public class WebSSOResourceTest {
     }
 
     @Override
-    public JWT issueToken(Principal p, String algorithm, long expiry)
-        throws TokenServiceException {
-      return issueToken(p, Collections.emptyList(), algorithm, expiry);
-    }
-
-    @Override
     public boolean verifyToken(JWT token, RSAPublicKey publicKey) throws TokenServiceException {
       try {
         JWSVerifier verifier = useHMAC ? new MACVerifier(HMAC_SECRET) : new RSASSAVerifier(publicKey);
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 065cb93..e1a60e8 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
@@ -50,6 +50,8 @@ 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.JWTokenAttributesBuilder;
 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.TokenStateService;
@@ -70,6 +72,7 @@ public class TokenResource {
   private static final String TOKEN_TYPE = "token_type";
   private static final String ACCESS_TOKEN = "access_token";
   private static final String TOKEN_ID = "token_id";
+  private static final String MANAGED_TOKEN = "managed";
   private static final String TARGET_URL = "target_url";
   private static final String ENDPOINT_PUBLIC_CERT = "endpoint_public_cert";
   private static final String BEARER = "Bearer";
@@ -395,11 +398,16 @@ public class TokenResource {
     }
 
     try {
+      final boolean managedToken = tokenStateService != null;
       JWT token;
+      JWTokenAttributes jwtAttributes;
       if (targetAudiences.isEmpty()) {
-        token = ts.issueToken(p, signatureAlgorithm, expires);
+        jwtAttributes = new JWTokenAttributesBuilder().setPrincipal(p).setAlgorithm(signatureAlgorithm).setExpires(expires).setManaged(managedToken).build();
+        token = ts.issueToken(jwtAttributes);
       } else {
-        token = ts.issueToken(p, targetAudiences, signatureAlgorithm, expires);
+        jwtAttributes = new JWTokenAttributesBuilder().setPrincipal(p).setAudiences(targetAudiences).setAlgorithm(signatureAlgorithm).setExpires(expires)
+            .setManaged(managedToken).build();
+        token = ts.issueToken(jwtAttributes);
       }
 
       if (token != null) {
@@ -410,6 +418,7 @@ public class TokenResource {
         HashMap<String, Object> map = new HashMap<>();
         map.put(ACCESS_TOKEN, accessToken);
         map.put(TOKEN_ID, tokenId);
+        map.put(MANAGED_TOKEN, String.valueOf(managedToken));
         map.put(TOKEN_TYPE, BEARER);
         map.put(EXPIRES_IN, expires);
         if (tokenTargetUrl != null) {
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 9f27ef9..54e92a4 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
@@ -31,6 +31,7 @@ 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;
 import org.apache.knox.gateway.services.security.token.TokenStateService;
 import org.apache.knox.gateway.services.security.token.TokenUtils;
@@ -179,7 +180,7 @@ public class TokenServiceResourceTest {
 
   @Test
   public void testGetToken() throws Exception {
-    configureCommonExpectations(Collections.singletonMap("org.apache.knox.gateway.gateway.cluster", "test"));
+    configureCommonExpectations(Collections.singletonMap("org.apache.knox.gateway.gateway.cluster", "test"), Boolean.TRUE);
 
     TokenResource tr = new TokenResource();
     tr.context = context;
@@ -199,6 +200,7 @@ public class TokenServiceResourceTest {
     assertNotNull(expiry);
 
     assertNotNull(getTagValue(retString, "token_id"));
+    assertTrue(Boolean.parseBoolean(getTagValue(retString, "managed")));
 
     // Verify the token
     JWT parsedToken = new JWTToken(accessToken);
@@ -1151,67 +1153,30 @@ public class TokenServiceResourceTest {
     }
 
     @Override
-    public JWT issueToken(Subject subject, String algorithm) {
-      Principal p = (Principal) subject.getPrincipals().toArray()[0];
-      return issueToken(p, algorithm);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, String algorithm) {
-      return issueToken(p, null, algorithm);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, String audience, String algorithm) {
-      return issueToken(p, audience, algorithm, -1);
-    }
-
-    @Override
     public boolean verifyToken(JWT token) {
       JWSVerifier verifier = new RSASSAVerifier(publicKey);
       return token.verify(verifier);
     }
 
     @Override
-    public JWT issueToken(Principal p, String audience, String algorithm,
-                               long expires) {
-      ArrayList<String> audiences = null;
-      if (audience != null) {
-        audiences = new ArrayList<>();
-        audiences.add(audience);
-      }
-      return issueToken(p, audiences, algorithm, expires);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, List<String> audiences, String algorithm, long expires,
-                          String signingkeyName, String signingkeyAlias, char[] signingkeyPassphrase) {
-      return issueToken(p, audiences, algorithm, expires);
-    }
-
-    @Override
-    public JWT issueToken(Principal p, List<String> audiences, String algorithm, long expires) {
+    public JWT issueToken(JWTokenAttributes jwtAttributes) {
       String[] claimArray = new String[4];
       claimArray[0] = "KNOXSSO";
-      claimArray[1] = p.getName();
+      claimArray[1] = jwtAttributes.getPrincipal().getName();
       claimArray[2] = null;
-      if (expires == -1) {
+      if (jwtAttributes.getExpires() == -1) {
         claimArray[3] = null;
       } else {
-        claimArray[3] = String.valueOf(expires);
+        claimArray[3] = String.valueOf(jwtAttributes.getExpires());
       }
 
-      JWT token = new JWTToken(algorithm, claimArray, audiences);
+      JWT token = new JWTToken(jwtAttributes.getAlgorithm(), claimArray, jwtAttributes.getAudiences());
       JWSSigner signer = new RSASSASigner(privateKey);
       token.sign(signer);
 
       return token;
     }
 
-    @Override
-    public JWT issueToken(Principal p, String algorithm, long expiry) {
-      return issueToken(p, Collections.emptyList(), algorithm, expiry);
-    }
 
     @Override
     public boolean verifyToken(JWT token, RSAPublicKey publicKey) {
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
new file mode 100644
index 0000000..b6db56c
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributes.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.services.security.token;
+
+import java.security.Principal;
+import java.util.List;
+
+public class JWTokenAttributes {
+
+  private final Principal principal;
+  private final List<String> audiences;
+  private final String algorithm;
+  private final long expires;
+  private final String signingKeystoreName;
+  private final String signingKeystoreAlias;
+  private final char[] signingKeystorePassphrase;
+  private final boolean managed;
+
+  JWTokenAttributes(Principal principal, List<String> audiences, String algorithm, long expires, String signingKeystoreName, String signingKeystoreAlias,
+      char[] signingKeystorePassphrase, boolean managed) {
+    super();
+    this.principal = principal;
+    this.audiences = audiences;
+    this.algorithm = algorithm;
+    this.expires = expires;
+    this.signingKeystoreName = signingKeystoreName;
+    this.signingKeystoreAlias = signingKeystoreAlias;
+    this.signingKeystorePassphrase = signingKeystorePassphrase;
+    this.managed = managed;
+  }
+
+  public Principal getPrincipal() {
+    return principal;
+  }
+
+  public List<String> getAudiences() {
+    return audiences;
+  }
+
+  public String getAlgorithm() {
+    return algorithm;
+  }
+
+  public long getExpires() {
+    return expires;
+  }
+
+  public String getSigningKeystoreName() {
+    return signingKeystoreName;
+  }
+
+  public String getSigningKeystoreAlias() {
+    return signingKeystoreAlias;
+  }
+
+  public char[] getSigningKeystorePassphrase() {
+    return signingKeystorePassphrase;
+  }
+
+  public boolean isManaged() {
+    return managed;
+  }
+
+}
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
new file mode 100644
index 0000000..c4028e4
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/JWTokenAttributesBuilder.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.services.security.token;
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.List;
+
+import javax.security.auth.Subject;
+
+public class JWTokenAttributesBuilder {
+
+  private Principal principal;
+  private List<String> audiences;
+  private String algorithm;
+  private long expires;
+  private String signingKeystoreName;
+  private String signingKeystoreAlias;
+  private char[] signingKeystorePassphrase;
+  private boolean managed;
+
+  public JWTokenAttributesBuilder setPrincipal(Subject subject) {
+    return setPrincipal((Principal) subject.getPrincipals().toArray()[0]);
+  }
+
+  public JWTokenAttributesBuilder setPrincipal(Principal principal) {
+    this.principal = principal;
+    return this;
+  }
+
+  public JWTokenAttributesBuilder setAudiences(String audience) {
+    return setAudiences(Collections.singletonList(audience));
+  }
+
+  public JWTokenAttributesBuilder setAudiences(List<String> audiences) {
+    this.audiences = audiences;
+    return this;
+  }
+
+  public JWTokenAttributesBuilder setAlgorithm(String algorithm) {
+    this.algorithm = algorithm;
+    return this;
+  }
+
+  public JWTokenAttributesBuilder setExpires(long expires) {
+    this.expires = expires;
+    return this;
+  }
+
+  public JWTokenAttributesBuilder setSigningKeystoreName(String signingKeystoreName) {
+    this.signingKeystoreName = signingKeystoreName;
+    return this;
+  }
+
+  public JWTokenAttributesBuilder setSigningKeystoreAlias(String signingKeystoreAlias) {
+    this.signingKeystoreAlias = signingKeystoreAlias;
+    return this;
+  }
+
+  public JWTokenAttributesBuilder setSigningKeystorePassphrase(char[] signingKeystorePassphrase) {
+    this.signingKeystorePassphrase = signingKeystorePassphrase;
+    return this;
+  }
+
+  public JWTokenAttributesBuilder setManaged(boolean managed) {
+    this.managed = managed;
+    return this;
+  }
+
+  public JWTokenAttributes build() {
+    return new JWTokenAttributes(principal, (audiences == null ? Collections.emptyList() : audiences), algorithm, expires, signingKeystoreName, signingKeystoreAlias,
+        signingKeystorePassphrase, managed);
+  }
+
+}
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 5ba10d1..837cd11 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
@@ -17,40 +17,17 @@
  */
 package org.apache.knox.gateway.services.security.token;
 
-import java.security.Principal;
 import java.security.interfaces.RSAPublicKey;
-import java.util.List;
-
-import javax.security.auth.Subject;
 
 import org.apache.knox.gateway.services.security.token.impl.JWT;
 
 public interface JWTokenAuthority {
 
-  JWT issueToken(Subject subject, String algorithm)
-      throws TokenServiceException;
-
-  JWT issueToken(Principal p, String algorithm)
-      throws TokenServiceException;
-
-  JWT issueToken(Principal p, String audience,
-      String algorithm) throws TokenServiceException;
+  JWT issueToken(JWTokenAttributes jwtAttributes) throws TokenServiceException;
 
   boolean verifyToken(JWT token) throws TokenServiceException;
 
   boolean verifyToken(JWT token, RSAPublicKey publicKey) throws TokenServiceException;
 
-  boolean verifyToken(JWT token, String jwksurl ,String algorithm ) throws TokenServiceException;
-
-  JWT issueToken(Principal p, String algorithm, long expires) throws TokenServiceException;
-
-  JWT issueToken(Principal p, String audience, String algorithm,
-      long expires) throws TokenServiceException;
-
-  JWT issueToken(Principal p, List<String> audiences, String algorithm,
-      long expires) throws TokenServiceException;
-
-  JWT issueToken(Principal p, List<String> audiences, String algorithm, long expires,
-                 String signingKeystoreName, String signingKeystoreAlias, char[] signingKeystorePassphrase)
-      throws TokenServiceException;
+  boolean verifyToken(JWT token, String jwksurl, String algorithm) throws TokenServiceException;
 }
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 b5be234..1b6d936 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
@@ -38,6 +38,7 @@ public class JWTToken implements JWT {
   private static JWTProviderMessages log = MessagesFactory.get( JWTProviderMessages.class );
 
   public static final String KNOX_ID_CLAIM = "knox.id";
+  public static final String MANAGED_TOKEN_CLAIM = "managed.token";
 
   SignedJWT jwt;
 
@@ -59,6 +60,10 @@ public class JWTToken implements JWT {
   }
 
   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) {
     JWSHeader header = new JWSHeader(new JWSAlgorithm(alg));
 
     if (claimsArray[2] != null) {
@@ -79,6 +84,8 @@ public class JWTToken implements JWT {
     // Add a private UUID claim for uniqueness
     builder.claim(KNOX_ID_CLAIM, String.valueOf(UUID.randomUUID()));
 
+    builder.claim(MANAGED_TOKEN_CLAIM, String.valueOf(managed));
+
     claims = builder.build();
 
     jwt = new SignedJWT(header, claims);