keycloak-aplcache
Changes
forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js 23(+7 -16)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html 4(+2 -2)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authenticator-config.html 1(+1 -0)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html 15(+1 -14)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html 13(+0 -13)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html 15(+1 -14)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java 12(+10 -2)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticatorFactory.java 32(+24 -8)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java 18(+13 -5)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticatorFactory.java 45(+34 -11)
services/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory 4(+2 -2)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java 44(+32 -12)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java 30(+9 -21)
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)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java 1(+0 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractCorsExampleAdapterTest.java 2(+0 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java 5(+0 -5)
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());