KEYCLOAK-1750 Option updateProfileOnFirstLogin moved from IdentityProvider to IdpReviewProfile authenticator

This commit is contained in:
mposolda 2015-11-09 22:09:37 +01:00
parent 99e75c69a0
commit 4ca442d1b2
28 changed files with 240 additions and 259 deletions

View file

@ -7,6 +7,7 @@
<constraints nullable="false"/> <constraints nullable="false"/>
</column> </column>
</addColumn> </addColumn>
<dropColumn tableName="IDENTITY_PROVIDER" columnName="UPDATE_PROFILE_FIRST_LGN_MD"/>
</changeSet> </changeSet>
</databaseChangeLog> </databaseChangeLog>

View file

@ -46,6 +46,7 @@ public class IdentityProviderRepresentation {
* @see #UPFLM_MISSING * @see #UPFLM_MISSING
* @see #UPFLM_OFF * @see #UPFLM_OFF
*/ */
@Deprecated
protected String updateProfileFirstLoginMode = UPFLM_ON; protected String updateProfileFirstLoginMode = UPFLM_ON;
protected boolean trustEmail; 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() { public String getUpdateProfileFirstLoginMode() {
return updateProfileFirstLoginMode; return updateProfileFirstLoginMode;
} }
/** /**
* @param updateProfileFirstLoginMode see {@link #updateProfileFirstLoginMode} * @deprecated deprecated and replaced by configuration on IdpReviewProfileAuthenticator
*/ */
@Deprecated
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) { public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode; this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
} }

View file

@ -79,16 +79,34 @@
<section> <section>
<title>Version specific migration</title> <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> <section>
<title>Migrating to 1.6.0.Final</title> <title>Migrating to 1.6.0.Final</title>
<simplesect> <simplesect>
<title>Refresh tokens are not reusable anymore</title> <title>Option that refresh tokens are not reusable anymore</title>
<para> <para>
Old versions of Keycloak allowed reusing refresh tokens multiple times. Keycloak no longer permits Old versions of Keycloak allowed reusing refresh tokens multiple times. Keycloak still permits this,
this by default. When a refresh token is used to obtain a new access token a new refresh token is also but also have an option <literal>Revoke refresh token</literal> to disallow it. Option is in in admin console under token settings.
included. This new refresh token should be used next time the access token is refreshed. If this is When a refresh token is used to obtain a new access token a new refresh token is also
a problem for you it's possible to enable reuse of refresh tokens in the admin console under token included. When option is enabled, then this new refresh token should be used next time the access token is refreshed.
settings. It won't be possible to reuse old refresh token multiple times.
</para> </para>
</simplesect> </simplesect>
<simplesect> <simplesect>

View file

