From 7c97e02715177fbc34fd8dabb5bb6b0dcd0fc36e Mon Sep 17 00:00:00 2001 From: Bill Burke Date: Mon, 11 Aug 2014 17:45:01 -0400 Subject: [PATCH] X-Frame-Options, Content-Security-Policy --- .../idm/RealmRepresentation.java | 9 +++++ .../freemarker/FreeMarkerAccountProvider.java | 5 ++- .../BrowserSecurityHeaderSetup.java | 23 ++++++++++++ .../theme/admin/base/resources/js/app.js | 33 +++++++++++------ .../base/resources/js/controllers/realm.js | 12 ++++--- ...sion-brute-force.html => brute-force.html} | 10 ++---- .../resources/partials/defense-headers.html | 36 +++++++++++++++++++ .../base/resources/partials/realm-detail.html | 3 +- .../base/resources/partials/realm-menu.html | 1 + .../resources/partials/session-realm.html | 1 - .../FreeMarkerLoginFormsProvider.java | 5 ++- .../models/BrowserSecurityHeaders.java | 27 ++++++++++++++ .../java/org/keycloak/models/RealmModel.java | 3 ++ .../keycloak/models/entities/RealmEntity.java | 9 +++++ .../models/utils/ModelToRepresentation.java | 1 + .../models/utils/RepresentationToModel.java | 11 ++++++ .../keycloak/models/cache/RealmAdapter.java | 13 +++++++ .../models/cache/entities/CachedRealm.java | 6 ++++ .../org/keycloak/models/jpa/RealmAdapter.java | 22 ++++++++++++ .../mongo/keycloak/adapters/RealmAdapter.java | 11 ++++++ .../services/managers/RealmManager.java | 3 ++ .../resources/admin/AdminConsole.java | 5 ++- .../testsuite/account/AccountTest.java | 5 +-- .../testsuite/admin/AdminAPITest.java | 3 ++ .../keycloak/testsuite/forms/LoginTest.java | 20 +++++++++++ 25 files changed, 246 insertions(+), 31 deletions(-) create mode 100755 forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java rename forms/common-themes/src/main/resources/theme/admin/base/resources/partials/{session-brute-force.html => brute-force.html} (91%) create mode 100755 forms/common-themes/src/main/resources/theme/admin/base/resources/partials/defense-headers.html create mode 100755 model/api/src/main/java/org/keycloak/models/BrowserSecurityHeaders.java diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java index 3bb7e836ef..dad5eac635 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java @@ -52,6 +52,7 @@ public class RealmRepresentation { protected Map> applicationScopeMappings; protected List applications; protected List oauthClients; + protected Map browserSecurityHeaders; protected Map socialProviders; protected Map smtpServer; protected List userFederationProviders; @@ -291,6 +292,14 @@ public class RealmRepresentation { this.updateProfileOnInitialSocialLogin = updateProfileOnInitialSocialLogin; } + public Map getBrowserSecurityHeaders() { + return browserSecurityHeaders; + } + + public void setBrowserSecurityHeaders(Map browserSecurityHeaders) { + this.browserSecurityHeaders = browserSecurityHeaders; + } + public Map getSocialProviders() { return socialProviders; } diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java index 3e89af8ea1..6ec3416205 100755 --- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java +++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java @@ -13,6 +13,7 @@ import org.keycloak.account.freemarker.model.SessionsBean; import org.keycloak.account.freemarker.model.TotpBean; import org.keycloak.account.freemarker.model.UrlBean; import org.keycloak.audit.Event; +import org.keycloak.freemarker.BrowserSecurityHeaderSetup; import org.keycloak.freemarker.FreeMarkerException; import org.keycloak.freemarker.FreeMarkerUtil; import org.keycloak.freemarker.Theme; @@ -136,7 +137,9 @@ public class FreeMarkerAccountProvider implements AccountProvider { try { String result = freeMarker.processTemplate(attributes, Templates.getTemplate(page), theme); - return Response.status(status).type(MediaType.TEXT_HTML).entity(result).build(); + Response.ResponseBuilder builder = Response.status(status).type(MediaType.TEXT_HTML).entity(result); + BrowserSecurityHeaderSetup.headers(builder, realm); + return builder.build(); } catch (FreeMarkerException e) { logger.error("Failed to process template", e); return Response.serverError().build(); diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java new file mode 100755 index 0000000000..da8fc5d0a6 --- /dev/null +++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/BrowserSecurityHeaderSetup.java @@ -0,0 +1,23 @@ +package org.keycloak.freemarker; + +import org.keycloak.models.BrowserSecurityHeaders; +import org.keycloak.models.RealmModel; + +import javax.ws.rs.core.Response; +import java.util.Map; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class BrowserSecurityHeaderSetup { + + public static Response.ResponseBuilder headers(Response.ResponseBuilder builder, RealmModel realm) { + for (Map.Entry entry : realm.getBrowserSecurityHeaders().entrySet()) { + String headerName = BrowserSecurityHeaders.headerAttributeMap.get(entry.getKey()); + if (headerName == null) continue; + builder.header(headerName, entry.getValue()); + } + return builder; + } +} diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js index 4f7b83ac4b..4c434c2a14 100755 --- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js +++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/app.js @@ -675,16 +675,7 @@ module.config([ '$routeProvider', function($routeProvider) { }, controller : 'RealmRevocationCtrl' }) - .when('/realms/:realm/sessions/brute-force', { - templateUrl : 'partials/session-brute-force.html', - resolve : { - realm : function(RealmLoader) { - return RealmLoader(); - } - }, - controller : 'RealmBruteForceCtrl' - }) - .when('/realms/:realm/sessions/realm', { + .when('/realms/:realm/sessions/realm', { templateUrl : 'partials/session-realm.html', resolve : { realm : function(RealmLoader) { @@ -761,6 +752,28 @@ module.config([ '$routeProvider', function($routeProvider) { }, controller : 'GenericUserFederationCtrl' }) + .when('/realms/:realm/defense/headers', { + templateUrl : 'partials/defense-headers.html', + resolve : { + realm : function(RealmLoader) { + return RealmLoader(); + }, + serverInfo : function(ServerInfoLoader) { + return ServerInfoLoader(); + } + + }, + controller : 'DefenseHeadersCtrl' + }) + .when('/realms/:realm/defense/brute-force', { + templateUrl : 'partials/brute-force.html', + resolve : { + realm : function(RealmLoader) { + return RealmLoader(); + } + }, + controller : 'RealmBruteForceCtrl' + }) .when('/logout', { templateUrl : 'partials/home.html', controller : 'LogoutCtrl' diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js index e89401d747..8ce2c34ba3 100755 --- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js +++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js @@ -340,8 +340,6 @@ function genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $l var oldCopy = angular.copy($scope.realm); - - $scope.changed = false; $scope.$watch('realm', function() { @@ -384,16 +382,20 @@ function genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $l } +module.controller('DefenseHeadersCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) { + genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/defense/headers"); +}); + module.controller('RealmLoginSettingsCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) { - genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/login-settings") + genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/login-settings"); }); module.controller('RealmThemeCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) { - genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/theme-settings") + genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/theme-settings"); }); module.controller('RealmCacheCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications) { - genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/cache-settings") + genericRealmUpdate($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, "/realms/" + realm.realm + "/cache-settings"); }); module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications, PasswordPolicy) { diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/session-brute-force.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/brute-force.html similarity index 91% rename from forms/common-themes/src/main/resources/theme/admin/base/resources/partials/session-brute-force.html rename to forms/common-themes/src/main/resources/theme/admin/base/resources/partials/brute-force.html index 3f9bd9a813..d02d7d0499 100755 --- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/session-brute-force.html +++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/brute-force.html @@ -1,16 +1,10 @@
-

{{realm.realm}} Brute Force Protection Settings

diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/defense-headers.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/defense-headers.html new file mode 100755 index 0000000000..734efa91cf --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/defense-headers.html @@ -0,0 +1,36 @@ +
+
+ +
+
+

{{realm.realm}} Browser Security Headers

+ +
+
+ +
+ +
+
+ +
+
+ + +
+ +
+
+

{{realm.realm}}

+
+ +
+
\ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html index f9c1e3be15..ac43458061 100755 --- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html +++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-detail.html @@ -15,17 +15,16 @@
-
+
-
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html index 1bc9c6bbda..b5dca73be5 100755 --- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html +++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html @@ -9,5 +9,6 @@
  • Applications
  • OAuth Clients
  • Sessions and Tokens
  • +
  • Security Defenses
  • Audit
  • \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/session-realm.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/session-realm.html index 866b2f7c65..f5f164a317 100755 --- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/session-realm.html +++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/session-realm.html @@ -4,7 +4,6 @@
  • Realm Sessions
  • Timeout Settings
  • Revocation
  • -
  • Brute Force Protection