keycloak-aplcache
Changes
services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java 28(+16 -12)
testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java 3(+2 -1)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java 4(+2 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LoginStatusIframeEndpointTest.java 28(+28 -0)
Details
diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index 89b15b8..a784936 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -33,6 +33,13 @@
interval: 5
};
+ var scripts = document.getElementsByTagName('script');
+ for (var i = 0; i < scripts.length; i++) {
+ if ((scripts[i].src.indexOf('keycloak.js') !== -1 || scripts[i].src.indexOf('keycloak.min.js') !== -1) && scripts[i].src.indexOf('version=') !== -1) {
+ kc.iframeVersion = scripts[i].src.substring(scripts[i].src.indexOf('version=') + 8).split('&')[0];
+ }
+ }
+
kc.init = function (initOptions) {
kc.authenticated = false;
@@ -831,6 +838,10 @@
}
var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html';
+ if (kc.iframeVersion) {
+ src = src + '?version=' + kc.iframeVersion;
+ }
+
iframe.setAttribute('src', src );
iframe.style.display = 'none';
document.body.appendChild(iframe);
diff --git a/adapters/oidc/js/src/main/resources/login-status-iframe.html b/adapters/oidc/js/src/main/resources/login-status-iframe.html
index b1012f7..f58f76a 100755
--- a/adapters/oidc/js/src/main/resources/login-status-iframe.html
+++ b/adapters/oidc/js/src/main/resources/login-status-iframe.html
@@ -28,7 +28,7 @@
} else if (!init) {
var req = new XMLHttpRequest();
- var url = location.href + "/init";
+ var url = location.href.split("?")[0] + "/init";
url += "?client_id=" + encodeURIComponent(clientId);
url += "&origin=" + encodeURIComponent(origin);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
index b4f8622..a478169 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LoginStatusIframeEndpoint.java
@@ -17,6 +17,7 @@
package org.keycloak.protocol.oidc.endpoints;
+import org.keycloak.common.Version;
import org.keycloak.common.util.UriUtils;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
@@ -28,8 +29,10 @@ import org.keycloak.utils.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -42,25 +45,25 @@ import java.util.Set;
public class LoginStatusIframeEndpoint {
@Context
- private UriInfo uriInfo;
-
- @Context
private KeycloakSession session;
- private RealmModel realm;
-
- public LoginStatusIframeEndpoint(RealmModel realm) {
- this.realm = realm;
- }
-
@GET
@Produces(MediaType.TEXT_HTML_UTF_8)
- public Response getLoginStatusIframe(@QueryParam("client_id") String client_id,
- @QueryParam("origin") String origin) {
+ public Response getLoginStatusIframe(@QueryParam("version") String version) {
+ CacheControl cacheControl;
+ if (version != null) {
+ if (!version.equals(Version.RESOURCES_VERSION)) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+ cacheControl = CacheControlUtil.getDefaultCacheControl();
+ } else {
+ cacheControl = CacheControlUtil.noCache();
+ }
+
InputStream resource = getClass().getClassLoader().getResourceAsStream("login-status-iframe.html");
if (resource != null) {
P3PHelper.addP3PHeader(session);
- return Response.ok(resource).cacheControl(CacheControlUtil.getDefaultCacheControl()).build();
+ return Response.ok(resource).cacheControl(cacheControl).build();
} else {
return Response.status(Response.Status.NOT_FOUND).build();
}
@@ -70,6 +73,7 @@ public class LoginStatusIframeEndpoint {
@Path("init")
public Response preCheck(@QueryParam("client_id") String clientId, @QueryParam("origin") String origin) {
try {
+ UriInfo uriInfo = session.getContext().getUri();
RealmModel realm = session.getContext().getRealm();
ClientModel client = session.realms().getClientByClientId(clientId, realm);
if (client != null) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
index b535636..160013f 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
@@ -171,7 +171,7 @@ public class OIDCLoginProtocolService {
@Path("login-status-iframe.html")
public Object getLoginStatusIframe() {
- LoginStatusIframeEndpoint endpoint = new LoginStatusIframeEndpoint(realm);
+ LoginStatusIframeEndpoint endpoint = new LoginStatusIframeEndpoint();
ResteasyProviderFactory.getInstance().injectProperties(endpoint);
return endpoint;
}
diff --git a/services/src/main/java/org/keycloak/services/resources/JsResource.java b/services/src/main/java/org/keycloak/services/resources/JsResource.java
index 3e41dad..404d3e4 100755
--- a/services/src/main/java/org/keycloak/services/resources/JsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/JsResource.java
@@ -17,14 +17,15 @@
package org.keycloak.services.resources;
-import org.keycloak.Config;
import org.keycloak.common.Version;
+import org.keycloak.services.util.CacheControlUtil;
import org.keycloak.utils.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Response;
import java.io.InputStream;
@@ -45,37 +46,29 @@ public class JsResource {
@GET
@Path("/keycloak.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
- public Response getKeycloakJs() {
- return getJs("keycloak.js");
+ public Response getKeycloakJs(@QueryParam("version") String version) {
+ return getJs("keycloak.js", version);
}
@GET
@Path("/{version}/keycloak.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
public Response getKeycloakJsWithVersion(@PathParam("version") String version) {
- if (!version.equals(Version.RESOURCES_VERSION)) {
- return Response.status(Response.Status.NOT_FOUND).build();
- }
-
- return getKeycloakJs();
+ return getJs("keycloak.js", version);
}
@GET
@Path("/keycloak.min.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
- public Response getKeycloakMinJs() {
- return getJs("keycloak.min.js");
+ public Response getKeycloakMinJs(@QueryParam("version") String version) {
+ return getJs("keycloak.min.js", version);
}
@GET
@Path("/{version}/keycloak.min.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
public Response getKeycloakMinJsWithVersion(@PathParam("version") String version) {
- if (!version.equals(Version.RESOURCES_VERSION)) {
- return Response.status(Response.Status.NOT_FOUND).build();
- }
-
- return getKeycloakMinJs();
+ return getJs("keycloak.min.js", version);
}
/**
@@ -86,46 +79,44 @@ public class JsResource {
@GET
@Path("/keycloak-authz.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
- public Response getKeycloakAuthzJs() {
- return getJs("keycloak-authz.js");
+ public Response getKeycloakAuthzJs(@QueryParam("version") String version) {
+ return getJs("keycloak-authz.js", version);
}
@GET
@Path("/{version}/keycloak-authz.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
public Response getKeycloakAuthzJsWithVersion(@PathParam("version") String version) {
- if (!version.equals(Version.RESOURCES_VERSION)) {
- return Response.status(Response.Status.NOT_FOUND).build();
- }
-
- return getKeycloakAuthzJs();
+ return getJs("keycloak-authz.js", version);
}
@GET
@Path("/keycloak-authz.min.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
- public Response getKeycloakAuthzMinJs() {
- return getJs("keycloak-authz.min.js");
+ public Response getKeycloakAuthzMinJs(@QueryParam("version") String version) {
+ return getJs("keycloak-authz.min.js", version);
}
@GET
@Path("/{version}/keycloak-authz.min.js")
@Produces(MediaType.TEXT_PLAIN_JAVASCRIPT)
public Response getKeycloakAuthzMinJsWithVersion(@PathParam("version") String version) {
- if (!version.equals(Version.RESOURCES_VERSION)) {
- return Response.status(Response.Status.NOT_FOUND).build();
- }
-
- return getKeycloakAuthzMinJs();
+ return getJs("keycloak-authz.min.js", version);
}
- private Response getJs(String name) {
+ private Response getJs(String name, String version) {
+ CacheControl cacheControl;
+ if (version != null) {
+ if (!version.equals(Version.RESOURCES_VERSION)) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+ cacheControl = CacheControlUtil.getDefaultCacheControl();
+ } else {
+ cacheControl = CacheControlUtil.noCache();
+ }
+
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(name);
if (inputStream != null) {
- CacheControl cacheControl = new CacheControl();
- cacheControl.setNoTransform(false);
- cacheControl.setMaxAge(Config.scope("theme").getInt("staticMaxAge", -1));
-
return Response.ok(inputStream).type("text/javascript").cacheControl(cacheControl).build();
} else {
return Response.status(Response.Status.NOT_FOUND).build();
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java
index cd1b216..1f56a80 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/runonserver/SerializationUtil.java
@@ -50,7 +50,7 @@ public class SerializationUtil {
oos.writeObject(t);
oos.close();
- return Base64.encodeBytes(os.toByteArray());
+ return "EXCEPTION:" + Base64.encodeBytes(os.toByteArray());
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -58,6 +58,7 @@ public class SerializationUtil {
public static Throwable decodeException(String result) {
try {
+ result = result.substring("EXCEPTION:".length());
byte[] bytes = Base64.decode(result);
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(is);
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java
index 684c383..533dfbb 100755
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java
@@ -101,7 +101,7 @@ public class KeycloakTestingClient {
String encoded = SerializationUtil.encode(function);
String result = testing(realm != null ? realm : "master").runOnServer(encoded);
- if (result != null && !result.isEmpty() && !result.trim().startsWith("{")) {
+ if (result != null && !result.isEmpty() && result.trim().startsWith("EXCEPTION:")) {
Throwable t = SerializationUtil.decodeException(result);
if (t instanceof AssertionError) {
throw (AssertionError) t;
@@ -117,7 +117,7 @@ public class KeycloakTestingClient {
String encoded = SerializationUtil.encode(function);
String result = testing(realm != null ? realm : "master").runOnServer(encoded);
- if (result != null && !result.isEmpty() && !result.trim().startsWith("{")) {
+ if (result != null && !result.isEmpty() && result.trim().startsWith("EXCEPTION:")) {
Throwable t = SerializationUtil.decodeException(result);
if (t instanceof AssertionError) {
throw (AssertionError) t;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LoginStatusIframeEndpointTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LoginStatusIframeEndpointTest.java
index 84144f6..e2ab0f8 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LoginStatusIframeEndpointTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/LoginStatusIframeEndpointTest.java
@@ -30,13 +30,18 @@ import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.common.Version;
import org.keycloak.models.Constants;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.ActionURIUtils;
+import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
import java.io.IOException;
import java.net.URLEncoder;
@@ -56,6 +61,11 @@ import static org.junit.Assert.assertTrue;
*/
public class LoginStatusIframeEndpointTest extends AbstractKeycloakTest {
+ @Deployment
+ public static WebArchive deploy() {
+ return RunOnServerDeployment.create(LoginStatusIframeEndpointTest.class);
+ }
+
@Test
public void checkIframe() throws IOException {
CookieStore cookieStore = new BasicCookieStore();
@@ -185,6 +195,24 @@ public class LoginStatusIframeEndpointTest extends AbstractKeycloakTest {
}
}
+ @Test
+ public void checkIframeCache() throws IOException {
+ String version = testingClient.server().fetch(session -> Version.RESOURCES_VERSION, String.class);
+
+ CloseableHttpClient client = HttpClients.createDefault();
+ HttpGet get = new HttpGet(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/realms/master/protocol/openid-connect/login-status-iframe.html");
+ CloseableHttpResponse response = client.execute(get);
+
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals("no-cache, must-revalidate, no-transform, no-store", response.getHeaders("Cache-Control")[0].getValue());
+
+ get = new HttpGet(suiteContext.getAuthServerInfo().getContextRoot() + "/auth/realms/master/protocol/openid-connect/login-status-iframe.html?version=" + version);
+ response = client.execute(get);
+
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertTrue(response.getHeaders("Cache-Control")[0].getValue().contains("max-age"));
+ }
+
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java
index 4101ffc..4c0862d 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/runonserver/RunOnServerTest.java
@@ -45,6 +45,12 @@ public class RunOnServerTest extends AbstractKeycloakTest {
}
@Test
+ public void runOnServerString() throws IOException {
+ String string = testingClient.server().fetch(session -> "Hello world!", String.class);
+ assertEquals("Hello world!", string);
+ }
+
+ @Test
public void runOnServerRep() throws IOException {
final String realmName = "master";
diff --git a/themes/src/main/resources/theme/base/admin/index.ftl b/themes/src/main/resources/theme/base/admin/index.ftl
index 3feb9e3..aebc488 100755
--- a/themes/src/main/resources/theme/base/admin/index.ftl
+++ b/themes/src/main/resources/theme/base/admin/index.ftl
@@ -20,6 +20,7 @@
var consoleBaseUrl = '${consoleBaseUrl}';
var resourceUrl = '${resourceUrl}';
var masterRealm = '${masterRealm}';
+ var resourceVersion = '${resourceVersion}';
</script>
<!-- Minimized versions (for those that have one) -->
@@ -58,7 +59,7 @@
<script src="${resourceUrl}/lib/ui-ace/min/ace.js"></script>
<script src="${resourceUrl}/lib/ui-ace/ui-ace.min.js"></script>
- <script src="${authUrl}/js/${resourceVersion}/keycloak.js" type="text/javascript"></script>
+ <script src="${authUrl}/js/keycloak.js?version=${resourceVersion}" type="text/javascript"></script>
<script src="${resourceUrl}/js/app.js" type="text/javascript"></script>
<script src="${resourceUrl}/js/controllers/realm.js" type="text/javascript"></script>