From 4d762159ef1011d808859b7bb8b877115e104bb3 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 19 Oct 2017 19:32:21 -0200 Subject: [PATCH] KEYCLOAK-5717 --- .../migration/migrators/MigrateTo3_4_0.java | 16 +++++++++++++++- .../keycloak/models/BrowserSecurityHeaders.java | 2 ++ .../testsuite/migration/MigrationTest.java | 11 +++++++++++ .../admin/messages/admin-messages_en.properties | 2 ++ .../resources/partials/defense-headers.html | 7 +++++++ 5 files changed, 37 insertions(+), 1 deletion(-) 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 8c4f930100..53e152f3e0 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 Marek Posolda */ @@ -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 securityHeaders = r.getBrowserSecurityHeaders(); + if (securityHeaders != null) { + + Map 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 d8d8d38719..1b10128f29 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 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 721f525751..d2bc334c6f 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 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 09a8c3fe47..4a6798d969 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 f2787cda74..0a8ffbd262 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 @@ {{:: 'x-xss-protection-tooltip' | translate}} +
+ +
+ +
+ {{:: 'strict-transport-security-tooltip' | translate}} +