KEYCLOAK-17457 Failed OfflineServletsAdapterTest
This commit is contained in:
parent
1e2db74d86
commit
ca019c36e8
3 changed files with 157 additions and 100 deletions
|
@ -12,8 +12,9 @@ import java.util.Map;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Updater for client attributes. See {@link ServerResourceUpdater} for further details.
|
||||
|
|
|
@ -214,15 +214,19 @@ public abstract class AbstractServletsAdapterTest extends AbstractAdapterTest {
|
|||
setTimeOffset(timeOffset);
|
||||
|
||||
for (String servletUri : servletUris) {
|
||||
String timeOffsetUri = UriBuilder.fromUri(servletUri)
|
||||
.queryParam(AdapterActionsFilter.TIME_OFFSET_PARAM, timeOffset)
|
||||
.build().toString();
|
||||
|
||||
DroneUtils.getCurrentDriver().navigate().to(timeOffsetUri);
|
||||
waitForPageToLoad();
|
||||
String pageSource = DroneUtils.getCurrentDriver().getPageSource();
|
||||
System.out.println(pageSource);
|
||||
setAdapterServletTimeOffset(timeOffset, servletUri);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setAdapterServletTimeOffset(int timeOffset, String servletUri) {
|
||||
String timeOffsetUri = UriBuilder.fromUri(servletUri)
|
||||
.queryParam(AdapterActionsFilter.TIME_OFFSET_PARAM, timeOffset)
|
||||
.build().toString();
|
||||
|
||||
DroneUtils.getCurrentDriver().navigate().to(timeOffsetUri);
|
||||
waitForPageToLoad();
|
||||
String pageSource = DroneUtils.getCurrentDriver().getPageSource();
|
||||
log.info(pageSource);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.List;
|
|||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
|
@ -19,20 +18,29 @@ import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
|
|||
import org.keycloak.testsuite.adapter.page.OfflineToken;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
|
||||
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.pages.AccountApplicationsPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.OAuthGrantPage;
|
||||
import org.keycloak.testsuite.util.ClientManager;
|
||||
import org.keycloak.testsuite.utils.io.IOUtil;
|
||||
import org.keycloak.util.TokenUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||
|
||||
/**
|
||||
|
@ -58,6 +66,10 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest {
|
|||
@Page
|
||||
protected OAuthGrantPage oauthGrantPage;
|
||||
|
||||
private final String DEFAULT_USERNAME = "test-user@localhost";
|
||||
private final String DEFAULT_PASSWORD = "password";
|
||||
private final String OFFLINE_CLIENT_ID = "offline-client";
|
||||
|
||||
@Deployment(name = OfflineToken.DEPLOYMENT_NAME)
|
||||
protected static WebArchive offlineClient() {
|
||||
return servletDeployment(OfflineToken.DEPLOYMENT_NAME, AdapterActionsFilter.class, AbstractShowTokensServlet.class, OfflineTokenServlet.class, ErrorServlet.class, ServletTestUtils.class);
|
||||
|
@ -77,131 +89,171 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testServlet() throws Exception {
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
public void testServlet() {
|
||||
try {
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
Assert.assertEquals(TokenUtil.TOKEN_TYPE_OFFLINE, offlineTokenPage.getRefreshToken().getType());
|
||||
Assert.assertEquals(0, offlineTokenPage.getRefreshToken().getExpiration());
|
||||
assertThat(offlineTokenPage.getRefreshToken(), notNullValue());
|
||||
assertThat(TokenUtil.TOKEN_TYPE_OFFLINE, is(offlineTokenPage.getRefreshToken().getType()));
|
||||
assertThat(offlineTokenPage.getRefreshToken().getExp(), nullValue());
|
||||
|
||||
String accessTokenId = offlineTokenPage.getAccessToken().getId();
|
||||
String refreshTokenId = offlineTokenPage.getRefreshToken().getId();
|
||||
String accessTokenId = offlineTokenPage.getAccessToken().getId();
|
||||
String refreshTokenId = offlineTokenPage.getRefreshToken().getId();
|
||||
|
||||
setAdapterAndServerTimeOffset(9999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
Assert.assertNotEquals(offlineTokenPage.getRefreshToken().getId(), refreshTokenId);
|
||||
Assert.assertNotEquals(offlineTokenPage.getAccessToken().getId(), accessTokenId);
|
||||
setAdapterAndServerTimeOffset(9999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
// Ensure that logout works for webapp (even if offline token will be still valid in Keycloak DB)
|
||||
offlineTokenPage.logout();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
assertThat(offlineTokenPage.getRefreshToken().getId(), not(refreshTokenId));
|
||||
assertThat(offlineTokenPage.getAccessToken().getId(), not(accessTokenId));
|
||||
|
||||
setAdapterAndServerTimeOffset(0);
|
||||
events.clear();
|
||||
// Ensure that logout works for webapp (even if offline token will be still valid in Keycloak DB)
|
||||
offlineTokenPage.logout();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
} finally {
|
||||
events.clear();
|
||||
resetTimeOffsetAuthenticated();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServletWithRevoke() {
|
||||
// Login to servlet first with offline token
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
try { // Login to servlet first with offline token
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
|
||||
Assert.assertEquals(TokenUtil.TOKEN_TYPE_OFFLINE, offlineTokenPage.getRefreshToken().getType());
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
// Assert refresh works with increased time
|
||||
setAdapterAndServerTimeOffset(9999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
setAdapterAndServerTimeOffset(0);
|
||||
assertThat(offlineTokenPage.getRefreshToken(), notNullValue());
|
||||
assertThat(offlineTokenPage.getRefreshToken().getType(), is(TokenUtil.TOKEN_TYPE_OFFLINE));
|
||||
|
||||
events.clear();
|
||||
// Assert refresh works with increased time
|
||||
setAdapterAndServerTimeOffset(9999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
setAdapterAndServerTimeOffset(0);
|
||||
|
||||
// Go to account service and revoke grant
|
||||
accountAppPage.open();
|
||||
events.clear();
|
||||
|
||||
List<String> additionalGrants = accountAppPage.getApplications().get("offline-client").getAdditionalGrants();
|
||||
Assert.assertEquals(1, additionalGrants.size());
|
||||
Assert.assertEquals("Offline Token", additionalGrants.get(0));
|
||||
accountAppPage.revokeGrant("offline-client");
|
||||
pause(500);
|
||||
Assert.assertEquals(0, accountAppPage.getApplications().get("offline-client").getAdditionalGrants().size());
|
||||
// Go to account service and revoke grant
|
||||
accountAppPage.open();
|
||||
|
||||
events.expect(EventType.REVOKE_GRANT)
|
||||
.client("account").detail(Details.REVOKED_CLIENT, "offline-client").assertEvent();
|
||||
List<String> additionalGrants = accountAppPage.getApplications().get(OFFLINE_CLIENT_ID).getAdditionalGrants();
|
||||
assertThat(additionalGrants.size(), is(1));
|
||||
assertThat(additionalGrants.get(0), is("Offline Token"));
|
||||
|
||||
// Assert refresh doesn't work now (increase time one more time)
|
||||
setAdapterAndServerTimeOffset(19999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
setAdapterAndServerTimeOffset(0);
|
||||
accountAppPage.revokeGrant(OFFLINE_CLIENT_ID);
|
||||
pause(500);
|
||||
assertThat(accountAppPage.getApplications().get(OFFLINE_CLIENT_ID).getAdditionalGrants().size(), is(0));
|
||||
|
||||
events.expect(EventType.REVOKE_GRANT)
|
||||
.client("account").detail(Details.REVOKED_CLIENT, OFFLINE_CLIENT_ID).assertEvent();
|
||||
|
||||
// Assert refresh doesn't work now (increase time one more time)
|
||||
setAdapterAndServerTimeOffset(19999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
} finally {
|
||||
events.clear();
|
||||
resetTimeOffsetAuthenticated();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServletWithConsent() {
|
||||
ClientManager.realm(adminClient.realm("test")).clientId("offline-client").consentRequired(true);
|
||||
public void testServletWithConsent() throws IOException {
|
||||
try (Closeable cau = ClientAttributeUpdater.forClient(adminClient, TEST, OFFLINE_CLIENT_ID)
|
||||
.setConsentRequired(true).update()) {
|
||||
|
||||
// Assert grant page doesn't have 'Offline Access' role when offline token is not requested
|
||||
offlineTokenPage.navigateTo();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
oauthGrantPage.assertCurrent();
|
||||
waitUntilElement(By.xpath("//body")).text().not().contains("Offline access");
|
||||
oauthGrantPage.cancel();
|
||||
// Assert grant page doesn't have 'Offline Access' role when offline token is not requested
|
||||
offlineTokenPage.navigateTo();
|
||||
|
||||
// Assert grant page has 'Offline Access' role now
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
oauthGrantPage.assertCurrent();
|
||||
waitUntilElement(By.xpath("//body")).text().contains(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT);
|
||||
oauthGrantPage.assertCurrent();
|
||||
waitUntilElement(By.xpath("//body")).text().not().contains("Offline access");
|
||||
oauthGrantPage.cancel();
|
||||
|
||||
oauthGrantPage.accept();
|
||||
// Assert grant page has 'Offline Access' role now
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
Assert.assertEquals(TokenUtil.TOKEN_TYPE_OFFLINE, offlineTokenPage.getRefreshToken().getType());
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
oauthGrantPage.assertCurrent();
|
||||
waitUntilElement(By.xpath("//body")).text().contains(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT);
|
||||
|
||||
accountAppPage.open();
|
||||
AccountApplicationsPage.AppEntry offlineClient = accountAppPage.getApplications().get("offline-client");
|
||||
Assert.assertThat(offlineClient.getClientScopesGranted(), Matchers.hasItem(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT));
|
||||
Assert.assertThat(offlineClient.getAdditionalGrants(), Matchers.hasItem("Offline Token"));
|
||||
oauthGrantPage.accept();
|
||||
|
||||
//This was necessary to be introduced, otherwise other testcases will fail
|
||||
offlineTokenPage.logout();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
assertThat(offlineTokenPage.getRefreshToken(), notNullValue());
|
||||
assertThat(offlineTokenPage.getRefreshToken().getType(), is(TokenUtil.TOKEN_TYPE_OFFLINE));
|
||||
|
||||
events.clear();
|
||||
|
||||
// Revert change
|
||||
ClientManager.realm(adminClient.realm("test")).clientId("offline-client").consentRequired(false);
|
||||
accountAppPage.open();
|
||||
AccountApplicationsPage.AppEntry offlineClient = accountAppPage.getApplications().get(OFFLINE_CLIENT_ID);
|
||||
assertThat(offlineClient.getClientScopesGranted(), Matchers.hasItem(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT));
|
||||
assertThat(offlineClient.getAdditionalGrants(), Matchers.hasItem("Offline Token"));
|
||||
|
||||
//This was necessary to be introduced, otherwise other testcases will fail
|
||||
offlineTokenPage.logout();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
} finally {
|
||||
events.clear();
|
||||
resetTimeOffsetAuthenticated();
|
||||
}
|
||||
}
|
||||
|
||||
private void setAdapterAndServerTimeOffset(int timeOffset) {
|
||||
super.setAdapterAndServerTimeOffset(timeOffset, offlineTokenPage.toString());
|
||||
}
|
||||
|
||||
private void resetTimeOffsetAuthenticated() {
|
||||
resetTimeOffsetAuthenticated(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset time offset for remote environment.
|
||||
* After the token expiration, process of re-authentication is necessary.
|
||||
*
|
||||
* @param username
|
||||
* @param password
|
||||
*/
|
||||
private void resetTimeOffsetAuthenticated(String username, String password) {
|
||||
if (testContext.getAppServerInfo().isUndertow()) {
|
||||
setAdapterAndServerTimeOffset(0);
|
||||
return;
|
||||
}
|
||||
super.setAdapterServletTimeOffset(0, offlineTokenPage.toString());
|
||||
|
||||
if (loginPage.isCurrent()) {
|
||||
loginPage.login(username, password);
|
||||
waitForPageToLoad();
|
||||
offlineTokenPage.logout();
|
||||
}
|
||||
setTimeOffset(0);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue