keycloak-aplcache

Changes

testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/jira/JBossJiraParser.java 43(+0 -43)

testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/jira/Jira.java 28(+0 -28)

testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/jira/JiraTestExecutionDecider.java 61(+0 -61)

testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/jira/Status.java 36(+0 -36)

Details

diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml
index 4f7d5fc..c5d7d52 100644
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml
@@ -7,6 +7,7 @@
                 <constraints nullable="false"/>
             </column>
         </addColumn>
+        <dropColumn tableName="IDENTITY_PROVIDER" columnName="UPDATE_PROFILE_FIRST_LGN_MD"/>
 
     </changeSet>
 </databaseChangeLog>
\ No newline at end of file
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 864d255..0dc7f0a 100755
--- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
@@ -46,6 +46,7 @@ public class IdentityProviderRepresentation {
      * @see #UPFLM_MISSING
      * @see #UPFLM_OFF
      */
+    @Deprecated
     protected String updateProfileFirstLoginMode = UPFLM_ON;
 
     protected boolean trustEmail;
@@ -107,15 +108,17 @@ public class IdentityProviderRepresentation {
     }
 
     /**
-     * @return see {@link #updateProfileFirstLoginMode}
+     * @deprecated deprecated and replaced by configuration on IdpReviewProfileAuthenticator
      */
+    @Deprecated
     public String getUpdateProfileFirstLoginMode() {
         return updateProfileFirstLoginMode;
     }
 
     /**
-     * @param updateProfileFirstLoginMode see {@link #updateProfileFirstLoginMode}
+     * @deprecated deprecated and replaced by configuration on IdpReviewProfileAuthenticator
      */
+    @Deprecated
     public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
         this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
     }
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml b/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml
index 650ed76..b0a443d 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml
@@ -80,15 +80,33 @@
     <section>
         <title>Version specific migration</title>
         <section>
+            <title>Migrating to 1.7.0.CR1</title>
+            <simplesect>
+                <title>Option 'Update Profile On First Login' moved from Identity provider to Review Profile authenticator</title>
+                <para>
+                    In this version, we added <literal>First Broker Login</literal>, which allows you to specify what exactly should be done
+                    when new user is logged through Identity provider (or Social provider), but there is no existing Keycloak user
+                    yet linked to the social account. As part of this work, we added option <literal>First Login Flow</literal> to identity providers where
+                    you can specify the flow and then you can configure this flow under <literal>Authentication</literal> tab in admin console.
+                </para>
+                <para>
+                    We also removed the option <literal>Update Profile On First Login</literal> from the Identity provider settings and moved it
+                    to the configuration of <literal>Review Profile</literal> authenticator. So once you specify which flow should be used for your
+                    Identity provider (by default it's <literal>First Broker Login</literal> flow), you go to <literal>Authentication</literal> tab, select the flow
+                    and then you configure the option under <literal>Review Profile</literal> authenticator.
+                </para>
+            </simplesect>
+        </section>
+        <section>
             <title>Migrating to 1.6.0.Final</title>
             <simplesect>
-                <title>Refresh tokens are not reusable anymore</title>
+                <title>Option that refresh tokens are not reusable anymore</title>
                 <para>
-                    Old versions of Keycloak allowed reusing refresh tokens multiple times. Keycloak no longer permits
-                    this by default. When a refresh token is used to obtain a new access token a new refresh token is also
-                    included. This new refresh token should be used next time the access token is refreshed. If this is
-                    a problem for you it's possible to enable reuse of refresh tokens in the admin console under token
-                    settings.
+                    Old versions of Keycloak allowed reusing refresh tokens multiple times. Keycloak still permits this,
+                    but also have an option <literal>Revoke refresh token</literal> to disallow it. Option is in in admin console under token settings.
+                    When a refresh token is used to obtain a new access token a new refresh token is also
+                    included. When option is enabled, then this new refresh token should be used next time the access token is refreshed.
+                    It won't be possible to reuse old refresh token multiple times.
                 </para>
             </simplesect>
             <simplesect>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
index 96ee94d..7fbbc80 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -1348,12 +1348,15 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'RealmOtpPolicyCtrl'
         })
