// KEYCLOAK-3823: Test that sending notBefore policy invalidates JWKPublicKeyLocator cache
  @Test
  public void testPublicKeyCacheInvalidatedWhenPushedNotBefore() {
    driver.manage().timeouts().pageLoadTimeout(1000, TimeUnit.SECONDS);

    // increase accessTokenLifespan to 1200
    RealmRepresentation demoRealm = adminClient.realm(DEMO).toRepresentation();
    demoRealm.setAccessTokenLifespan(1200);
    adminClient.realm(DEMO).update(demoRealm);

    // authenticate in tokenMinTTL app
    loginToTokenMinTtlApp();
    String accessTokenString = tokenMinTTLPage.getAccessTokenString();

    // Generate new realm public key
    String oldActiveKeyProviderId = getActiveKeyProvider();

    generateNewRealmKey();

    // Send REST request to customer-db app. It should be successfully authenticated even that token
    // is signed by the old key
    int status = invokeRESTEndpoint(accessTokenString);
    Assert.assertEquals(200, status);

    // Remove the old realm key now
    adminClient.realm(DEMO).components().component(oldActiveKeyProviderId).remove();

    // Set some offset to ensure pushing notBefore will pass
    setAdapterAndServerTimeOffset(
        130,
        customerDb.toString() + "/unsecured/foo",
        tokenMinTTLPage.toString() + "/unsecured/foo");

    // Send notBefore policy from the realm
    demoRealm.setNotBefore(Time.currentTime() - 1);
    adminClient.realm(DEMO).update(demoRealm);
    GlobalRequestResult result = adminClient.realm(DEMO).pushRevocation();
    Assert.assertTrue(result.getSuccessRequests().contains(customerDb.toString()));

    // Send REST request. New request to the publicKey cache should be sent, and key is no longer
    // returned as token contains the old kid
    status = invokeRESTEndpoint(accessTokenString);
    Assert.assertEquals(401, status);

    // Revert public keys change and time offset
    resetKeycloakDeploymentForAdapter(customerDb.toString() + "/unsecured/foo");
    resetKeycloakDeploymentForAdapter(tokenMinTTLPage.toString() + "/unsecured/foo");
  }
  // KEYCLOAK-3824: Test for public-key-cache-ttl
  @Test
  public void testPublicKeyCacheTtl() {
    // increase accessTokenLifespan to 1200
    RealmRepresentation demoRealm = adminClient.realm(DEMO).toRepresentation();
    demoRealm.setAccessTokenLifespan(1200);
    adminClient.realm(DEMO).update(demoRealm);

    // authenticate in tokenMinTTL app
    loginToTokenMinTtlApp();
    String accessTokenString = tokenMinTTLPage.getAccessTokenString();

    // Send REST request to customer-db app. I should be successfully authenticated
    int status = invokeRESTEndpoint(accessTokenString);
    Assert.assertEquals(200, status);

    // Re-generate realm public key and remove the old key
    String oldActiveKeyProviderId = getActiveKeyProvider();
    generateNewRealmKey();
    adminClient.realm(DEMO).components().component(oldActiveKeyProviderId).remove();

    // Send REST request to the customer-db app. Should be still succcessfully authenticated as the
    // JWKPublicKeyLocator cache is still valid
    status = invokeRESTEndpoint(accessTokenString);
    Assert.assertEquals(200, status);

    // TimeOffset to 900 on the REST app side. Token is still valid (1200) but JWKPublicKeyLocator
    // should try to download new key (public-key-cache-ttl=600)
    setAdapterAndServerTimeOffset(900, customerDb.toString() + "/unsecured/foo");

    // Send REST request. New request to the publicKey cache should be sent, and key is no longer
    // returned as token contains the old kid
    status = invokeRESTEndpoint(accessTokenString);
    Assert.assertEquals(401, status);

    // Revert public keys change and time offset
    resetKeycloakDeploymentForAdapter(customerDb.toString() + "/unsecured/foo");
    resetKeycloakDeploymentForAdapter(tokenMinTTLPage.toString() + "/unsecured/foo");
  }
  @Test
  public void testRealmKeyRotationWithNewKeyDownload() throws Exception {
    // Login success first
    loginToTokenMinTtlApp();

    // Logout
    String logoutUri =
        OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
            .queryParam(OAuth2Constants.REDIRECT_URI, tokenMinTTLPage.toString())
            .build("demo")
            .toString();
    driver.navigate().to(logoutUri);
    assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);

    // Generate new realm key
    generateNewRealmKey();

    // Try to login again. It should fail now because not yet allowed to download new keys
    tokenMinTTLPage.navigateTo();
    testRealmLoginPage.form().waitForUsernameInputPresent();
    assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
    testRealmLoginPage.form().login("*****@*****.**", "password");
    URLAssert.assertCurrentUrlStartsWith(driver, tokenMinTTLPage.getInjectedUrl().toString());
    Assert.assertNull(tokenMinTTLPage.getAccessToken());

    driver.navigate().to(logoutUri);
    assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);

    setAdapterAndServerTimeOffset(300, tokenMinTTLPage.toString() + "/unsecured/foo");

    // Try to login. Should work now due to realm key change
    loginToTokenMinTtlApp();
    driver.navigate().to(logoutUri);

    // Revert public keys change
    resetKeycloakDeploymentForAdapter(tokenMinTTLPage.toString() + "/unsecured/foo");
  }