KEYCLOAK-1750 Option updateProfileOnFirstLogin moved from IdentityProvider to IdpReviewProfile authenticator
This commit is contained in:
parent
99e75c69a0
commit
4ca442d1b2
28 changed files with 240 additions and 259 deletions
|
@ -7,6 +7,7 @@
|
|||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<dropColumn tableName="IDENTITY_PROVIDER" columnName="UPDATE_PROFILE_FIRST_LGN_MD"/>
|
||||
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -79,16 +79,34 @@
|
|||
|
||||
<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>
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
@ -52,19 +52,6 @@
|
|||
</div>
|
||||
<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">
|
||||
|
|
|
@ -52,19 +52,6 @@
|
|||
</div>
|
||||
<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">
|
||||
|
|
|
@ -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>
|
||||
|
@ -63,19 +63,6 @@
|
|||
</div>
|
||||
<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">
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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-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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.keycloak.events.Details;
|
|||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.AuthenticatorConfigModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
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>
|
||||
*/
|
||||
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
|
||||
public boolean requiresUser() {
|
||||
|
@ -61,10 +62,17 @@ public class IdpUpdateProfileAuthenticator extends AbstractIdpAuthenticator {
|
|||
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();
|
||||
return IdentityProviderRepresentation.UPFLM_ON.equals(idpConfig.getUpdateProfileFirstLoginMode())
|
||||
|| (IdentityProviderRepresentation.UPFLM_MISSING.equals(idpConfig.getUpdateProfileFirstLoginMode()) && !Validation.validateUserMandatoryFields(realm, userCtx));
|
||||
return IdentityProviderRepresentation.UPFLM_ON.equals(updateProfileFirstLogin)
|
||||
|| (IdentityProviderRepresentation.UPFLM_MISSING.equals(updateProfileFirstLogin) && !Validation.validateUserMandatoryFields(realm, userCtx));
|
||||
}
|
||||
|
||||
@Override
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ 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.IdpReviewProfileAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.broker.IdpConfirmLinkAuthenticatorFactory
|
||||
org.keycloak.authentication.authenticators.broker.IdpEmailVerificationAuthenticatorFactory
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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": {
|
||||
|
|
Loading…
Reference in a new issue