keycloak-aplcache

Merge pull request #2390 from stianst/1.9.x KEYCLOAK-2686

3/21/2016 11:12:21 AM

Details

diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
index 7c1f097..7eb1f07 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
@@ -18,10 +18,13 @@
 package org.keycloak.migration.migrators;
 
 import org.keycloak.migration.ModelVersion;
-import org.keycloak.models.BrowserSecurityHeaders;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 public class MigrateTo1_9_2 {
 
     public static final ModelVersion VERSION = new ModelVersion("1.9.2");
@@ -29,7 +32,11 @@ public class MigrateTo1_9_2 {
     public void migrate(KeycloakSession session) {
         for (RealmModel realm : session.realms().getRealms()) {
             if (realm.getBrowserSecurityHeaders() != null) {
-                realm.getBrowserSecurityHeaders().put("xFrameOptions", "nosniff");
+
+                Map<String, String> browserSecurityHeaders = new HashMap<>(realm.getBrowserSecurityHeaders());
+                browserSecurityHeaders.put("xFrameOptions", "nosniff");
+
+                realm.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
             }
         }
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java b/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
index a2f148e..cf19c30 100755
--- a/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
@@ -22,6 +22,7 @@ import com.google.zxing.WriterException;
 import com.google.zxing.client.j2se.MatrixToImageWriter;
 import com.google.zxing.common.BitMatrix;
 import com.google.zxing.qrcode.QRCodeWriter;
+import org.keycloak.services.util.CacheControlUtil;
 
 import javax.servlet.ServletException;
 import javax.ws.rs.GET;
@@ -29,6 +30,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.CacheControl;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.StreamingOutput;
 import java.io.IOException;
@@ -87,7 +89,18 @@ public class QRCodeResource {
             }
         };
 
-        return Response.ok(stream).build();
-    }
+        /*
+         * This response is served with extra headers that tell the browser to not do any caching.
+         * The reason is that this page will include a QR code that can give an attacker access to
+         * the time based tokens, so it's best to take precautions and make sure there are no copies
+         * of the QR code lost in a cache.
+         */
+        CacheControl cacheControl = CacheControlUtil.noCache();
 
+        return Response.ok(stream) //
+                .cacheControl(cacheControl) //
+                .header("Pragma","no-cache") //
+                .header("Expires", "0") //
+                .build();
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java b/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
index fc2ef80..b7b5c10 100755
--- a/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
+++ b/services/src/main/java/org/keycloak/services/util/CacheControlUtil.java
@@ -46,9 +46,14 @@ public class CacheControlUtil {
     }
 
     public static CacheControl noCache() {
+
         CacheControl cacheControl = new CacheControl();
+        cacheControl.setMustRevalidate(true);
         cacheControl.setNoCache(true);
+        cacheControl.setNoStore(true);
+
         return cacheControl;
     }
 
+
 }