keycloak-uncached

Changes

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 d1d5b05..04e856b 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
@@ -556,6 +556,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">