diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index 845ea3006a..e67ee0eff9 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -362,8 +362,24 @@
}
}
+ function domReady() {
+ var promise = createPromise();
+
+ var checkReadyState = function () {
+ if (document.readyState === 'interactive' || document.readyState === 'complete') {
+ document.removeEventListener('readystatechange', checkReadyState);
+ promise.setSuccess();
+ }
+ }
+ document.addEventListener('readystatechange', checkReadyState);
+
+ checkReadyState(); // just in case the event was already fired and we missed it (in case the init is done later than at the load time, i.e. it's done from code)
+
+ return promise.promise;
+ }
+
configPromise.then(function () {
- check3pCookiesSupported().then(processInit)
+ domReady().then(check3pCookiesSupported).then(processInit)
.catch(function() {
promise.setError();
});
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestJavascriptResource.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestJavascriptResource.java
index 992ab892c2..7bfe6d8163 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestJavascriptResource.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestJavascriptResource.java
@@ -41,6 +41,14 @@ public class TestJavascriptResource {
return resourceToString("/javascript/index.html");
}
+ @GET
+ @Path("/init-in-head.html")
+ @Produces(MediaType.TEXT_HTML)
+ public String getJavascriptTestingEnvironmentWithInitInHead() throws IOException {
+ session.getProvider(SecurityHeadersProvider.class).options().skipHeaders();
+ return resourceToString("/javascript/init-in-head.html");
+ }
+
@GET
@Path("/silent-check-sso.html")
@Produces(MediaType.TEXT_HTML)
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/javascript/init-in-head.html b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/javascript/init-in-head.html
new file mode 100644
index 0000000000..5cea6bd608
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/resources/javascript/init-in-head.html
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+Result
+
+
+Events
+
+
+
+
+
+
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java
index 54b33be1c5..9a2693b0d9 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/javascript/JavascriptTestExecutor.java
@@ -322,4 +322,9 @@ public class JavascriptTestExecutor {
return this;
}
+
+ public JavascriptTestExecutor validateOutputField(JavascriptStateValidator validator) {
+ validator.validate(jsDriver, output, events);
+ return this;
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/javascript/JavascriptAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/javascript/JavascriptAdapterTest.java
index ba30f75e81..97ad45d3f1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/javascript/JavascriptAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/javascript/JavascriptAdapterTest.java
@@ -18,6 +18,8 @@ import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.arquillian.SuiteContext;
+import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
+import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
import org.keycloak.testsuite.auth.page.account.Applications;
import org.keycloak.testsuite.auth.page.login.OAuthGrant;
import org.keycloak.testsuite.auth.page.login.UpdatePassword;
@@ -47,16 +49,11 @@ import static org.hamcrest.collection.IsMapContaining.hasEntry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
-import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
-
-import static org.junit.Assume.assumeFalse;
+import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_HOST;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
-import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_HOST;
/**
* @author mhajas
@@ -65,6 +62,7 @@ import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_HOST;
public class JavascriptAdapterTest extends AbstractJavascriptTest {
private String testAppUrl;
+ private String testAppWithInitInHeadUrl;
protected JavascriptTestExecutor testExecutor;
private static int TIME_SKEW_TOLERANCE = 3;
@@ -90,7 +88,9 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
@Before
public void setDefaultEnvironment() {
- testAppUrl = authServerContextRootPage.toString().replace(AUTH_SERVER_HOST, JS_APP_HOST) + JAVASCRIPT_URL + "/index.html";
+ String testAppRootUrl = authServerContextRootPage.toString().replace(AUTH_SERVER_HOST, JS_APP_HOST) + JAVASCRIPT_URL;
+ testAppUrl = testAppRootUrl + "/index.html";
+ testAppWithInitInHeadUrl = testAppRootUrl + "/init-in-head.html";
jsDriverTestRealmLoginPage.setAuthRealm(REALM_NAME);
oAuthGrantPage.setAuthRealm(REALM_NAME);
@@ -101,10 +101,8 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
events.poll();
jsDriver.manage().deleteAllCookies();
- jsDriver.navigate().to(testAppUrl);
+ navigateToTestApp(testAppUrl);
- waitUntilElement(outputArea).is().present();
- assertCurrentUrlStartsWith(testAppUrl, jsDriver);
testExecutor = JavascriptTestExecutor.create(jsDriver, jsDriverTestRealmLoginPage);
jsDriver.manage().deleteAllCookies();
@@ -121,6 +119,14 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
}
private void assertOnTestAppUrl(WebDriver jsDriver, Object output, WebElement events) {
+ assertOnTestAppUrl(jsDriver, output, events, testAppUrl);
+ }
+
+ private void assertOnTestAppWithInitInHeadUrl(WebDriver jsDriver, Object output, WebElement events) {
+ assertOnTestAppUrl(jsDriver, output, events, testAppWithInitInHeadUrl);
+ }
+
+ private void assertOnTestAppUrl(WebDriver jsDriver, Object output, WebElement events, String testAppUrl) {
waitForPageToLoad();
assertCurrentUrlStartsWith(testAppUrl, jsDriver);
}
@@ -748,7 +754,24 @@ public class JavascriptAdapterTest extends AbstractJavascriptTest {
});
}
+ @Test
+ // KEYCLOAK-15158
+ public void testInitInHead() {
+ navigateToTestApp(testAppWithInitInHeadUrl);
+
+ testExecutor.validateOutputField(this::assertInitNotAuth)
+ .login(this::assertOnLoginPage)
+ .loginForm(testUser, this::assertOnTestAppWithInitInHeadUrl)
+ .validateOutputField(this::assertInitAuth);
+ }
+
protected void assertAdapterIsLoggedIn(WebDriver driver1, Object output, WebElement events) {
assertTrue(testExecutor.isLoggedIn());
}
+
+ protected void navigateToTestApp(final String testAppUrl) {
+ jsDriver.navigate().to(testAppUrl);
+ waitUntilElement(outputArea).is().present();
+ assertCurrentUrlStartsWith(testAppUrl, jsDriver);
+ }
}