@ -1348,12 +1348,15 @@ module.config([ '$routeProvider', function($routeProvider) {
}, },
controller : 'RealmOtpPolicyCtrl' controller : 'RealmOtpPolicyCtrl'
}) })
.when('/realms/:realm/authentication/config/:provider/:config', { .when('/realms/:realm/authentication/flows/:flow/config/:provider/:config', {
templateUrl : resourceUrl + '/partials/authenticator-config.html', templateUrl : resourceUrl + '/partials/authenticator-config.html',
resolve : { resolve : {
realm : function(RealmLoader) { realm : function(RealmLoader) {
return RealmLoader(); return RealmLoader();
}, },
flow : function(AuthenticationFlowLoader) {
return AuthenticationFlowLoader();
},
configType : function(AuthenticationConfigDescriptionLoader) { configType : function(AuthenticationConfigDescriptionLoader) {
return AuthenticationConfigDescriptionLoader(); return AuthenticationConfigDescriptionLoader();
}, },
@ -1363,12 +1366,15 @@ module.config([ '$routeProvider', function($routeProvider) {
}, },
controller : 'AuthenticationConfigCtrl' 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', templateUrl : resourceUrl + '/partials/authenticator-config.html',
resolve : { resolve : {
realm : function(RealmLoader) { realm : function(RealmLoader) {
return RealmLoader(); return RealmLoader();
}, },
flow : function(AuthenticationFlowLoader) {
return AuthenticationFlowLoader();
},
configType : function(AuthenticationConfigDescriptionLoader) { configType : function(AuthenticationConfigDescriptionLoader) {
return AuthenticationConfigDescriptionLoader(); return AuthenticationConfigDescriptionLoader();
}, },

View file

@ -599,15 +599,6 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
$scope.realm = angular.copy(realm); $scope.realm = angular.copy(realm);
$scope.initProvider = function() {
if (instance && instance.alias) {
} else {
$scope.identityProvider.updateProfileFirstLoginMode = "on";
}
};
$scope.initSamlProvider = function() { $scope.initSamlProvider = function() {
$scope.nameIdFormats = [ $scope.nameIdFormats = [
/* /*
@ -658,7 +649,6 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
} else { } else {
$scope.identityProvider.config.nameIDPolicyFormat = $scope.nameIdFormats[0].format; $scope.identityProvider.config.nameIDPolicyFormat = $scope.nameIdFormats[0].format;
$scope.identityProvider.config.signatureAlgorithm = $scope.signatureAlgorithms[1]; $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.alias = providerFactory.id;
$scope.identityProvider.providerId = providerFactory.id; $scope.identityProvider.providerId = providerFactory.id;
$scope.identityProvider.enabled = true; $scope.identityProvider.enabled = true;
$scope.identityProvider.updateProfileFirstLoginMode = "off";
$scope.identityProvider.authenticateByDefault = false; $scope.identityProvider.authenticateByDefault = false;
$scope.identityProvider.firstBrokerLoginFlowAlias = 'first broker login'; $scope.identityProvider.firstBrokerLoginFlowAlias = 'first broker login';
$scope.newIdentityProvider = true; $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.realm = realm;
$scope.flow = flow;
$scope.configType = configType; $scope.configType = configType;
$scope.create = false; $scope.create = false;
$scope.config = angular.copy(config); $scope.config = angular.copy(config);
@ -1935,7 +1925,7 @@ module.controller('AuthenticationConfigCtrl', function($scope, realm, configType
}, $scope.config, function() { }, $scope.config, function() {
$scope.changed = false; $scope.changed = false;
config = angular.copy($scope.config); 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."); 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() { Dialog.confirmDelete($scope.config.alias, 'config', function() {
AuthenticationConfig.remove({ realm: realm.realm, config : $scope.config.id }, function() { AuthenticationConfig.remove({ realm: realm.realm, config : $scope.config.id }, function() {
Notifications.success("The config has been deleted."); 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.realm = realm;
$scope.flow = flow;
$scope.create = true; $scope.create = true;
$scope.config = { config: {}}; $scope.config = { config: {}};
$scope.configType = configType; $scope.configType = configType;
@ -1980,7 +1971,7 @@ module.controller('AuthenticationConfigCreateCtrl', function($scope, realm, conf
}, $scope.config, function(data, headers) { }, $scope.config, function(data, headers) {
var l = headers().location; var l = headers().location;
var id = l.substring(l.lastIndexOf("/") + 1); 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); console.log('redirect url: ' + url);
$location.url(url); $location.url(url);
Notifications.success("Config has been created."); Notifications.success("Config has been created.");

View file

@ -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"><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="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-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="#/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/config/{{execution.providerId}}/{{execution.authenticationConfig}}">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> </ul>
</div> </div>
</td> </td>

View file

@ -2,6 +2,7 @@
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/authentication/flows">Authentication Flows</a></li> <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-show="create">Create Authenticator Config</li>
<li class="active" data-ng-hide="create">{{config.alias}}</li> <li class="active" data-ng-hide="create">{{config.alias}}</li>
</ol> </ol>

View file

@ -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"> <ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/identity-provider-settings">{{:: 'identity-providers' | translate}}</a></li> <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">{{:: 'identity-providers' | translate}}</a></li>
<li>{{identityProvider.alias}}</li> <li>{{identityProvider.alias}}</li>
@ -52,19 +52,6 @@
</div> </div>
<kc-tooltip>{{:: 'identity-provider.stored-tokens-readable.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'identity-provider.stored-tokens-readable.tooltip' | translate}}</kc-tooltip>
</div> </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"> <div class="form-group">
<label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label> <label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
<div class="col-md-6"> <div class="col-md-6">

View file

@ -52,19 +52,6 @@
</div> </div>
<kc-tooltip>{{:: 'identity-provider.stored-tokens-readable.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'identity-provider.stored-tokens-readable.tooltip' | translate}}</kc-tooltip>
</div> </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"> <div class="form-group">
<label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label> <label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
<div class="col-md-6"> <div class="col-md-6">

View file

@ -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"> <ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/identity-provider-settings">{{:: 'identity-providers' | translate}}</a></li> <li><a href="#/realms/{{realm.realm}}/identity-provider-settings">{{:: 'identity-providers' | translate}}</a></li>
<li>{{identityProvider.alias}}</li> <li>{{identityProvider.alias}}</li>
@ -63,19 +63,6 @@
</div> </div>
<kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip> <kc-tooltip>{{:: 'identity-provider.enabled.tooltip' | translate}}</kc-tooltip>
</div> </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"> <div class="form-group">
<label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label> <label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
<div class="col-md-6"> <div class="col-md-6">

View file

@ -12,7 +12,7 @@
<form id="kc-register-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post"> <form id="kc-register-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
<div id="kc-form-buttons" class="${properties.kcFormGroupClass!}"> <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> <button type="submit" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="submitAction" value="linkAccount">${msg("confirmLinkIdpContinue", idpAlias)}</button>
</div> </div>

View file

@ -142,7 +142,7 @@ federatedIdentityExistsMessage=User with {0} {1} already exists. Please login to
confirmLinkIdpTitle=Account already exists confirmLinkIdpTitle=Account already exists
federatedIdentityConfirmLinkMessage=User with {0} {1} already exists. How do you want to continue? federatedIdentityConfirmLinkMessage=User with {0} {1} already exists. How do you want to continue?
federatedIdentityConfirmReauthenticateMessage=Authenticate as {0} to link your account with {1} federatedIdentityConfirmReauthenticateMessage=Authenticate as {0} to link your account with {1}
confirmLinkIdpUpdateProfile=Update profile info confirmLinkIdpReviewProfile=Review profile info
confirmLinkIdpContinue=Link {0} with existing account confirmLinkIdpContinue=Link {0} with existing account
configureTotpMessage=You need to set up Mobile Authenticator to activate your account. configureTotpMessage=You need to set up Mobile Authenticator to activate your account.

View file

@ -45,14 +45,6 @@ public class IdentityProviderModel implements Serializable {
private String providerId; private String providerId;
private boolean enabled; 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; private boolean trustEmail;
@ -81,7 +73,6 @@ public class IdentityProviderModel implements Serializable {
this.alias = model.getAlias(); this.alias = model.getAlias();
this.config = new HashMap<String, String>(model.getConfig()); this.config = new HashMap<String, String>(model.getConfig());
this.enabled = model.isEnabled(); this.enabled = model.isEnabled();
this.updateProfileFirstLoginMode = model.getUpdateProfileFirstLoginMode();
this.trustEmail = model.isTrustEmail(); this.trustEmail = model.isTrustEmail();
this.storeToken = model.isStoreToken(); this.storeToken = model.isStoreToken();
this.authenticateByDefault = model.isAuthenticateByDefault(); this.authenticateByDefault = model.isAuthenticateByDefault();
@ -121,20 +112,6 @@ public class IdentityProviderModel implements Serializable {
this.enabled = enabled; 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() { public boolean isStoreToken() {
return this.storeToken; return this.storeToken;
} }

View file

@ -30,7 +30,6 @@ public class IdentityProviderEntity {
private String providerId; private String providerId;
private String name; private String name;
private boolean enabled; private boolean enabled;
private String updateProfileFirstLoginMode;
private boolean trustEmail; private boolean trustEmail;
private boolean storeToken; private boolean storeToken;
protected boolean addReadTokenRoleOnCreate; protected boolean addReadTokenRoleOnCreate;
@ -63,14 +62,6 @@ public class IdentityProviderEntity {
this.enabled = enabled; this.enabled = enabled;
} }
public String getUpdateProfileFirstLoginMode() {
return updateProfileFirstLoginMode;
}
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}
public boolean isAuthenticateByDefault() { public boolean isAuthenticateByDefault() {
return authenticateByDefault; return authenticateByDefault;
} }

View file

@ -1,9 +1,14 @@
package org.keycloak.models.utils; package org.keycloak.models.utils;
import java.util.HashMap;
import java.util.Map;
import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @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 CLIENT_AUTHENTICATION_FLOW = "clients";
public static final String FIRST_BROKER_LOGIN_FLOW = "first broker login"; 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) { public static void addFlows(RealmModel realm) {
if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm); if (realm.getFlowByAlias(BROWSER_FLOW) == null) browserFlow(realm);
if (realm.getFlowByAlias(DIRECT_GRANT_FLOW) == null) directGrantFlow(realm, false); if (realm.getFlowByAlias(DIRECT_GRANT_FLOW) == null) directGrantFlow(realm, false);
@ -321,24 +328,41 @@ public class DefaultAuthenticationFlows {
firstBrokerLogin.setTopLevel(true); firstBrokerLogin.setTopLevel(true);
firstBrokerLogin.setBuiltIn(true); firstBrokerLogin.setBuiltIn(true);
firstBrokerLogin = realm.addAuthenticationFlow(firstBrokerLogin); 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(); AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
execution.setParentFlow(firstBrokerLogin.getId()); execution.setParentFlow(firstBrokerLogin.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED); execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
execution.setAuthenticator("idp-update-profile"); execution.setAuthenticator("idp-review-profile");
execution.setPriority(10); execution.setPriority(10);
execution.setAuthenticatorFlow(false); execution.setAuthenticatorFlow(false);
execution.setAuthenticatorConfig(reviewProfileConfig.getId());
realm.addAuthenticatorExecution(execution); 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 = new AuthenticationExecutionModel();
execution.setParentFlow(firstBrokerLogin.getId()); execution.setParentFlow(firstBrokerLogin.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE); execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
execution.setAuthenticator("idp-create-user-if-unique"); execution.setAuthenticator("idp-create-user-if-unique");
execution.setPriority(20); execution.setPriority(20);
execution.setAuthenticatorFlow(false); execution.setAuthenticatorFlow(false);
execution.setAuthenticatorConfig(createUserIfUniqueConfig.getId());
realm.addAuthenticatorExecution(execution); realm.addAuthenticatorExecution(execution);
AuthenticationFlowModel linkExistingAccountFlow = new AuthenticationFlowModel(); AuthenticationFlowModel linkExistingAccountFlow = new AuthenticationFlowModel();
linkExistingAccountFlow.setTopLevel(false); linkExistingAccountFlow.setTopLevel(false);
linkExistingAccountFlow.setBuiltIn(true); linkExistingAccountFlow.setBuiltIn(true);

View file

@ -389,7 +389,6 @@ public class ModelToRepresentation {
providerRep.setAlias(identityProviderModel.getAlias()); providerRep.setAlias(identityProviderModel.getAlias());
providerRep.setEnabled(identityProviderModel.isEnabled()); providerRep.setEnabled(identityProviderModel.isEnabled());
providerRep.setStoreToken(identityProviderModel.isStoreToken()); providerRep.setStoreToken(identityProviderModel.isStoreToken());
providerRep.setUpdateProfileFirstLoginMode(identityProviderModel.getUpdateProfileFirstLoginMode());
providerRep.setTrustEmail(identityProviderModel.isTrustEmail()); providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault()); providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
providerRep.setConfig(identityProviderModel.getConfig()); providerRep.setConfig(identityProviderModel.getConfig());

View file

@ -1080,7 +1080,6 @@ public class RepresentationToModel {
identityProviderModel.setAlias(representation.getAlias()); identityProviderModel.setAlias(representation.getAlias());
identityProviderModel.setProviderId(representation.getProviderId()); identityProviderModel.setProviderId(representation.getProviderId());
identityProviderModel.setEnabled(representation.isEnabled()); identityProviderModel.setEnabled(representation.isEnabled());
identityProviderModel.setUpdateProfileFirstLoginMode(representation.getUpdateProfileFirstLoginMode());
identityProviderModel.setTrustEmail(representation.isTrustEmail()); identityProviderModel.setTrustEmail(representation.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault()); identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault());
identityProviderModel.setStoreToken(representation.isStoreToken()); identityProviderModel.setStoreToken(representation.isStoreToken());

View file

@ -1216,7 +1216,6 @@ public class RealmAdapter implements RealmModel {
identityProviderModel.setInternalId(entity.getInternalId()); identityProviderModel.setInternalId(entity.getInternalId());
identityProviderModel.setConfig(entity.getConfig()); identityProviderModel.setConfig(entity.getConfig());
identityProviderModel.setEnabled(entity.isEnabled()); identityProviderModel.setEnabled(entity.isEnabled());
identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
identityProviderModel.setTrustEmail(entity.isTrustEmail()); identityProviderModel.setTrustEmail(entity.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault()); identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
identityProviderModel.setFirstBrokerLoginFlowId(entity.getFirstBrokerLoginFlowId()); identityProviderModel.setFirstBrokerLoginFlowId(entity.getFirstBrokerLoginFlowId());
@ -1250,7 +1249,6 @@ public class RealmAdapter implements RealmModel {
entity.setEnabled(identityProvider.isEnabled()); entity.setEnabled(identityProvider.isEnabled());
entity.setStoreToken(identityProvider.isStoreToken()); entity.setStoreToken(identityProvider.isStoreToken());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
entity.setTrustEmail(identityProvider.isTrustEmail()); entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId()); entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId());
@ -1278,7 +1276,6 @@ public class RealmAdapter implements RealmModel {
if (entity.getInternalId().equals(identityProvider.getInternalId())) { if (entity.getInternalId().equals(identityProvider.getInternalId())) {
entity.setAlias(identityProvider.getAlias()); entity.setAlias(identityProvider.getAlias());
entity.setEnabled(identityProvider.isEnabled()); entity.setEnabled(identityProvider.isEnabled());
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
entity.setTrustEmail(identityProvider.isTrustEmail()); entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId()); entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId());

View file

@ -42,9 +42,6 @@ public class IdentityProviderEntity {
@Column(name="ENABLED") @Column(name="ENABLED")
private boolean enabled; private boolean enabled;
@Column(name = "UPDATE_PROFILE_FIRST_LGN_MD")
private String updateProfileFirstLoginMode;
@Column(name = "TRUST_EMAIL") @Column(name = "TRUST_EMAIL")
private boolean trustEmail; private boolean trustEmail;
@ -106,14 +103,6 @@ public class IdentityProviderEntity {
this.enabled = enabled; this.enabled = enabled;
} }
public String getUpdateProfileFirstLoginMode() {
return updateProfileFirstLoginMode;
}
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}
public boolean isStoreToken() { public boolean isStoreToken() {
return this.storeToken; return this.storeToken;
} }

View file

@ -823,7 +823,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
identityProviderModel.setInternalId(entity.getInternalId()); identityProviderModel.setInternalId(entity.getInternalId());
identityProviderModel.setConfig(entity.getConfig()); identityProviderModel.setConfig(entity.getConfig());
identityProviderModel.setEnabled(entity.isEnabled()); identityProviderModel.setEnabled(entity.isEnabled());
identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
identityProviderModel.setTrustEmail(entity.isTrustEmail()); identityProviderModel.setTrustEmail(entity.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault()); identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
identityProviderModel.setFirstBrokerLoginFlowId(entity.getFirstBrokerLoginFlowId()); identityProviderModel.setFirstBrokerLoginFlowId(entity.getFirstBrokerLoginFlowId());
@ -855,7 +854,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
entity.setAlias(identityProvider.getAlias()); entity.setAlias(identityProvider.getAlias());
entity.setProviderId(identityProvider.getProviderId()); entity.setProviderId(identityProvider.getProviderId());
entity.setEnabled(identityProvider.isEnabled()); entity.setEnabled(identityProvider.isEnabled());
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
entity.setTrustEmail(identityProvider.isTrustEmail()); entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setStoreToken(identityProvider.isStoreToken()); entity.setStoreToken(identityProvider.isStoreToken());
@ -884,7 +882,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
if (entity.getInternalId().equals(identityProvider.getInternalId())) { if (entity.getInternalId().equals(identityProvider.getInternalId())) {
entity.setAlias(identityProvider.getAlias()); entity.setAlias(identityProvider.getAlias());
entity.setEnabled(identityProvider.isEnabled()); entity.setEnabled(identityProvider.isEnabled());
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
entity.setTrustEmail(identityProvider.isTrustEmail()); entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId()); entity.setFirstBrokerLoginFlowId(identityProvider.getFirstBrokerLoginFlowId());

View file

@ -14,6 +14,7 @@ import org.keycloak.events.Details;
import org.keycloak.events.EventBuilder; import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType; import org.keycloak.events.EventType;
import org.keycloak.login.LoginFormsProvider; import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -26,9 +27,9 @@ import org.keycloak.services.validation.Validation;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/ */
public class IdpUpdateProfileAuthenticator extends AbstractIdpAuthenticator { public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator {
protected static Logger logger = Logger.getLogger(IdpUpdateProfileAuthenticator.class); protected static Logger logger = Logger.getLogger(IdpReviewProfileAuthenticator.class);
@Override @Override
public boolean requiresUser() { public boolean requiresUser() {
@ -61,10 +62,17 @@ public class IdpUpdateProfileAuthenticator extends AbstractIdpAuthenticator {
return true; return true;
} }
IdentityProviderModel idpConfig = brokerContext.getIdpConfig(); String updateProfileFirstLogin;
AuthenticatorConfigModel authenticatorConfig = context.getAuthenticatorConfig();
if (authenticatorConfig == null || !authenticatorConfig.getConfig().containsKey(IdpReviewProfileAuthenticatorFactory.UPDATE_PROFILE_ON_FIRST_LOGIN)) {
updateProfileFirstLogin = IdentityProviderRepresentation.UPFLM_MISSING;
} else {
updateProfileFirstLogin = authenticatorConfig.getConfig().get(IdpReviewProfileAuthenticatorFactory.UPDATE_PROFILE_ON_FIRST_LOGIN);
}
RealmModel realm = context.getRealm(); RealmModel realm = context.getRealm();
return IdentityProviderRepresentation.UPFLM_ON.equals(idpConfig.getUpdateProfileFirstLoginMode()) return IdentityProviderRepresentation.UPFLM_ON.equals(updateProfileFirstLogin)
|| (IdentityProviderRepresentation.UPFLM_MISSING.equals(idpConfig.getUpdateProfileFirstLoginMode()) && !Validation.validateUserMandatoryFields(realm, userCtx)); || (IdentityProviderRepresentation.UPFLM_MISSING.equals(updateProfileFirstLogin) && !Validation.validateUserMandatoryFields(realm, userCtx));
} }
@Override @Override

View file

@ -0,0 +1,107 @@
package org.keycloak.authentication.authenticators.broker;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.keycloak.Config;
import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.AuthenticatorFactory;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class IdpReviewProfileAuthenticatorFactory implements AuthenticatorFactory {
public static final String PROVIDER_ID = "idp-review-profile";
static IdpReviewProfileAuthenticator SINGLETON = new IdpReviewProfileAuthenticator();
public static final String UPDATE_PROFILE_ON_FIRST_LOGIN = "update.profile.on.first.login";
@Override
public Authenticator create(KeycloakSession session) {
return SINGLETON;
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String getReferenceCategory() {
return "reviewProfile";
}
@Override
public boolean isConfigurable() {
return true;
}
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
AuthenticationExecutionModel.Requirement.REQUIRED,
AuthenticationExecutionModel.Requirement.DISABLED};
@Override
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
return REQUIREMENT_CHOICES;
}
@Override
public String getDisplayType() {
return "Review Profile";
}
@Override
public String getHelpText() {
return "User reviews and updates profile data retrieved from Identity Provider in the displayed form";
}
@Override
public boolean isUserSetupAllowed() {
return false;
}
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(UPDATE_PROFILE_ON_FIRST_LOGIN);
property.setLabel("{{:: 'update-profile-on-first-login' | translate}}");
property.setType(ProviderConfigProperty.LIST_TYPE);
List<String> updateProfileValues = Arrays.asList(IdentityProviderRepresentation.UPFLM_ON, IdentityProviderRepresentation.UPFLM_MISSING, IdentityProviderRepresentation.UPFLM_OFF);
property.setDefaultValue(updateProfileValues);
property.setHelpText("Define conditions under which a user has to review and update his profile after first-time login. Value 'On' means that"
+ " page for reviewing profile will be displayed and user can review and update his profile. Value 'off' means that page won't be displayed."
+ " Value 'missing' means that page is displayed just when some required attribute is missing (wasn't downloaded from identity provider). Value 'missing' is the default one");
configProperties.add(property);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
}

View file

@ -1,84 +0,0 @@
package org.keycloak.authentication.authenticators.broker;
import java.util.List;
import org.keycloak.Config;
import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.AuthenticatorFactory;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ProviderConfigProperty;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class IdpUpdateProfileAuthenticatorFactory implements AuthenticatorFactory {
public static final String PROVIDER_ID = "idp-update-profile";
static IdpUpdateProfileAuthenticator SINGLETON = new IdpUpdateProfileAuthenticator();
@Override
public Authenticator create(KeycloakSession session) {
return SINGLETON;
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String getReferenceCategory() {
return "updateProfile";
}
@Override
public boolean isConfigurable() {
return false;
}
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
AuthenticationExecutionModel.Requirement.REQUIRED,
AuthenticationExecutionModel.Requirement.DISABLED};
@Override
public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
return REQUIREMENT_CHOICES;
}
@Override
public String getDisplayType() {
return "Update Profile";
}
@Override
public String getHelpText() {
return "Updates profile data retrieved from Identity Provider in the displayed form";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return null;
}
@Override
public boolean isUserSetupAllowed() {
return false;
}
}

View file

@ -9,7 +9,7 @@ org.keycloak.authentication.authenticators.resetcred.ResetCredentialChooseUser
org.keycloak.authentication.authenticators.resetcred.ResetCredentialEmail org.keycloak.authentication.authenticators.resetcred.ResetCredentialEmail
org.keycloak.authentication.authenticators.resetcred.ResetOTP org.keycloak.authentication.authenticators.resetcred.ResetOTP
org.keycloak.authentication.authenticators.resetcred.ResetPassword org.keycloak.authentication.authenticators.resetcred.ResetPassword
org.keycloak.authentication.authenticators.broker.IdpUpdateProfileAuthenticatorFactory org.keycloak.authentication.authenticators.broker.IdpReviewProfileAuthenticatorFactory
org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticatorFactory org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticatorFactory
org.keycloak.authentication.authenticators.broker.IdpConfirmLinkAuthenticatorFactory org.keycloak.authentication.authenticators.broker.IdpConfirmLinkAuthenticatorFactory
org.keycloak.authentication.authenticators.broker.IdpEmailVerificationAuthenticatorFactory org.keycloak.authentication.authenticators.broker.IdpEmailVerificationAuthenticatorFactory

View file

@ -52,7 +52,6 @@ public class IdentityProviderTest extends AbstractClientTest {
assertEquals("clientSecret", representation.getConfig().get("clientSecret")); assertEquals("clientSecret", representation.getConfig().get("clientSecret"));
assertTrue(representation.isEnabled()); assertTrue(representation.isEnabled());
assertFalse(representation.isStoreToken()); assertFalse(representation.isStoreToken());
assertEquals(IdentityProviderRepresentation.UPFLM_ON, representation.getUpdateProfileFirstLoginMode());
assertFalse(representation.isTrustEmail()); assertFalse(representation.isTrustEmail());
} }

View file

@ -23,15 +23,20 @@ import org.junit.Before;
import org.junit.ClassRule; import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; 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.ClientModel;
import org.keycloak.models.Constants; import org.keycloak.models.Constants;
import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.UserModel.RequiredAction; 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.IDToken;
import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.services.Urls; import org.keycloak.services.Urls;
@ -138,7 +143,7 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testSuccessfulAuthentication() { public void testSuccessfulAuthentication() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
UserModel user = assertSuccessfulAuthentication(identityProviderModel, "test-user", "new@email.com", true); UserModel user = assertSuccessfulAuthentication(identityProviderModel, "test-user", "new@email.com", true);
Assert.assertEquals("617-666-7777", user.getFirstAttribute("mobile")); Assert.assertEquals("617-666-7777", user.getFirstAttribute("mobile"));
@ -147,7 +152,7 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() { public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_MISSING);
assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false); assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
} }
@ -155,7 +160,7 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testSuccessfulAuthenticationUpdateProfileOnMissing_missingEmail() { public void testSuccessfulAuthenticationUpdateProfileOnMissing_missingEmail() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_MISSING);
assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", "new@email.com", true); assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", "new@email.com", true);
} }
@ -163,7 +168,7 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testSuccessfulAuthenticationWithoutUpdateProfile() { public void testSuccessfulAuthenticationWithoutUpdateProfile() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false); assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
} }
@ -182,7 +187,7 @@ public abstract class AbstractIdentityProviderTest {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
try { try {
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
identityProviderModel.setTrustEmail(false); identityProviderModel.setTrustEmail(false);
UserModel federatedUser = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "test-user@localhost", false); UserModel federatedUser = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "test-user@localhost", false);
@ -251,7 +256,7 @@ public abstract class AbstractIdentityProviderTest {
try { try {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", null, false); UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", null, false);
@ -268,12 +273,12 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testSuccessfulAuthenticationWithoutUpdateProfile_emailProvided_emailVerifyEnabled_emailTrustEnabled() { public void testSuccessfulAuthenticationWithoutUpdateProfile_emailProvided_emailVerifyEnabled_emailTrustEnabled() {
getRealm().setVerifyEmail(true); getRealm().setVerifyEmail(true);
setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
brokerServerRule.stopSession(this.session, true); brokerServerRule.stopSession(this.session, true);
this.session = brokerServerRule.startSession(); this.session = brokerServerRule.startSession();
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
try { try {
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
identityProviderModel.setTrustEmail(true); identityProviderModel.setTrustEmail(true);
UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false); UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
@ -300,7 +305,7 @@ public abstract class AbstractIdentityProviderTest {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
try { try {
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
identityProviderModel.setTrustEmail(true); identityProviderModel.setTrustEmail(true);
UserModel user = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "new@email.com", true); UserModel user = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "new@email.com", true);
@ -320,7 +325,7 @@ public abstract class AbstractIdentityProviderTest {
try { try {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
authenticateWithIdentityProvider(identityProviderModel, "test-user", false); authenticateWithIdentityProvider(identityProviderModel, "test-user", false);
@ -368,7 +373,7 @@ public abstract class AbstractIdentityProviderTest {
try { try {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
authenticateWithIdentityProvider(identityProviderModel, "test-user-noemail", false); authenticateWithIdentityProvider(identityProviderModel, "test-user-noemail", false);
@ -475,7 +480,7 @@ public abstract class AbstractIdentityProviderTest {
public void testUserAlreadyExistsWhenNotUpdatingProfile() { public void testUserAlreadyExistsWhenNotUpdatingProfile() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF); setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_OFF);
this.driver.navigate().to("http://localhost:8081/test-app/"); 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 // Link my "pedroigor" identity with "test-user" from brokered Keycloak
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
accountFederatedIdentityPage.clickAddProvider(identityProviderModel.getAlias()); accountFederatedIdentityPage.clickAddProvider(identityProviderModel.getAlias());
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/")); assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8082/auth/"));
@ -609,6 +615,7 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testTokenStorageAndRetrievalByApplication() { public void testTokenStorageAndRetrievalByApplication() {
setUpdateProfileFirstLogin(IdentityProviderRepresentation.UPFLM_ON);
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setStoreToken(true); identityProviderModel.setStoreToken(true);
@ -774,7 +781,6 @@ public abstract class AbstractIdentityProviderTest {
assertNotNull(identityProviderModel); assertNotNull(identityProviderModel);
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON);
identityProviderModel.setEnabled(true); identityProviderModel.setEnabled(true);
return identityProviderModel; return identityProviderModel;
@ -851,4 +857,18 @@ public abstract class AbstractIdentityProviderTest {
return htmlVerificationUrl; 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);
}
});
}
} }

View file

@ -81,7 +81,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
identityProviderModel.getConfig().put("config-added", "value-added"); identityProviderModel.getConfig().put("config-added", "value-added");
identityProviderModel.setEnabled(false); identityProviderModel.setEnabled(false);
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
identityProviderModel.setTrustEmail(true); identityProviderModel.setTrustEmail(true);
identityProviderModel.setStoreToken(true); identityProviderModel.setStoreToken(true);
identityProviderModel.setAuthenticateByDefault(true); identityProviderModel.setAuthenticateByDefault(true);
@ -97,7 +96,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("value-added", identityProviderModel.getConfig().get("config-added")); assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
assertFalse(identityProviderModel.isEnabled()); assertFalse(identityProviderModel.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, identityProviderModel.getUpdateProfileFirstLoginMode());
assertTrue(identityProviderModel.isTrustEmail()); assertTrue(identityProviderModel.isTrustEmail());
assertTrue(identityProviderModel.isStoreToken()); assertTrue(identityProviderModel.isStoreToken());
assertTrue(identityProviderModel.isAuthenticateByDefault()); assertTrue(identityProviderModel.isAuthenticateByDefault());
@ -105,7 +103,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
identityProviderModel.getConfig().remove("config-added"); identityProviderModel.getConfig().remove("config-added");
identityProviderModel.setEnabled(true); identityProviderModel.setEnabled(true);
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
identityProviderModel.setTrustEmail(false); identityProviderModel.setTrustEmail(false);
identityProviderModel.setAuthenticateByDefault(false); identityProviderModel.setAuthenticateByDefault(false);
@ -118,7 +115,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertFalse(identityProviderModel.getConfig().containsKey("config-added")); assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
assertTrue(identityProviderModel.isEnabled()); assertTrue(identityProviderModel.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, identityProviderModel.getUpdateProfileFirstLoginMode());
assertFalse(identityProviderModel.isTrustEmail()); assertFalse(identityProviderModel.isTrustEmail());
assertFalse(identityProviderModel.isAuthenticateByDefault()); assertFalse(identityProviderModel.isAuthenticateByDefault());
this.realmManager.removeRealm(realm); this.realmManager.removeRealm(realm);
@ -167,7 +163,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-google", config.getAlias()); assertEquals("model-google", config.getAlias());
assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
assertEquals(true, config.isTrustEmail()); assertEquals(true, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(true, config.isStoreToken()); assertEquals(true, config.isStoreToken());
@ -186,7 +181,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-saml-signed-idp", config.getAlias()); assertEquals("model-saml-signed-idp", config.getAlias());
assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isTrustEmail()); assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
@ -207,7 +201,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-oidc-idp", config.getAlias()); assertEquals("model-oidc-idp", config.getAlias());
assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(false, config.isEnabled()); assertEquals(false, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
assertEquals(false, config.isTrustEmail()); assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
@ -222,7 +215,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-facebook", config.getAlias()); assertEquals("model-facebook", config.getAlias());
assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
assertEquals(false, config.isTrustEmail()); assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
@ -241,7 +233,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-github", config.getAlias()); assertEquals("model-github", config.getAlias());
assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
assertEquals(false, config.isTrustEmail()); assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
@ -258,17 +249,16 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
OAuth2IdentityProviderConfig config = liIdentityProvider.getConfig(); OAuth2IdentityProviderConfig config = liIdentityProvider.getConfig();
assertEquals("model-linkedin", config.getAlias()); assertEquals("model-linkedin", config.getAlias());
assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, config.getUpdateProfileFirstLoginMode());
assertEquals(false, config.isTrustEmail()); assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());
assertEquals("clientSecret", config.getClientSecret()); assertEquals("clientSecret", config.getClientSecret());
assertEquals(LinkedInIdentityProvider.AUTH_URL, config.getAuthorizationUrl()); assertEquals(LinkedInIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
assertEquals(LinkedInIdentityProvider.TOKEN_URL, config.getTokenUrl()); assertEquals(LinkedInIdentityProvider.TOKEN_URL, config.getTokenUrl());
assertEquals(LinkedInIdentityProvider.PROFILE_URL, config.getUserInfoUrl()); assertEquals(LinkedInIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
} }
private void assertStackoverflowIdentityProviderConfig(IdentityProviderModel identityProvider) { private void assertStackoverflowIdentityProviderConfig(IdentityProviderModel identityProvider) {
@ -278,7 +268,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-stackoverflow", config.getAlias()); assertEquals("model-stackoverflow", config.getAlias());
assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
assertEquals(false, config.isTrustEmail()); assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
@ -297,7 +286,6 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-twitter", config.getAlias()); assertEquals("model-twitter", config.getAlias());
assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
assertEquals(false, config.isTrustEmail()); assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(true, config.isStoreToken()); assertEquals(true, config.isStoreToken());

View file

@ -17,7 +17,6 @@
"alias" : "model-google", "alias" : "model-google",
"providerId" : "google", "providerId" : "google",
"enabled": true, "enabled": true,
"updateProfileFirstLogin" : "true",
"trustEmail" : "true", "trustEmail" : "true",
"storeToken": "true", "storeToken": "true",
"config": { "config": {
@ -29,7 +28,6 @@
"alias" : "model-facebook", "alias" : "model-facebook",
"providerId" : "facebook", "providerId" : "facebook",
"enabled": true, "enabled": true,
"updateProfileFirstLogin" : "false",
"firstBrokerLoginFlowAlias" : "browser", "firstBrokerLoginFlowAlias" : "browser",
"config": { "config": {
"authorizationUrl": "authorizationUrl", "authorizationUrl": "authorizationUrl",
@ -43,7 +41,6 @@
"alias" : "model-github", "alias" : "model-github",
"providerId" : "github", "providerId" : "github",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "on",
"storeToken": "false", "storeToken": "false",
"config": { "config": {
"authorizationUrl": "authorizationUrl", "authorizationUrl": "authorizationUrl",
@ -57,7 +54,6 @@
"alias" : "model-twitter", "alias" : "model-twitter",
"providerId" : "twitter", "providerId" : "twitter",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "off",
"storeToken": true, "storeToken": true,
"config": { "config": {
"authorizationUrl": "authorizationUrl", "authorizationUrl": "authorizationUrl",
@ -71,7 +67,6 @@
"alias" : "model-linkedin", "alias" : "model-linkedin",
"providerId" : "linkedin", "providerId" : "linkedin",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "missing",
"storeToken": false, "storeToken": false,
"config": { "config": {
"authorizationUrl": "authorizationUrl", "authorizationUrl": "authorizationUrl",
@ -85,7 +80,6 @@
"alias" : "model-stackoverflow", "alias" : "model-stackoverflow",
"providerId" : "stackoverflow", "providerId" : "stackoverflow",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "off",
"storeToken": false, "storeToken": false,
"config": { "config": {
"key": "keyValue", "key": "keyValue",
@ -100,7 +94,6 @@
"alias" : "model-saml-signed-idp", "alias" : "model-saml-signed-idp",
"providerId" : "saml", "providerId" : "saml",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "on",
"config": { "config": {
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml", "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml",
"nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", "nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
@ -116,7 +109,6 @@
"alias" : "kc-saml-signed-idp", "alias" : "kc-saml-signed-idp",
"providerId" : "saml", "providerId" : "saml",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "on",
"addReadTokenRoleOnCreate": true, "addReadTokenRoleOnCreate": true,
"config": { "config": {
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml", "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
@ -135,7 +127,6 @@
"alias" : "kc-saml-idp-basic", "alias" : "kc-saml-idp-basic",
"providerId" : "saml", "providerId" : "saml",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "on",
"trustEmail" : false, "trustEmail" : false,
"addReadTokenRoleOnCreate": true, "addReadTokenRoleOnCreate": true,
"config": { "config": {
@ -151,7 +142,6 @@
"alias" : "model-oidc-idp", "alias" : "model-oidc-idp",
"providerId" : "oidc", "providerId" : "oidc",
"enabled": false, "enabled": false,
"updateProfileFirstLoginMode" : "off",
"authenticateByDefault" : "false", "authenticateByDefault" : "false",
"config": { "config": {
"clientId": "clientId", "clientId": "clientId",
@ -167,7 +157,6 @@
"alias" : "kc-oidc-idp", "alias" : "kc-oidc-idp",
"providerId" : "keycloak-oidc", "providerId" : "keycloak-oidc",
"enabled": true, "enabled": true,
"updateProfileFirstLoginMode" : "off",
"storeToken" : true, "storeToken" : true,
"addReadTokenRoleOnCreate": true, "addReadTokenRoleOnCreate": true,
"config": { "config": {