From 6cbeeb1b1a772510b00881ea5ed5ea11379115ca Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Fri, 1 Aug 2014 11:20:23 +0100 Subject: [PATCH] KEYCLOAK-591 Require SSL for all external requests by default --- .../java/org/keycloak}/ClientConnection.java | 2 +- .../java/org/keycloak/enums/SslRequired.java | 43 +++++++++++++++++ .../adapters/config/AdapterConfig.java | 2 +- .../adapters/config/BaseAdapterConfig.java | 2 +- .../adapters/config/BaseRealmConfig.java | 14 +++--- .../idm/RealmRepresentation.java | 10 ++-- .../modules/MigrationFromOlderVersions.xml | 5 ++ .../en/en-US/modules/adapter-config.xml | 14 +++--- .../en/en-US/modules/jboss-adapter.xml | 4 +- examples/cordova/example-realm.json | 2 +- .../src/main/webapp/keycloak.json | 2 +- examples/cors/cors-realm.json | 2 +- .../src/main/webapp/WEB-INF/keycloak.json | 2 +- .../src/main/webapp/keycloak.json | 2 +- .../src/main/resources/META-INF/keycloak.json | 2 +- .../src/main/webapp/keycloak.json | 2 +- .../src/main/webapp/WEB-INF/keycloak.json | 2 +- .../src/main/webapp/WEB-INF/keycloak.json | 2 +- .../src/main/webapp/WEB-INF/keycloak.json | 2 +- examples/demo-template/subsystem-config.xml | 2 +- examples/demo-template/testrealm.json | 32 ++++++++++++- .../src/main/webapp/WEB-INF/keycloak.json | 2 +- .../src/main/webapp/WEB-INF/keycloak.json | 2 +- examples/js-console/example-realm.json | 2 +- .../js-console/src/main/webapp/keycloak.json | 2 +- .../base/resources/js/controllers/realm.js | 7 +-- .../base/resources/partials/realm-detail.html | 10 +++- .../adapters/AdapterDeploymentContext.java | 11 +++-- .../org/keycloak/adapters/HttpFacade.java | 2 + .../keycloak/adapters/KeycloakDeployment.java | 7 +-- .../adapters/KeycloakDeploymentBuilder.java | 7 ++- .../adapters/OAuthRequestAuthenticator.java | 7 ++- .../adapters/PreAuthActionsHandler.java | 2 +- .../adapters/RequestAuthenticator.java | 2 +- .../extension/KeycloakSubsystemParser.java | 4 +- .../subsystem/extension/RealmAddHandler.java | 2 +- .../extension/SharedAttributeDefinitons.java | 24 +++++----- .../extension/LocalDescriptions.properties | 4 +- .../main/resources/schema/keycloak_1_0.xsd | 2 +- .../extension/RealmDefinitionTestCase.java | 22 ++++++--- .../adapters/as7/CatalinaHttpFacade.java | 5 ++ .../adapters/tomcat7/CatalinaHttpFacade.java | 5 ++ .../adapters/undertow/UndertowHttpFacade.java | 5 ++ .../extension/KeycloakSubsystemParser.java | 4 +- .../subsystem/extension/RealmAddHandler.java | 2 +- .../extension/SharedAttributeDefinitons.java | 24 +++++----- .../extension/LocalDescriptions.properties | 4 +- .../resources/schema/wildfly-keycloak_1_0.xsd | 4 +- .../extension/RealmDefinitionTestCase.java | 22 ++++++--- .../extension/SubsystemParsingTestCase.java | 2 +- .../java/org/keycloak/models/RealmModel.java | 6 ++- .../keycloak/models/entities/RealmEntity.java | 10 ++-- .../models/utils/ModelToRepresentation.java | 2 +- .../models/utils/RepresentationToModel.java | 5 +- .../keycloak/models/cache/RealmAdapter.java | 11 +++-- .../models/cache/entities/CachedRealm.java | 9 ++-- .../org/keycloak/models/jpa/RealmAdapter.java | 10 ++-- .../models/jpa/entities/RealmEntity.java | 12 ++--- .../mongo/keycloak/adapters/RealmAdapter.java | 9 ++-- .../keycloak/example/BootstrapListener.java | 3 +- .../src/main/webapp/WEB-INF/testrealm.json | 2 +- .../filters/ClientConnectionFilter.java | 2 +- .../services/managers/AppAuthManager.java | 13 +++--- .../services/managers/ApplianceBootstrap.java | 3 +- .../services/managers/ApplicationManager.java | 6 +-- .../services/managers/AuditManager.java | 2 +- .../managers/AuthenticationManager.java | 46 +++++++++---------- .../managers/BruteForceProtector.java | 2 +- .../services/managers/OAuthClientManager.java | 4 +- .../services/managers/RealmManager.java | 2 + .../services/managers/TokenManager.java | 5 +- .../services/resources/AccountService.java | 10 ++-- .../services/resources/RealmsResource.java | 3 +- .../resources/RequiredActionsService.java | 12 ++--- .../services/resources/SocialResource.java | 6 +-- .../services/resources/TokenService.java | 36 ++++++++------- .../resources/admin/AdminConsole.java | 6 ++- .../services/resources/admin/AdminRoot.java | 6 ++- .../services/resources/flows/Flows.java | 9 ++-- .../services/resources/flows/OAuthFlows.java | 9 ++-- .../resources/flows/SocialRedirectFlows.java | 7 ++- .../testsuite/admin/AdminAPITest.java | 2 +- .../composites/CompositeRoleTest.java | 3 +- .../model/AuthenticationManagerTest.java | 4 +- .../keycloak/testsuite/model/ModelTest.java | 5 +- .../cust-app-keycloak-relative.json | 2 +- .../adapter-test/cust-app-keycloak.json | 2 +- .../customer-db-keycloak-relative.json | 2 +- .../adapter-test/customer-db-keycloak.json | 2 +- .../adapter-test/demorealm-relative.json | 2 +- .../resources/adapter-test/demorealm.json | 2 +- .../product-keycloak-relative.json | 2 +- .../adapter-test/product-keycloak.json | 2 +- .../test/resources/admin-test/testrealm.json | 4 +- .../test/resources/model/testcomposites.json | 4 +- .../test/resources/model/testrealm-demo.json | 2 +- .../src/test/resources/model/testrealm2.json | 2 +- .../src/test/resources/testcomposite.json | 4 +- .../src/test/resources/testrealm.json | 4 +- .../src/main/resources/perfrealm.json | 4 +- 100 files changed, 415 insertions(+), 255 deletions(-) rename {services/src/main/java/org/keycloak/services => core/src/main/java/org/keycloak}/ClientConnection.java (85%) create mode 100644 core/src/main/java/org/keycloak/enums/SslRequired.java diff --git a/services/src/main/java/org/keycloak/services/ClientConnection.java b/core/src/main/java/org/keycloak/ClientConnection.java similarity index 85% rename from services/src/main/java/org/keycloak/services/ClientConnection.java rename to core/src/main/java/org/keycloak/ClientConnection.java index 61491a42a5..23dc3a5582 100755 --- a/services/src/main/java/org/keycloak/services/ClientConnection.java +++ b/core/src/main/java/org/keycloak/ClientConnection.java @@ -1,4 +1,4 @@ -package org.keycloak.services; +package org.keycloak; /** * Information about the client connection diff --git a/core/src/main/java/org/keycloak/enums/SslRequired.java b/core/src/main/java/org/keycloak/enums/SslRequired.java new file mode 100644 index 0000000000..73d700dfa0 --- /dev/null +++ b/core/src/main/java/org/keycloak/enums/SslRequired.java @@ -0,0 +1,43 @@ +package org.keycloak.enums; + +import org.keycloak.ClientConnection; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * @author Stian Thorgersen + */ +public enum SslRequired { + + ALL, + EXTERNAL, + NONE; + + public boolean isRequired(ClientConnection connection) { + return isRequired(connection.getRemoteAddr()); + } + + public boolean isRequired(String address) { + switch (this) { + case ALL: + return true; + case NONE: + return false; + case EXTERNAL: + return !isLocal(address); + default: + return true; + } + } + + private boolean isLocal(String remoteAddress) { + try { + InetAddress inetAddress = InetAddress.getByName(remoteAddress); + return inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress(); + } catch (UnknownHostException e) { + return false; + } + } + +} diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java index 3833a1653a..39552b2214 100755 --- a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java +++ b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java @@ -9,7 +9,7 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder; * @author Bill Burke * @version $Revision: 1 $ */ -@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required", +@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required", "resource", "credentials", "use-resource-role-mappings", "enable-cors", "cors-max-age", "cors-allowed-methods", diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java index 8c383e58e7..58d49ea29a 100755 --- a/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java +++ b/core/src/main/java/org/keycloak/representations/adapters/config/BaseAdapterConfig.java @@ -12,7 +12,7 @@ import java.util.Map; * @author Bill Burke * @version $Revision: 1 $ */ -@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required", +@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required", "resource", "public-client", "credentials", "use-resource-role-mappings", "enable-cors", "cors-max-age", "cors-allowed-methods", diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java index f4a25929c7..4fe3905530 100755 --- a/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java +++ b/core/src/main/java/org/keycloak/representations/adapters/config/BaseRealmConfig.java @@ -9,7 +9,7 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder; * @author Bill Burke * @version $Revision: 1 $ */ -@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required"}) +@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required"}) public class BaseRealmConfig { @JsonProperty("realm") protected String realm; @@ -17,15 +17,15 @@ public class BaseRealmConfig { protected String realmKey; @JsonProperty("auth-server-url") protected String authServerUrl; - @JsonProperty("ssl-not-required") - protected boolean sslNotRequired; + @JsonProperty("ssl-required") + protected String sslRequired; - public boolean isSslNotRequired() { - return sslNotRequired; + public String getSslRequired() { + return sslRequired; } - public void setSslNotRequired(boolean sslNotRequired) { - this.sslNotRequired = sslNotRequired; + public void setSslRequired(String sslRequired) { + this.sslRequired = sslRequired; } public String getRealm() { 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 5f87feea96..ba38e9985f 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java @@ -19,7 +19,7 @@ public class RealmRepresentation { protected Integer accessCodeLifespan; protected Integer accessCodeLifespanUserAction; protected Boolean enabled; - protected Boolean sslNotRequired; + protected String sslRequired; protected Boolean passwordCredentialGrantAllowed; protected Boolean registrationAllowed; protected Boolean rememberMe; @@ -121,12 +121,12 @@ public class RealmRepresentation { this.enabled = enabled; } - public Boolean isSslNotRequired() { - return sslNotRequired; + public String getSslRequired() { + return sslRequired; } - public void setSslNotRequired(Boolean sslNotRequired) { - this.sslNotRequired = sslNotRequired; + public void setSslRequired(String sslRequired) { + this.sslRequired = sslRequired; } public Integer getAccessTokenLifespan() { diff --git a/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml b/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml index c881b617a7..1a12fa0633 100755 --- a/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml +++ b/docbook/reference/en/en-US/modules/MigrationFromOlderVersions.xml @@ -6,6 +6,11 @@ DB Schema has changed again. + + ssl-not-required property in adapter config has been removed. Replaced with + ssl-required, valid values are all (require SSL for all requests), external + (require SSL only for external request) and none (SSL not required). + diff --git a/docbook/reference/en/en-US/modules/adapter-config.xml b/docbook/reference/en/en-US/modules/adapter-config.xml index 64878a7cd4..6f158d91c5 100755 --- a/docbook/reference/en/en-US/modules/adapter-config.xml +++ b/docbook/reference/en/en-US/modules/adapter-config.xml @@ -10,7 +10,7 @@ "resource" : "customer-portal", "realm-public-key" : "MIGfMA0GCSqGSIb3D...31LwIDAQAB", "auth-server-url" : "https://localhost:8443/auth", - "ssl-not-required" : false, + "ssl-required" : "external", "user-resource-role-mappings" : false, "enable-cors" : true, "cors-max-age" : 1000, @@ -89,14 +89,14 @@ - ssl-not-required + ssl-required Ensures that all communication to and from the Keycloak server from the adapter is over HTTPS. This is OPTIONAL. The default value is - false - meaning - that HTTPS is required by default. + external + meaning that HTTPS is required by default for external requests. Valid values are 'all', 'external' + and 'none'. @@ -228,9 +228,9 @@ This is OPTIONAL if - ssl-not-required + ssl-required is - false + none or disable-trust-manager is true. The default value isfalse. diff --git a/docbook/reference/en/en-US/modules/jboss-adapter.xml b/docbook/reference/en/en-US/modules/jboss-adapter.xml index 90dc1cd0a7..bd9d3a9ed0 100755 --- a/docbook/reference/en/en-US/modules/jboss-adapter.xml +++ b/docbook/reference/en/en-US/modules/jboss-adapter.xml @@ -224,7 +224,7 @@ public class CustomerService { demo MIGfMA0GCSqGSIb3DQEBAQUAA http://localhost:8081/auth - true + external customer-portal password @@ -255,7 +255,7 @@ public class CustomerService { MIGfMA0GCSqGSIb3DQEBA http://localhost:8080/auth - true + external demo diff --git a/examples/cordova/example-realm.json b/examples/cordova/example-realm.json index 161a421d5b..615d2caac0 100755 --- a/examples/cordova/example-realm.json +++ b/examples/cordova/example-realm.json @@ -1,7 +1,7 @@ { "realm": "example", "enabled": true, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": true, "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", diff --git a/examples/cors/angular-product-app/src/main/webapp/keycloak.json b/examples/cors/angular-product-app/src/main/webapp/keycloak.json index 1246b2ed6d..d9c653ba0a 100755 --- a/examples/cors/angular-product-app/src/main/webapp/keycloak.json +++ b/examples/cors/angular-product-app/src/main/webapp/keycloak.json @@ -2,7 +2,7 @@ "realm" : "cors", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "resource" : "angular-product", "public-client" : true } \ No newline at end of file diff --git a/examples/cors/cors-realm.json b/examples/cors/cors-realm.json index 5f801cd09f..423ddb2e39 100755 --- a/examples/cors/cors-realm.json +++ b/examples/cors/cors-realm.json @@ -4,7 +4,7 @@ "accessTokenLifespan": 3000, "accessCodeLifespan": 10, "accessCodeLifespanUserAction": 6000, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": false, "social": false, "updateProfileOnInitialSocialLogin": false, diff --git a/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json b/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json index 066aec8a2c..23f6960207 100755 --- a/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json +++ b/examples/cors/database-service/src/main/webapp/WEB-INF/keycloak.json @@ -3,6 +3,6 @@ "resource" : "database-service", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "bearer-only" : true, - "ssl-not-required": true, + "ssl-required": "external", "enable-cors": true } diff --git a/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json b/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json index a55fae369d..72ecb5be56 100755 --- a/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json +++ b/examples/demo-template/angular-product-app/src/main/webapp/keycloak.json @@ -2,7 +2,7 @@ "realm" : "demo", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "resource" : "angular-product", "public-client" : true } \ No newline at end of file diff --git a/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json b/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json index bf07380bcd..51c8775c99 100644 --- a/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json +++ b/examples/demo-template/customer-app-cli/src/main/resources/META-INF/keycloak.json @@ -2,7 +2,7 @@ "realm" : "demo", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url" : "http://localhost:8080/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "resource" : "customer-portal-cli", "public-client" : true } \ No newline at end of file diff --git a/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json b/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json index c35e126912..224c70b76f 100644 --- a/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json +++ b/examples/demo-template/customer-app-js/src/main/webapp/keycloak.json @@ -2,7 +2,7 @@ "realm" : "demo", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "resource" : "customer-portal-js", "public-client" : true } \ No newline at end of file diff --git a/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json index d4d8f0a4cb..c2241b3e91 100755 --- a/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json +++ b/examples/demo-template/customer-app/src/main/webapp/WEB-INF/keycloak.json @@ -3,7 +3,7 @@ "resource": "customer-portal", "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url": "/auth", - "ssl-not-required": true, + "ssl-required" : "external", "expose-token": true, "credentials": { "secret": "password" diff --git a/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json index adf176ce8e..cba5c8dc49 100755 --- a/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json +++ b/examples/demo-template/database-service/src/main/webapp/WEB-INF/keycloak.json @@ -3,5 +3,5 @@ "resource" : "database-service", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "bearer-only" : true, - "ssl-not-required": true + "ssl-required" : "external" } diff --git a/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json index 2a7dbd25bf..fb07e7f110 100755 --- a/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json +++ b/examples/demo-template/product-app/src/main/webapp/WEB-INF/keycloak.json @@ -3,7 +3,7 @@ "resource" : "product-portal", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "credentials" : { "secret": "password" } diff --git a/examples/demo-template/subsystem-config.xml b/examples/demo-template/subsystem-config.xml index 59bdd6f3fe..b2b2c8e0f4 100755 --- a/examples/demo-template/subsystem-config.xml +++ b/examples/demo-template/subsystem-config.xml @@ -3,7 +3,7 @@ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB /auth - true + external demo diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json index 3c44a07672..816afd2756 100755 --- a/examples/demo-template/testrealm.json +++ b/examples/demo-template/testrealm.json @@ -7,7 +7,7 @@ "ssoSessionIdleTimeout": 600, "ssoSessionMaxLifespan": 36000, "passwordCredentialGrantAllowed": true, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": false, "social": false, "updateProfileOnInitialSocialLogin": false, @@ -30,6 +30,36 @@ "account": [ "manage-account" ] } }, + { + "username" : "stian", + "enabled": true, + "email" : "stian@redhat.com", + "firstName": "Stian", + "lastName": "Thorgersen", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "realmRoles": [ "user" ], + "applicationRoles": { + "account": [ "manage-account" ] + } + }, + { + "username" : "mposolda@redhat.com", + "enabled": true, + "email" : "mposolda@redhat.com", + "firstName": "Marek", + "lastName": "Posolda", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ], + "realmRoles": [ "user" ], + "applicationRoles": { + "account": [ "manage-account" ] + } + }, { "username" : "admin", "enabled": true, diff --git a/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/keycloak.json index a4635bba14..559df05f0a 100755 --- a/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/keycloak.json +++ b/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/keycloak.json @@ -2,7 +2,7 @@ "realm" : "demo", "resource" : "third-party", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "credentials" : { "secret": "password" } diff --git a/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json index a4635bba14..559df05f0a 100755 --- a/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json +++ b/examples/demo-template/third-party/src/main/webapp/WEB-INF/keycloak.json @@ -2,7 +2,7 @@ "realm" : "demo", "resource" : "third-party", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "credentials" : { "secret": "password" } diff --git a/examples/js-console/example-realm.json b/examples/js-console/example-realm.json index 35e8d2730f..ddbb6eaf6a 100755 --- a/examples/js-console/example-realm.json +++ b/examples/js-console/example-realm.json @@ -1,7 +1,7 @@ { "realm": "example", "enabled": true, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": true, "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", diff --git a/examples/js-console/src/main/webapp/keycloak.json b/examples/js-console/src/main/webapp/keycloak.json index 6f157b2160..c0c04d5aee 100644 --- a/examples/js-console/src/main/webapp/keycloak.json +++ b/examples/js-console/src/main/webapp/keycloak.json @@ -2,7 +2,7 @@ "realm" : "example", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "resource" : "js-console", "public-client" : true } 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 251a62f712..03df9a76cb 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 @@ -197,8 +197,6 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $ $scope.save = function() { var realmCopy = angular.copy($scope.realm); - var ssl = window.location.protocol == 'https:'; - realmCopy.sslNotRequired = !ssl; console.log('creating new realm **'); Realm.create(realmCopy, function() { Realm.query(function(data) { @@ -230,7 +228,7 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, ser if ($scope.createRealm) { $scope.realm = { enabled: true, - requireSsl: true + sslRequired: 'external' }; } else { if (Current.realm == null || Current.realm.realm != realm.realm) { @@ -256,7 +254,6 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, ser } */ $scope.realm = angular.copy(realm); - $scope.realm.requireSsl = !realm.sslNotRequired; } $scope.social = $scope.realm.social; @@ -276,8 +273,6 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, ser $scope.save = function() { var realmCopy = angular.copy($scope.realm); - realmCopy.sslNotRequired = !realmCopy.requireSsl; - delete realmCopy["requireSsl"]; if ($scope.createRealm) { Realm.save(realmCopy, function(data, headers) { console.log('creating new realm'); 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 bfaaa59298..f46bf7d7ca 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 @@ -73,9 +73,15 @@
- +
- +
+ +
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java index 7d81d3a5d3..676fcae510 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java @@ -5,6 +5,7 @@ import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.jboss.logging.Logger; +import org.keycloak.enums.SslRequired; import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.representations.idm.PublishedRealmRepresentation; import org.keycloak.util.JsonSerialization; @@ -187,12 +188,12 @@ public class AdapterDeploymentContext { } @Override - public boolean isSslRequired() { - return delegate.isSslRequired(); + public SslRequired getSslRequired() { + return delegate.getSslRequired(); } @Override - public void setSslRequired(boolean sslRequired) { + public void setSslRequired(SslRequired sslRequired) { delegate.setSslRequired(sslRequired); } @@ -281,10 +282,10 @@ public class AdapterDeploymentContext { KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(base); URI request = URI.create(facade.getRequest().getURI()); String scheme = request.getScheme(); - if (deployment.isSslRequired()) { + if (deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) { scheme = "https"; if (!request.getScheme().equals(scheme) && request.getPort() != -1) { - log.error("request scheme: " + request.getScheme() + " ssl required: " + deployment.isSslRequired()); + log.error("request scheme: " + request.getScheme() + " ssl required"); throw new RuntimeException("Can't resolve relative url from adapter config."); } } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java index a6eaff2956..3805eefc26 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java @@ -73,6 +73,8 @@ public interface HttpFacade { String getHeader(String name); List getHeaders(String name); InputStream getInputStream(); + + String getRemoteAddr(); } interface Response { diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java index 726502424a..645c859a87 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java @@ -4,6 +4,7 @@ import org.apache.http.client.HttpClient; import org.jboss.logging.Logger; import org.keycloak.OAuth2Constants; import org.keycloak.ServiceUrlConstants; +import org.keycloak.enums.SslRequired; import org.keycloak.util.KeycloakUriBuilder; import java.net.URI; @@ -37,7 +38,7 @@ public class KeycloakDeployment { protected HttpClient client; protected String scope; - protected boolean sslRequired = true; + protected SslRequired sslRequired = SslRequired.ALL; protected String stateCookieName = "OAuth_Token_Request_State"; protected boolean useResourceRoleMappings; protected boolean cors; @@ -168,11 +169,11 @@ public class KeycloakDeployment { this.scope = scope; } - public boolean isSslRequired() { + public SslRequired getSslRequired() { return sslRequired; } - public void setSslRequired(boolean sslRequired) { + public void setSslRequired(SslRequired sslRequired) { this.sslRequired = sslRequired; } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java index 2ccdcea522..61cf482da4 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java @@ -4,6 +4,7 @@ import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.keycloak.OAuth2Constants; import org.keycloak.ServiceUrlConstants; +import org.keycloak.enums.SslRequired; import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.util.KeycloakUriBuilder; import org.keycloak.util.PemUtils; @@ -40,7 +41,11 @@ public class KeycloakDeploymentBuilder { } deployment.setRealmKey(realmKey); } - deployment.setSslRequired(!adapterConfig.isSslNotRequired()); + if (adapterConfig.getSslRequired() != null) { + deployment.setSslRequired(SslRequired.valueOf(adapterConfig.getSslRequired().toUpperCase())); + } else { + deployment.setSslRequired(SslRequired.EXTERNAL); + } deployment.setResourceCredentials(adapterConfig.getCredentials()); deployment.setPublicClient(adapterConfig.isPublicClient()); deployment.setUseResourceRoleMappings(adapterConfig.isUseResourceRoleMappings()); diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java index b13b3cbe87..a7009d2d90 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java @@ -110,7 +110,7 @@ public abstract class OAuthRequestAuthenticator { protected String getRedirectUri(String state) { String url = getRequestUrl(); log.infof("callback uri: %s", url); - if (!isRequestSecure() && deployment.isSslRequired()) { + if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) { int port = sslRedirectPort(); if (port < 0) { // disabled? @@ -150,7 +150,7 @@ public abstract class OAuthRequestAuthenticator { } log.info("Sending redirect to login page: " + redirect); exchange.getResponse().setStatus(302); - exchange.getResponse().setCookie(deployment.getStateCookieName(), state, /* need to set path? */ null, null, -1, deployment.isSslRequired(), false); + exchange.getResponse().setCookie(deployment.getStateCookieName(), state, /* need to set path? */ null, null, -1, deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr()), false); exchange.getResponse().setHeader("Location", redirect); return true; } @@ -241,8 +241,7 @@ public abstract class OAuthRequestAuthenticator { */ protected AuthChallenge resolveCode(String code) { // abort if not HTTPS - if (deployment.isSslRequired() && !isRequestSecure()) { - + if (!isRequestSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) { log.error("Adapter requires SSL. Request: " + facade.getRequest().getURI()); return challenge(403); } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java index 16203a8700..095be57ba2 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java @@ -153,7 +153,7 @@ public class PreAuthActionsHandler { } protected JWSInput verifyAdminRequest() throws Exception { - if (deployment.isSslRequired() && !facade.getRequest().isSecure()) { + if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) { log.warn("SSL is required for adapter admin action"); facade.getResponse().sendError(403, "ssl required"); diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java index 349ba1121c..9e5b6175bc 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java @@ -82,7 +82,7 @@ public abstract class RequestAuthenticator { } protected boolean verifySSL() { - if (!facade.getRequest().isSecure() && deployment.isSslRequired()) { + if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) { log.warn("SSL is required to authenticate"); return true; } diff --git a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java index e9876808d5..9856e69484 100755 --- a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java +++ b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java @@ -83,7 +83,7 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader
  • true if the attributes are valid, false otherwise. */ public static boolean validateTruststoreSetIfRequired(ModelNode attributes) { - if (!isSet(attributes, SSL_NOT_REQUIRED) && !isSet(attributes, DISABLE_TRUST_MANAGER)) { - if (!(isSet(attributes, TRUSTSTORE) && isSet(attributes, TRUSTSTORE_PASSWORD))) { - return false; - } + if (isSet(attributes, DISABLE_TRUST_MANAGER)) { + return true; } - return true; + if (isSet(attributes, SSL_REQUIRED) && attributes.get(SSL_REQUIRED.getName()).asString().equals("none")) { + return true; + } + + return isSet(attributes, TRUSTSTORE) && isSet(attributes, TRUSTSTORE_PASSWORD); } private static boolean isSet(ModelNode attributes, SimpleAttributeDefinition def) { diff --git a/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties b/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties index a79c67298a..42435c3558 100755 --- a/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties +++ b/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties @@ -10,7 +10,7 @@ keycloak.realm.remove=Remove a realm from the subsystem. keycloak.realm.realm-public-key=Public key of the realm keycloak.realm.auth-server-url=Base URL of the Realm Auth Server keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests -keycloak.realm.ssl-not-required=SSL is not required for secure interactions +keycloak.realm.ssl-required=Specify if SSL is required (valid values are all, external and none) keycloak.realm.allow-any-hostname=SSL Setting keycloak.realm.truststore=Truststore used for adapter client HTTPS requests keycloak.realm.truststore-password=Password of the Truststore @@ -31,7 +31,7 @@ keycloak.secure-deployment.remove=Remove a deployment to be secured by Keycloak keycloak.secure-deployment.realm-public-key=Public key of the realm keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests -keycloak.secure-deployment.ssl-not-required=SSL is not required for secure interactions +keycloak.secure-deployment.ssl-required=Specify if SSL is required (valid values are all, external and none) keycloak.secure-deployment.allow-any-hostname=SSL Setting keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests keycloak.secure-deployment.truststore-password=Password of the Truststore diff --git a/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd b/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd index 48cb4538e9..3e79c4f929 100755 --- a/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd +++ b/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd @@ -69,7 +69,7 @@ - + diff --git a/integration/as7-eap-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java b/integration/as7-eap-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java index 6c67895fed..dec35a5779 100755 --- a/integration/as7-eap-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java +++ b/integration/as7-eap-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java @@ -47,28 +47,38 @@ public class RealmDefinitionTestCase { @Test public void testIsTruststoreSetIfRequired() throws Exception { - model.get("ssl-not-required").set(true); + model.get("ssl-required").set("none"); model.get("disable-trust-manager").set(true); Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(true); + model.get("ssl-required").set("none"); model.get("disable-trust-manager").set(false); Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("all"); model.get("disable-trust-manager").set(true); Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("all"); model.get("disable-trust-manager").set(false); Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("external"); + model.get("disable-trust-manager").set(false); + Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); + + model.get("ssl-required").set("all"); model.get("disable-trust-manager").set(false); model.get("truststore").set("foo"); Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("all"); + model.get("disable-trust-manager").set(false); + model.get("truststore").set("foo"); + model.get("truststore-password").set("password"); + Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); + + model.get("ssl-required").set("external"); model.get("disable-trust-manager").set(false); model.get("truststore").set("foo"); model.get("truststore-password").set("password"); diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaHttpFacade.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaHttpFacade.java index 6c47500b70..05bdd228ac 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaHttpFacade.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaHttpFacade.java @@ -87,6 +87,11 @@ public class CatalinaHttpFacade implements HttpFacade { public String getHeader(String name) { return request.getHeader(name); } + + @Override + public String getRemoteAddr() { + return request.getRemoteAddr(); + } } protected class ResponseFacade implements Response { diff --git a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaHttpFacade.java b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaHttpFacade.java index 8c4618fbe2..4833557816 100755 --- a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaHttpFacade.java +++ b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/CatalinaHttpFacade.java @@ -86,6 +86,11 @@ public class CatalinaHttpFacade implements HttpFacade { public String getHeader(String name) { return request.getHeader(name); } + + @Override + public String getRemoteAddr() { + return request.getRemoteAddr(); + } } protected class ResponseFacade implements Response { diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java index 308233fd66..b08f5eff9b 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java @@ -102,6 +102,11 @@ public class UndertowHttpFacade implements HttpFacade { public InputStream getInputStream() { return exchange.getInputStream(); } + + @Override + public String getRemoteAddr() { + return exchange.getSourceAddress().getAddress().getHostAddress(); + } } protected class ResponseFacade implements Response { diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java index 0fbdfa236b..f3b2ffc2a1 100755 --- a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java +++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/KeycloakSubsystemParser.java @@ -83,7 +83,7 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader
  • true if the attributes are valid, false otherwise. */ public static boolean validateTruststoreSetIfRequired(ModelNode attributes) { - if (!isSet(attributes, SSL_NOT_REQUIRED) && !isSet(attributes, DISABLE_TRUST_MANAGER)) { - if (!(isSet(attributes, TRUSTSTORE) && isSet(attributes, TRUSTSTORE_PASSWORD))) { - return false; - } + if (isSet(attributes, DISABLE_TRUST_MANAGER)) { + return true; } - return true; + if (isSet(attributes, SSL_REQUIRED) && attributes.get(SSL_REQUIRED.getName()).asString().equals("none")) { + return true; + } + + return isSet(attributes, TRUSTSTORE) && isSet(attributes, TRUSTSTORE_PASSWORD); } private static boolean isSet(ModelNode attributes, SimpleAttributeDefinition def) { diff --git a/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties b/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties index adc1c1cfed..30a063ad38 100755 --- a/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties +++ b/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties @@ -10,7 +10,7 @@ keycloak.realm.remove=Remove a realm from the subsystem. keycloak.realm.realm-public-key=Public key of the realm keycloak.realm.auth-server-url=Base URL of the Realm Auth Server keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests -keycloak.realm.ssl-not-required=SSL is not required for secure interactions +keycloak.realm.ssl-required=Specify if SSL is required (valid values are all, external and none) keycloak.realm.allow-any-hostname=SSL Setting keycloak.realm.truststore=Truststore used for adapter client HTTPS requests keycloak.realm.truststore-password=Password of the Truststore @@ -31,7 +31,7 @@ keycloak.secure-deployment.remove=Remove a deployment to be secured by Keycloak keycloak.secure-deployment.realm-public-key=Public key of the realm keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests -keycloak.secure-deployment.ssl-not-required=SSL is not required for secure interactions +keycloak.secure-deployment.ssl-required=Specify if SSL is required (valid values are all, external and none) keycloak.secure-deployment.allow-any-hostname=SSL Setting keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests keycloak.secure-deployment.truststore-password=Password of the Truststore diff --git a/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd b/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd index 6e9208a206..8a9979b661 100755 --- a/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd +++ b/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd @@ -39,7 +39,7 @@ - + @@ -71,7 +71,7 @@ - + diff --git a/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java b/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java index 2c8338b6a5..26ec2cbdf5 100755 --- a/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java +++ b/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/RealmDefinitionTestCase.java @@ -48,28 +48,38 @@ public class RealmDefinitionTestCase { @Test public void testIsTruststoreSetIfRequired() throws Exception { - model.get("ssl-not-required").set(true); + model.get("ssl-required").set("none"); model.get("disable-trust-manager").set(true); Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(true); + model.get("ssl-required").set("none"); model.get("disable-trust-manager").set(false); Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("all"); model.get("disable-trust-manager").set(true); Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("all"); model.get("disable-trust-manager").set(false); Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("external"); + model.get("disable-trust-manager").set(false); + Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); + + model.get("ssl-required").set("all"); model.get("disable-trust-manager").set(false); model.get("truststore").set("foo"); Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); - model.get("ssl-not-required").set(false); + model.get("ssl-required").set("all"); + model.get("disable-trust-manager").set(false); + model.get("truststore").set("foo"); + model.get("truststore-password").set("password"); + Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model)); + + model.get("ssl-required").set("external"); model.get("disable-trust-manager").set(false); model.get("truststore").set("foo"); model.get("truststore-password").set("password"); diff --git a/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/SubsystemParsingTestCase.java b/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/SubsystemParsingTestCase.java index 090feb12e8..b73c3c5f98 100644 --- a/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/SubsystemParsingTestCase.java +++ b/integration/wildfly-subsystem/src/test/java/org/keycloak/subsystem/extension/SubsystemParsingTestCase.java @@ -56,7 +56,7 @@ public class SubsystemParsingTestCase extends AbstractSubsystemTest { node.get("realm-public-key").set("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"); node.get("auth-url").set("http://localhost:8080/auth-server/rest/realms/demo/tokens/login"); node.get("code-url").set("http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes"); - node.get("ssl-not-required").set(true); + node.get("ssl-required").set("external"); node.get("expose-token").set(true); ModelNode credential = new ModelNode(); credential.get("password").set("password"); diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java index 36b14b7e13..1fe666da53 100755 --- a/model/api/src/main/java/org/keycloak/models/RealmModel.java +++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java @@ -1,5 +1,7 @@ package org.keycloak.models; +import org.keycloak.enums.SslRequired; + import java.security.PrivateKey; import java.security.PublicKey; import java.util.List; @@ -22,9 +24,9 @@ public interface RealmModel extends RoleContainerModel { void setEnabled(boolean enabled); - boolean isSslNotRequired(); + SslRequired getSslRequired(); - void setSslNotRequired(boolean sslNotRequired); + void setSslRequired(SslRequired sslRequired); boolean isRegistrationAllowed(); diff --git a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java index 16907575d7..59ac516127 100755 --- a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java +++ b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java @@ -12,7 +12,7 @@ public class RealmEntity extends AbstractIdentifiableEntity { private String name; private boolean enabled; - private boolean sslNotRequired; + private String sslRequired; private boolean registrationAllowed; private boolean rememberMe; private boolean verifyEmail; @@ -79,12 +79,12 @@ public class RealmEntity extends AbstractIdentifiableEntity { this.enabled = enabled; } - public boolean isSslNotRequired() { - return sslNotRequired; + public String getSslRequired() { + return sslRequired; } - public void setSslNotRequired(boolean sslNotRequired) { - this.sslNotRequired = sslNotRequired; + public void setSslRequired(String sslRequired) { + this.sslRequired = sslRequired; } public boolean isPasswordCredentialGrantAllowed() { diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index ec0c8442ba..b6495ab980 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -85,7 +85,7 @@ public class ModelToRepresentation { rep.setSocial(realm.isSocial()); rep.setNotBefore(realm.getNotBefore()); rep.setUpdateProfileOnInitialSocialLogin(realm.isUpdateProfileOnInitialSocialLogin()); - rep.setSslNotRequired(realm.isSslNotRequired()); + rep.setSslRequired(realm.getSslRequired().name().toLowerCase()); rep.setPublicKey(realm.getPublicKeyPem()); rep.setPrivateKey(realm.getPrivateKeyPem()); rep.setPasswordCredentialGrantAllowed(realm.isPasswordCredentialGrantAllowed()); diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java index 4df881c67b..c7ab432b25 100755 --- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java +++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java @@ -17,6 +17,7 @@ import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialValueModel; import org.keycloak.models.UserModel; +import org.keycloak.enums.SslRequired; import org.keycloak.representations.idm.UserFederationProviderRepresentation; import org.keycloak.representations.idm.ApplicationRepresentation; import org.keycloak.representations.idm.AuthenticationLinkRepresentation; @@ -73,7 +74,7 @@ public class RepresentationToModel { newRealm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction()); else newRealm.setAccessCodeLifespanUserAction(300); - if (rep.isSslNotRequired() != null) newRealm.setSslNotRequired(rep.isSslNotRequired()); + if (rep.getSslRequired() != null) newRealm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase())); if (rep.isPasswordCredentialGrantAllowed() != null) newRealm.setPasswordCredentialGrantAllowed(rep.isPasswordCredentialGrantAllowed()); if (rep.isRegistrationAllowed() != null) newRealm.setRegistrationAllowed(rep.isRegistrationAllowed()); if (rep.isRememberMe() != null) newRealm.setRememberMe(rep.isRememberMe()); @@ -249,7 +250,7 @@ public class RepresentationToModel { if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed()); if (rep.isUpdateProfileOnInitialSocialLogin() != null) realm.setUpdateProfileOnInitialSocialLogin(rep.isUpdateProfileOnInitialSocialLogin()); - if (rep.isSslNotRequired() != null) realm.setSslNotRequired((rep.isSslNotRequired())); + if (rep.getSslRequired() != null) realm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase())); if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan()); if (rep.getAccessCodeLifespanUserAction() != null) realm.setAccessCodeLifespanUserAction(rep.getAccessCodeLifespanUserAction()); diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java index 6639208f57..7964c9df95 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java @@ -11,6 +11,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; import org.keycloak.models.cache.entities.CachedRealm; +import org.keycloak.enums.SslRequired; import org.keycloak.models.utils.KeycloakModelUtils; import java.security.PrivateKey; @@ -78,15 +79,15 @@ public class RealmAdapter implements RealmModel { } @Override - public boolean isSslNotRequired() { - if (updated != null) return updated.isSslNotRequired(); - return cached.isSslNotRequired(); + public SslRequired getSslRequired() { + if (updated != null) return updated.getSslRequired(); + return cached.getSslRequired(); } @Override - public void setSslNotRequired(boolean sslNotRequired) { + public void setSslRequired(SslRequired sslRequired) { getDelegateForUpdate(); - updated.setSslNotRequired(sslNotRequired); + updated.setSslRequired(sslRequired); } @Override diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java index 83befd28a1..6900ad3b72 100755 --- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java +++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java @@ -10,6 +10,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; import org.keycloak.models.cache.RealmCache; +import org.keycloak.enums.SslRequired; import java.util.ArrayList; import java.util.HashMap; @@ -28,7 +29,7 @@ public class CachedRealm { private String id; private String name; private boolean enabled; - private boolean sslNotRequired; + private SslRequired sslRequired; private boolean registrationAllowed; private boolean rememberMe; private boolean verifyEmail; @@ -86,7 +87,7 @@ public class CachedRealm { id = model.getId(); name = model.getName(); enabled = model.isEnabled(); - sslNotRequired = model.isSslNotRequired(); + sslRequired = model.getSslRequired(); registrationAllowed = model.isRegistrationAllowed(); rememberMe = model.isRememberMe(); verifyEmail = model.isVerifyEmail(); @@ -187,8 +188,8 @@ public class CachedRealm { return enabled; } - public boolean isSslNotRequired() { - return sslNotRequired; + public SslRequired getSslRequired() { + return sslRequired; } public boolean isRegistrationAllowed() { diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index bc57ef16f8..aaab7fe0d2 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -3,8 +3,8 @@ package org.keycloak.models.jpa; import org.keycloak.models.ApplicationModel; import org.keycloak.models.AuthenticationProviderModel; import org.keycloak.models.ClientModel; -import org.keycloak.models.UserFederationProvider; import org.keycloak.models.UserFederationProviderModel; +import org.keycloak.enums.SslRequired; import org.keycloak.models.jpa.entities.UserFederationProviderEntity; import org.keycloak.models.KeycloakSession; import org.keycloak.models.OAuthClientModel; @@ -86,13 +86,13 @@ public class RealmAdapter implements RealmModel { } @Override - public boolean isSslNotRequired() { - return realm.isSslNotRequired(); + public SslRequired getSslRequired() { + return realm.getSslRequired() != null ? SslRequired.valueOf(realm.getSslRequired()) : null; } @Override - public void setSslNotRequired(boolean sslNotRequired) { - realm.setSslNotRequired(sslNotRequired); + public void setSslRequired(SslRequired sslRequired) { + realm.setSslRequired(sslRequired.name()); em.flush(); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java index eef663afa5..edf244d5e8 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java @@ -44,8 +44,8 @@ public class RealmEntity { @Column(name="ENABLED") protected boolean enabled; - @Column(name="SSL_NOT_REQUIRED") - protected boolean sslNotRequired; + @Column(name="SSL_REQUIRED") + protected String sslRequired; @Column(name="REGISTRATION_ALLOWED") protected boolean registrationAllowed; @Column(name="PASSWORD_CRED_GRANT_ALLOWED") @@ -186,12 +186,12 @@ public class RealmEntity { this.enabled = enabled; } - public boolean isSslNotRequired() { - return sslNotRequired; + public String getSslRequired() { + return sslRequired; } - public void setSslNotRequired(boolean sslNotRequired) { - this.sslNotRequired = sslNotRequired; + public void setSslRequired(String sslRequired) { + this.sslRequired = sslRequired; } public boolean isPasswordCredentialGrantAllowed() { diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java index f42365e6ac..0b549ab403 100755 --- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java +++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java @@ -18,6 +18,7 @@ import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; import org.keycloak.models.entities.AuthenticationProviderEntity; import org.keycloak.models.entities.RequiredCredentialEntity; +import org.keycloak.enums.SslRequired; import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity; import org.keycloak.models.mongo.keycloak.entities.MongoOAuthClientEntity; import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity; @@ -89,13 +90,13 @@ public class RealmAdapter extends AbstractMongoAdapter impleme } @Override - public boolean isSslNotRequired() { - return realm.isSslNotRequired(); + public SslRequired getSslRequired() { + return SslRequired.valueOf(realm.getSslRequired()); } @Override - public void setSslNotRequired(boolean sslNotRequired) { - realm.setSslNotRequired(sslNotRequired); + public void setSslRequired(SslRequired sslRequired) { + realm.setSslRequired(sslRequired.name()); updateRealm(); } diff --git a/project-integrations/aerogear-ups/app/src/main/java/org/keycloak/example/BootstrapListener.java b/project-integrations/aerogear-ups/app/src/main/java/org/keycloak/example/BootstrapListener.java index 248785173e..53b7a35a0b 100755 --- a/project-integrations/aerogear-ups/app/src/main/java/org/keycloak/example/BootstrapListener.java +++ b/project-integrations/aerogear-ups/app/src/main/java/org/keycloak/example/BootstrapListener.java @@ -1,6 +1,7 @@ package org.keycloak.example; import org.keycloak.adapters.AdapterDeploymentContext; +import org.keycloak.enums.SslRequired; import org.keycloak.representations.adapters.config.AdapterConfig; import javax.servlet.ServletContextEvent; @@ -18,7 +19,7 @@ public class BootstrapListener implements ServletContextListener { config.setRealm("aerogear"); config.setResource("unified-push-server"); config.setAuthServerUrl("/auth"); - config.setSslNotRequired(true); + config.setSslRequired(SslRequired.EXTERNAL.name()); config.setPublicClient(true); config.setDisableTrustManager(true); deploymentContext.updateDeployment(config); diff --git a/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/testrealm.json b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/testrealm.json index 5b442b0b14..ab37d0ac92 100755 --- a/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/testrealm.json +++ b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/testrealm.json @@ -4,7 +4,7 @@ "accessTokenLifespan": 3000, "accessCodeLifespan": 10, "accessCodeLifespanUserAction": 6000, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": false, "social": false, "adminTheme": "aerogear", diff --git a/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java b/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java index 7f9e74dfbd..f172d39123 100755 --- a/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java +++ b/services/src/main/java/org/keycloak/services/filters/ClientConnectionFilter.java @@ -1,7 +1,7 @@ package org.keycloak.services.filters; import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import javax.servlet.Filter; import javax.servlet.FilterChain; diff --git a/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java b/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java index 451131da6c..8155e01cc5 100755 --- a/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AppAuthManager.java @@ -2,6 +2,7 @@ package org.keycloak.services.managers; import org.jboss.logging.Logger; import org.jboss.resteasy.spi.UnauthorizedException; +import org.keycloak.ClientConnection; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -18,12 +19,12 @@ public class AppAuthManager extends AuthenticationManager { protected static Logger logger = Logger.getLogger(AppAuthManager.class); @Override - public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers) { - AuthResult authResult = super.authenticateIdentityCookie(session, realm, uriInfo, headers); + public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) { + AuthResult authResult = super.authenticateIdentityCookie(session, realm, uriInfo, connection, headers); if (authResult == null) return null; // refresh the cookies! - createLoginCookie(realm, authResult.getUser(), authResult.getSession(), uriInfo); - if (authResult.getSession().isRememberMe()) createRememberMeCookie(realm, uriInfo); + createLoginCookie(realm, authResult.getUser(), authResult.getSession(), uriInfo, connection); + if (authResult.getSession().isRememberMe()) createRememberMeCookie(realm, uriInfo, connection); return authResult; } @@ -39,10 +40,10 @@ public class AppAuthManager extends AuthenticationManager { return tokenString; } - public AuthResult authenticateBearerToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers) { + public AuthResult authenticateBearerToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) { String tokenString = extractAuthorizationHeaderToken(headers); if (tokenString == null) return null; - AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, true, tokenString); + AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, connection, true, tokenString); return authResult; } diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java index 8f5490ff1c..4d149a5891 100755 --- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java +++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java @@ -12,6 +12,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; +import org.keycloak.enums.SslRequired; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.idm.CredentialRepresentation; @@ -57,7 +58,7 @@ public class ApplianceBootstrap { realm.setSsoSessionMaxLifespan(36000); realm.setAccessCodeLifespan(60); realm.setAccessCodeLifespanUserAction(300); - realm.setSslNotRequired(true); + realm.setSslRequired(SslRequired.EXTERNAL); realm.setRegistrationAllowed(false); KeycloakModelUtils.generateRealmKeys(realm); realm.setAuthenticationProviders(Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER)); diff --git a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java index 45a6dcd241..3f5de4d3e5 100755 --- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java @@ -46,7 +46,7 @@ public class ApplicationManager { } } - @JsonPropertyOrder({"realm", "realm-public-key", "bearer-only", "auth-server-url", "ssl-not-required", + @JsonPropertyOrder({"realm", "realm-public-key", "bearer-only", "auth-server-url", "ssl-required", "resource", "public-client", "credentials", "use-resource-role-mappings"}) public static class InstallationAdapterConfig extends BaseRealmConfig { @@ -107,7 +107,7 @@ public class ApplicationManager { InstallationAdapterConfig rep = new InstallationAdapterConfig(); rep.setRealm(realmModel.getName()); rep.setRealmKey(realmModel.getPublicKeyPem()); - rep.setSslNotRequired(realmModel.isSslNotRequired()); + rep.setSslRequired(realmModel.getSslRequired().name().toLowerCase()); if (applicationModel.isPublicClient() && !applicationModel.isBearerOnly()) rep.setPublicClient(true); if (applicationModel.isBearerOnly()) rep.setBearerOnly(true); @@ -140,7 +140,7 @@ public class ApplicationManager { buffer.append(" true\n"); } } - buffer.append(" ").append(realmModel.isSslNotRequired()).append("\n"); + buffer.append(" ").append(realmModel.getSslRequired().name()).append("\n"); buffer.append(" ").append(applicationModel.getName()).append("\n"); String cred = applicationModel.getSecret(); if (!applicationModel.isBearerOnly() && !applicationModel.isPublicClient()) { diff --git a/services/src/main/java/org/keycloak/services/managers/AuditManager.java b/services/src/main/java/org/keycloak/services/managers/AuditManager.java index bc63c67ecc..1ddd4782fa 100644 --- a/services/src/main/java/org/keycloak/services/managers/AuditManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuditManager.java @@ -6,7 +6,7 @@ import org.keycloak.audit.AuditListener; import org.keycloak.audit.AuditProvider; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import java.util.LinkedList; import java.util.List; diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java index 7df23f236a..e6cd6c9398 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -17,7 +17,7 @@ import org.keycloak.models.UserSessionModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.AccessToken; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.util.CookieHelper; import org.keycloak.util.Time; @@ -63,15 +63,15 @@ public class AuthenticationManager { return valid; } - public static void logout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo) { + public static void logout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection) { if (userSession == null) return; UserModel user = userSession.getUser(); logger.infov("Logging out: {0} ({1})", user.getUsername(), userSession.getId()); session.sessions().removeUserSession(realm, userSession); - expireIdentityCookie(realm, uriInfo); - expireRememberMeCookie(realm, uriInfo); + expireIdentityCookie(realm, uriInfo, connection); + expireRememberMeCookie(realm, uriInfo, connection); new ResourceAdminManager().logoutUser(uriInfo.getRequestUri(), realm, user.getId(), userSession.getId()); @@ -94,12 +94,12 @@ public class AuthenticationManager { return token; } - public void createLoginCookie(RealmModel realm, UserModel user, UserSessionModel session, UriInfo uriInfo) { + public void createLoginCookie(RealmModel realm, UserModel user, UserSessionModel session, UriInfo uriInfo, ClientConnection connection) { logger.info("createLoginCookie"); String cookiePath = getIdentityCookiePath(realm, uriInfo); AccessToken identityToken = createIdentityToken(realm, user, session); String encoded = encodeToken(realm, identityToken); - boolean secureOnly = !realm.isSslNotRequired(); + boolean secureOnly = realm.getSslRequired().isRequired(connection); logger.debugv("creatingLoginCookie - name: {0} path: {1}", KEYCLOAK_IDENTITY_COOKIE, cookiePath); int maxAge = NewCookie.DEFAULT_MAX_AGE; if (session.isRememberMe()) { @@ -119,9 +119,9 @@ public class AuthenticationManager { } - public void createRememberMeCookie(RealmModel realm, UriInfo uriInfo) { + public void createRememberMeCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) { String path = getIdentityCookiePath(realm, uriInfo); - boolean secureOnly = !realm.isSslNotRequired(); + boolean secureOnly = realm.getSslRequired().isRequired(connection); // remember me cookie should be persistent //NewCookie cookie = new NewCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getCentralLoginLifespan(), secureOnly);// todo httponly , true); CookieHelper.addCookie(KEYCLOAK_REMEMBER_ME, "true", path, null, null, realm.getSsoSessionIdleTimeout(), secureOnly, true); @@ -134,18 +134,18 @@ public class AuthenticationManager { return encodedToken; } - public static void expireIdentityCookie(RealmModel realm, UriInfo uriInfo) { + public static void expireIdentityCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) { logger.debug("Expiring identity cookie"); String path = getIdentityCookiePath(realm, uriInfo); - expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true); - expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false); - expireRememberMeCookie(realm, uriInfo); + expireCookie(realm, KEYCLOAK_IDENTITY_COOKIE, path, true, connection); + expireCookie(realm, KEYCLOAK_SESSION_COOKIE, path, false, connection); + expireRememberMeCookie(realm, uriInfo, connection); } - public static void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo) { + public static void expireRememberMeCookie(RealmModel realm, UriInfo uriInfo, ClientConnection connection) { logger.debug("Expiring remember me cookie"); String path = getIdentityCookiePath(realm, uriInfo); String cookieName = KEYCLOAK_REMEMBER_ME; - expireCookie(realm, cookieName, path, true); + expireCookie(realm, cookieName, path, true, connection); } protected static String getIdentityCookiePath(RealmModel realm, UriInfo uriInfo) { @@ -153,17 +153,17 @@ public class AuthenticationManager { return uri.getRawPath(); } - public static void expireCookie(RealmModel realm, String cookieName, String path, boolean httpOnly) { + public static void expireCookie(RealmModel realm, String cookieName, String path, boolean httpOnly, ClientConnection connection) { logger.debugv("Expiring cookie: {0} path: {1}", cookieName, path); - boolean secureOnly = !realm.isSslNotRequired(); + boolean secureOnly = realm.getSslRequired().isRequired(connection);; CookieHelper.addCookie(cookieName, "", path, null, "Expiring cookie", 0, secureOnly, httpOnly); } - public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers) { - return authenticateIdentityCookie(session, realm, uriInfo, headers, true); + public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) { + return authenticateIdentityCookie(session, realm, uriInfo, connection, headers, true); } - public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, UriInfo uriInfo, HttpHeaders headers, boolean checkActive) { + public AuthResult authenticateIdentityCookie(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers, boolean checkActive) { logger.info("authenticateIdentityCookie"); Cookie cookie = headers.getCookies().get(KEYCLOAK_IDENTITY_COOKIE); if (cookie == null) { @@ -172,16 +172,16 @@ public class AuthenticationManager { } String tokenString = cookie.getValue(); - AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, checkActive, tokenString); + AuthResult authResult = verifyIdentityToken(session, realm, uriInfo, connection, checkActive, tokenString); if (authResult == null) { - expireIdentityCookie(realm, uriInfo); + expireIdentityCookie(realm, uriInfo, connection); return null; } authResult.getSession().setLastSessionRefresh(Time.currentTime()); return authResult; } - protected AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, boolean checkActive, String tokenString) { + protected AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, String tokenString) { try { AccessToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName(), checkActive); logger.info("identity token verified"); @@ -205,7 +205,7 @@ public class AuthenticationManager { UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState()); if (!isSessionValid(realm, userSession)) { - if (userSession != null) logout(session, realm, userSession, uriInfo); + if (userSession != null) logout(session, realm, userSession, uriInfo, connection); logger.info("User session not active"); return null; } diff --git a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java index 3dab8308b8..dd2b7af70b 100755 --- a/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java +++ b/services/src/main/java/org/keycloak/services/managers/BruteForceProtector.java @@ -6,7 +6,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.RealmModel; import org.keycloak.models.UsernameLoginFailureModel; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import java.util.ArrayList; import java.util.Collections; diff --git a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java index f69df5155f..25ce6a239a 100755 --- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java +++ b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java @@ -39,7 +39,7 @@ public class OAuthClientManager { } } - @JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required", + @JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required", "resource", "public-client", "credentials"}) public static class InstallationAdapterConfig extends BaseRealmConfig { @JsonProperty("public-client") @@ -79,7 +79,7 @@ public class OAuthClientManager { InstallationAdapterConfig rep = new InstallationAdapterConfig(); rep.setRealm(realmModel.getName()); rep.setRealmKey(realmModel.getPublicKeyPem()); - rep.setSslNotRequired(realmModel.isSslNotRequired()); + rep.setSslRequired(realmModel.getSslRequired().name().toLowerCase()); rep.setAuthServerUrl(baseUri.toString()); if (model.isPublicClient()) rep.setPublicClient(true); diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index b5d4dd5650..c82a803aac 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -2,6 +2,7 @@ package org.keycloak.services.managers; import org.jboss.logging.Logger; import org.keycloak.Config; +import org.keycloak.enums.SslRequired; import org.keycloak.exportimport.util.ImportUtils; import org.keycloak.models.AccountRoles; import org.keycloak.models.AdminRoles; @@ -121,6 +122,7 @@ public class RealmManager { realm.setQuickLoginCheckMilliSeconds(1000); realm.setMaxDeltaTimeSeconds(60 * 60 * 12); // 12 hours realm.setFailureFactor(30); + realm.setSslRequired(SslRequired.EXTERNAL); } public boolean removeRealm(RealmModel realm) { diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java index 16a8fca5ed..7fa008e757 100755 --- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java +++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java @@ -1,6 +1,7 @@ package org.keycloak.services.managers; import org.jboss.logging.Logger; +import org.keycloak.ClientConnection; import org.keycloak.OAuthErrorException; import org.keycloak.audit.Audit; import org.keycloak.audit.Details; @@ -62,7 +63,7 @@ public class TokenManager { return new AccessCode(realm, clientSession); } - public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, RealmModel realm, ClientModel client, String encodedRefreshToken, Audit audit) throws OAuthErrorException { + public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel client, String encodedRefreshToken, Audit audit) throws OAuthErrorException { JWSInput jws = new JWSInput(encodedRefreshToken); RefreshToken refreshToken = null; try { @@ -95,7 +96,7 @@ public class TokenManager { UserSessionModel userSession = session.sessions().getUserSession(realm, refreshToken.getSessionState()); int currentTime = Time.currentTime(); if (!AuthenticationManager.isSessionValid(realm, userSession)) { - AuthenticationManager.logout(session, realm, userSession, uriInfo); + AuthenticationManager.logout(session, realm, userSession, uriInfo, connection); throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active"); } diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java index f0fddfa6eb..e89777a210 100755 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -24,6 +24,7 @@ package org.keycloak.services.resources; import org.jboss.logging.Logger; import org.jboss.resteasy.spi.BadRequestException; import org.jboss.resteasy.spi.HttpRequest; +import org.keycloak.ClientConnection; import org.keycloak.OAuth2Constants; import org.keycloak.account.AccountPages; import org.keycloak.account.AccountProvider; @@ -120,6 +121,9 @@ public class AccountService { @Context private UriInfo uriInfo; + @Context + private ClientConnection clientConnection; + @Context private KeycloakSession session; @@ -143,11 +147,11 @@ public class AccountService { account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo); boolean passwordUpdateSupported = false; - AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, headers); + AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers); if (authResult != null) { auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, true); } else { - authResult = authManager.authenticateBearerToken(session, realm, uriInfo, headers); + authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers); if (authResult != null) { auth = new Auth(realm, authResult.getToken(), authResult.getUser(), application, false); } @@ -521,7 +525,7 @@ public class AccountService { String redirectUri = UriBuilder.fromUri(Urls.accountSocialPage(uriInfo.getBaseUri(), realm.getName())).build().toString(); try { - return Flows.social(realm, uriInfo, provider) + return Flows.social(realm, uriInfo, clientConnection, provider) .user(user) .putClientAttribute(OAuth2Constants.CLIENT_ID, Constants.ACCOUNT_MANAGEMENT_APP) .putClientAttribute(OAuth2Constants.STATE, UUID.randomUUID().toString()) diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java index 6fafca45df..09ed95cfdc 100755 --- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java @@ -5,14 +5,13 @@ import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.BadRequestException; import org.jboss.resteasy.spi.NotFoundException; import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.jboss.resteasy.spi.UnauthorizedException; import org.keycloak.audit.Audit; import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import org.keycloak.services.managers.AuditManager; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.BruteForceProtector; diff --git a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java index 904004568f..402664ee87 100755 --- a/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/RequiredActionsService.java @@ -43,7 +43,7 @@ import org.keycloak.models.UserModel.RequiredAction; import org.keycloak.models.UserSessionModel; import org.keycloak.models.utils.TimeBasedOTP; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import org.keycloak.services.managers.AccessCode; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.TokenManager; @@ -291,11 +291,11 @@ public class RequiredActionsService { ClientModel client = realm.findClient(clientId); if (client == null) { - return Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager).forwardToSecurityFailure( + return Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager).forwardToSecurityFailure( "Unknown login requester."); } if (!client.isEnabled()) { - return Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager).forwardToSecurityFailure( + return Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager).forwardToSecurityFailure( "Login requester not enabled."); } @@ -383,14 +383,14 @@ public class RequiredActionsService { UserSessionModel userSession = session.sessions().getUserSession(realm, accessCode.getSessionState()); if (!AuthenticationManager.isSessionValid(realm, userSession)) { - AuthenticationManager.logout(session, realm, userSession, uriInfo); - return Flows.oauth(this.session, realm, request, uriInfo, authManager, tokenManager).redirectError(accessCode.getClient(), "access_denied", accessCode.getState(), accessCode.getRedirectUri()); + AuthenticationManager.logout(session, realm, userSession, uriInfo, clientConnection); + return Flows.oauth(this.session, realm, request, uriInfo, clientConnection, authManager, tokenManager).redirectError(accessCode.getClient(), "access_denied", accessCode.getState(), accessCode.getRedirectUri()); } audit.session(userSession); audit.success(); - return Flows.oauth(this.session, realm, request, uriInfo, authManager, tokenManager).redirectAccessCode(accessCode, + return Flows.oauth(this.session, realm, request, uriInfo, clientConnection, authManager, tokenManager).redirectAccessCode(accessCode, userSession, accessCode.getState(), accessCode.getRedirectUri()); } } diff --git a/services/src/main/java/org/keycloak/services/resources/SocialResource.java b/services/src/main/java/org/keycloak/services/resources/SocialResource.java index d1691c1b31..e9acd79288 100755 --- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java +++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java @@ -39,7 +39,7 @@ import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import org.keycloak.services.managers.AuditManager; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; @@ -127,7 +127,7 @@ public class SocialResource { .detail(Details.AUTH_METHOD, authMethod); AuthenticationManager authManager = new AuthenticationManager(); - OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager); if (!realm.isEnabled()) { audit.error(Errors.REALM_DISABLED); @@ -300,7 +300,7 @@ public class SocialResource { } try { - return Flows.social(realm, uriInfo, provider) + return Flows.social(realm, uriInfo, clientConnection, provider) .putClientAttribute(OAuth2Constants.CLIENT_ID, clientId) .putClientAttribute(OAuth2Constants.SCOPE, scope) .putClientAttribute(OAuth2Constants.STATE, state) diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java index aef626c771..ee2282ff2d 100755 --- a/services/src/main/java/org/keycloak/services/resources/TokenService.java +++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java @@ -32,7 +32,7 @@ import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import org.keycloak.services.managers.AccessCode; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus; @@ -326,7 +326,7 @@ public class TokenService { String refreshToken = form.getFirst(OAuth2Constants.REFRESH_TOKEN); AccessToken accessToken; try { - accessToken = tokenManager.refreshAccessToken(session, uriInfo, realm, client, refreshToken, audit); + accessToken = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, audit); } catch (OAuthErrorException e) { Map error = new HashMap(); error.put(OAuth2Constants.ERROR, e.getError()); @@ -380,7 +380,7 @@ public class TokenService { audit.detail(Details.REMEMBER_ME, "true"); } - OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager); if (!checkSsl()) { return oauth.forwardToSecurityFailure("HTTPS required"); @@ -414,9 +414,9 @@ public class TokenService { AuthenticationStatus status = authManager.authenticateForm(session, clientConnection, realm, formData); if (remember) { - authManager.createRememberMeCookie(realm, uriInfo); + authManager.createRememberMeCookie(realm, uriInfo, clientConnection); } else { - authManager.expireRememberMeCookie(realm, uriInfo); + authManager.expireRememberMeCookie(realm, uriInfo, clientConnection); } UserModel user = KeycloakModelUtils.findUserByNameOrEmail(session, realm, username); @@ -484,7 +484,7 @@ public class TokenService { .detail(Details.EMAIL, email) .detail(Details.REGISTER_METHOD, "form"); - OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager); if (!realm.isEnabled()) { logger.warn("Realm not enabled"); @@ -686,7 +686,7 @@ public class TokenService { UserSessionModel userSession = session.sessions().getUserSession(realm, accessCode.getSessionState()); if (!AuthenticationManager.isSessionValid(realm, userSession)) { - AuthenticationManager.logout(session, realm, userSession, uriInfo); + AuthenticationManager.logout(session, realm, userSession, uriInfo, clientConnection); Map res = new HashMap(); res.put(OAuth2Constants.ERROR, "invalid_grant"); res.put(OAuth2Constants.ERROR_DESCRIPTION, "Session not active"); @@ -804,7 +804,7 @@ public class TokenService { audit.event(EventType.LOGIN).client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code"); - OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager); if (!checkSsl()) { return oauth.forwardToSecurityFailure("HTTPS required"); @@ -842,7 +842,7 @@ public class TokenService { } logger.info("Checking cookie..."); - AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, headers); + AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers); if (authResult != null) { UserModel user = authResult.getUser(); UserSessionModel session = authResult.getSession(); @@ -887,7 +887,7 @@ public class TokenService { audit.event(EventType.REGISTER).client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code"); - OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager); if (!checkSsl()) { return oauth.forwardToSecurityFailure("HTTPS required"); @@ -923,7 +923,7 @@ public class TokenService { return oauth.forwardToSecurityFailure("Registration not allowed"); } - authManager.expireIdentityCookie(realm, uriInfo); + authManager.expireIdentityCookie(realm, uriInfo, clientConnection); return Flows.forms(session, realm, uriInfo).createRegistration(); } @@ -950,7 +950,7 @@ public class TokenService { } // authenticate identity cookie, but ignore an access token timeout as we're logging out anyways. - AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, headers, false); + AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers, false); if (authResult != null) { logout(authResult.getSession()); } else if (sessionState != null) { @@ -973,7 +973,7 @@ public class TokenService { } private void logout(UserSessionModel userSession) { - authManager.logout(session, realm, userSession, uriInfo); + authManager.logout(session, realm, userSession, uriInfo, clientConnection); audit.user(userSession.getUser()).session(userSession).success(); } @@ -989,7 +989,7 @@ public class TokenService { public Response processOAuth(final MultivaluedMap formData) { audit.event(EventType.LOGIN).detail(Details.RESPONSE_TYPE, "code"); - OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager); if (!checkSsl()) { return oauth.forwardToSecurityFailure("HTTPS required"); @@ -1022,7 +1022,7 @@ public class TokenService { } if (!AuthenticationManager.isSessionValid(realm, userSession)) { - AuthenticationManager.logout(session, realm, userSession, uriInfo); + AuthenticationManager.logout(session, realm, userSession, uriInfo, clientConnection); audit.error(Errors.INVALID_CODE); return oauth.forwardToSecurityFailure("Session not active"); } @@ -1138,7 +1138,11 @@ public class TokenService { } private boolean checkSsl() { - return realm.isSslNotRequired() || uriInfo.getBaseUri().getScheme().equals("https"); + if (uriInfo.getBaseUri().getScheme().equals("https")) { + return true; + } else { + return !realm.getSslRequired().isRequired(clientConnection); + } } private Response createError(String error, String errorDescription, Response.Status status) { diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java index f211e3b2ff..2d7c0caa40 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java @@ -6,6 +6,7 @@ import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpResponse; import org.jboss.resteasy.spi.NotFoundException; +import org.keycloak.ClientConnection; import org.keycloak.Config; import org.keycloak.freemarker.Theme; import org.keycloak.freemarker.ThemeProvider; @@ -54,6 +55,9 @@ public class AdminConsole { @Context protected UriInfo uriInfo; + @Context + protected ClientConnection clientConnection; + @Context protected HttpRequest request; @@ -174,7 +178,7 @@ public class AdminConsole { @NoCache public Response whoAmI(final @Context HttpHeaders headers) { RealmManager realmManager = new RealmManager(session); - AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, headers); + AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers); if (authResult == null) { return Response.status(401).build(); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java index 07c7525bfa..5b3954451e 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java @@ -6,6 +6,7 @@ import org.jboss.resteasy.spi.HttpResponse; import org.jboss.resteasy.spi.NotFoundException; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.UnauthorizedException; +import org.keycloak.ClientConnection; import org.keycloak.jose.jws.JWSInput; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; @@ -41,6 +42,9 @@ public class AdminRoot { @Context protected UriInfo uriInfo; + @Context + protected ClientConnection clientConnection; + @Context protected HttpRequest request; @@ -142,7 +146,7 @@ public class AdminRoot { if (realm == null) { throw new UnauthorizedException("Unknown realm in token"); } - AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, headers); + AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers); if (authResult == null) { logger.debug("Token not valid"); throw new UnauthorizedException("Bearer"); diff --git a/services/src/main/java/org/keycloak/services/resources/flows/Flows.java b/services/src/main/java/org/keycloak/services/resources/flows/Flows.java index 4f96bdd90a..781edbcfdb 100755 --- a/services/src/main/java/org/keycloak/services/resources/flows/Flows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/Flows.java @@ -22,6 +22,7 @@ package org.keycloak.services.resources.flows; import org.jboss.resteasy.spi.HttpRequest; +import org.keycloak.ClientConnection; import org.keycloak.login.LoginFormsProvider; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -43,13 +44,13 @@ public class Flows { return session.getProvider(LoginFormsProvider.class).setRealm(realm).setUriInfo(uriInfo); } - public static OAuthFlows oauth(KeycloakSession session, RealmModel realm, HttpRequest request, UriInfo uriInfo, AuthenticationManager authManager, + public static OAuthFlows oauth(KeycloakSession session, RealmModel realm, HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection, AuthenticationManager authManager, TokenManager tokenManager) { - return new OAuthFlows(session, realm, request, uriInfo, authManager, tokenManager); + return new OAuthFlows(session, realm, request, uriInfo, clientConnection, authManager, tokenManager); } - public static SocialRedirectFlows social(RealmModel realm, UriInfo uriInfo, SocialProvider provider) { - return new SocialRedirectFlows(realm, uriInfo, provider); + public static SocialRedirectFlows social(RealmModel realm, UriInfo uriInfo, ClientConnection clientConnection, SocialProvider provider) { + return new SocialRedirectFlows(realm, uriInfo, clientConnection, provider); } public static ErrorFlows errors() { diff --git a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java index 93cd4897b6..621bb1c99e 100755 --- a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java @@ -24,6 +24,7 @@ package org.keycloak.services.resources.flows; import org.jboss.logging.Logger; import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.jboss.resteasy.spi.HttpRequest; +import org.keycloak.ClientConnection; import org.keycloak.OAuth2Constants; import org.keycloak.audit.Audit; import org.keycloak.audit.Details; @@ -68,16 +69,18 @@ public class OAuthFlows { private final UriInfo uriInfo; + private ClientConnection clientConnection; private final AuthenticationManager authManager; private final TokenManager tokenManager; - OAuthFlows(KeycloakSession session, RealmModel realm, HttpRequest request, UriInfo uriInfo, AuthenticationManager authManager, + OAuthFlows(KeycloakSession session, RealmModel realm, HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection, AuthenticationManager authManager, TokenManager tokenManager) { this.session = session; this.realm = realm; this.request = request; this.uriInfo = uriInfo; + this.clientConnection = clientConnection; this.authManager = authManager; this.tokenManager = tokenManager; } @@ -104,8 +107,8 @@ public class OAuthFlows { } // refresh the cookies! - authManager.createLoginCookie(realm, accessCode.getUser(), userSession, uriInfo); - if (userSession.isRememberMe()) authManager.createRememberMeCookie(realm, uriInfo); + authManager.createLoginCookie(realm, accessCode.getUser(), userSession, uriInfo, clientConnection); + if (userSession.isRememberMe()) authManager.createRememberMeCookie(realm, uriInfo, clientConnection); return location.build(); } diff --git a/services/src/main/java/org/keycloak/services/resources/flows/SocialRedirectFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/SocialRedirectFlows.java index 5091bc3b9b..93eb48aa8a 100755 --- a/services/src/main/java/org/keycloak/services/resources/flows/SocialRedirectFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/SocialRedirectFlows.java @@ -1,5 +1,6 @@ package org.keycloak.services.resources.flows; +import org.keycloak.ClientConnection; import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; @@ -20,12 +21,14 @@ public class SocialRedirectFlows { private final RealmModel realm; private final UriInfo uriInfo; + private ClientConnection clientConnection; private final SocialProvider socialProvider; private final SocialResource.State state; - SocialRedirectFlows(RealmModel realm, UriInfo uriInfo, SocialProvider provider) { + SocialRedirectFlows(RealmModel realm, UriInfo uriInfo, ClientConnection clientConnection, SocialProvider provider) { this.realm = realm; this.uriInfo = uriInfo; + this.clientConnection = clientConnection; this.socialProvider = provider; state = new SocialResource.State(); @@ -62,7 +65,7 @@ public class SocialRedirectFlows { .jsonContent(authRequest.getAttributes()) .rsa256(realm.getPrivateKey()); - CookieHelper.addCookie("KEYCLOAK_SOCIAL", encoded, cookiePath, null, null, -1, !realm.isSslNotRequired(), true); + CookieHelper.addCookie("KEYCLOAK_SOCIAL", encoded, cookiePath, null, null, -1, realm.getSslRequired().isRequired(clientConnection), true); } return Response.status(302).location(authRequest.getAuthUri()).build(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java index 6b39c49eda..1978122b22 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java @@ -243,7 +243,7 @@ public class AdminAPITest { if (rep.isResetPasswordAllowed() != null) Assert.assertEquals(rep.isResetPasswordAllowed(), storedRealm.isResetPasswordAllowed()); if (rep.isUpdateProfileOnInitialSocialLogin() != null) Assert.assertEquals(rep.isUpdateProfileOnInitialSocialLogin(), storedRealm.isUpdateProfileOnInitialSocialLogin()); - if (rep.isSslNotRequired() != null) Assert.assertEquals(rep.isSslNotRequired(), storedRealm.isSslNotRequired()); + if (rep.getSslRequired() != null) Assert.assertEquals(rep.getSslRequired(), storedRealm.getSslRequired()); if (rep.getAccessCodeLifespan() != null) Assert.assertEquals(rep.getAccessCodeLifespan(), storedRealm.getAccessCodeLifespan()); if (rep.getAccessCodeLifespanUserAction() != null) Assert.assertEquals(rep.getAccessCodeLifespanUserAction(), storedRealm.getAccessCodeLifespanUserAction()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java index a255f46ce7..d37cc6b3f6 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/composites/CompositeRoleTest.java @@ -26,6 +26,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; +import org.keycloak.enums.SslRequired; import org.keycloak.models.ApplicationModel; import org.keycloak.models.AuthenticationProviderModel; import org.keycloak.models.KeycloakSession; @@ -67,7 +68,7 @@ public class CompositeRoleTest { realm.setSsoSessionMaxLifespan(10000); realm.setAccessCodeLifespanUserAction(1000); realm.setAccessCodeLifespan(1000); - realm.setSslNotRequired(true); + realm.setSslRequired(SslRequired.EXTERNAL); realm.setEnabled(true); realm.addRequiredCredential(UserCredentialModel.PASSWORD); realm.setAuthenticationProviders(Arrays.asList(AuthenticationProviderModel.DEFAULT_PROVIDER)); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java index 583035687d..b74ef186e1 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AuthenticationManagerTest.java @@ -2,10 +2,8 @@ package org.keycloak.testsuite.model; import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.jboss.resteasy.spi.ResteasyProviderFactory; -import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.keycloak.models.AuthenticationProviderModel; import org.keycloak.models.RealmModel; @@ -14,7 +12,7 @@ import org.keycloak.models.UserModel; import org.keycloak.models.UserModel.RequiredAction; import org.keycloak.models.utils.TimeBasedOTP; import org.keycloak.representations.idm.CredentialRepresentation; -import org.keycloak.services.ClientConnection; +import org.keycloak.ClientConnection; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager.AuthenticationStatus; import org.keycloak.services.managers.BruteForceProtector; diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java index 56d9afe351..4ba264fa9f 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ModelTest.java @@ -2,6 +2,7 @@ package org.keycloak.testsuite.model; import org.junit.Assert; import org.junit.Test; +import org.keycloak.enums.SslRequired; import org.keycloak.models.PasswordPolicy; import org.keycloak.models.RealmModel; import org.keycloak.models.utils.ModelToRepresentation; @@ -17,7 +18,7 @@ public class ModelTest extends AbstractModelTest { realm.setRegistrationAllowed(true); realm.setResetPasswordAllowed(true); realm.setSocial(true); - realm.setSslNotRequired(true); + realm.setSslRequired(SslRequired.EXTERNAL); realm.setVerifyEmail(true); realm.setAccessTokenLifespan(1000); realm.setPasswordPolicy(new PasswordPolicy("length")); @@ -50,7 +51,7 @@ public class ModelTest extends AbstractModelTest { Assert.assertEquals(expected.isRegistrationAllowed(), actual.isRegistrationAllowed()); Assert.assertEquals(expected.isResetPasswordAllowed(), actual.isResetPasswordAllowed()); Assert.assertEquals(expected.isSocial(), actual.isSocial()); - Assert.assertEquals(expected.isSslNotRequired(), actual.isSslNotRequired()); + Assert.assertEquals(expected.getSslRequired(), actual.getSslRequired()); Assert.assertEquals(expected.isVerifyEmail(), actual.isVerifyEmail()); Assert.assertEquals(expected.getAccessTokenLifespan(), actual.getAccessTokenLifespan()); diff --git a/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak-relative.json b/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak-relative.json index 7e20025125..a796d1a2fc 100755 --- a/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak-relative.json +++ b/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak-relative.json @@ -2,7 +2,7 @@ "realm": "demo", "resource": "customer-portal", "auth-server-url": "/auth", - "ssl-not-required": true, + "ssl-required" : "external", "credentials": { "secret": "password" } diff --git a/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak.json b/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak.json index e1f7b69d42..e9ad98722c 100755 --- a/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak.json +++ b/testsuite/integration/src/test/resources/adapter-test/cust-app-keycloak.json @@ -3,7 +3,7 @@ "resource": "customer-portal", "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url": "http://localhost:8081/auth", - "ssl-not-required": true, + "ssl-required" : "external", "expose-token": true, "credentials": { "secret": "password" diff --git a/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak-relative.json b/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak-relative.json index 4ab9db2718..c457468ace 100755 --- a/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak-relative.json +++ b/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak-relative.json @@ -2,7 +2,7 @@ "realm" : "demo", "resource" : "customer-db", "auth-server-url": "/auth", - "ssl-not-required": true, + "ssl-required" : "external", "bearer-only" : true, "enable-cors" : true diff --git a/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak.json b/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak.json index 3848817ba0..285b047b60 100755 --- a/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak.json +++ b/testsuite/integration/src/test/resources/adapter-test/customer-db-keycloak.json @@ -2,7 +2,7 @@ "realm" : "demo", "resource" : "customer-db", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", - "ssl-not-required" : true, + "ssl-required" : "external", "bearer-only" : true, "enable-cors" : true diff --git a/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json b/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json index c1855c65f7..d920209c76 100755 --- a/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json +++ b/testsuite/integration/src/test/resources/adapter-test/demorealm-relative.json @@ -4,7 +4,7 @@ "accessTokenLifespan": 3000, "accessCodeLifespan": 10, "accessCodeLifespanUserAction": 6000, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": false, "social": false, "updateProfileOnInitialSocialLogin": false, diff --git a/testsuite/integration/src/test/resources/adapter-test/demorealm.json b/testsuite/integration/src/test/resources/adapter-test/demorealm.json index 68b3c6df92..1ece4021e4 100755 --- a/testsuite/integration/src/test/resources/adapter-test/demorealm.json +++ b/testsuite/integration/src/test/resources/adapter-test/demorealm.json @@ -4,7 +4,7 @@ "accessTokenLifespan": 3000, "accessCodeLifespan": 10, "accessCodeLifespanUserAction": 6000, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": false, "social": false, "passwordCredentialGrantAllowed": true, diff --git a/testsuite/integration/src/test/resources/adapter-test/product-keycloak-relative.json b/testsuite/integration/src/test/resources/adapter-test/product-keycloak-relative.json index 4e5cd4c06b..9ef62ff67a 100755 --- a/testsuite/integration/src/test/resources/adapter-test/product-keycloak-relative.json +++ b/testsuite/integration/src/test/resources/adapter-test/product-keycloak-relative.json @@ -2,7 +2,7 @@ "realm" : "demo", "resource" : "product-portal", "auth-server-url" : "/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "credentials" : { "secret": "password" } diff --git a/testsuite/integration/src/test/resources/adapter-test/product-keycloak.json b/testsuite/integration/src/test/resources/adapter-test/product-keycloak.json index e0f30dbbb1..3cfd478157 100755 --- a/testsuite/integration/src/test/resources/adapter-test/product-keycloak.json +++ b/testsuite/integration/src/test/resources/adapter-test/product-keycloak.json @@ -3,7 +3,7 @@ "resource" : "product-portal", "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url" : "http://localhost:8081/auth", - "ssl-not-required" : true, + "ssl-required" : "external", "credentials" : { "secret": "password" } diff --git a/testsuite/integration/src/test/resources/admin-test/testrealm.json b/testsuite/integration/src/test/resources/admin-test/testrealm.json index 2af419ad34..55a2fe1bce 100755 --- a/testsuite/integration/src/test/resources/admin-test/testrealm.json +++ b/testsuite/integration/src/test/resources/admin-test/testrealm.json @@ -1,7 +1,7 @@ { "realm": "admin-test-1", "enabled": true, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": true, "resetPasswordAllowed": true, "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", @@ -95,4 +95,4 @@ } ] } -} \ No newline at end of file +} diff --git a/testsuite/integration/src/test/resources/model/testcomposites.json b/testsuite/integration/src/test/resources/model/testcomposites.json index ce128c1617..ef4f999a03 100755 --- a/testsuite/integration/src/test/resources/model/testcomposites.json +++ b/testsuite/integration/src/test/resources/model/testcomposites.json @@ -5,7 +5,7 @@ "accessTokenLifespan": 600, "accessCodeLifespan": 600, "accessCodeLifespanUserAction": 600, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": true, "resetPasswordAllowed": true, "requiredCredentials": [ "password" ], @@ -184,4 +184,4 @@ } ] } -} \ No newline at end of file +} diff --git a/testsuite/integration/src/test/resources/model/testrealm-demo.json b/testsuite/integration/src/test/resources/model/testrealm-demo.json index 5d5d828d1e..fb307bcc37 100755 --- a/testsuite/integration/src/test/resources/model/testrealm-demo.json +++ b/testsuite/integration/src/test/resources/model/testrealm-demo.json @@ -4,7 +4,7 @@ "accessTokenLifespan": 300, "accessCodeLifespan": 10, "accessCodeLifespanUserAction": 600, - "sslNotRequired": true, + "sslRequired": "external", "updateProfileOnInitialSocialLogin": false, "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", diff --git a/testsuite/integration/src/test/resources/model/testrealm2.json b/testsuite/integration/src/test/resources/model/testrealm2.json index 08073c10a6..5ce0084d80 100755 --- a/testsuite/integration/src/test/resources/model/testrealm2.json +++ b/testsuite/integration/src/test/resources/model/testrealm2.json @@ -4,7 +4,7 @@ "accessTokenLifespan": 3000, "accessCodeLifespan": 10, "accessCodeLifespanUserAction": 6000, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": false, "social": false, "updateProfileOnInitialSocialLogin": false, diff --git a/testsuite/integration/src/test/resources/testcomposite.json b/testsuite/integration/src/test/resources/testcomposite.json index 4b5e4c57aa..65e615b2a8 100755 --- a/testsuite/integration/src/test/resources/testcomposite.json +++ b/testsuite/integration/src/test/resources/testcomposite.json @@ -5,7 +5,7 @@ "accessTokenLifespan": 600, "accessCodeLifespan": 600, "accessCodeLifespanUserAction": 600, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": true, "resetPasswordAllowed": true, "requiredCredentials": [ "password" ], @@ -196,4 +196,4 @@ } ] } -} \ No newline at end of file +} diff --git a/testsuite/integration/src/test/resources/testrealm.json b/testsuite/integration/src/test/resources/testrealm.json index b937db3126..ced8c26c54 100755 --- a/testsuite/integration/src/test/resources/testrealm.json +++ b/testsuite/integration/src/test/resources/testrealm.json @@ -2,7 +2,7 @@ "id": "test", "realm": "test", "enabled": true, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": true, "resetPasswordAllowed": true, "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", @@ -96,4 +96,4 @@ } ] } -} \ No newline at end of file +} diff --git a/testsuite/performance-web/src/main/resources/perfrealm.json b/testsuite/performance-web/src/main/resources/perfrealm.json index dc4c959b57..28c8ac1166 100644 --- a/testsuite/performance-web/src/main/resources/perfrealm.json +++ b/testsuite/performance-web/src/main/resources/perfrealm.json @@ -2,7 +2,7 @@ "id": "perf-realm", "realm": "perf-realm", "enabled": true, - "sslNotRequired": true, + "sslRequired": "external", "registrationAllowed": true, "resetPasswordAllowed": true, "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", @@ -109,4 +109,4 @@ } ] } -} \ No newline at end of file +}