/*
 * 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.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_ISSUER;
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.JWTokenAttributes.DEFAULT_ISSUER;
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;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
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;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.KeyLengthException;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import 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.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.KnoxToken;
import org.apache.knox.gateway.services.security.token.PersistentTokenStateService;
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;
import org.apache.knox.gateway.services.security.token.UnknownTokenException;
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.impl.TokenMAC;
import org.apache.knox.gateway.services.token.impl.JDBCTokenStateService;
import org.apache.knox.gateway.util.JsonUtils;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Some tests for the token service
 */
public class TokenServiceResourceTest {

  private static RSAPublicKey publicKey;
  private static RSAPrivateKey privateKey;

  private static final String TOKEN_API_PATH = "https://gateway-host:8443/gateway/sandbox/knoxtoken/api/v1";
  private static final String TOKEN_PATH = "/token";
  private static final String JKWS_PATH = "/jwks.json";
  private static final String USER_NAME = "alice";

  private ServletContext context;
  private HttpServletRequest request;
  private JWTokenAuthority authority;
  private TestTokenStateService tss = new TestTokenStateService();
  private char[] hmacSecret;

  private enum TokenLifecycleOperation {
    Renew,
    Revoke
  }

  @BeforeClass
  public static void setUpBeforeClass() throws Exception {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair KPair = kpg.generateKeyPair();

    publicKey = (RSAPublicKey) KPair.getPublic();
    privateKey = (RSAPrivateKey) KPair.getPrivate();
  }

  private void configureCommonExpectations(Map<String, String> contextExpectations) throws Exception {
    configureCommonExpectations(contextExpectations, null, null);
  }

  private void configureCommonExpectations(Map<String, String> contextExpectations, String expectedSubjectDN) throws Exception {
    configureCommonExpectations(contextExpectations, expectedSubjectDN, null);
  }

  private void configureCommonExpectations(Map<String, String> contextExpectations, Boolean serverManagedTssEnabled) throws Exception {
    configureCommonExpectations(contextExpectations, null, serverManagedTssEnabled);
  }

  private void configureCommonExpectations(Map<String, String> contextExpectations, String expectedSubjectDN, Boolean serverManagedTssEnabled) throws Exception {
    context = EasyMock.createNiceMock(ServletContext.class);
    contextExpectations.forEach((key, value) -> EasyMock.expect(context.getInitParameter(key)).andReturn(value).anyTimes());
    EasyMock.expect(context.getInitParameterNames()).andReturn(Collections.enumeration(contextExpectations.keySet())).anyTimes();
    request = EasyMock.createNiceMock(HttpServletRequest.class);
    EasyMock.expect(request.getServletContext()).andReturn(context).anyTimes();
    Principal principal = EasyMock.createNiceMock(Principal.class);
    EasyMock.expect(principal.getName()).andReturn(USER_NAME).anyTimes();
    EasyMock.expect(request.getUserPrincipal()).andReturn(principal).anyTimes();
    EasyMock.expect(request.getRequestURL()).andReturn(new StringBuffer(TOKEN_API_PATH+TOKEN_PATH)).anyTimes();
    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();
    }
    if (contextExpectations.containsKey(TokenResource.IMPERSONATION_ENABLED_PARAM)) {
      EasyMock.expect(request.getParameter(TokenResource.IMPERSONATION_ENABLED_PARAM)).andReturn(contextExpectations.get(TokenResource.IMPERSONATION_ENABLED_PARAM)).anyTimes();
    }
    EasyMock.expect(request.getParameterNames()).andReturn(Collections.emptyEnumeration()).anyTimes();

