keycloak-uncached
Changes
services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java 103(+103 -0)
services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticatorFactory.java 102(+102 -0)
services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory 3(+2 -1)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java 18(+14 -4)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java 2(+1 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java 4(+2 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java 2(+1 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java 4(+3 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java 1(+1 -0)
themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html 7(+0 -7)
Details
diff --git a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
index 524cbb3..2466f12 100755
--- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
@@ -123,10 +123,15 @@ public class IdentityProviderRepresentation {
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}
+ /**
+ * @deprecated Replaced by configuration option in identity provider authenticator
+ */
+ @Deprecated
public boolean isAuthenticateByDefault() {
return authenticateByDefault;
}
+ @Deprecated
public void setAuthenticateByDefault(boolean authenticateByDefault) {
this.authenticateByDefault = authenticateByDefault;
}
diff --git a/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java b/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java
index c2e6dab..a59508b 100755
--- a/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java
+++ b/server-spi/src/main/java/org/keycloak/migration/MigrationModel.java
@@ -23,11 +23,6 @@ package org.keycloak.migration;
* @version $Revision: 1 $
*/
public interface MigrationModel {
- /**
- * Must have the form of major.minor.micro as the version is parsed and numbers are compared
- */
- String LATEST_VERSION = "2.1.0";
-
String getStoredVersion();
void setStoredVersion(String version);
}
diff --git a/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java b/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
index 6a2f448..e2b55e1 100755
--- a/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -18,6 +18,7 @@
package org.keycloak.migration;
import org.jboss.logging.Logger;
+import org.keycloak.migration.migrators.MigrateTo1_2_0;
import org.keycloak.migration.migrators.MigrateTo1_3_0;
import org.keycloak.migration.migrators.MigrateTo1_4_0;
import org.keycloak.migration.migrators.MigrateTo1_5_0;
@@ -28,7 +29,8 @@ import org.keycloak.migration.migrators.MigrateTo1_9_0;
import org.keycloak.migration.migrators.MigrateTo1_9_2;
import org.keycloak.migration.migrators.MigrateTo2_0_0;
import org.keycloak.migration.migrators.MigrateTo2_1_0;
-import org.keycloak.migration.migrators.MigrationTo1_2_0_CR1;
+import org.keycloak.migration.migrators.MigrateTo2_2_0;
+import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.KeycloakSession;
/**
@@ -38,82 +40,41 @@ import org.keycloak.models.KeycloakSession;
public class MigrationModelManager {
private static Logger logger = Logger.getLogger(MigrationModelManager.class);
+ private static final Migration[] migrations = {
+ new MigrateTo1_2_0(),
+ new MigrateTo1_3_0(),
+ new MigrateTo1_4_0(),
+ new MigrateTo1_5_0(),
+ new MigrateTo1_6_0(),
+ new MigrateTo1_7_0(),
+ new MigrateTo1_8_0(),
+ new MigrateTo1_9_0(),
+ new MigrateTo1_9_2(),
+ new MigrateTo2_0_0(),
+ new MigrateTo2_1_0(),
+ new MigrateTo2_2_0(),
+ };
+
public static void migrate(KeycloakSession session) {
+ ModelVersion latest = migrations[migrations.length-1].getVersion();
MigrationModel model = session.realms().getMigrationModel();
- String storedVersion = model.getStoredVersion();
- if (MigrationModel.LATEST_VERSION.equals(storedVersion)) return;
ModelVersion stored = null;
- if (storedVersion != null) {
- stored = new ModelVersion(storedVersion);
- }
-
- if (stored == null || stored.lessThan(MigrationTo1_2_0_CR1.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.2.0.CR1 updates");
- }
- new MigrationTo1_2_0_CR1().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo1_3_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.3.0 updates");
- }
- new MigrateTo1_3_0().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo1_4_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.4.0 updates");
- }
- new MigrateTo1_4_0().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo1_5_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.5.0 updates");
- }
- new MigrateTo1_5_0().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo1_6_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.6.0 updates");
+ if (model.getStoredVersion() != null) {
+ stored = new ModelVersion(model.getStoredVersion());
+ if (latest.equals(stored)) {
+ return;
}
- new MigrateTo1_6_0().migrate(session);
}
- if (stored == null || stored.lessThan(MigrateTo1_7_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.7.0 updates");
- }
- new MigrateTo1_7_0().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo1_8_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.8.0 updates");
- }
- new MigrateTo1_8_0().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo1_9_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.9.0 updates");
- }
- new MigrateTo1_9_0().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo1_9_2.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 1.9.2 updates");
- }
- new MigrateTo1_9_2().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo2_0_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 2.0.0 updates");
- }
- new MigrateTo2_0_0().migrate(session);
- }
- if (stored == null || stored.lessThan(MigrateTo2_1_0.VERSION)) {
- if (stored != null) {
- logger.debug("Migrating older model to 2.1.0 updates");
+
+ for (Migration m : migrations) {
+ if (stored == null || stored.lessThan(m.getVersion())) {
+ if (stored != null) {
+ logger.debugf("Migrating older model to %s", m.getVersion());
+ }
+ m.migrate(session);
}
- new MigrateTo2_1_0().migrate(session);
}
- model.setStoredVersion(MigrationModel.LATEST_VERSION);
+ model.setStoredVersion(latest.toString());
}
}
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
index 8d573c7..ee33714 100755
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_3_0.java
@@ -37,9 +37,13 @@ import javax.naming.directory.SearchControls;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class MigrateTo1_3_0 {
+public class MigrateTo1_3_0 implements Migration {
+
public static final ModelVersion VERSION = new ModelVersion("1.3.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
index 5fbab26..9f28f91 100755
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_4_0.java
@@ -34,9 +34,13 @@ import java.util.List;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class MigrateTo1_4_0 {
+public class MigrateTo1_4_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.4.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
index 1a7f83e..6969d5c 100755
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_5_0.java
@@ -32,9 +32,13 @@ import java.util.List;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class MigrateTo1_5_0 {
+public class MigrateTo1_5_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.5.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
index 17ddf1b..c3d9222 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_6_0.java
@@ -27,10 +27,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
-public class MigrateTo1_6_0 {
+public class MigrateTo1_6_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.6.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
MigrationProvider provider = session.getProvider(MigrationProvider.class);
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
index 47abe62..3d4a5d5 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_7_0.java
@@ -31,10 +31,14 @@ import org.keycloak.models.utils.DefaultAuthenticationFlows;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
-public class MigrateTo1_7_0 {
+public class MigrateTo1_7_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.7.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
index 94e0243..549cde9 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_8_0.java
@@ -30,10 +30,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
-public class MigrateTo1_8_0 {
+public class MigrateTo1_8_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.8.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java
index fb24598..e91f126 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_0.java
@@ -33,10 +33,14 @@ import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
-public class MigrateTo1_9_0 {
+public class MigrateTo1_9_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.9.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
RealmModel realm = session.realms().getRealm(Config.getAdminRealm());
if (realm != null && realm.getDisplayNameHtml() != null && realm.getDisplayNameHtml().equals("<strong>Keycloak</strong>")) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
index 2473937..3a41058 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo1_9_2.java
@@ -25,10 +25,14 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-public class MigrateTo1_9_2 {
+public class MigrateTo1_9_2 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("1.9.2");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
if (realm.getBrowserSecurityHeaders() != null) {
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
index 23368f3..d36a858 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_0_0.java
@@ -23,10 +23,14 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
-public class MigrateTo2_0_0 {
+public class MigrateTo2_0_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("2.0.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateAuthorizationServices(realm);
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
index 9e7b931..995dafb 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
@@ -38,9 +38,13 @@ import java.util.stream.Collectors;
*
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/
-public class MigrateTo2_1_0 {
+public class MigrateTo2_1_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("2.1.0");
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateDefaultRequiredAction(realm);
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java
new file mode 100644
index 0000000..1dbcba4
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_2_0.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.migration.migrators;
+
+import org.jboss.logging.Logger;
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.AuthenticatorConfigModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MigrateTo2_2_0 implements Migration {
+ public static final ModelVersion VERSION = new ModelVersion("2.2.0");
+
+ private static final Logger LOG = Logger.getLogger(MigrateTo2_2_0.class);
+
+ public ModelVersion getVersion() {
+ return VERSION;
+ }
+
+ public void migrate(KeycloakSession session) {
+ for (RealmModel realm : session.realms().getRealms()) {
+ addIdentityProviderAuthenticator(realm);
+ }
+ }
+
+ private void addIdentityProviderAuthenticator(RealmModel realm) {
+ String defaultProvider = null;
+ for (IdentityProviderModel provider : realm.getIdentityProviders()) {
+ if (provider.isEnabled() && provider.isAuthenticateByDefault()) {
+ defaultProvider = provider.getAlias();
+ break;
+ }
+ }
+
+ DefaultAuthenticationFlows.addIdentityProviderAuthenticator(realm, defaultProvider);
+ }
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/Migration.java b/server-spi/src/main/java/org/keycloak/migration/migrators/Migration.java
new file mode 100644
index 0000000..e37dad2
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/Migration.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.migration.migrators;
+
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.KeycloakSession;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface Migration {
+
+ void migrate(KeycloakSession session);
+
+ ModelVersion getVersion();
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java b/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java
index 383edd5..8845879 100755
--- a/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java
+++ b/server-spi/src/main/java/org/keycloak/migration/ModelVersion.java
@@ -98,4 +98,19 @@ public class ModelVersion {
if (comp < 0) return true;
return false;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ModelVersion)) {
+ return false;
+ }
+
+ ModelVersion v = (ModelVersion) obj;
+ return v.getMajor() == major && v.getMinor() == minor && v.getMicro() != micro;
+ }
+
+ @Override
+ public String toString() {
+ return major + "." + minor + "." + micro;
+ }
}
diff --git a/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java b/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java
index 82e373f..2425c7d 100755
--- a/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/IdentityProviderModel.java
@@ -120,10 +120,12 @@ public class IdentityProviderModel implements Serializable {
this.storeToken = storeToken;
}
+ @Deprecated
public boolean isAuthenticateByDefault() {
return authenticateByDefault;
}
+ @Deprecated
public void setAuthenticateByDefault(boolean authenticateByDefault) {
this.authenticateByDefault = authenticateByDefault;
}
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
index 7b2c61b..a738d05 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
@@ -276,6 +276,7 @@ public class DefaultAuthenticationFlows {
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
+ addIdentityProviderAuthenticator(realm, null);
AuthenticationFlowModel forms = new AuthenticationFlowModel();
forms.setTopLevel(false);
@@ -317,6 +318,45 @@ public class DefaultAuthenticationFlows {
realm.addAuthenticatorExecution(execution);
}
+ public static void addIdentityProviderAuthenticator(RealmModel realm, String defaultProvider) {
+ String browserFlowId = null;
+ for (AuthenticationFlowModel f : realm.getAuthenticationFlows()) {
+ if (f.getAlias().equals(DefaultAuthenticationFlows.BROWSER_FLOW)) {
+ browserFlowId = f.getId();
+ break;
+ }
+ }
+
+ if (browserFlowId != null) {
+ for (AuthenticationExecutionModel e : realm.getAuthenticationExecutions(browserFlowId)) {
+ if ("identity-provider-redirector".equals(e.getAuthenticator())) {
+ return;
+ }
+ }
+
+ AuthenticationExecutionModel execution;
+ execution = new AuthenticationExecutionModel();
+ execution.setParentFlow(browserFlowId);
+ execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
+ execution.setAuthenticator("identity-provider-redirector");
+ execution.setPriority(25);
+ execution.setAuthenticatorFlow(false);
+
+ if (defaultProvider != null) {
+ AuthenticatorConfigModel configModel = new AuthenticatorConfigModel();
+
+ Map<String, String> config = new HashMap<>();
+ config.put("defaultProvider", defaultProvider);
+ configModel.setConfig(config);
+ configModel = realm.addAuthenticatorConfig(configModel);
+
+ execution.setAuthenticatorConfig(configModel.getId());
+ }
+
+ realm.addAuthenticatorExecution(execution);
+ }
+ }
+
public static void clientAuthFlow(RealmModel realm) {
AuthenticationFlowModel clients = new AuthenticationFlowModel();
clients.setAlias(CLIENT_AUTHENTICATION_FLOW);
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 6accef0..75b4b73 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -565,6 +565,19 @@ public class RepresentationToModel {
if (newRealm.getFlowByAlias(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW) == null) {
DefaultAuthenticationFlows.firstBrokerLoginFlow(newRealm, true);
}
+
+ // Added in 2.2
+ String defaultProvider = null;
+ if (rep.getIdentityProviders() != null) {
+ for (IdentityProviderRepresentation i : rep.getIdentityProviders()) {
+ if (i.isEnabled() && i.isAuthenticateByDefault()) {
+ defaultProvider = i.getProviderId();
+ break;
+ }
+ }
+ }
+
+ DefaultAuthenticationFlows.addIdentityProviderAuthenticator(newRealm, defaultProvider);
}
private static void convertDeprecatedSocialProviders(RealmRepresentation rep) {
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java
new file mode 100644
index 0000000..795d0c2
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticator.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.authentication.authenticators.browser;
+
+import org.jboss.logging.Logger;
+import org.keycloak.authentication.AuthenticationFlowContext;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.services.Urls;
+import org.keycloak.services.managers.ClientSessionCode;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class IdentityProviderAuthenticator implements Authenticator {
+
+ private static final Logger LOG = Logger.getLogger(IdentityProviderAuthenticator.class);
+
+ @Override
+ public void authenticate(AuthenticationFlowContext context) {
+ if (context.getUriInfo().getQueryParameters().containsKey(AdapterConstants.KC_IDP_HINT)) {
+ String providerId = context.getUriInfo().getQueryParameters().getFirst(AdapterConstants.KC_IDP_HINT);
+ if (providerId == null || providerId.equals("")) {
+ LOG.tracef("Skipping: kc_idp_hint query parameter is empty");
+ context.attempted();
+ } else {
+ LOG.tracef("Redirecting: %s set to %s", AdapterConstants.KC_IDP_HINT, providerId);
+ redirect(context, providerId);
+ }
+ } else if (context.getAuthenticatorConfig() != null && context.getAuthenticatorConfig().getConfig().containsKey(IdentityProviderAuthenticatorFactory.DEFAULT_PROVIDER)) {
+ String defaultProvider = context.getAuthenticatorConfig().getConfig().get(IdentityProviderAuthenticatorFactory.DEFAULT_PROVIDER);
+ LOG.tracef("Redirecting: default provider set to %s", defaultProvider);
+ redirect(context, defaultProvider);
+ } else {
+ LOG.tracef("No default provider set or %s query parameter provided", AdapterConstants.KC_IDP_HINT);
+ context.attempted();
+ }
+ }
+
+ private void redirect(AuthenticationFlowContext context, String providerId) {
+ List<IdentityProviderModel> identityProviders = context.getRealm().getIdentityProviders();
+ for (IdentityProviderModel identityProvider : identityProviders) {
+ if (identityProvider.isEnabled() && providerId.equals(identityProvider.getAlias())) {
+ String accessCode = new ClientSessionCode(context.getRealm(), context.getClientSession()).getCode();
+ Response response = Response.temporaryRedirect(
+ Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode))
+ .build();
+
+ LOG.debugf("Redirecting to %s", providerId);
+ context.forceChallenge(response);
+ return;
+ }
+ }
+
+ LOG.warnf("Provider not found or not enabled for realm %s", providerId);
+ context.attempted();
+ }
+
+ @Override
+ public void action(AuthenticationFlowContext context) {
+ }
+
+ @Override
+ public boolean requiresUser() {
+ return false;
+ }
+
+ @Override
+ public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
+ return true;
+ }
+
+ @Override
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
+ }
+
+ @Override
+ public void close() {
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticatorFactory.java
new file mode 100644
index 0000000..635c95e
--- /dev/null
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/IdentityProviderAuthenticatorFactory.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.authentication.authenticators.browser;
+
+import org.keycloak.Config;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.keycloak.provider.ProviderConfigProperty.STRING_TYPE;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class IdentityProviderAuthenticatorFactory implements AuthenticatorFactory {
+
+ protected static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
+ AuthenticationExecutionModel.Requirement.ALTERNATIVE, AuthenticationExecutionModel.Requirement.DISABLED
+ };
+
+ protected static final String DEFAULT_PROVIDER = "defaultProvider";
+
+ @Override
+ public String getDisplayType() {
+ return "Identity Provider Redirector";
+ }
+
+ @Override
+ public String getReferenceCategory() {
+ return null;
+ }
+
+ @Override
+ public boolean isConfigurable() {
+ return true;
+ }
+
+ @Override
+ public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+ return REQUIREMENT_CHOICES;
+ }
+
+ @Override
+ public boolean isUserSetupAllowed() {
+ return true;
+ }
+
+ @Override
+ public String getHelpText() {
+ return "Redirects to default Identity Provider or Identity Provider specified with kc_idp_hint query parameter";
+ }
+
+ @Override
+ public List<ProviderConfigProperty> getConfigProperties() {
+ ProviderConfigProperty rep = new ProviderConfigProperty(DEFAULT_PROVIDER, "Default Identity Provider", "To automatically redirect to an identity provider set to the alias of the identity provider", STRING_TYPE, null);
+ return Collections.singletonList(rep);
+ }
+
+ @Override
+ public Authenticator create(KeycloakSession session) {
+ return new IdentityProviderAuthenticator();
+ }
+
+ @Override
+ public void init(Config.Scope config) {
+ }
+
+ @Override
+ public void postInit(KeycloakSessionFactory factory) {
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public String getId() {
+ return "identity-provider-redirector";
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
index bfbf7a1..12dba27 100755
--- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
+++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
@@ -17,8 +17,6 @@
package org.keycloak.protocol;
-import java.util.List;
-
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
@@ -31,14 +29,11 @@ import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.LoginProtocol.Error;
import org.keycloak.services.ServicesLogger;
-import org.keycloak.services.Urls;
import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.resources.LoginActionsService;
/**
@@ -95,15 +90,6 @@ public abstract class AuthorizationEndpointBase {
* @return response to be returned to the browser
*/
protected Response handleBrowserAuthenticationRequest(ClientSessionModel clientSession, LoginProtocol protocol, boolean isPassive, boolean redirectToAuthentication) {
-
- List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
- for (IdentityProviderModel identityProvider : identityProviders) {
- if (identityProvider.isEnabled() && identityProvider.isAuthenticateByDefault()) {
- // TODO if we are isPassive we should propagate this flag to default identity provider also if possible
- return buildRedirectToIdentityProvider(identityProvider.getAlias(), new ClientSessionCode(realm, clientSession).getCode());
- }
- }
-
AuthenticationFlowModel flow = getAuthenticationFlow();
String flowId = flow.getId();
AuthenticationProcessor processor = createProcessor(clientSession, flowId, LoginActionsService.AUTHENTICATE_PATH);
@@ -147,11 +133,4 @@ public abstract class AuthorizationEndpointBase {
return realm.getBrowserFlow();
}
- protected Response buildRedirectToIdentityProvider(String providerId, String accessCode) {
- logger.debug("Automatically redirect to identity provider: " + providerId);
- return Response.temporaryRedirect(
- Urls.identityProviderAuthnRequest(this.uriInfo.getBaseUri(), providerId, this.realm.getName(), accessCode))
- .build();
- }
-
}
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 1b4db29..3f18b27 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -29,11 +29,9 @@ import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
-import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.AuthorizationEndpointBase;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
@@ -46,7 +44,6 @@ import org.keycloak.protocol.oidc.utils.RedirectUtils;
import org.keycloak.services.ErrorPageException;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.Urls;
-import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.LoginActionsService;
import org.keycloak.services.util.CacheControlUtil;
@@ -313,19 +310,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
}
private Response buildAuthorizationCodeAuthorizationResponse() {
- String idpHint = request.getIdpHint();
-
- if (idpHint != null && !"".equals(idpHint)) {
- IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(idpHint);
-
- if (identityProviderModel == null) {
- return session.getProvider(LoginFormsProvider.class)
- .setError(Messages.IDENTITY_PROVIDER_NOT_FOUND, idpHint)
- .createErrorPage();
- }
- return buildRedirectToIdentityProvider(idpHint, new ClientSessionCode(realm, clientSession).getCode());
- }
-
this.event.event(EventType.LOGIN);
clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory b/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
index 97c9299..fa7ee28 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
+++ b/services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
@@ -20,6 +20,7 @@ org.keycloak.authentication.authenticators.browser.UsernamePasswordFormFactory
org.keycloak.authentication.authenticators.browser.OTPFormAuthenticatorFactory
org.keycloak.authentication.authenticators.browser.ScriptBasedAuthenticatorFactory
org.keycloak.authentication.authenticators.browser.SpnegoAuthenticatorFactory
+org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticatorFactory
org.keycloak.authentication.authenticators.directgrant.ValidateOTP
org.keycloak.authentication.authenticators.directgrant.ValidatePassword
org.keycloak.authentication.authenticators.directgrant.ValidateUsername
@@ -33,4 +34,4 @@ org.keycloak.authentication.authenticators.broker.IdpConfirmLinkAuthenticatorFac
org.keycloak.authentication.authenticators.broker.IdpEmailVerificationAuthenticatorFactory
org.keycloak.authentication.authenticators.broker.IdpUsernamePasswordFormFactory
org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticatorFactory
-org.keycloak.protocol.saml.profile.ecp.authenticator.HttpBasicAuthenticator
+org.keycloak.protocol.saml.profile.ecp.authenticator.HttpBasicAuthenticator
\ No newline at end of file
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
index 7c1f47b..36c291f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/IdentityProviderHintTest.java
@@ -20,19 +20,19 @@ package org.keycloak.testsuite.broker;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
+import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
import org.keycloak.services.managers.RealmManager;
+import org.keycloak.testsuite.KeycloakServer;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testsuite.KeycloakServer;
-import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
@@ -94,6 +94,16 @@ public class IdentityProviderHintTest {
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
- assertEquals("Could not find an identity provider with the identifier.", this.driver.findElement(By.className("instruction")).getText());
+ System.out.println(driver.getPageSource());
+ assertTrue(driver.getTitle().equals("Log in to realm-with-broker"));
+ }
+
+ private AuthenticationExecutionInfoRepresentation findExecution(RealmResource realm) {
+ for (AuthenticationExecutionInfoRepresentation e : realm.flows().getExecutions("browser")) {
+ if (e.getProviderId().equals("identity-provider-redirector")) {
+ return e;
+ }
+ }
+ return null;
}
}
diff --git a/testsuite/integration/src/test/resources/log4j.properties b/testsuite/integration/src/test/resources/log4j.properties
index 5d5369c..f0ff6ac 100755
--- a/testsuite/integration/src/test/resources/log4j.properties
+++ b/testsuite/integration/src/test/resources/log4j.properties
@@ -74,4 +74,7 @@ log4j.logger.org.apache.directory.server.core=warn
log4j.logger.org.apache.directory.server.ldap.LdapProtocolHandler=error
# Enable to view HttpClient connection pool activity
-#log4j.logger.org.apache.http.impl.conn=debug
\ No newline at end of file
+#log4j.logger.org.apache.http.impl.conn=debug
+
+# Enable to view details from identity provider authenticator
+# log4j.logger.org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticator=trace
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java
index f115c49..c32ba08 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java
@@ -104,7 +104,7 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
}
void compareExecution(AuthenticationExecutionExportRepresentation expected, AuthenticationExecutionExportRepresentation actual) {
- Assert.assertEquals("Execution flowAlias - " + actual.getAuthenticator(), expected.getFlowAlias(), actual.getFlowAlias());
+ Assert.assertEquals("Execution flowAlias - " + actual.getFlowAlias(), expected.getFlowAlias(), actual.getFlowAlias());
Assert.assertEquals("Execution authenticator - " + actual.getAuthenticator(), expected.getAuthenticator(), actual.getAuthenticator());
Assert.assertEquals("Execution userSetupAllowed - " + actual.getAuthenticator(), expected.isUserSetupAllowed(), actual.isUserSetupAllowed());
Assert.assertEquals("Execution authenticatorFlow - " + actual.getAuthenticator(), expected.isAutheticatorFlow(), actual.isAutheticatorFlow());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java
index 42015ed..d7caba4 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java
@@ -94,7 +94,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// we'll need auth-cookie later
AuthenticationExecutionInfoRepresentation authCookieExec = findExecutionByProvider("auth-cookie", executionReps);
- compareExecution(newExecInfo("Review Profile", "idp-review-profile", true, 0, 3, DISABLED, null, new String[]{REQUIRED, DISABLED}), exec);
+ compareExecution(newExecInfo("Review Profile", "idp-review-profile", true, 0, 4, DISABLED, null, new String[]{REQUIRED, DISABLED}), exec);
// remove execution
authMgmtResource.removeExecution(exec.getId());
@@ -164,7 +164,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
// Note: there is no checking in addExecution if requirement is one of requirementChoices
// Thus we can have OPTIONAL which is neither ALTERNATIVE, nor DISABLED
- compareExecution(newExecInfo("Cookie", "auth-cookie", false, 0, 2, OPTIONAL, null, new String[]{ALTERNATIVE, DISABLED}), exec);
+ compareExecution(newExecInfo("Cookie", "auth-cookie", false, 0, 3, OPTIONAL, null, new String[]{ALTERNATIVE, DISABLED}), exec);
}
@Test
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java
index fc50bc6..90f8874 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java
@@ -203,7 +203,7 @@ public class FlowTest extends AbstractAuthenticationTest {
// adjust expected values before comparing
browser.setAlias("Copy of browser");
browser.setBuiltIn(false);
- browser.getAuthenticationExecutions().get(2).setFlowAlias("Copy of browser forms");
+ browser.getAuthenticationExecutions().get(3).setFlowAlias("Copy of browser forms");
compareFlows(browser, copyOfBrowser);
// get new flow directly and compare
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java
index 3640af5..ee79c27 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java
@@ -125,12 +125,14 @@ public class InitialFlowsTest extends AbstractAuthenticationTest {
AuthenticationFlowRepresentation flow = newFlow("browser", "browser based authentication", "basic-flow", true, true);
addExecExport(flow, null, false, "auth-cookie", false, null, ALTERNATIVE, 10);
addExecExport(flow, null, false, "auth-spnego", false, null, DISABLED, 20);
+ addExecExport(flow, null, false, "identity-provider-redirector", false, null, ALTERNATIVE, 25);
addExecExport(flow, "forms", false, null, true, null, ALTERNATIVE, 30);
List<AuthenticationExecutionInfoRepresentation> execs = new LinkedList<>();
addExecInfo(execs, "Cookie", "auth-cookie", false, 0, 0, ALTERNATIVE, null, new String[]{ALTERNATIVE, DISABLED});
addExecInfo(execs, "Kerberos", "auth-spnego", false, 0, 1, DISABLED, null, new String[]{ALTERNATIVE, REQUIRED, DISABLED});
- addExecInfo(execs, "forms", null, false, 0, 2, ALTERNATIVE, true, new String[]{ALTERNATIVE, REQUIRED, DISABLED});
+ addExecInfo(execs, "Identity Provider Redirector", "identity-provider-redirector", true, 0, 2, ALTERNATIVE, null, new String[]{ALTERNATIVE, DISABLED});
+ addExecInfo(execs, "forms", null, false, 0, 3, ALTERNATIVE, true, new String[]{ALTERNATIVE, REQUIRED, DISABLED});
addExecInfo(execs, "Username Password Form", "auth-username-password-form", false, 1, 0, REQUIRED, null, new String[]{REQUIRED});
addExecInfo(execs, "OTP Form", "auth-otp-form", false, 1, 1, OPTIONAL, null, new String[]{REQUIRED, OPTIONAL, DISABLED});
expected.add(new FlowExecutions(flow, execs));
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java
index 858e06e..4e07e6f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java
@@ -146,6 +146,7 @@ public class ProvidersTest extends AbstractAuthenticationTest {
addProviderInfo(result, "direct-grant-validate-username", "Username Validation",
"Validates the username supplied as a 'username' form parameter in direct grant request");
addProviderInfo(result, "http-basic-authenticator", "HTTP Basic Authentication", "Validates username and password from Authorization HTTP header");
+ addProviderInfo(result, "identity-provider-redirector", "Identity Provider Redirector", "Redirects to default Identity Provider or Identity Provider specified with kc_idp_hint query parameter");
addProviderInfo(result, "idp-confirm-link", "Confirm link existing account", "Show the form where user confirms if he wants " +
"to link identity provider with existing account or rather edit user profile data retrieved from identity provider to avoid conflict");
addProviderInfo(result, "idp-create-user-if-unique", "Create User If Unique", "Detect if there is existing Keycloak account " +
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties b/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
index 04c79fe..ce33acf 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/log4j.properties
@@ -61,3 +61,5 @@ log4j.logger.org.hibernate=off
log4j.logger.org.jboss.resteasy=warn
log4j.logger.org.apache.directory.api=warn
log4j.logger.org.apache.directory.server.core=warn
+
+log4j.logger.org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticator=trace
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 81690be..bbbf9b9 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -35,13 +35,6 @@
<kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <label class="col-md-2 control-label" for="authenticateByDefault">{{:: 'authenticate-by-default' | translate}}</label>
- <div class="col-md-6">
- <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
- </div>
- <kc-tooltip>{{:: 'identity-provider.authenticate-by-default.tooltip' | translate}}</kc-tooltip>
- </div>
- <div class="form-group">
<label class="col-md-2 control-label" for="storeToken">{{:: 'store-tokens' | translate}}</label>
<div class="col-md-6">
<input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index f9b8c74..eaf4439 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -32,13 +32,6 @@
<kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <label class="col-md-2 control-label" for="authenticateByDefault">{{:: 'authenticate-by-default' | translate}}</label>
- <div class="col-md-6">
- <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
- </div>
- <kc-tooltip>{{:: 'identity-provider.authenticate-by-default.tooltip' | translate}}</kc-tooltip>
- </div>
- <div class="form-group">
<label class="col-md-2 control-label" for="storeToken">{{:: 'store-tokens' | translate}}</label>
<div class="col-md-6">
<input ng-model="identityProvider.storeToken" id="storeToken" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index 9599d98..6c7ceb7 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -71,13 +71,6 @@
<kc-tooltip>{{:: 'trust-email.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
- <label class="col-md-2 control-label" for="authenticateByDefault">{{:: 'authenticate-by-default' | translate}}</label>
- <div class="col-md-6">
- <input ng-model="identityProvider.authenticateByDefault" name="identityProvider.authenticateByDefault" id="authenticateByDefault" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
- </div>
- <kc-tooltip>{{:: 'identity-provider.authenticate-by-default.tooltip' | translate}}</kc-tooltip>
- </div>
- <div class="form-group">
<label class="col-md-2 control-label" for="guiOrder">{{:: 'gui-order' | translate}}</label>
<div class="col-md-6">
<input class="form-control" id="guiOrder" type="text" ng-model="identityProvider.config.guiOrder">