-        .when('/realms/:realm/authentication/config/:provider/:config', {
+        .when('/realms/:realm/authentication/flows/:flow/config/:provider/:config', {
             templateUrl : resourceUrl + '/partials/authenticator-config.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
+                flow : function(AuthenticationFlowLoader) {
+                    return AuthenticationFlowLoader();
+                },
                 configType : function(AuthenticationConfigDescriptionLoader) {
                     return AuthenticationConfigDescriptionLoader();
                 },
@@ -1363,12 +1366,15 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'AuthenticationConfigCtrl'
         })
-        .when('/create/authentication/:realm/execution/:executionId/provider/:provider', {
+        .when('/create/authentication/:realm/flows/:flow/execution/:executionId/provider/:provider', {
             templateUrl : resourceUrl + '/partials/authenticator-config.html',
             resolve : {
                 realm : function(RealmLoader) {
                     return RealmLoader();
                 },
+                flow : function(AuthenticationFlowLoader) {
+                    return AuthenticationFlowLoader();
+                },
                 configType : function(AuthenticationConfigDescriptionLoader) {
                     return AuthenticationConfigDescriptionLoader();
                 },
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 37ec3ab..e21b50e 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -599,15 +599,6 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
 
     $scope.realm = angular.copy(realm);
 
-    $scope.initProvider = function() {
-        if (instance && instance.alias) {
-
-        } else {
-            $scope.identityProvider.updateProfileFirstLoginMode = "on";
-        }
-
-    };
-
     $scope.initSamlProvider = function() {
         $scope.nameIdFormats = [
             /*
@@ -658,7 +649,6 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
         } else {
             $scope.identityProvider.config.nameIDPolicyFormat = $scope.nameIdFormats[0].format;
             $scope.identityProvider.config.signatureAlgorithm = $scope.signatureAlgorithms[1];
-            $scope.identityProvider.updateProfileFirstLoginMode = "off";
         }
     }
 
@@ -676,7 +666,6 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
         $scope.identityProvider.alias = providerFactory.id;
         $scope.identityProvider.providerId = providerFactory.id;
         $scope.identityProvider.enabled = true;
-        $scope.identityProvider.updateProfileFirstLoginMode = "off";
         $scope.identityProvider.authenticateByDefault = false;
         $scope.identityProvider.firstBrokerLoginFlowAlias = 'first broker login';
         $scope.newIdentityProvider = true;
@@ -1909,8 +1898,9 @@ module.controller('RequiredActionsCtrl', function($scope, realm, unregisteredReq
 
 });
 
-module.controller('AuthenticationConfigCtrl', function($scope, realm, configType, config, AuthenticationConfig, Notifications, Dialog, $location) {
+module.controller('AuthenticationConfigCtrl', function($scope, realm, flow, configType, config, AuthenticationConfig, Notifications, Dialog, $location) {
     $scope.realm = realm;
+    $scope.flow = flow;
     $scope.configType = configType;
     $scope.create = false;
     $scope.config = angular.copy(config);
@@ -1935,7 +1925,7 @@ module.controller('AuthenticationConfigCtrl', function($scope, realm, configType
         }, $scope.config, function() {
             $scope.changed = false;
             config = angular.copy($scope.config);
-            $location.url("/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + config.id);
+            $location.url("/realms/" + realm.realm + '/authentication/flows/' + flow.id + '/config/' + configType.providerId + "/" + config.id);
             Notifications.success("Your changes have been saved.");
         });
     };
@@ -1954,15 +1944,16 @@ module.controller('AuthenticationConfigCtrl', function($scope, realm, configType
         Dialog.confirmDelete($scope.config.alias, 'config', function() {
             AuthenticationConfig.remove({ realm: realm.realm, config : $scope.config.id }, function() {
                 Notifications.success("The config has been deleted.");
-                $location.url("/realms/" + realm.realm + '/authentication/flows');
+                $location.url("/realms/" + realm.realm + '/authentication/flows/' + flow.id);
             });
         });
     };
 
 });
 
-module.controller('AuthenticationConfigCreateCtrl', function($scope, realm, configType, execution, AuthenticationExecutionConfig, Notifications, Dialog, $location) {
+module.controller('AuthenticationConfigCreateCtrl', function($scope, realm, flow, configType, execution, AuthenticationExecutionConfig, Notifications, Dialog, $location) {
     $scope.realm = realm;
+    $scope.flow = flow;
     $scope.create = true;
     $scope.config = { config: {}};
     $scope.configType = configType;
@@ -1980,7 +1971,7 @@ module.controller('AuthenticationConfigCreateCtrl', function($scope, realm, conf
         }, $scope.config, function(data, headers) {
             var l = headers().location;
             var id = l.substring(l.lastIndexOf("/") + 1);
-            var url = "/realms/" + realm.realm + '/authentication/config/' + configType.providerId + "/" + id;
+            var url = "/realms/" + realm.realm + '/authentication/flows/' + flow.id + '/config/' + configType.providerId + "/" + id;
             console.log('redirect url: ' + url);
             $location.url(url);
             Notifications.success("Config has been created.");
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
index e055978..a77cf9f 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
@@ -53,8 +53,8 @@
                         <li data-ng-hide="flow.builtIn"><a href="" ng-click="removeExecution(execution)">Delete</a></li>
                         <li data-ng-hide="flow.builtIn || !execution.authenticationFlow"><a href="" ng-click="addSubFlowExecution(execution)">Add Execution</a></li>
                         <li data-ng-hide="flow.builtIn || !execution.authenticationFlow"><a href="" ng-click="addSubFlow(execution)">Add Flow</a></li>
-                        <li data-ng-show="execution.configurable && execution.authenticationConfig == null"><a href="#/create/authentication/{{realm.realm}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Config</a></li>
-                        <li data-ng-show="execution.configurable && execution.authenticationConfig != null"><a href="#/realms/{{realm.realm}}/authentication/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Config</a></li>
+                        <li data-ng-show="execution.configurable && execution.authenticationConfig == null"><a href="#/create/authentication/{{realm.realm}}/flows/{{flow.id}}/execution/{{execution.id}}/provider/{{execution.providerId}}">Config</a></li>
+                        <li data-ng-show="execution.configurable && execution.authenticationConfig != null"><a href="#/realms/{{realm.realm}}/authentication/flows/{{flow.id}}/config/{{execution.providerId}}/{{execution.authenticationConfig}}">Config</a></li>
                     </ul>
                 </div>
             </td>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
index 5856806..f587568 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html
@@ -2,6 +2,7 @@
 
     <ol class="breadcrumb">
         <li><a href="#/realms/{{realm.realm}}/authentication/flows">Authentication Flows</a></li>
+        <li><a href="#/realms/{{realm.realm}}/authentication/flows/{{flow.alias}}">{{flow.alias | capitalize}}</a></li>
         <li class="active" data-ng-show="create">Create Authenticator Config</li>
         <li class="active" data-ng-hide="create">{{config.alias}}</li>
     </ol>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 317709e..4cbd12a 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -1,4 +1,4 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
     <ol class="breadcrumb">
         <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">{{:: 'identity-providers' | translate}}</a></li>
         <li>{{identityProvider.alias}}</li>
@@ -53,19 +53,6 @@
                 <kc-tooltip>{{:: 'identity-provider.stored-tokens-readable.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group">
-                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">{{:: 'update-profile-on-first-login' | translate}}</label>
-                <div class="col-md-2">
-                		<div>
-                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
-                            <option value="on">{{:: 'on' | translate}}</option>
-                            <option value="missing">{{:: 'on-missing-info' | translate}}</option>
-                            <option value="off">{{:: 'off' | translate}}</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>{{:: 'update-profile-on-first-login.tooltip' | translate}}</kc-tooltip>
-            </div>
-            <div class="form-group">
                 <label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
                 <div class="col-md-6">
                     <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index 53cbf3a..c8f6c37 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -53,19 +53,6 @@
                 <kc-tooltip>{{:: 'identity-provider.stored-tokens-readable.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group">
-                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">{{:: 'update-profile-on-first-login' | translate}}</label>
-                <div class="col-md-2">
-                		<div>
-                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
-                            <option value="on">{{:: 'on' | translate}}</option>
-                            <option value="missing">{{:: 'on-missing-info' | translate}}</option>
-                            <option value="off">{{:: 'off' | translate}}</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>{{:: 'update-profile-on-first-login.tooltip' | translate}}</kc-tooltip>
-            </div>
-            <div class="form-group">
                 <label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
                 <div class="col-md-6">
                     <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index a4e3f13..5897f99 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -1,4 +1,4 @@
-<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2" data-ng-init="initProvider()">
+<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
     <ol class="breadcrumb">
         <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">{{:: 'identity-providers' | translate}}</a></li>
         <li>{{identityProvider.alias}}</li>
@@ -64,19 +64,6 @@
                 <kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group">
-                <label class="col-md-2 control-label" for="updateProfileFirstLoginMode">{{:: 'update-profile-on-first-login' | translate}}</label>
-                <div class="col-md-2">
-                		<div>
-                        <select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
-                            <option value="on">{{:: 'on' | translate}}</option>
-                            <option value="missing">{{:: 'on-missing-info' | translate}}</option>
-                            <option value="off">{{:: 'off' | translate}}</option>
-                        </select>
-                    </div>
-                </div>
-                <kc-tooltip>{{:: 'update-profile-on-first-login.tooltip' | translate}}</kc-tooltip>
-            </div>
-            <div class="form-group">
                 <label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
                 <div class="col-md-6">
                     <input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-confirm.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-confirm.ftl
index 28b12d0..02923d9 100644
--- a/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-confirm.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-confirm.ftl
@@ -12,7 +12,7 @@
         <form id="kc-register-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
 
                 <div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
-                    <button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="submitAction" value="updateProfile">${msg("confirmLinkIdpUpdateProfile")}</button>
+                    <button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="submitAction" value="updateProfile">${msg("confirmLinkIdpReviewProfile")}</button>
                     <button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="submitAction" value="linkAccount">${msg("confirmLinkIdpContinue", idpAlias)}</button>
                 </div>
 
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
index ca18e21..803ef2d 100644
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -142,7 +142,7 @@ federatedIdentityExistsMessage=User with {0} {1} already exists. Please login to
 confirmLinkIdpTitle=Account already exists
 federatedIdentityConfirmLinkMessage=User with {0} {1} already exists. How do you want to continue?
 federatedIdentityConfirmReauthenticateMessage=Authenticate as {0} to link your account with {1}
-confirmLinkIdpUpdateProfile=Update profile info
+confirmLinkIdpReviewProfile=Review profile info
 confirmLinkIdpContinue=Link {0} with existing account
 
 configureTotpMessage=You need to set up Mobile Authenticator to activate your account.
diff --git a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
index 4ea6602..f92f1d2 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
@@ -30,7 +30,6 @@ public class IdentityProviderEntity {
     private String providerId;
     private String name;
     private boolean enabled;
-    private String updateProfileFirstLoginMode;
     private boolean trustEmail;
     private boolean storeToken;
     protected boolean addReadTokenRoleOnCreate;
@@ -63,14 +62,6 @@ public class IdentityProviderEntity {
         this.enabled = enabled;
     }
 
-    public String getUpdateProfileFirstLoginMode() {
-        return updateProfileFirstLoginMode;
-    }
-
-    public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
-        this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
-    }
-
     public boolean isAuthenticateByDefault() {
         return authenticateByDefault;
     }
diff --git a/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java b/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
index 288b1f0..862f723 100755
--- a/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
+++ b/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
@@ -45,14 +45,6 @@ public class IdentityProviderModel implements Serializable {
     private String providerId;
 
     private boolean enabled;
-
-    /**
-     * For possible values see {@link IdentityProviderRepresentation#getUpdateProfileFirstLoginMode()}
-     * @see IdentityProviderRepresentation#UPFLM_ON
-     * @see IdentityProviderRepresentation#UPFLM_MISSING
-     * @see IdentityProviderRepresentation#UPFLM_OFF
-     */
-    protected String updateProfileFirstLoginMode = IdentityProviderRepresentation.UPFLM_ON;
     
     private boolean trustEmail;
 
@@ -81,7 +73,6 @@ public class IdentityProviderModel implements Serializable {
         this.alias = model.getAlias();
         this.config = new HashMap<String, String>(model.getConfig());
         this.enabled = model.isEnabled();
-        this.updateProfileFirstLoginMode = model.getUpdateProfileFirstLoginMode();
         this.trustEmail = model.isTrustEmail();
         this.storeToken = model.isStoreToken();
         this.authenticateByDefault = model.isAuthenticateByDefault();
@@ -121,20 +112,6 @@ public class IdentityProviderModel implements Serializable {
         this.enabled = enabled;
     }
 
-    /**
-     * @see IdentityProviderRepresentation#getUpdateProfileFirstLoginMode() 
-     */
-    public String getUpdateProfileFirstLoginMode() {
-        return updateProfileFirstLoginMode;
-    }
-
-    /**
-     * @see IdentityProviderRepresentation#setUpdateProfileFirstLoginMode(String) 
-     */
-    public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
-        this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
-    }
-
     public boolean isStoreToken() {
         return this.storeToken;
     }
diff --git a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
index a88e805..a874f5e 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java
@@ -1,9 +1,14 @@
 package org.keycloak.models.utils;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.keycloak.models.AuthenticationExecutionModel;
 import org.keycloak.models.AuthenticationFlowModel;
+import org.keycloak.models.AuthenticatorConfigModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -21,6 +26,8 @@ public class DefaultAuthenticationFlows {
     public static final String CLIENT_AUTHENTICATION_FLOW = "clients";
     public static final String FIRST_BROKER_LOGIN_FLOW = "first broker login";
 
+    public static final String IDP_REVIEW_PROFILE_CONFIG_ALIAS = "review profile config";
+
     public static void addFlows(RealmModel realm) {
         if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm);
         if (realm.getFlowByAlias(DIRECT_GRANT_FLOW) == null) directGrantFlow(realm, false);
@@ -321,24 +328,41 @@ public class DefaultAuthenticationFlows {
         firstBrokerLogin.setTopLevel(true);
         firstBrokerLogin.setBuiltIn(true);
         firstBrokerLogin = realm.addAuthenticationFlow(firstBrokerLogin);
-        // realm.setClientAuthenticationFlow(clients);
+
+        AuthenticatorConfigModel reviewProfileConfig = new AuthenticatorConfigModel();
+        reviewProfileConfig.setAlias(IDP_REVIEW_PROFILE_CONFIG_ALIAS);
+        Map<String, String> config = new HashMap<>();
+        config.put("update.profile.on.first.login", IdentityProviderRepresentation.UPFLM_MISSING);
+        reviewProfileConfig.setConfig(config);
+        reviewProfileConfig = realm.addAuthenticatorConfig(reviewProfileConfig);
 
         AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
         execution.setParentFlow(firstBrokerLogin.getId());
         execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
-        execution.setAuthenticator("idp-update-profile");
+        execution.setAuthenticator("idp-review-profile");
         execution.setPriority(10);
         execution.setAuthenticatorFlow(false);
+        execution.setAuthenticatorConfig(reviewProfileConfig.getId());
         realm.addAuthenticatorExecution(execution);
 
+
+        AuthenticatorConfigModel createUserIfUniqueConfig = new AuthenticatorConfigModel();
+        createUserIfUniqueConfig.setAlias("create unique user config");
+        config = new HashMap<>();
+        config.put("require.password.update.after.registration", "false");
+        createUserIfUniqueConfig.setConfig(config);
+        createUserIfUniqueConfig = realm.addAuthenticatorConfig(createUserIfUniqueConfig);
+
         execution = new AuthenticationExecutionModel();
         execution.setParentFlow(firstBrokerLogin.getId());
         execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
-        execution.setAuthenticator("idp-detect-duplications");
+        execution.setAuthenticator("idp-create-user-if-unique");
         execution.setPriority(20);
         execution.setAuthenticatorFlow(false);
+        execution.setAuthenticatorConfig(createUserIfUniqueConfig.getId());
         realm.addAuthenticatorExecution(execution);
 
+
         AuthenticationFlowModel linkExistingAccountFlow = new AuthenticationFlowModel();
         linkExistingAccountFlow.setTopLevel(false);
         linkExistingAccountFlow.setBuiltIn(true);
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index b975b56..69fcc07 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -389,7 +389,6 @@ public class ModelToRepresentation {
         providerRep.setAlias(identityProviderModel.getAlias());
         providerRep.setEnabled(identityProviderModel.isEnabled());
         providerRep.setStoreToken(identityProviderModel.isStoreToken());
-        providerRep.setUpdateProfileFirstLoginMode(identityProviderModel.getUpdateProfileFirstLoginMode());
         providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
         providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
         providerRep.setConfig(identityProviderModel.getConfig());
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 110b376..a31d355 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1080,7 +1080,6 @@ public class RepresentationToModel {
         identityProviderModel.setAlias(representation.getAlias());
         identityProviderModel.setProviderId(representation.getProviderId());
         identityProviderModel.setEnabled(representation.isEnabled());
-        identityProviderModel.setUpdateProfileFirstLoginMode(representation.getUpdateProfileFirstLoginMode());
         identityProviderModel.setTrustEmail(representation.isTrustEmail());
         identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault());
         identityProviderModel.setStoreToken(representation.isStoreToken());
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
index 5071c9b..6bbc31c 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
@@ -42,9 +42,6 @@ public class IdentityProviderEntity {
     @Column(name="ENABLED")
     private boolean enabled;
 
-    @Column(name = "UPDATE_PROFILE_FIRST_LGN_MD")
-    private String updateProfileFirstLoginMode;
-
     @Column(name = "TRUST_EMAIL")
     private boolean trustEmail;
 
@@ -106,14 +103,6 @@ public class IdentityProviderEntity {
         this.enabled = enabled;
     }
 
-    public String getUpdateProfileFirstLoginMode() {
-        return updateProfileFirstLoginMode;
-    }
-
-    public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
-        this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
-    }
-
     public boolean isStoreToken() {
         return this.storeToken;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 1cd8b45..106eaf8 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1216,7 +1216,6 @@ public class RealmAdapter implements RealmModel {
             identityProviderModel.setInternalId(entity.getInternalId());
             identityProviderModel.setConfig(entity.getConfig());
             identityProviderModel.setEnabled(entity.isEnabled());
-            identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
             identityProviderModel.setTrustEmail(entity.isTrustEmail());
             identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
             identityProviderModel.setFirstBrokerLoginFlowId(entity.getFirstBrokerLoginFlowId());
@@ -1250,7 +1249,6 @@ public class RealmAdapter implements RealmModel {
         entity.setEnabled(identityProvider.isEnabled());
         entity.setStoreToken(identityProvider.isStoreToken());
         entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
-        entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
         entity.setTrustEmail(identityProvider.isTrustEmail());
         entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
         entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId());
@@ -1278,7 +1276,6 @@ public class RealmAdapter implements RealmModel {
             if (entity.getInternalId().equals(identityProvider.getInternalId())) {
                 entity.setAlias(identityProvider.getAlias());
                 entity.setEnabled(identityProvider.isEnabled());
-                entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
                 entity.setTrustEmail(identityProvider.isTrustEmail());
                 entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
                 entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId());
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 479862c..9894977 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -823,7 +823,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
             identityProviderModel.setInternalId(entity.getInternalId());
             identityProviderModel.setConfig(entity.getConfig());
             identityProviderModel.setEnabled(entity.isEnabled());
-            identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
             identityProviderModel.setTrustEmail(entity.isTrustEmail());
             identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
             identityProviderModel.setFirstBrokerLoginFlowId(entity.getFirstBrokerLoginFlowId());
@@ -855,7 +854,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
         entity.setAlias(identityProvider.getAlias());
         entity.setProviderId(identityProvider.getProviderId());
         entity.setEnabled(identityProvider.isEnabled());
-        entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
         entity.setTrustEmail(identityProvider.isTrustEmail());
         entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
         entity.setStoreToken(identityProvider.isStoreToken());
@@ -884,7 +882,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
             if (entity.getInternalId().equals(identityProvider.getInternalId())) {
                 entity.setAlias(identityProvider.getAlias());
                 entity.setEnabled(identityProvider.isEnabled());
-                entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
                 entity.setTrustEmail(identityProvider.isTrustEmail());
                 entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
                 entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId());
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 ec98dd2..70551a1 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
@@ -9,8 +9,8 @@ org.keycloak.authentication.authenticators.resetcred.ResetCredentialChooseUser
 org.keycloak.authentication.authenticators.resetcred.ResetCredentialEmail
 org.keycloak.authentication.authenticators.resetcred.ResetOTP
 org.keycloak.authentication.authenticators.resetcred.ResetPassword
-org.keycloak.authentication.authenticators.broker.IdpUpdateProfileAuthenticatorFactory
-org.keycloak.authentication.authenticators.broker.IdpDetectDuplicationsAuthenticatorFactory
+org.keycloak.authentication.authenticators.broker.IdpReviewProfileAuthenticatorFactory
+org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticatorFactory
 org.keycloak.authentication.authenticators.broker.IdpConfirmLinkAuthenticatorFactory
 org.keycloak.authentication.authenticators.broker.IdpEmailVerificationAuthenticatorFactory
 org.keycloak.authentication.authenticators.broker.IdpUsernamePasswordFormFactory
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
index a7bae96..f88fb4a 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
@@ -52,7 +52,6 @@ public class IdentityProviderTest extends AbstractClientTest {
         assertEquals("clientSecret", representation.getConfig().get("clientSecret"));
         assertTrue(representation.isEnabled());
         assertFalse(representation.isStoreToken());
-        assertEquals(IdentityProviderRepresentation.UPFLM_ON, representation.getUpdateProfileFirstLoginMode());
         assertFalse(representation.isTrustEmail());
     }
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
index f1d4e10..8af43b2 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
@@ -23,15 +23,20 @@ import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
+import org.keycloak.authentication.authenticators.broker.IdpReviewProfileAuthenticatorFactory;
+import org.keycloak.models.AuthenticatorConfigModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionTask;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.RequiredAction;
+import org.keycloak.models.utils.DefaultAuthenticationFlows;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.representations.IDToken;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
 import org.keycloak.services.Urls;
@@ -138,7 +143,7 @@ public abstract class AbstractIdentityProviderTest {
     @Test
     public void testSuccessfulAuthentication() {
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON);
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
 
         UserModel user = assertSuccessfulAuthentication(identityProviderModel, "test-user", "new@email.com", true);
         Assert.assertEquals("617-666-7777", user.getFirstAttribute("mobile"));
@@ -147,7 +152,7 @@ public abstract class AbstractIdentityProviderTest {
     @Test
     public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_MISSING);
 
         assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
     }
@@ -155,7 +160,7 @@ public abstract class AbstractIdentityProviderTest {
     @Test
     public void testSuccessfulAuthenticationUpdateProfileOnMissing_missingEmail() {
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_MISSING);
 
         assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", "new@email.com", true);
     }
@@ -163,7 +168,7 @@ public abstract class AbstractIdentityProviderTest {
     @Test
     public void testSuccessfulAuthenticationWithoutUpdateProfile() {
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
 
         assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
     }
@@ -182,7 +187,7 @@ public abstract class AbstractIdentityProviderTest {
 
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
         try {
-            identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
+            setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
             identityProviderModel.setTrustEmail(false);
 
             UserModel federatedUser = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "test-user@localhost", false);
@@ -251,7 +256,7 @@ public abstract class AbstractIdentityProviderTest {
 
         try {
             IdentityProviderModel identityProviderModel = getIdentityProviderModel();
-            identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
+            setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
 
             UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", null, false);
 
@@ -268,12 +273,12 @@ public abstract class AbstractIdentityProviderTest {
     @Test
     public void testSuccessfulAuthenticationWithoutUpdateProfile_emailProvided_emailVerifyEnabled_emailTrustEnabled() {
         getRealm().setVerifyEmail(true);
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
         brokerServerRule.stopSession(this.session, true);
         this.session = brokerServerRule.startSession();
 
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
         try {
-            identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
             identityProviderModel.setTrustEmail(true);
 
             UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
@@ -300,7 +305,7 @@ public abstract class AbstractIdentityProviderTest {
 
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
         try {
-            identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON);
+            setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
             identityProviderModel.setTrustEmail(true);
 
             UserModel user = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "new@email.com", true);
@@ -320,7 +325,7 @@ public abstract class AbstractIdentityProviderTest {
 
         try {
             IdentityProviderModel identityProviderModel = getIdentityProviderModel();
-            identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
+            setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
 
             authenticateWithIdentityProvider(identityProviderModel, "test-user", false);
 
@@ -368,7 +373,7 @@ public abstract class AbstractIdentityProviderTest {
 
         try {
             IdentityProviderModel identityProviderModel = getIdentityProviderModel();
-            identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
+            setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
 
             authenticateWithIdentityProvider(identityProviderModel, "test-user-noemail", false);
 
@@ -475,7 +480,7 @@ public abstract class AbstractIdentityProviderTest {
     public void testUserAlreadyExistsWhenNotUpdatingProfile() {
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
 
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
 
         this.driver.navigate().to("http://localhost:8081/test-app/");
 
@@ -509,6 +514,7 @@ public abstract class AbstractIdentityProviderTest {
 
         // Link my "pedroigor" identity with "test-user" from brokered Keycloak
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
         accountFederatedIdentityPage.clickAddProvider(identityProviderModel.getAlias());
 
         assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
@@ -609,6 +615,7 @@ public abstract class AbstractIdentityProviderTest {
 
     @Test
     public void testTokenStorageAndRetrievalByApplication() {
+        setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
         IdentityProviderModel identityProviderModel = getIdentityProviderModel();
 
         identityProviderModel.setStoreToken(true);
@@ -774,7 +781,6 @@ public abstract class AbstractIdentityProviderTest {
 
         assertNotNull(identityProviderModel);
 
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON);
         identityProviderModel.setEnabled(true);
 
         return identityProviderModel;
@@ -851,4 +857,18 @@ public abstract class AbstractIdentityProviderTest {
 
         return htmlVerificationUrl;
     }
+
+    private void setUpdateProfileFirstLogin(final String updateProfileFirstLogin) {
+        KeycloakModelUtils.runJobInTransaction(this.session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
+
+            @Override
+            public void run(KeycloakSession session) {
+                RealmModel realm = session.realms().getRealm("realm-with-broker");
+                AuthenticatorConfigModel reviewProfileConfig = realm.getAuthenticatorConfigByAlias(DefaultAuthenticationFlows.IDP_REVIEW_PROFILE_CONFIG_ALIAS);
+                reviewProfileConfig.getConfig().put(IdpReviewProfileAuthenticatorFactory.UPDATE_PROFILE_ON_FIRST_LOGIN, updateProfileFirstLogin);
+                realm.updateAuthenticatorConfig(reviewProfileConfig);
+            }
+
+        });
+    }
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
index b5bc056..8e23f11 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
@@ -81,7 +81,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
 
         identityProviderModel.getConfig().put("config-added", "value-added");
         identityProviderModel.setEnabled(false);
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
         identityProviderModel.setTrustEmail(true);
         identityProviderModel.setStoreToken(true);
         identityProviderModel.setAuthenticateByDefault(true);
@@ -97,7 +96,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
 
         assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
         assertFalse(identityProviderModel.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, identityProviderModel.getUpdateProfileFirstLoginMode());
         assertTrue(identityProviderModel.isTrustEmail());
         assertTrue(identityProviderModel.isStoreToken());
         assertTrue(identityProviderModel.isAuthenticateByDefault());
@@ -105,7 +103,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
 
         identityProviderModel.getConfig().remove("config-added");
         identityProviderModel.setEnabled(true);
-        identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
         identityProviderModel.setTrustEmail(false);
         identityProviderModel.setAuthenticateByDefault(false);
 
@@ -118,7 +115,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
 
         assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
         assertTrue(identityProviderModel.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, identityProviderModel.getUpdateProfileFirstLoginMode());
         assertFalse(identityProviderModel.isTrustEmail());
         assertFalse(identityProviderModel.isAuthenticateByDefault());
         this.realmManager.removeRealm(realm);
@@ -167,7 +163,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         assertEquals("model-google", config.getAlias());
         assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
         assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
         assertEquals(true, config.isTrustEmail());
         assertEquals(false, config.isAuthenticateByDefault());
         assertEquals(true, config.isStoreToken());
@@ -186,7 +181,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         assertEquals("model-saml-signed-idp", config.getAlias());
         assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
         assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
         assertEquals(false, config.isAuthenticateByDefault());
         assertEquals(false, config.isTrustEmail());
         assertEquals(false, config.isStoreToken());
@@ -207,7 +201,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         assertEquals("model-oidc-idp", config.getAlias());
         assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
         assertEquals(false, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
         assertEquals(false, config.isTrustEmail());
         assertEquals(false, config.isAuthenticateByDefault());
         assertEquals(false, config.isStoreToken());
@@ -222,7 +215,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         assertEquals("model-facebook", config.getAlias());
         assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
         assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
         assertEquals(false, config.isTrustEmail());
         assertEquals(false, config.isAuthenticateByDefault());
         assertEquals(false, config.isStoreToken());
@@ -241,7 +233,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         assertEquals("model-github", config.getAlias());
         assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
         assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
         assertEquals(false, config.isTrustEmail());
         assertEquals(false, config.isAuthenticateByDefault());
         assertEquals(false, config.isStoreToken());
@@ -258,17 +249,16 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         OAuth2IdentityProviderConfig config = liIdentityProvider.getConfig();
 
         assertEquals("model-linkedin", config.getAlias());
-      assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
-      assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, config.getUpdateProfileFirstLoginMode());
+        assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
+        assertEquals(true, config.isEnabled());
         assertEquals(false, config.isTrustEmail());
-      assertEquals(false, config.isAuthenticateByDefault());
-      assertEquals(false, config.isStoreToken());
-      assertEquals("clientId", config.getClientId());
-      assertEquals("clientSecret", config.getClientSecret());
-      assertEquals(LinkedInIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
-      assertEquals(LinkedInIdentityProvider.TOKEN_URL, config.getTokenUrl());
-      assertEquals(LinkedInIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
+        assertEquals(false, config.isAuthenticateByDefault());
+        assertEquals(false, config.isStoreToken());
+        assertEquals("clientId", config.getClientId());
+        assertEquals("clientSecret", config.getClientSecret());
+        assertEquals(LinkedInIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
+        assertEquals(LinkedInIdentityProvider.TOKEN_URL, config.getTokenUrl());
+        assertEquals(LinkedInIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
     }
 
     private void assertStackoverflowIdentityProviderConfig(IdentityProviderModel identityProvider) {
@@ -278,7 +268,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         assertEquals("model-stackoverflow", config.getAlias());
         assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
         assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
         assertEquals(false, config.isTrustEmail());
         assertEquals(false, config.isAuthenticateByDefault());
         assertEquals(false, config.isStoreToken());
@@ -297,7 +286,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
         assertEquals("model-twitter", config.getAlias());
         assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
         assertEquals(true, config.isEnabled());
-        assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
         assertEquals(false, config.isTrustEmail());
         assertEquals(false, config.isAuthenticateByDefault());
         assertEquals(true, config.isStoreToken());
diff --git a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
index a4f204d..0b8b79e 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
@@ -17,7 +17,6 @@
             "alias" : "model-google",
             "providerId" : "google",
             "enabled": true,
-            "updateProfileFirstLogin" : "true",
             "trustEmail" : "true",
             "storeToken": "true",
             "config": {
@@ -29,7 +28,6 @@
             "alias" : "model-facebook",
             "providerId" : "facebook",
             "enabled": true,
-            "updateProfileFirstLogin" : "false",
             "firstBrokerLoginFlowAlias" : "browser",
             "config": {
                 "authorizationUrl": "authorizationUrl",
@@ -43,7 +41,6 @@
             "alias" : "model-github",
             "providerId" : "github",
             "enabled": true,
-            "updateProfileFirstLoginMode" : "on",
             "storeToken": "false",
             "config": {
                 "authorizationUrl": "authorizationUrl",
@@ -57,7 +54,6 @@
             "alias" : "model-twitter",
             "providerId" : "twitter",
             "enabled": true,
-            "updateProfileFirstLoginMode" : "off",
             "storeToken": true,
             "config": {
                 "authorizationUrl": "authorizationUrl",
@@ -71,7 +67,6 @@
             "alias" : "model-linkedin",
             "providerId" : "linkedin",
             "enabled": true,
-            "updateProfileFirstLoginMode" : "missing",
             "storeToken": false,
             "config": {
                 "authorizationUrl": "authorizationUrl",
@@ -85,7 +80,6 @@
             "alias" : "model-stackoverflow",
             "providerId" : "stackoverflow",
             "enabled": true,
-            "updateProfileFirstLoginMode" : "off",
             "storeToken": false,
             "config": {
                 "key": "keyValue",
@@ -100,7 +94,6 @@
           "alias" : "model-saml-signed-idp",
           "providerId" : "saml",
           "enabled": true,
-          "updateProfileFirstLoginMode" : "on",
           "config": {
             "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml",
             "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
@@ -116,7 +109,6 @@
             "alias" : "kc-saml-signed-idp",
             "providerId" : "saml",
             "enabled": true,
-            "updateProfileFirstLoginMode" : "on",
             "addReadTokenRoleOnCreate": true,
             "config": {
                 "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
@@ -135,7 +127,6 @@
             "alias" : "kc-saml-idp-basic",
             "providerId" : "saml",
             "enabled": true,
-            "updateProfileFirstLoginMode" : "on",
             "trustEmail" : false,
             "addReadTokenRoleOnCreate": true,
             "config": {
@@ -151,7 +142,6 @@
             "alias" : "model-oidc-idp",
             "providerId" : "oidc",
             "enabled": false,
-            "updateProfileFirstLoginMode" : "off",
             "authenticateByDefault" : "false",
             "config": {
                 "clientId": "clientId",
@@ -167,7 +157,6 @@
             "alias" : "kc-oidc-idp",
             "providerId" : "keycloak-oidc",
             "enabled": true,
-            "updateProfileFirstLoginMode" : "off",
             "storeToken" : true,
             "addReadTokenRoleOnCreate": true,
             "config": {
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java
index b8b2323..d23d4b5 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java
@@ -36,7 +36,6 @@ public class KeycloakArquillianExtension implements LoadableExtension {
                 .service(DeployableContainer.class, CustomUndertowContainer.class);
 
         builder
-                //.service(TestExecutionDecider.class, JiraTestExecutionDecider.class)
                 .service(TestExecutionDecider.class, MigrationTestExecutionDecider.class);
 
         builder
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractCorsExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractCorsExampleAdapterTest.java
index 72db4bb..24933cb 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractCorsExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractCorsExampleAdapterTest.java
@@ -10,7 +10,6 @@ import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
 import org.keycloak.testsuite.adapter.page.AngularCorsProductExample;
 import org.keycloak.testsuite.adapter.page.CorsDatabaseServiceExample;
-import org.keycloak.testsuite.arquillian.jira.Jira;
 import org.keycloak.testsuite.auth.page.account.Account;
 
 import java.io.File;
@@ -63,7 +62,6 @@ public abstract class AbstractCorsExampleAdapterTest extends AbstractExampleAdap
         driver.manage().deleteAllCookies();
     }
 
-    @Jira("KEYCLOAK-1546")
     @Test
     public void angularCorsProductTest() {
         angularCorsProductExample.navigateTo();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java
index 9fb8165..8a470ad 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java
@@ -34,7 +34,6 @@ import org.keycloak.testsuite.adapter.page.CustomerPortal;
 import org.keycloak.testsuite.adapter.page.InputPortal;
 import org.keycloak.testsuite.adapter.page.ProductPortal;
 import org.keycloak.testsuite.adapter.page.SecurePortal;
-import org.keycloak.testsuite.arquillian.jira.Jira;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
 import org.keycloak.util.BasicAuthHelper;
@@ -224,7 +223,6 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
     }
 
     @Test
-    @Jira(value = "KEYCLOAK-1478") // rejected
     public void testLoginSSOIdleRemoveExpiredUserSessions() {
         // test login to customer-portal which does a bearer request to customer-db
         customerPortal.navigateTo();
@@ -279,7 +277,6 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
         testRealmResource().update(demoRealmRep);
     }
 
-    @Jira("KEYCLOAK-518")
     @Test
     public void testNullBearerToken() {
         Client client = ClientBuilder.newClient();
@@ -293,7 +290,6 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
         client.close();
     }
 
-    @Jira("KEYCLOAK-1368")
     @Test
     public void testNullBearerTokenCustomErrorPage() {
         Client client = ClientBuilder.newClient();
@@ -326,7 +322,6 @@ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAd
         client.close();
     }
 
-    @Jira("KEYCLOAK-518")
     @Test
     public void testBadUser() {
         Client client = ClientBuilder.newClient();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSessionServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSessionServletAdapterTest.java
index 79c0bef..cd969a3 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSessionServletAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSessionServletAdapterTest.java
@@ -16,7 +16,6 @@ import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.adapter.page.SessionPortal;
-import org.keycloak.testsuite.arquillian.jira.Jira;
 import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
 import org.keycloak.testsuite.auth.page.account.Sessions;
 import org.keycloak.testsuite.auth.page.login.Login;
@@ -60,7 +59,6 @@ public abstract class AbstractSessionServletAdapterTest extends AbstractServlets
     @SecondBrowser
     protected WebDriver driver2;
 
-    @Jira("KEYCLOAK-732")
     @Test
     public void testSingleSessionInvalidated() {
 
@@ -102,7 +100,6 @@ public abstract class AbstractSessionServletAdapterTest extends AbstractServlets
     }
 
     @Test
-    @Jira("KEYCLOAK-741, KEYCLOAK-1485")
     public void testSessionInvalidatedAfterFailedRefresh() {
         RealmRepresentation testRealmRep = testRealmResource().toRepresentation();
         ClientResource sessionPortalRes = null;
@@ -139,7 +136,6 @@ public abstract class AbstractSessionServletAdapterTest extends AbstractServlets
     }
 
     @Test
-    @Jira("KEYCLOAK-942")
     public void testAdminApplicationLogout() {
         // login as bburke
         loginAndCheckSession(driver, testRealmLoginPage);
@@ -157,7 +153,6 @@ public abstract class AbstractSessionServletAdapterTest extends AbstractServlets
     }
 
     @Test
-    @Jira("KEYCLOAK-1216, KEYCLOAK-1485")
     public void testAccountManagementSessionsLogout() {
         // login as bburke
         loginAndCheckSession(driver, testRealmLoginPage);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java
index 8e63593..72455e2 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/authentication/OTPPolicyTest.java
@@ -26,7 +26,6 @@ import static org.junit.Assert.*;
 import org.junit.Before;
 import org.junit.Test;
 import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.arquillian.jira.Jira;
 import org.keycloak.testsuite.console.AbstractConsoleTest;
 import org.keycloak.testsuite.console.page.authentication.otppolicy.OTPPolicy;
 import org.keycloak.testsuite.console.page.authentication.otppolicy.OTPPolicyForm.Digits;
@@ -67,7 +66,6 @@ public class OTPPolicyTest extends AbstractConsoleTest {
     }      
     
     @Test
-    @Jira(value = "KEYCLOAK-2031")
     public void invalidValuesTest() {
         otpPolicyPage.form().setValues(OTPType.TIME_BASED, OTPHashAlg.SHA1, Digits.EMPTY, "", "30");
         assertEquals("Error! Missing or invalid field(s). Please verify the fields in red.", otpPolicyPage.getErrorMessage());