    GatewayServices services = EasyMock.createNiceMock(GatewayServices.class);
    EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).andReturn(services).anyTimes();

    GatewayConfig config = EasyMock.createNiceMock(GatewayConfig.class);
    EasyMock.expect(context.getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(config).anyTimes();
    EasyMock.expect(config.getSigningKeystoreName()).andReturn(null).anyTimes();
    if (serverManagedTssEnabled != null) {
      if (serverManagedTssEnabled) {
        EasyMock.expect(config.isServerManagedTokenStateEnabled()).andReturn(true).anyTimes();
      }
    }
    final String tokenStateServiceType = ServiceType.TOKEN_STATE_SERVICE.getShortName();
    if (contextExpectations.containsKey(tokenStateServiceType)) {
      EasyMock.expect(config.getServiceParameter(tokenStateServiceType, "impl")).andReturn(contextExpectations.get(tokenStateServiceType)).anyTimes();
    }
    EasyMock.expect(config.getKnoxTokenHashAlgorithm()).andReturn(HmacAlgorithms.HMAC_SHA_256.getName()).anyTimes();
    EasyMock.expect(config.getMaximumNumberOfTokensPerUser())
        .andReturn(contextExpectations.containsKey(KNOX_TOKEN_USER_LIMIT) ? Integer.parseInt(contextExpectations.get(KNOX_TOKEN_USER_LIMIT)) : -1).anyTimes();
    EasyMock.expect(services.getService(ServiceType.TOKEN_STATE_SERVICE)).andReturn(tss).anyTimes();

    AliasService aliasService = EasyMock.createNiceMock(AliasService.class);
    EasyMock.expect(services.getService(ServiceType.ALIAS_SERVICE)).andReturn(aliasService).anyTimes();
    EasyMock.expect(aliasService.getPasswordFromAliasForGateway(TokenUtils.SIGNING_HMAC_SECRET_ALIAS)).andReturn(hmacSecret).anyTimes();
    EasyMock.expect(aliasService.getPasswordFromAliasForGateway(TokenMAC.KNOX_TOKEN_HASH_KEY_ALIAS_NAME)).andReturn("sPj8FCgQhCEi6G18kBfpswxYSki33plbelGLs0hMSbk".toCharArray()).anyTimes();

    authority = new TestJWTokenAuthority(publicKey, privateKey);
    EasyMock.expect(services.getService(ServiceType.TOKEN_SERVICE)).andReturn(authority).anyTimes();

    if (StringUtils.isNotBlank(expectedSubjectDN)) {
      X509Certificate trustedCertMock = EasyMock.createMock(X509Certificate.class);
      EasyMock.expect(trustedCertMock.getSubjectDN()).andReturn(new PrimaryPrincipal(expectedSubjectDN)).anyTimes();
      ArrayList<X509Certificate> certArrayList = new ArrayList<>();
      certArrayList.add(trustedCertMock);
      X509Certificate[] certs = {};
      EasyMock.expect(request.getAttribute("javax.servlet.request.X509Certificate")).andReturn(certArrayList.toArray(certs)).anyTimes();
      EasyMock.replay(trustedCertMock);
    }
    else {
      EasyMock.expect(request.getAttribute("javax.servlet.request.X509Certificate")).andReturn(null).anyTimes();
    }

    EasyMock.replay(principal, services, context, request, aliasService, config);
  }

  @Test(expected = KeyLengthException.class)
  public void testInvalidHmacSecretThrowsException() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    hmacSecret = "1234".toCharArray();
    contextExpectations.put("knox.token.sigalg", JWSAlgorithm.HS256.getName());
    configureCommonExpectations(contextExpectations);
    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();
  }

  @Test
  public void testValidHmacSecretNoException() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    hmacSecret = "12345678123456781234567812345678".toCharArray();
    contextExpectations.put("knox.token.sigalg", JWSAlgorithm.HS256.getName());
    configureCommonExpectations(contextExpectations);
    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();
  }

  @Test
  public void testClientData() {
    TokenResource tr = new TokenResource();

    Map<String,Object> clientDataMap = new HashMap<>();
    tr.addClientDataToMap("cookie.name=hadoop-jwt,test=value".split(","), clientDataMap);
    Assert.assertEquals(2, clientDataMap.size());

    clientDataMap = new HashMap<>();
    tr.addClientDataToMap("cookie.name=hadoop-jwt".split(","), clientDataMap);
    Assert.assertEquals(1, clientDataMap.size());

    clientDataMap = new HashMap<>();
    tr.addClientDataToMap("".split(","), clientDataMap);
    Assert.assertEquals(0, clientDataMap.size());
  }

  @Test
  public void testGetToken() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("org.apache.knox.gateway.gateway.cluster", "test");
    contextExpectations.put(TokenResource.TOKEN_CLIENT_DATA, "sampleClientData=param1=value1&param2=value2");
    configureCommonExpectations(contextExpectations, Boolean.TRUE);

    TokenResource tr = new TokenResource();
    tr.context = context;
    tr.request = request;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    assertNotNull(getTagValue(retString, "token_id"));
    assertTrue(Boolean.parseBoolean(getTagValue(retString, "managed")));
    assertEquals(getTagValue(retString, "sampleClientData"), "param1=value1&param2=value2");

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));
  }

  /*
   * KNOX-2266
   */
  @Test
  public void testConcurrentGetToken() throws Exception {

    configureCommonExpectations(Collections.singletonMap("org.apache.knox.gateway.gateway.cluster", "test"));

    final TokenResource tr = new TokenResource();
    tr.context = context;
    tr.request = request;
    tr.init();

    // Request two tokens concurrently
    Callable<Response> task = tr::doGet;
    List<Callable<Response>> tasks = Collections.nCopies(2, task);
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    List<Future<Response>> futures = executorService.invokeAll(tasks);
    List<Response> responses = new ArrayList<>(futures.size());
    for (Future<Response> f : futures) {
      responses.add(f.get());
    }

    // Parse the responses
    String accessToken1 = getTagValue(responses.get(0).getEntity().toString(), "access_token");
    assertNotNull(accessToken1);
    JWT jwt1 = new JWTToken(accessToken1);

    String accessToken2 = getTagValue(responses.get(1).getEntity().toString(), "access_token");
    assertNotNull(accessToken1);
    JWT jwt2 = new JWTToken(accessToken2);

    // Verify the tokens
    assertNotEquals("Access tokens should be different.", accessToken1, accessToken2);
    assertEquals("The token expirations should be the same.", jwt1.getExpires(), jwt2.getExpires());
    assertNotEquals("Tokens should have unique IDs.", TokenUtils.getTokenId(jwt1), TokenUtils.getTokenId(jwt2));
  }

  @Test
  public void testAudiences() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.audiences", "recipient1,recipient2");
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));

    // Verify the audiences
    List<String> audiences = Arrays.asList(parsedToken.getAudienceClaims());
    assertEquals(2, audiences.size());
    assertTrue(audiences.contains("recipient1"));
    assertTrue(audiences.contains("recipient2"));
  }

  @Test
  public void testAudiencesWhitespace() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.audiences", " recipient1,recipient2 ");
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));

    // Verify the audiences
    List<String> audiences = Arrays.asList(parsedToken.getAudienceClaims());
    assertEquals(2, audiences.size());
    assertTrue(audiences.contains("recipient1"));
    assertTrue(audiences.contains("recipient2"));
  }

  @Test
  public void testValidClientCert() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.client.cert.required", "true");
    contextExpectations.put("knox.token.allowed.principals", "CN=localhost, OU=Test, O=Hadoop, L=Test, ST=Test, C=US");
    configureCommonExpectations(contextExpectations, "CN=localhost,OU=Test, O=Hadoop, L=Test, ST=Test, C=US");

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));
  }

  @Test
  public void testValidClientCertWrongUser() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.client.cert.required", "true");
    contextExpectations.put("knox.token.allowed.principals", "CN=remotehost, OU=Test, O=Hadoop, L=Test, ST=Test, C=US");
    configureCommonExpectations(contextExpectations, "CN=localhost,OU=Test, O=Hadoop, L=Test, ST=Test, C=US");

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(403, retResponse.getStatus());
  }

  @Test
  public void testMissingClientCert() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.client.cert.required", "true");
    contextExpectations.put("knox.token.allowed.principals", "CN=remotehost, OU=Test, O=Hadoop, L=Test, ST=Test, C=US");
    configureCommonExpectations(contextExpectations, (String) null);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(403, retResponse.getStatus());
  }

  @Test
  public void testSignatureAlgorithm() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.sigalg", "RS512");
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));
    assertTrue(parsedToken.getHeader().contains("RS512"));
  }

  @Test
  public void testDefaultTTL() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.ttl", null);
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));

    Date expiresDate = parsedToken.getExpiresDate();
    Date now = new Date();
    assertTrue(expiresDate.after(now));
    assertTrue((expiresDate.getTime() - now.getTime()) < 30000L);
  }

  @Test
  public void testCustomTTL() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.ttl", "60000");
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));

    Date expiresDate = parsedToken.getExpiresDate();
    Date now = new Date();
    assertTrue(expiresDate.after(now));
    long diff = expiresDate.getTime() - now.getTime();
    assertTrue(diff < 60000L && diff > 30000L);
  }

  @Test
  public void testNegativeTTL() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.ttl", "-60000");
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));

    Date expiresDate = parsedToken.getExpiresDate();
    Date now = new Date();
    assertTrue(expiresDate.after(now));
    assertTrue((expiresDate.getTime() - now.getTime()) < 30000L);
  }

  @Test
  public void testOverflowTTL() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.ttl", String.valueOf(Long.MAX_VALUE));
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);
    String expiry = getTagValue(retString, "expires_in");
    assertNotNull(expiry);

    // Verify the token
    JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));

    Date expiresDate = parsedToken.getExpiresDate();
    Date now = new Date();
    assertTrue(expiresDate.after(now));
    assertTrue((expiresDate.getTime() - now.getTime()) < 30000L);
  }


  @Test
  public void testTokenRenewal_ServerManagedStateConfiguredAtGatewayOnly() throws Exception {
    final String caller = "yarn";
    Response renewalResponse = doTestTokenRenewal(null, true, caller, null, createTestSubject(caller)).getValue();
    validateSuccessfulRenewalResponse(renewalResponse);
  }

  @Test
  public void testTokenRenewal_ServerManagedStateDisabledAtGatewayWithServiceOverride() throws Exception {
    final String caller = "yarn";
    Response renewalResponse = doTestTokenRenewal(true, false, caller, null, createTestSubject(caller)).getValue();
    validateSuccessfulRenewalResponse(renewalResponse);
  }

  @Test
  public void testTokenRenewal_ServerManagedStateEnabledAtGatewayWithServiceOverride() throws Exception {
    final String caller = "yarn";
    Map.Entry<TestTokenStateService, Response> result =
            doTestTokenRenewal(false, true, caller, null, createTestSubject(caller));

    // Make sure the expiration was not recorded by the TokenStateService, since it is disabled for this test
    TestTokenStateService tss = result.getKey();
    assertEquals("TokenStateService should be disabled for this test.", 0, tss.expirationData.size());

    Response renewalResponse = result.getValue();
    validateSuccessfulRenewalResponse(renewalResponse);
    String responseContent = (String) renewalResponse.getEntity();
    assertNotNull(responseContent);
    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
  }

  @Test
  public void testTokenRenewal_ServerManagedStateNotConfiguredAtAll() throws Exception {
    Map.Entry<TestTokenStateService, Response> result = doTestTokenRenewal(null, null, null, null, null);

    // Make sure the expiration was not recorded by the TokenStateService, since it is disabled for this test
    TestTokenStateService tss = result.getKey();
    assertEquals("TokenStateService should be disabled for this test.", 0, tss.expirationData.size());

    Response renewalResponse = result.getValue();
    validateSuccessfulRenewalResponse(renewalResponse);
    String responseContent = (String) renewalResponse.getEntity();
    assertNotNull(responseContent);
    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
  }

  @Test
  public void testTokenRenewal_Disabled() throws Exception {
    Map.Entry<TestTokenStateService, Response> result = doTestTokenRenewal(false, null, null, null);

    // Make sure the expiration was not recorded by the TokenStateService, since it is disabled for this test
    TestTokenStateService tss = result.getKey();
    assertEquals("TokenStateService should be disabled for this test.", 0, tss.expirationData.size());

    Response renewalResponse = result.getValue();
    validateSuccessfulRenewalResponse(renewalResponse);
    String responseContent = (String) renewalResponse.getEntity();
    assertNotNull(responseContent);
    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
  }

  @Test
  public void testTokenRenewal_Enabled_NoRenewersNoSubject() throws Exception {
    Response renewalResponse = doTestTokenRenewal(true, null, null);
    validateRenewalResponse(renewalResponse, 403, false, "Caller (null) not authorized to renew tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRenewal_Enabled_NoRenewersWithSubject() throws Exception {
    final String caller = "yarn";
    Response renewalResponse = doTestTokenRenewal(true, null, createTestSubject(caller));
    validateRenewalResponse(renewalResponse,
                            403,
                            false,
                            "Caller (" + caller + ") not authorized to renew tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRenewal_Enabled_WithRenewersNoSubject() throws Exception {
    Response renewalResponse = doTestTokenRenewal(true, "larry, moe,  curly ", null);
    validateRenewalResponse(renewalResponse,
                            403,
                            false,
                            "Caller (null) not authorized to renew tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRenewal_Enabled_WithRenewersWithInvalidSubject() throws Exception {
    final String caller = "shemp";
    Response renewalResponse = doTestTokenRenewal(true, "larry, moe,  curly ", createTestSubject(caller));
    validateRenewalResponse(renewalResponse,
                            403,
                            false,
                            "Caller (" + caller + ") not authorized to renew tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRenewal_Enabled_WithRenewersWithValidSubject() throws Exception {
    final String caller = "shemp";
    Response renewalResponse =
                      doTestTokenRenewal(true, ("larry, moe,  curly ," + caller), createTestSubject(caller));
    validateSuccessfulRenewalResponse(renewalResponse);
  }

  @Test
  public void testTokenRenewal_Enabled_WithDefaultMaxTokenLifetime() throws Exception {
    final String caller = "yarn";

    // Max lifetime duration is 10ms
    Map.Entry<TestTokenStateService, Response> testResult =
                  doTestTokenRenewal(true, caller, null, createTestSubject(caller));

    TestTokenStateService tss = testResult.getKey();
    assertEquals(1, tss.issueTimes.size());
    String token = tss.issueTimes.keySet().iterator().next();

    // Verify that the configured max lifetime was honored
    assertEquals(tss.getDefaultMaxLifetimeDuration(), tss.getMaxLifetime(token) - tss.getIssueTime(token));
  }


  @Test
  public void testTokenRenewal_Enabled_WithConfigurableMaxTokenLifetime() throws Exception {
    final String caller = "yarn";

    // Max lifetime duration is 10ms
    Map.Entry<TestTokenStateService, Response> testResult =
                                              doTestTokenRenewal(true, caller, 10L, createTestSubject(caller));

    TestTokenStateService tss = testResult.getKey();
    assertEquals(1, tss.issueTimes.size());
    String token = tss.issueTimes.keySet().iterator().next();

    // Verify that the configured max lifetime was honored
    assertEquals(10L, tss.getMaxLifetime(token) - tss.getIssueTime(token));
  }


  @Test
  public void testTokenRevocation_ServerManagedStateNotConfigured() throws Exception {
    Response renewalResponse = doTestTokenRevocation(null, null, null);
    validateRevocationResponse(renewalResponse,
                               400,
                               false,
                               "Token revocation support is not configured", TokenResource.ErrorCode.CONFIGURATION_ERROR);
  }

  @Test
  public void testTokenRevocation_Disabled() throws Exception {
    Response renewalResponse = doTestTokenRevocation(false, null, null);
    validateRevocationResponse(renewalResponse,
                               400,
                               false,
                               "Token revocation support is not configured", TokenResource.ErrorCode.CONFIGURATION_ERROR);
  }

  @Test
  public void testTokenRevocation_Enabled_NoRenewersNoSubject() throws Exception {
    Response renewalResponse = doTestTokenRevocation(true, null, null);
    validateRevocationResponse(renewalResponse,
                               403,
                               false,
                               "Caller (null) not authorized to revoke tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRevocation_Enabled_NoRenewersWithSubject() throws Exception {
    final String caller = "yarn";
    Response renewalResponse = doTestTokenRevocation(true, null, createTestSubject(caller));
    validateRevocationResponse(renewalResponse,
                               403,
                               false,
                               "Caller (" + caller + ") not authorized to revoke tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRevocation_Enabled_WithRenewersNoSubject() throws Exception {
    Response renewalResponse = doTestTokenRevocation(true, "larry, moe,  curly ", null);
    validateRevocationResponse(renewalResponse,
                               403,
                               false,
                               "Caller (null) not authorized to revoke tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRevocation_Enabled_WithRenewersWithInvalidSubject() throws Exception {
    final String caller = "shemp";
    Response renewalResponse = doTestTokenRevocation(true, "larry, moe,  curly ", createTestSubject(caller));
    validateRevocationResponse(renewalResponse,
                               403,
                               false,
                               "Caller (" + caller + ") not authorized to revoke tokens.", TokenResource.ErrorCode.UNAUTHORIZED);
  }

  @Test
  public void testTokenRevocation_Enabled_WithRenewersWithValidSubject() throws Exception {
    final String caller = "shemp";
    Response renewalResponse =
        doTestTokenRevocation(true, ("larry, moe,  curly ," + caller), createTestSubject(caller));
    validateSuccessfulRevocationResponse(renewalResponse);
  }

  @Test
  public void testTokenRevocation_Enabled_RevokeOwnToken() throws Exception {
    final Response renewalResponse = doTestTokenRevocation(true, null, createTestSubject(USER_NAME));
    validateSuccessfulRevocationResponse(renewalResponse);
  }

  @Test
  public void testKidJkuClaims() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.ttl", "60000");
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    Response retResponse = tr.doGet();

    assertEquals(200, retResponse.getStatus());

    // Parse the response
    final String retString = retResponse.getEntity().toString();
    final String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);

    // Verify the token
    final JWT parsedToken = new JWTToken(accessToken);
    assertEquals("alice", parsedToken.getSubject());
    assertTrue(authority.verifyToken(parsedToken));

    assertNotNull(parsedToken.getClaim("kid"));
    assertEquals(TOKEN_API_PATH+JKWS_PATH, parsedToken.getClaim("jku"));
  }

  @Test
  public void testGetTokenStateStatusTokenStateServiceNotEnabled() throws Exception {
    testGetTokenStateStatus(Collections.singletonMap(TokenStateService.CONFIG_SERVER_MANAGED, "false"), "false", null, null, null);
  }

  @Test
  public void testGetTokenStateStatusTokenStateServiceConfiguredProperly() throws Exception {
    final Map<String, String> expectations = new HashMap<>();
    expectations.put(TokenStateService.CONFIG_SERVER_MANAGED, "true");
    expectations.put(ServiceType.TOKEN_STATE_SERVICE.getShortName(), TestTokenStateService.class.getCanonicalName());
    testGetTokenStateStatus(expectations, "true", "TestTokenStateService", "TestTokenStateService", "false");
  }

  @Test
  public void testGetTokenStateStatusTokenStateServiceIsMisconfigured() throws Exception {
    final Map<String, String> expectations = new HashMap<>();
    expectations.put(TokenStateService.CONFIG_SERVER_MANAGED, "true");
    expectations.put(ServiceType.TOKEN_STATE_SERVICE.getShortName(), JDBCTokenStateService.class.getCanonicalName());
    testGetTokenStateStatus(expectations, "true", "JDBCTokenStateService", "TestTokenStateService", "false");
  }

  private void testGetTokenStateStatus(Map<String, String> expectations, String expectedTokenManagementFlag, String expectedConfiguredTssBackend, String expectedActualTssBackend,
      String expectedAllowedTssFlag) throws Exception {
    configureCommonExpectations(expectations);

    final TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    final Response response = tr.getTokenStateServiceStatus();
    assertEquals(200, response.getStatus());
    final String statusJson = response.getEntity().toString();
    final Map<String, String> statusMap = JsonUtils.getMapFromJsonString(statusJson);
    if (expectedTokenManagementFlag != null) {
      assertEquals(statusMap.get("tokenManagementEnabled"), expectedTokenManagementFlag);
    }
    if (expectedConfiguredTssBackend != null) {
      assertEquals(statusMap.get("configuredTssBackend"), expectedConfiguredTssBackend);
    }
    if (expectedActualTssBackend != null) {
      assertEquals(statusMap.get("actualTssBackend"), expectedActualTssBackend);
    }
    if (expectedAllowedTssFlag != null) {
      assertEquals(statusMap.get("allowedTssForTokengen"), expectedAllowedTssFlag);
    }
    assertTrue(Boolean.parseBoolean(statusMap.get("lifespanInputEnabled")));
  }

  @Test
  public void testGettingTokenWithLifespanLessThanConfiguredTTL() throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.ttl", "172800000"); // 2 days
    contextExpectations.put(TokenResource.LIFESPAN, "P1DT0H0M"); // 1 day 0 hour 0 minute
    configureCommonExpectations(contextExpectations);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    final Response retResponse = tr.doGet();
    final String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);

    // Verify the token
    final JWT parsedToken = new JWTToken(accessToken);
    assertTrue(authority.verifyToken(parsedToken));

    final Date expiresDate = parsedToken.getExpiresDate();

    final Calendar nowPlus23Hours = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
    nowPlus23Hours.add(Calendar.HOUR_OF_DAY, 23);

    final Calendar tomorrowPlus23Hours = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
    tomorrowPlus23Hours.add(Calendar.HOUR_OF_DAY, 47);

    final long oneHourInMills = 3600000L;
    assertTrue(expiresDate.after(nowPlus23Hours.getTime()));
    assertTrue(expiresDate.before(tomorrowPlus23Hours.getTime())); // make sure the supplied lifespan was used and not the configured TTL
    assertTrue((expiresDate.getTime() - nowPlus23Hours.getTime().getTime()) < oneHourInMills);
  }

  @Test
  public void testGettingTokenWithLifespanGreaterThanConfiguredTTL() throws Exception {
    testGettingTokenWithConfiguredTTL("P1D");
  }

  @Test
  public void testGettingTokenWithConfiguredTTLIfLifespanIsInvalid() throws Exception {
    testGettingTokenWithConfiguredTTL("InvalidLifespanPattern");
  }

  private void testGettingTokenWithConfiguredTTL(String lifespan) throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    final long oneMinute = 60000L;
    contextExpectations.put("knox.token.ttl", String.valueOf(oneMinute));
    contextExpectations.put(TokenResource.LIFESPAN, lifespan); // 1 day
    configureCommonExpectations(contextExpectations);

    final TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Issue a token
    final Response retResponse = tr.doGet();
    final String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);

    // Verify the token
    final JWT parsedToken = new JWTToken(accessToken);
    assertTrue(authority.verifyToken(parsedToken));

    final Date expiresDate = parsedToken.getExpiresDate();
    final Date now = new Date();

    assertTrue(expiresDate.after(now));
    assertTrue((expiresDate.getTime() - now.getTime()) < oneMinute); // the configured TTL was used even if lifespan was supplied
  }

  @Test
  public void testConfiguredTokenLimitPerUser() throws Exception {
    testLimitingTokensPerUser(KNOX_TOKEN_USER_LIMIT_DEFAULT, KNOX_TOKEN_USER_LIMIT_DEFAULT);
  }

  @Test
  public void testUnlimitedTokensPerUser() throws Exception {
    testLimitingTokensPerUser(-1, 100);
  }

  @Test
  public void testTokenLimitChangeAfterAlreadyHavingTokens() throws Exception {
    Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put(KNOX_TOKEN_USER_LIMIT, "-1");
    configureCommonExpectations(contextExpectations, Boolean.TRUE);
    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();
    // already have N tokens
    int numberOfPreExistingTokens = 5;
    for (int i = 0; i < numberOfPreExistingTokens; i++) {
      tr.doGet();
    }
    Response getKnoxTokensResponse = getUserTokensResponse(tr);
    Collection<String> tokens = ((Map<String, Collection<String>>) JsonUtils.getObjectFromJsonString(getKnoxTokensResponse.getEntity().toString()))
            .get("tokens");
    assertEquals(tokens.size(), numberOfPreExistingTokens);
    // change the limit and try generate one more
    contextExpectations.put(KNOX_TOKEN_USER_LIMIT, Integer.toString(numberOfPreExistingTokens -1));
    configureCommonExpectations(contextExpectations, Boolean.TRUE);
    tr.request = request;
    tr.context = context;
    tr.init();
    Response response = tr.doGet();
    assertTrue(response.getEntity().toString().contains("Unable to get token - token limit exceeded."));
  }

  private Response getUserTokensResponse(TokenResource tokenResource) {
    return getUserTokensResponse(tokenResource, false);
  }

  private Response getUserTokensResponse(TokenResource tokenResource, boolean createdBy) {
    final MultivaluedMap<String, String> queryParameters = new MultivaluedHashMap<>();
    queryParameters.put(createdBy ? "createdBy" : "userName", Arrays.asList(USER_NAME));
    final UriInfo uriInfo = EasyMock.createNiceMock(UriInfo.class);
    EasyMock.expect(uriInfo.getQueryParameters()).andReturn(queryParameters).anyTimes();
    EasyMock.replay(uriInfo);
    return tokenResource.getUserTokens(uriInfo);
  }

  @Test
  public void testTokenLimitPerUserExceeded() throws Exception {
    try {
      testLimitingTokensPerUser(10, 11);
      fail("Exception should have been thrown");
    } catch (Exception e) {
      assertTrue(e.getMessage().contains("Unable to get token - token limit exceeded."));
    }
  }

  @Test
  public void testTokenLimitPerUserExceededShouldRevokeOldestToken() throws Exception {
    try {
      testLimitingTokensPerUser(10, 11, true);
    } catch (Exception e) {
      fail("Exception should NOT have been thrown");
    }
  }

  private void testLimitingTokensPerUser(int configuredLimit, int numberOfTokens) throws Exception {
    testLimitingTokensPerUser(configuredLimit, numberOfTokens, false);
  }

  private void testLimitingTokensPerUser(int configuredLimit, int numberOfTokens, boolean revokeOldestToken) throws Exception {
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put(KNOX_TOKEN_USER_LIMIT, String.valueOf(configuredLimit));
    if (revokeOldestToken) {
      contextExpectations.put(KNOX_TOKEN_USER_LIMIT_EXCEEDED_ACTION, TokenResource.UserLimitExceededAction.REMOVE_OLDEST.name());
    }
    configureCommonExpectations(contextExpectations, Boolean.TRUE);

    final TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    for (int i = 0; i < numberOfTokens; i++) {
      final Response getTokenResponse = Subject.doAs(createTestSubject(USER_NAME), (PrivilegedAction<Response>) () -> tr.doGet());
      if (getTokenResponse.getStatus() != Response.Status.OK.getStatusCode()) {
        throw new Exception(getTokenResponse.getEntity().toString());
      }
    }
    final Response getKnoxTokensResponse = getUserTokensResponse(tr);
    final Collection<String> tokens = ((Map<String, Collection<String>>) JsonUtils.getObjectFromJsonString(getKnoxTokensResponse.getEntity().toString()))
        .get("tokens");
    assertEquals(tokens.size(), revokeOldestToken ? configuredLimit : numberOfTokens);
  }

  @Test
  public void testCreateImpersonatedToken() throws Exception {
    testCreateImpersonatedToken(true);
  }

  @Test
  public void testImpersonationDisabled() throws Exception {
    testCreateImpersonatedToken(false);
  }

  private void testCreateImpersonatedToken(boolean enableImpersonation) throws Exception {
    final String impersonatedUser = "testUser";
    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put(TokenResource.QUERY_PARAMETER_DOAS, impersonatedUser);
    contextExpectations.put(TokenResource.PROXYUSER_PREFIX + "." + USER_NAME + ".users", impersonatedUser);
    contextExpectations.put(TokenResource.PROXYUSER_PREFIX + "." + USER_NAME + ".hosts", "*");
    contextExpectations.put(TokenResource.IMPERSONATION_ENABLED_PARAM, Boolean.toString(enableImpersonation));
    configureCommonExpectations(contextExpectations, Boolean.TRUE);

    final TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    tr.doGet();

    final Response getKnoxTokensResponse = getUserTokensResponse(tr, enableImpersonation);
    final Collection<LinkedHashMap<String, Object>> tokens = ((Map<String, Collection<LinkedHashMap<String, Object>>>) JsonUtils
        .getObjectFromJsonString(getKnoxTokensResponse.getEntity().toString())).get("tokens");
    final LinkedHashMap<String, Object> knoxToken = tokens.iterator().next();
    final Map<String, String> metadata = (Map<String, String>) knoxToken.get("metadata");
    if (enableImpersonation) {
      assertEquals(metadata.get("createdBy"), USER_NAME);
      assertEquals(metadata.get("userName"), impersonatedUser);
    } else {
      assertNull(metadata.get("createdBy"));
      assertEquals(USER_NAME, metadata.get("userName"));
    }
  }

  @Test
  public void testDefaultIssuer() throws Exception {
    Map<String, String> contextExpectations = new HashMap<>();
    configureCommonExpectations(contextExpectations, Boolean.TRUE);

    TokenResource tr = new TokenResource();
    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(DEFAULT_ISSUER, payload.get("iss"));
  }

  @Test
  public void testConfiguredIssuer() throws Exception {
    Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put(KNOX_TOKEN_ISSUER, "test issuer");
    configureCommonExpectations(contextExpectations, Boolean.TRUE);

    TokenResource tr = new TokenResource();
    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("test issuer", payload.get("iss"));
  }

  @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());
  }

  @Test
  public void passcodeShouldNotBeInResponseIfTokenStateServiceIsDisabled() throws Exception {
    testPasscodeToken(false, false, false);
  }

  @Test
  public void passcodeShouldNotBeInResponseIfTokenStateServiceIsNotPersistent() throws Exception {
    testPasscodeToken(true, false, false);
  }

  @Test
  public void passcodeShouldBeInResponseIfTokenStateServiceIsEnabledAndPersistent() throws Exception {
    testPasscodeToken(true, true, true);
  }

  private void testPasscodeToken(boolean serverManagedTssEnabled, boolean usePersistentTokenStore, boolean expectPasscodeInResponse) throws Exception {
    try {
      if (usePersistentTokenStore) {
        tss = new PersistentTestTokenStateService();
      }
      configureCommonExpectations(new HashMap<>(), serverManagedTssEnabled);

      final TokenResource tr = new TokenResource();
      tr.context = context;
      tr.request = request;
      tr.init();

      // Issue a token
      final Response response = tr.doGet();
      assertEquals(200, response.getStatus());
      final String retString = response.getEntity().toString();
      final String passcode = getTagValue(retString, TokenResource.PASSCODE);
      if (expectPasscodeInResponse) {
        assertNotNull(passcode);
      } else {
        assertNull(passcode);
      }
    } finally {
      tss = new TestTokenStateService();
    }
  }

  /**
   *
   * @param isTokenStateServerManaged true, if server-side token state management should be enabled; Otherwise, false or null.
   * @param renewers A comma-delimited list of permitted renewer user names
   * @param caller The user name making the request
   *
   * @return The Response from the token renewal request
   *
   * @throws Exception
   */
  private Response doTestTokenRenewal(final Boolean isTokenStateServerManaged,
                                      final String  renewers,
                                      final Subject caller) throws Exception {
    return doTestTokenRenewal(isTokenStateServerManaged, renewers, null, caller).getValue();
  }

  /**
   *
   * @param isTokenStateServerManaged true, if server-side token state management should be enabled; Otherwise, false or null.
   * @param renewers                  A comma-delimited list of permitted renewer user names
   * @param maxTokenLifetime          The maximum duration (milliseconds) for a token's lifetime
   * @param caller                    The user name making the request
   *
   * @return The Response from the token renewal request
   *
   * @throws Exception
   */
  private Map.Entry<TestTokenStateService, Response> doTestTokenRenewal(final Boolean isTokenStateServerManaged,
                                                                        final String  renewers,
                                                                        final Long    maxTokenLifetime,
                                                                        final Subject caller) throws Exception {
    return doTestTokenRenewal(isTokenStateServerManaged,
                              null,
                              renewers,
                              maxTokenLifetime,
                              caller);
  }

  /**
   *
   * @param serviceLevelConfig true, if server-side token state management should be enabled; Otherwise, false or null.
   * @param gatewayLevelConfig true, if server-side token state management should be enabled; Otherwise, false or null.
   * @param renewers           A comma-delimited list of permitted renewer user names
   * @param maxTokenLifetime   The maximum duration (milliseconds) for a token's lifetime
   * @param caller             The user name making the request
   *
   * @return The Response from the token renewal request
   *
   * @throws Exception
   */
  private Map.Entry<TestTokenStateService, Response> doTestTokenRenewal(final Boolean serviceLevelConfig,
                                                                        final Boolean gatewayLevelConfig,
                                                                        final String  renewers,
                                                                        final Long    maxTokenLifetime,
                                                                        final Subject caller) throws Exception {
    return doTestTokenLifecyle(TokenLifecycleOperation.Renew,
                               serviceLevelConfig,
                               gatewayLevelConfig,
                               renewers,
                               maxTokenLifetime,
                               caller);
  }


  /**
   *
   * @param isTokenStateServerManaged true, if server-side token state management should be enabled; Otherwise, false or null.
   * @param renewers A comma-delimited list of permitted renewer user names
   * @param caller The user name making the request
   *
   * @return The Response from the token revocation request
   *
   * @throws Exception
   */
  private Response doTestTokenRevocation(final Boolean isTokenStateServerManaged,
                                         final String  renewers,
                                         final Subject caller) throws Exception {
    return doTestTokenLifecyle(TokenLifecycleOperation.Revoke, isTokenStateServerManaged, renewers, caller);
  }

  /**
   * @param operation     A TokenLifecycleOperation
   * @param serverManaged true, if server-side token state management should be enabled; Otherwise, false or null.
   * @param renewers      A comma-delimited list of permitted renewer user names
   * @param caller        The user name making the request
   *
   * @return The Response from the token revocation request
   *
   * @throws Exception
   */
  private Response doTestTokenLifecyle(final TokenLifecycleOperation operation,
                                       final Boolean                 serverManaged,
                                       final String                  renewers,
                                       final Subject                 caller) throws Exception {
    return doTestTokenLifecyle(operation, serverManaged, renewers, null, caller).getValue();
  }

  /**
   * @param operation          A TokenLifecycleOperation
   * @param serviceLevelConfig true, if server-side token state management should be enabled at the service level;
   *                           Otherwise, false or null.
   * @param renewers           A comma-delimited list of permitted renewer user names
   * @param maxTokenLifetime   The maximum lifetime duration for a token.
   * @param caller             The user name making the request
   *
   * @return The Response from the token revocation request
   *
   * @throws Exception
   */
  private Map.Entry<TestTokenStateService, Response> doTestTokenLifecyle(final TokenLifecycleOperation operation,
                                                                         final Boolean                 serviceLevelConfig,
                                                                         final String                  renewers,
                                                                         final Long                    maxTokenLifetime,
                                                                         final Subject                 caller) throws Exception {
    return doTestTokenLifecyle(operation, serviceLevelConfig, null, renewers, maxTokenLifetime, caller);
  }

  /**
   * @param operation          A TokenLifecycleOperation
   * @param serviceLevelConfig true, if server-side token state management should be enabled at the service level;
   *                           Otherwise, false or null.
   * @param gatewayLevelConfig true, if server-side token state management should be enabled at the gateway level;
   *                           Otherwise, false or null.
   * @param renewers           A comma-delimited list of permitted renewer user names
   * @param maxTokenLifetime   The maximum lifetime duration for a token.
   * @param caller             The user name making the request
   *
   * @return The Response from the token revocation request
   *
   * @throws Exception
   */
  private Map.Entry<TestTokenStateService, Response> doTestTokenLifecyle(final TokenLifecycleOperation operation,
                                                                         final Boolean                 serviceLevelConfig,
                                                                         final Boolean                 gatewayLevelConfig,
                                                                         final String                  renewers,
                                                                         final Long                    maxTokenLifetime,
                                                                         final Subject                 caller) throws Exception {

    final Map<String, String> contextExpectations = new HashMap<>();
    contextExpectations.put("knox.token.audiences", "recipient1,recipient2");
    contextExpectations.put("knox.token.ttl", String.valueOf(Long.MAX_VALUE));
    if (serviceLevelConfig != null) {
      contextExpectations.put("knox.token.exp.server-managed", String.valueOf(serviceLevelConfig));
      if (maxTokenLifetime != null) {
        contextExpectations.put("knox.token.exp.renew-interval", String.valueOf(maxTokenLifetime / 2));
        contextExpectations.put("knox.token.exp.max-lifetime", maxTokenLifetime.toString());
      }
    }
    contextExpectations.put("knox.token.renewer.whitelist", renewers);

    configureCommonExpectations(contextExpectations, gatewayLevelConfig);

    TokenResource tr = new TokenResource();
    tr.request = request;
    tr.context = context;
    tr.init();

    // Request a token
    Response retResponse = tr.doGet();
    assertEquals(200, retResponse.getStatus());

    // Parse the response
    String retString = retResponse.getEntity().toString();
    String accessToken = getTagValue(retString, "access_token");
    assertNotNull(accessToken);

    Response response;
    switch (operation) {
      case Renew:
        response = requestTokenRenewal(tr, accessToken, caller);
        break;
      case Revoke:
        response = requestTokenRevocation(tr, accessToken, caller);
        break;
      default:
        throw new Exception("Invalid operation: " + operation);
    }

    return new AbstractMap.SimpleEntry<>(tss, response);
  }

  private static Response requestTokenRenewal(final TokenResource tr, final String tokenData, final Subject caller) {
    Response response;
    if (caller != null) {
      response = Subject.doAs(caller, (PrivilegedAction<Response>) () -> tr.renew(tokenData));
    } else {
      response = tr.renew(tokenData);
    }
    return response;
  }

  private static Response requestTokenRevocation(final TokenResource tr, final String tokenData, final Subject caller) {
    Response response;
    if (caller != null) {
      response = Subject.doAs(caller, (PrivilegedAction<Response>) () -> tr.revoke(tokenData));
    } else {
      response = tr.revoke(tokenData);
    }
    return response;
  }

  private static void validateSuccessfulRenewalResponse(final Response response) throws IOException {
    validateRenewalResponse(response, 200, true, null, null);
  }

  private static void validateRenewalResponse(final Response response,
                                              final int      expectedStatusCode,
                                              final boolean  expectedResult,
                                              final String   expectedMessage,
                                              final TokenResource.ErrorCode expectedCode) throws IOException {
    assertEquals(expectedStatusCode, response.getStatus());
    assertTrue(response.hasEntity());
    String responseContent = (String) response.getEntity();
    assertNotNull(responseContent);
    assertFalse(responseContent.isEmpty());
    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(), json.get("code"));
    }
  }

  private static void validateSuccessfulRevocationResponse(final Response response) throws IOException {
    validateRevocationResponse(response, 200, true, null, null);
  }

  private static void validateRevocationResponse(final Response response,
                                                 final int      expectedStatusCode,
                                                 final boolean  expectedResult,
                                                 final String   expectedMessage,
                                                 final TokenResource.ErrorCode expectedCode) throws IOException {
    assertEquals(expectedStatusCode, response.getStatus());
    assertTrue(response.hasEntity());
    String responseContent = (String) response.getEntity();
    assertNotNull(responseContent);
    assertFalse(responseContent.isEmpty());
    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(), json.get("code"));
    }
  }


  private String getTagValue(String token, String tagName) {
    if (!token.contains(tagName)) {
      return null;
    }
    String searchString = tagName + "\":";
    String value = token.substring(token.indexOf(searchString) + searchString.length());
    if (value.startsWith("\"")) {
      value = value.substring(1);
    }
    if (value.contains("\"")) {
      return value.substring(0, value.indexOf('\"'));
    } else if (value.contains(",")) {
      return value.substring(0, value.indexOf(','));
    } else {
      return value.substring(0, value.length() - 1);
    }
  }

  /**
   * Create a Subject for testing.
   *
   * @param username The user identifier
   *
   * @return A Subject
   */
  private Subject createTestSubject(final String username) {
    Subject s = new Subject();

    Set<Principal> principals = s.getPrincipals();
    principals.add(new PrimaryPrincipal(username));

    return s;
  }

  private static Map<String, Object> parseJSONResponse(final String response) throws IOException {
    return (new ObjectMapper()).readValue(response, new TypeReference<Map<String, Object>>(){});
  }


  private static class TestTokenStateService implements TokenStateService {

    private Map<String, Long> expirationData = new HashMap<>();
    private Map<String, Long> issueTimes = new HashMap<>();
    private Map<String, Long> maxLifetimes = new HashMap<>();
    private final Map<String, TokenMetadata> tokenMetadata = new ConcurrentHashMap<>();

    long getIssueTime(final String token) {
      return issueTimes.get(token);
    }

    long getMaxLifetime(final String token) {
      return maxLifetimes.get(token);
    }

    @Override
    public long getTokenIssueTime(String tokenId) throws UnknownTokenException {
      return issueTimes.getOrDefault(tokenId, 0L);
    }

    @Override
    public void addToken(JWTToken token, long issueTime) {
      addToken(TokenUtils.getTokenId(token), issueTime, token.getExpiresDate().getTime());
    }

    @Override
    public long getDefaultRenewInterval() {
      return 250;
    }

    @Override
    public long getDefaultMaxLifetimeDuration() {
      return 500;
    }

    @Override
    public void addToken(String tokenId, long issueTime, long expiration) {
      addToken(tokenId, issueTime, expiration, getDefaultMaxLifetimeDuration());
    }

    @Override
    public void addToken(String tokenId, long issueTime, long expiration, long maxLifetimeDuration) {
      issueTimes.put(tokenId, issueTime);
      expirationData.put(tokenId, expiration);
      maxLifetimes.put(tokenId, issueTime + maxLifetimeDuration);
    }

    @Override
    public boolean isExpired(JWTToken token) {
      return false;
    }

    @Override
    public void revokeToken(JWTToken token) {
      revokeToken(TokenUtils.getTokenId(token));
    }

    @Override
    public void revokeToken(String tokenId) {
      issueTimes.remove(tokenId);
      expirationData.remove(tokenId);
      maxLifetimes.remove(tokenId);
      tokenMetadata.remove(tokenId);
    }

    @Override
    public long renewToken(JWTToken token) {
      return renewToken(TokenUtils.getTokenId(token));
    }

    @Override
    public long renewToken(String tokenId) {
      return renewToken(tokenId, 0L);
    }

    @Override
    public long renewToken(JWTToken token, long renewInterval) {
      return renewToken(TokenUtils.getTokenId(token), renewInterval);
    }

    @Override
    public long renewToken(String tokenId, long renewInterval) {
      return 0;
    }

    @Override
    public long getTokenExpiration(JWT token) throws UnknownTokenException {
      return 0;
    }

    @Override
    public long getTokenExpiration(String tokenId) {
      return expirationData.getOrDefault(tokenId, 0L);
    }

    @Override
    public long getTokenExpiration(String tokenId, boolean validate) throws UnknownTokenException {
      return 0;
    }

    @Override
    public void addMetadata(String tokenId, TokenMetadata metadata) {
      tokenMetadata.put(tokenId, metadata);
    }

    @Override
    public TokenMetadata getTokenMetadata(String tokenId) throws UnknownTokenException {
      return tokenMetadata.get(tokenId);
    }

    @Override
    public Collection<KnoxToken> getTokens(String userName) {
      return fetchTokens(userName, false);
    }

    @Override
    public Collection<KnoxToken> getDoAsTokens(String createdBy) {
      return fetchTokens(createdBy, true);
    }

    private Collection<KnoxToken> fetchTokens(String userName, boolean createdBy) {
      final Collection<KnoxToken> tokens = new TreeSet<>();
      final Predicate<Map.Entry<String, TokenMetadata>> filterPredicate;
      if (createdBy) {
        filterPredicate = entry -> userName.equals(entry.getValue().getCreatedBy());
      } else {
        filterPredicate = entry -> userName.equals(entry.getValue().getUserName());
      }
      tokenMetadata.entrySet().stream().filter(filterPredicate).forEach(metadata -> {
        String tokenId = metadata.getKey();
        try {
          tokens.add(new KnoxToken(tokenId, getTokenIssueTime(tokenId), getTokenExpiration(tokenId), getMaxLifetime(tokenId), metadata.getValue()));
        } catch (UnknownTokenException e) {
          // NOP
        }
      });
      return tokens;
    }

    @Override
    public void init(GatewayConfig config, Map<String, String> options) throws ServiceLifecycleException {
    }

    @Override
    public void start() throws ServiceLifecycleException {
    }

    @Override
    public void stop() throws ServiceLifecycleException {
    }
  }

  private static class PersistentTestTokenStateService extends TestTokenStateService implements PersistentTokenStateService {
  }

  private static class TestJWTokenAuthority implements JWTokenAuthority {

    private RSAPublicKey publicKey;
    private RSAPrivateKey privateKey;

    TestJWTokenAuthority(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
      this.publicKey = publicKey;
      this.privateKey = privateKey;
    }

    @Override
    public boolean verifyToken(JWT token) {
      JWSVerifier verifier = new RSASSAVerifier(publicKey);
      return token.verify(verifier);
    }

    @Override
    public JWT issueToken(JWTokenAttributes jwtAttributes) {
      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] = jwtAttributes.getJku();

      jwtAttributes.setKid("E0LDZulQ0XE_otJ5aoQtQu-RnXv8hU-M9U4dD7vDioA");
      JWT token = new JWTToken(jwtAttributes);
      JWSSigner signer = new RSASSASigner(privateKey);
      token.sign(signer);

      return token;
    }


    @Override
    public boolean verifyToken(JWT token, RSAPublicKey publicKey) {
      JWSVerifier verifier = new RSASSAVerifier(publicKey);
      return token.verify(verifier);
    }

    @Override
    public boolean verifyToken(JWT token, String jwksurl, String algorithm, Set<JOSEObjectType> allowedJwsTypes) {
     return false;
    }
  }
}
