keycloak-aplcache

KEYCLOAK-5717

10/19/2017 7:32:21 PM

Details

diff --git a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java
index 8c4f930..53e152f 100644
--- a/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java
+++ b/server-spi-private/src/main/java/org/keycloak/migration/migrators/MigrateTo3_4_0.java
@@ -21,6 +21,10 @@ import org.keycloak.migration.ModelVersion;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.utils.DefaultKeyProviders;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
@@ -31,7 +35,17 @@ public class MigrateTo3_4_0 implements Migration {
     @Override
     public void migrate(KeycloakSession session) {
         session.realms().getRealms().stream().forEach(
-                r -> DefaultKeyProviders.createAesProvider(r)
+                r -> {
+                    DefaultKeyProviders.createAesProvider(r);
+                    Map<String, String> securityHeaders = r.getBrowserSecurityHeaders();
+                    if (securityHeaders != null) {
+
+                        Map<String, String> browserSecurityHeaders = new HashMap<>(securityHeaders);
+                        browserSecurityHeaders.put("strictTransportSecurity", "max-age=31536000; includeSubDomains");
+
+                        r.setBrowserSecurityHeaders(Collections.unmodifiableMap(browserSecurityHeaders));
+                    }
+                }
         );
     }
 
diff --git a/server-spi-private/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java b/server-spi-private/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java
index d8d8d38..1b10128 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java
@@ -36,6 +36,7 @@ public class BrowserSecurityHeaders {
         headerMap.put("xContentTypeOptions", "X-Content-Type-Options");
         headerMap.put("xRobotsTag", "X-Robots-Tag");
         headerMap.put("xXSSProtection", "X-XSS-Protection");
+        headerMap.put("strictTransportSecurity", "Strict-Transport-Security");
 
         Map<String, String> dh = new HashMap<>();
         dh.put("xFrameOptions", "SAMEORIGIN");
@@ -43,6 +44,7 @@ public class BrowserSecurityHeaders {
         dh.put("xContentTypeOptions", "nosniff");
         dh.put("xRobotsTag", "none");
         dh.put("xXSSProtection", "1; mode=block");
+        dh.put("strictTransportSecurity", "max-age=31536000; includeSubDomains");
 
         defaultHeaders = Collections.unmodifiableMap(dh);
         headerAttributeMap = Collections.unmodifiableMap(headerMap);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
index 721f525..d2bc334 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
@@ -131,6 +131,7 @@ public class MigrationTest extends AbstractKeycloakTest {
         testMigrationTo3_0_0();
         testMigrationTo3_2_0();
         testMigrationTo3_3_0();
+        testMigrationTo3_4_0();
     }
     @Test
     @Migration(versionFrom = "2.2.1.Final")
@@ -218,6 +219,16 @@ public class MigrationTest extends AbstractKeycloakTest {
         }
     }
 
+    private void testMigrationTo3_4_0() {
+        Map<String, String> securityHeaders = masterRealm.toRepresentation().getBrowserSecurityHeaders();
+        if (securityHeaders != null) {
+            assertEquals("max-age=31536000; includeSubDomains",
+                    securityHeaders.get("strictTransportSecurity"));
+        } else {
+            fail("Browser security headers not found");
+        }
+    }
+
     private void testDockerAuthenticationFlow(RealmResource... realms) {
         for (RealmResource realm : realms) {
             AuthenticationFlowRepresentation flow = null;
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 09a8c3f..4a6798d 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -132,6 +132,8 @@ robots-tag=X-Robots-Tag
 robots-tag-tooltip=Prevent pages from appearing in search engines (click label for more information)
 x-xss-protection=X-XSS-Protection
 x-xss-protection-tooltip=This header configures the Cross-site scripting (XSS) filter in your browser. Using the default behavior, the browser will prevent rendering of the page when a XSS attack is detected (click label for more information)
+strict-transport-security=HTTP Strict Transport Security (HSTS)
+strict-transport-security-tooltip=The Strict-Transport-Security HTTP header tells browsers to always use HTTPS. Once a browser sees this header, it will only visit the site over HTTPS for the time specified (1 year) at max-age, including the subdomains.
 permanent-lockout=Permanent Lockout
 permanent-lockout.tooltip=Lock the user permanently when the user exceeds the maximum login failures.
 max-login-failures=Max Login Failures
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html b/themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html
index f2787cd..0a8ffbd 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/defense-headers.html
@@ -43,6 +43,13 @@
                 </div>
                 <kc-tooltip>{{:: 'x-xss-protection-tooltip' | translate}}</kc-tooltip>
             </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="strictTransportSecurity"><a href="https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#hsts" target="_blank">{{:: 'strict-transport-security' | translate}}</a></label>
+                <div class="col-sm-6">
+                    <input class="form-control" id="strictTransportSecurity" type="text" ng-model="realm.browserSecurityHeaders.strictTransportSecurity">
+                </div>
+                <kc-tooltip>{{:: 'strict-transport-security-tooltip' | translate}}</kc-tooltip>
+            </div>
         </fieldset>
         <div class="form-group" data-ng-show="access.manageRealm">
             <div class="col-md-10 col-md-offset-2">