KEYCLOAK-1371 - Perform "Update Profile on First Login" only if some of
mandatory user profile fields is missing from identity provider
This commit is contained in:
parent
fb60ca115f
commit
dcc19a39d7
27 changed files with 293 additions and 127 deletions
|
@ -112,7 +112,17 @@
|
|||
</addColumn>
|
||||
<addColumn tableName="IDENTITY_PROVIDER">
|
||||
<column name="TRUST_EMAIL" type="BOOLEAN" defaultValueBoolean="false"/>
|
||||
<column name="UPDATE_PROFILE_FIRST_LOGIN_MODE" type="VARCHAR(10)" defaultValue="on">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<!-- migrate value from UPDATE_PROFILE_FIRST_LOGIN to UPDATE_PROFILE_FIRST_LOGIN_MODE then drop it -->
|
||||
<update tableName="IDENTITY_PROVIDER">
|
||||
<column name="UPDATE_PROFILE_FIRST_LOGIN_MODE" value="off"/>
|
||||
<where>UPDATE_PROFILE_FIRST_LOGIN = false</where>
|
||||
</update>
|
||||
<dropColumn tableName="IDENTITY_PROVIDER" columnName="UPDATE_PROFILE_FIRST_LOGIN"/>
|
||||
|
||||
<addColumn tableName="USER_REQUIRED_ACTION">
|
||||
<column name="REQUIRED_ACTION" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
|
|
|
@ -29,7 +29,25 @@ public class IdentityProviderRepresentation {
|
|||
protected String internalId;
|
||||
protected String providerId;
|
||||
protected boolean enabled = true;
|
||||
protected boolean updateProfileFirstLogin = true;
|
||||
|
||||
public static final String UPFLM_ON = "on";
|
||||
public static final String UPFLM_MISSING = "missing";
|
||||
public static final String UPFLM_OFF = "off";
|
||||
|
||||
/**
|
||||
* Mode of profile update after first login when user is created over this identity provider. Possible values:
|
||||
* <ul>
|
||||
* <li><code>on</code> - update profile page is presented for all users
|
||||
* <li><code>missing</code> - update profile page is presented for users with missing some of mandatory user profile fields
|
||||
* <li><code>off</code> - update profile page is newer shown after first login
|
||||
* </ul>
|
||||
*
|
||||
* @see #UPFLM_ON
|
||||
* @see #UPFLM_MISSING
|
||||
* @see #UPFLM_OFF
|
||||
*/
|
||||
protected String updateProfileFirstLoginMode = UPFLM_ON;
|
||||
|
||||
protected boolean trustEmail;
|
||||
protected boolean storeToken;
|
||||
protected boolean addReadTokenRoleOnCreate;
|
||||
|
@ -76,12 +94,29 @@ public class IdentityProviderRepresentation {
|
|||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isUpdateProfileFirstLogin() {
|
||||
return this.updateProfileFirstLogin;
|
||||
/**
|
||||
*
|
||||
* Deprecated because replaced by {@link #updateProfileFirstLoginMode}. Kept here to allow import of old realms.
|
||||
*
|
||||
* @deprecated {@link #setUpdateProfileFirstLoginMode(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
|
||||
this.updateProfileFirstLoginMode = updateProfileFirstLogin ? UPFLM_ON : UPFLM_OFF;
|
||||
}
|
||||
|
||||
public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
|
||||
this.updateProfileFirstLogin = updateProfileFirstLogin;
|
||||
/**
|
||||
* @return see {@link #updateProfileFirstLoginMode}
|
||||
*/
|
||||
public String getUpdateProfileFirstLoginMode() {
|
||||
return updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param updateProfileFirstLoginMode see {@link #updateProfileFirstLoginMode}
|
||||
*/
|
||||
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
|
||||
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
public boolean isAuthenticateByDefault() {
|
||||
|
|
|
@ -299,9 +299,11 @@
|
|||
</entry>
|
||||
<entry>
|
||||
Allows you to force users to update their profile right after the authentication finishes and
|
||||
before the account is actually created in Keycloak. When enabled, users will be presented with the
|
||||
before the account is actually created in Keycloak. When "On", users will be always presented with the
|
||||
<emphasis>update profile page</emphasis> asking for additional information in order to federate their identities.
|
||||
If disabled, the account will be created with the minimal information obtained from the identity provider
|
||||
When "On missing info", users will be presented with the <emphasis>update profile page</emphasis> only if some
|
||||
mandatory information (email, first name, last name) is not provided by identity provider.
|
||||
If "Off", the account will be created with the minimal information obtained from the identity provider
|
||||
during the authentication process.
|
||||
</entry>
|
||||
</row>
|
||||
|
|
|
@ -597,7 +597,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
|
|||
if (instance && instance.alias) {
|
||||
|
||||
} else {
|
||||
$scope.identityProvider.updateProfileFirstLogin = false;
|
||||
$scope.identityProvider.updateProfileFirstLoginMode = "on";
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -645,7 +645,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
|
|||
|
||||
} else {
|
||||
$scope.identityProvider.config.nameIDPolicyFormat = $scope.nameIdFormats[0].format;
|
||||
$scope.identityProvider.updateProfileFirstLogin = false;
|
||||
$scope.identityProvider.updateProfileFirstLoginMode = "off";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +663,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
|
|||
$scope.identityProvider.alias = providerFactory.id;
|
||||
$scope.identityProvider.providerId = providerFactory.id;
|
||||
$scope.identityProvider.enabled = true;
|
||||
$scope.identityProvider.updateProfileFirstLogin = false;
|
||||
$scope.identityProvider.updateProfileFirstLoginMode = "off";
|
||||
$scope.identityProvider.authenticateByDefault = false;
|
||||
$scope.newIdentityProvider = true;
|
||||
}
|
||||
|
|
|
@ -59,11 +59,17 @@
|
|||
<kc-tooltip>Enable/disable new users can read any stored tokens. This assigns the broker.read-token role.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="updateProfileFirstLogin">Update Profile on First Login</label>
|
||||
<div class="col-md-6">
|
||||
<input ng-model="identityProvider.updateProfileFirstLogin" name="identityProvider.updateProfileFirstLogin" id="updateProfileFirstLogin" onoffswitch />
|
||||
<label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
|
||||
<div class="col-md-2">
|
||||
<div>
|
||||
<select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
|
||||
<option value="on">On</option>
|
||||
<option value="missing">On missing info</option>
|
||||
<option value="off">Off</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip>
|
||||
<kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="trustEmail">Trust email</label>
|
||||
|
|
|
@ -60,11 +60,17 @@
|
|||
<kc-tooltip>Enable/disable new users can read any stored tokens. This assigns the broker.read-token role.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="updateProfileFirstLogin">Update Profile on First Login</label>
|
||||
<div class="col-md-6">
|
||||
<input ng-model="identityProvider.updateProfileFirstLogin" name="identityProvider.updateProfileFirstLogin" id="updateProfileFirstLogin" onoffswitch />
|
||||
<label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
|
||||
<div class="col-md-2">
|
||||
<div>
|
||||
<select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
|
||||
<option value="on">On</option>
|
||||
<option value="missing">On missing info</option>
|
||||
<option value="off">Off</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip>
|
||||
<kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="trustEmail">Trust email</label>
|
||||
|
|
|
@ -70,11 +70,17 @@
|
|||
<kc-tooltip>Enable/disable this identity provider.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="updateProfileFirstLogin">Update Profile on First Login</label>
|
||||
<div class="col-md-6">
|
||||
<input ng-model="identityProvider.updateProfileFirstLogin" name="identityProvider.updateProfileFirstLogin" id="updateProfileFirstLogin" onoffswitch />
|
||||
<label class="col-md-2 control-label" for="updateProfileFirstLoginMode">Update Profile on First Login</label>
|
||||
<div class="col-md-2">
|
||||
<div>
|
||||
<select id="updateProfileFirstLoginMode" ng-model="identityProvider.updateProfileFirstLoginMode" class="form-control">
|
||||
<option value="on">On</option>
|
||||
<option value="missing">On missing info</option>
|
||||
<option value="off">Off</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip>
|
||||
<kc-tooltip>Define under which conditions must user update his profile right after the first login.</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="trustEmail">Trust email</label>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<caption class="hidden">Table of identity providers</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="3" class="kc-table-actions">
|
||||
<th colspan="4" class="kc-table-actions">
|
||||
<div class="dropdown pull-right">
|
||||
<select class="form-control" ng-model="provider"
|
||||
ng-options="p.name group by p.groupName for p in allProviders track by p.id"
|
||||
|
@ -21,6 +21,7 @@
|
|||
<tr ng-show="configuredProviders.length > 0">
|
||||
<th>Name</th>
|
||||
<th>Provider</th>
|
||||
<th>Enabled</th>
|
||||
<th width="15%">GUI order</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -30,6 +31,7 @@
|
|||
<a href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}">{{identityProvider.alias}}</a>
|
||||
</td>
|
||||
<td>{{identityProvider.providerId}}</td>
|
||||
<td>{{identityProvider.enabled}}</td>
|
||||
<td>{{identityProvider.config.guiOrder}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.keycloak.models;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
|
||||
/**
|
||||
* <p>A model type representing the configuration for identity providers. It provides some common properties and also a {@link org.keycloak.models.IdentityProviderModel#config}
|
||||
* for configuration options and properties specifics to a identity provider.</p>
|
||||
|
@ -43,7 +45,13 @@ public class IdentityProviderModel {
|
|||
|
||||
private boolean enabled;
|
||||
|
||||
private boolean updateProfileFirstLogin = true;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
@ -70,7 +78,7 @@ public class IdentityProviderModel {
|
|||
this.alias = model.getAlias();
|
||||
this.config = new HashMap<String, String>(model.getConfig());
|
||||
this.enabled = model.isEnabled();
|
||||
this.updateProfileFirstLogin = model.isUpdateProfileFirstLogin();
|
||||
this.updateProfileFirstLoginMode = model.getUpdateProfileFirstLoginMode();
|
||||
this.trustEmail = model.isTrustEmail();
|
||||
this.storeToken = model.isStoreToken();
|
||||
this.authenticateByDefault = model.isAuthenticateByDefault();
|
||||
|
@ -109,12 +117,18 @@ public class IdentityProviderModel {
|
|||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isUpdateProfileFirstLogin() {
|
||||
return this.updateProfileFirstLogin;
|
||||
/**
|
||||
* @see IdentityProviderRepresentation#getUpdateProfileFirstLoginMode()
|
||||
*/
|
||||
public String getUpdateProfileFirstLoginMode() {
|
||||
return updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
|
||||
this.updateProfileFirstLogin = updateProfileFirstLogin;
|
||||
/**
|
||||
* @see IdentityProviderRepresentation#setUpdateProfileFirstLoginMode(String)
|
||||
*/
|
||||
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
|
||||
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
public boolean isStoreToken() {
|
||||
|
|
|
@ -30,7 +30,7 @@ public class IdentityProviderEntity {
|
|||
private String providerId;
|
||||
private String name;
|
||||
private boolean enabled;
|
||||
private boolean updateProfileFirstLogin;
|
||||
private String updateProfileFirstLoginMode;
|
||||
private boolean trustEmail;
|
||||
private boolean storeToken;
|
||||
protected boolean addReadTokenRoleOnCreate;
|
||||
|
@ -62,12 +62,12 @@ public class IdentityProviderEntity {
|
|||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isUpdateProfileFirstLogin() {
|
||||
return updateProfileFirstLogin;
|
||||
public String getUpdateProfileFirstLoginMode() {
|
||||
return updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
|
||||
this.updateProfileFirstLogin = updateProfileFirstLogin;
|
||||
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
|
||||
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
public boolean isAuthenticateByDefault() {
|
||||
|
|
|
@ -325,7 +325,7 @@ public class ModelToRepresentation {
|
|||
providerRep.setAlias(identityProviderModel.getAlias());
|
||||
providerRep.setEnabled(identityProviderModel.isEnabled());
|
||||
providerRep.setStoreToken(identityProviderModel.isStoreToken());
|
||||
providerRep.setUpdateProfileFirstLogin(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
providerRep.setUpdateProfileFirstLoginMode(identityProviderModel.getUpdateProfileFirstLoginMode());
|
||||
providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
|
||||
providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
|
||||
providerRep.setConfig(identityProviderModel.getConfig());
|
||||
|
|
|
@ -919,7 +919,7 @@ public class RepresentationToModel {
|
|||
identityProviderModel.setAlias(representation.getAlias());
|
||||
identityProviderModel.setProviderId(representation.getProviderId());
|
||||
identityProviderModel.setEnabled(representation.isEnabled());
|
||||
identityProviderModel.setUpdateProfileFirstLogin(representation.isUpdateProfileFirstLogin());
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(representation.getUpdateProfileFirstLoginMode());
|
||||
identityProviderModel.setTrustEmail(representation.isTrustEmail());
|
||||
identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault());
|
||||
identityProviderModel.setStoreToken(representation.isStoreToken());
|
||||
|
|
|
@ -1164,7 +1164,7 @@ public class RealmAdapter implements RealmModel {
|
|||
identityProviderModel.setInternalId(entity.getInternalId());
|
||||
identityProviderModel.setConfig(entity.getConfig());
|
||||
identityProviderModel.setEnabled(entity.isEnabled());
|
||||
identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
|
||||
identityProviderModel.setTrustEmail(entity.isTrustEmail());
|
||||
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
|
||||
identityProviderModel.setStoreToken(entity.isStoreToken());
|
||||
|
@ -1197,7 +1197,7 @@ public class RealmAdapter implements RealmModel {
|
|||
entity.setEnabled(identityProvider.isEnabled());
|
||||
entity.setStoreToken(identityProvider.isStoreToken());
|
||||
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
|
||||
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
|
||||
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
|
||||
entity.setTrustEmail(identityProvider.isTrustEmail());
|
||||
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
|
||||
entity.setConfig(identityProvider.getConfig());
|
||||
|
@ -1224,7 +1224,7 @@ public class RealmAdapter implements RealmModel {
|
|||
if (entity.getInternalId().equals(identityProvider.getInternalId())) {
|
||||
entity.setAlias(identityProvider.getAlias());
|
||||
entity.setEnabled(identityProvider.isEnabled());
|
||||
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
|
||||
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
|
||||
entity.setTrustEmail(identityProvider.isTrustEmail());
|
||||
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
|
||||
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
|
||||
|
|
|
@ -41,8 +41,8 @@ public class IdentityProviderEntity {
|
|||
@Column(name="ENABLED")
|
||||
private boolean enabled;
|
||||
|
||||
@Column(name="UPDATE_PROFILE_FIRST_LOGIN")
|
||||
private boolean updateProfileFirstLogin;
|
||||
@Column(name = "UPDATE_PROFILE_FIRST_LOGIN_MODE")
|
||||
private String updateProfileFirstLoginMode;
|
||||
|
||||
@Column(name = "TRUST_EMAIL")
|
||||
private boolean trustEmail;
|
||||
|
@ -102,12 +102,12 @@ public class IdentityProviderEntity {
|
|||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isUpdateProfileFirstLogin() {
|
||||
return this.updateProfileFirstLogin;
|
||||
public String getUpdateProfileFirstLoginMode() {
|
||||
return updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
|
||||
this.updateProfileFirstLogin = updateProfileFirstLogin;
|
||||
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
|
||||
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
|
||||
}
|
||||
|
||||
public boolean isStoreToken() {
|
||||
|
|
|
@ -782,7 +782,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
identityProviderModel.setInternalId(entity.getInternalId());
|
||||
identityProviderModel.setConfig(entity.getConfig());
|
||||
identityProviderModel.setEnabled(entity.isEnabled());
|
||||
identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(entity.getUpdateProfileFirstLoginMode());
|
||||
identityProviderModel.setTrustEmail(entity.isTrustEmail());
|
||||
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
|
||||
identityProviderModel.setStoreToken(entity.isStoreToken());
|
||||
|
@ -813,7 +813,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
entity.setAlias(identityProvider.getAlias());
|
||||
entity.setProviderId(identityProvider.getProviderId());
|
||||
entity.setEnabled(identityProvider.isEnabled());
|
||||
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
|
||||
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
|
||||
entity.setTrustEmail(identityProvider.isTrustEmail());
|
||||
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
|
||||
entity.setStoreToken(identityProvider.isStoreToken());
|
||||
|
@ -826,7 +826,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
|
||||
@Override
|
||||
public void removeIdentityProviderByAlias(String alias) {
|
||||
IdentityProviderEntity toRemove;
|
||||
for (IdentityProviderEntity entity : realm.getIdentityProviders()) {
|
||||
if (entity.getAlias().equals(alias)) {
|
||||
realm.getIdentityProviders().remove(entity);
|
||||
|
@ -842,7 +841,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
if (entity.getInternalId().equals(identityProvider.getInternalId())) {
|
||||
entity.setAlias(identityProvider.getAlias());
|
||||
entity.setEnabled(identityProvider.isEnabled());
|
||||
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
|
||||
entity.setUpdateProfileFirstLoginMode(identityProvider.getUpdateProfileFirstLoginMode());
|
||||
entity.setTrustEmail(identityProvider.isTrustEmail());
|
||||
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
|
||||
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
|
||||
|
|
|
@ -443,7 +443,7 @@ public class AuthenticationManager {
|
|||
Iterator<String> i = user.getRequiredActions().iterator();
|
||||
String action = i.next();
|
||||
|
||||
if (action.equals(UserModel.RequiredAction.VERIFY_EMAIL.name()) && Validation.isEmpty(user.getEmail())) {
|
||||
if (action.equals(UserModel.RequiredAction.VERIFY_EMAIL.name()) && Validation.isBlank(user.getEmail())) {
|
||||
if (i.hasNext())
|
||||
action = i.next();
|
||||
else
|
||||
|
|
|
@ -580,7 +580,7 @@ public class AccountService {
|
|||
String totp = formData.getFirst("totp");
|
||||
String totpSecret = formData.getFirst("totpSecret");
|
||||
|
||||
if (Validation.isEmpty(totp)) {
|
||||
if (Validation.isBlank(totp)) {
|
||||
setReferrerOnPage();
|
||||
return account.setError(Messages.MISSING_TOTP).createResponse(AccountPages.TOTP);
|
||||
} else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) {
|
||||
|
@ -640,7 +640,7 @@ public class AccountService {
|
|||
String passwordConfirm = formData.getFirst("password-confirm");
|
||||
|
||||
if (requireCurrent) {
|
||||
if (Validation.isEmpty(password)) {
|
||||
if (Validation.isBlank(password)) {
|
||||
setReferrerOnPage();
|
||||
return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
|
||||
}
|
||||
|
|
|
@ -44,10 +44,10 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager.AuthResult;
|
||||
|
@ -71,6 +71,7 @@ import javax.ws.rs.core.Response;
|
|||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -278,13 +279,14 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
|||
try {
|
||||
federatedUser = createUser(context);
|
||||
|
||||
if (identityProviderConfig.isUpdateProfileFirstLogin()) {
|
||||
if (IdentityProviderRepresentation.UPFLM_ON.equals(identityProviderConfig.getUpdateProfileFirstLoginMode())
|
||||
|| (IdentityProviderRepresentation.UPFLM_MISSING.equals(identityProviderConfig.getUpdateProfileFirstLoginMode()) && !Validation.validateUserMandatoryFields(realmModel, federatedUser))) {
|
||||
if (isDebugEnabled()) {
|
||||
LOGGER.debugf("Identity provider requires update profile action.", federatedUser);
|
||||
}
|
||||
federatedUser.addRequiredAction(UPDATE_PROFILE);
|
||||
}
|
||||
if(identityProviderConfig.isTrustEmail() && federatedUser.getEmail() != null && federatedUser.getEmail().trim().length()>0){
|
||||
if(identityProviderConfig.isTrustEmail() && !Validation.isBlank(federatedUser.getEmail())){
|
||||
federatedUser.setEmailVerified(true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -509,7 +511,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
|||
String username = context.getModelUsername();
|
||||
if (username == null) {
|
||||
username = context.getUsername();
|
||||
if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isEmpty(context.getEmail())) {
|
||||
if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isBlank(context.getEmail())) {
|
||||
username = context.getEmail();
|
||||
} else if (username == null) {
|
||||
username = context.getIdpConfig().getAlias() + "." + context.getId();
|
||||
|
|
|
@ -829,7 +829,7 @@ public class LoginActionsService {
|
|||
String totpSecret = formData.getFirst("totpSecret");
|
||||
|
||||
LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class).setUser(user);
|
||||
if (Validation.isEmpty(totp)) {
|
||||
if (Validation.isBlank(totp)) {
|
||||
return loginForms.setError(Messages.MISSING_TOTP)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.createResponse(RequiredAction.CONFIGURE_TOTP);
|
||||
|
@ -875,7 +875,7 @@ public class LoginActionsService {
|
|||
|
||||
LoginFormsProvider loginForms = session.getProvider(LoginFormsProvider.class)
|
||||
.setUser(user);
|
||||
if (Validation.isEmpty(passwordNew)) {
|
||||
if (Validation.isBlank(passwordNew)) {
|
||||
return loginForms.setError(Messages.MISSING_PASSWORD)
|
||||
.setClientSessionCode(accessCode.getCode())
|
||||
.createResponse(RequiredAction.UPDATE_PASSWORD);
|
||||
|
|
|
@ -2,11 +2,13 @@ package org.keycloak.services.validation;
|
|||
|
||||
import org.keycloak.models.PasswordPolicy;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.FormMessage;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -26,26 +28,26 @@ public class Validation {
|
|||
public static List<FormMessage> validateRegistrationForm(RealmModel realm, MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes, PasswordPolicy policy) {
|
||||
List<FormMessage> errors = new ArrayList<>();
|
||||
|
||||
if (!realm.isRegistrationEmailAsUsername() && isEmpty(formData.getFirst(FIELD_USERNAME))) {
|
||||
if (!realm.isRegistrationEmailAsUsername() && isBlank(formData.getFirst(FIELD_USERNAME))) {
|
||||
addError(errors, FIELD_USERNAME, Messages.MISSING_USERNAME);
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst(FIELD_FIRST_NAME))) {
|
||||
if (isBlank(formData.getFirst(FIELD_FIRST_NAME))) {
|
||||
addError(errors, FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME);
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst(FIELD_LAST_NAME))) {
|
||||
if (isBlank(formData.getFirst(FIELD_LAST_NAME))) {
|
||||
addError(errors, FIELD_LAST_NAME, Messages.MISSING_LAST_NAME);
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst(FIELD_EMAIL))) {
|
||||
if (isBlank(formData.getFirst(FIELD_EMAIL))) {
|
||||
addError(errors, FIELD_EMAIL, Messages.MISSING_EMAIL);
|
||||
} else if (!isEmailValid(formData.getFirst(FIELD_EMAIL))) {
|
||||
addError(errors, FIELD_EMAIL, Messages.INVALID_EMAIL);
|
||||
}
|
||||
|
||||
if (requiredCredentialTypes.contains(CredentialRepresentation.PASSWORD)) {
|
||||
if (isEmpty(formData.getFirst(FIELD_PASSWORD))) {
|
||||
if (isBlank(formData.getFirst(FIELD_PASSWORD))) {
|
||||
addError(errors, FIELD_PASSWORD, Messages.MISSING_PASSWORD);
|
||||
} else if (!formData.getFirst(FIELD_PASSWORD).equals(formData.getFirst(FIELD_PASSWORD_CONFIRM))) {
|
||||
addError(errors, FIELD_PASSWORD_CONFIRM, Messages.INVALID_PASSWORD_CONFIRM);
|
||||
|
@ -72,19 +74,19 @@ public class Validation {
|
|||
public static List<FormMessage> validateUpdateProfileForm(RealmModel realm, MultivaluedMap<String, String> formData) {
|
||||
List<FormMessage> errors = new ArrayList<>();
|
||||
|
||||
if (realm != null && realm.isEditUsernameAllowed() && isEmpty(formData.getFirst(FIELD_USERNAME))) {
|
||||
if (realm != null && realm.isEditUsernameAllowed() && isBlank(formData.getFirst(FIELD_USERNAME))) {
|
||||
addError(errors, FIELD_USERNAME, Messages.MISSING_USERNAME);
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst(FIELD_FIRST_NAME))) {
|
||||
if (isBlank(formData.getFirst(FIELD_FIRST_NAME))) {
|
||||
addError(errors, FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME);
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst(FIELD_LAST_NAME))) {
|
||||
if (isBlank(formData.getFirst(FIELD_LAST_NAME))) {
|
||||
addError(errors, FIELD_LAST_NAME, Messages.MISSING_LAST_NAME);
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst(FIELD_EMAIL))) {
|
||||
if (isBlank(formData.getFirst(FIELD_EMAIL))) {
|
||||
addError(errors, FIELD_EMAIL, Messages.MISSING_EMAIL);
|
||||
} else if (!isEmailValid(formData.getFirst(FIELD_EMAIL))) {
|
||||
addError(errors, FIELD_EMAIL, Messages.INVALID_EMAIL);
|
||||
|
@ -92,10 +94,37 @@ public class Validation {
|
|||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if user object contains all mandatory fields.
|
||||
*
|
||||
* @param realm user is for
|
||||
* @param user to validate
|
||||
* @return true if user object contains all mandatory values, false if some mandatory value is missing
|
||||
*/
|
||||
public static boolean validateUserMandatoryFields(RealmModel realm, UserModel user){
|
||||
return!(isBlank(user.getFirstName()) || isBlank(user.getLastName()) || isBlank(user.getEmail()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if string is empty (null or lenght is 0)
|
||||
*
|
||||
* @param s to check
|
||||
* @return true if string is empty
|
||||
*/
|
||||
public static boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if string is blank (null or lenght is 0 or contains only white characters)
|
||||
*
|
||||
* @param s to check
|
||||
* @return true if string is blank
|
||||
*/
|
||||
public static boolean isBlank(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
}
|
||||
|
||||
public static boolean isEmailValid(String email) {
|
||||
return EMAIL_PATTERN.matcher(email).matches();
|
||||
|
|
|
@ -24,4 +24,26 @@ public class ValidationTest {
|
|||
Assert.assertFalse(Validation.isEmailValid("abc@foo."));
|
||||
Assert.assertFalse(Validation.isEmailValid("abc@foo..bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEmpty(){
|
||||
Assert.assertTrue(Validation.isEmpty(null));
|
||||
Assert.assertTrue(Validation.isEmpty(""));
|
||||
Assert.assertFalse(Validation.isEmpty(" "));
|
||||
Assert.assertFalse(Validation.isEmpty(" "));
|
||||
Assert.assertFalse(Validation.isEmpty("a"));
|
||||
Assert.assertFalse(Validation.isEmpty(" a "));
|
||||
Assert.assertFalse(Validation.isEmpty("asgadfgedfs"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsBlank(){
|
||||
Assert.assertTrue(Validation.isBlank(null));
|
||||
Assert.assertTrue(Validation.isBlank(""));
|
||||
Assert.assertTrue(Validation.isBlank(" "));
|
||||
Assert.assertTrue(Validation.isBlank(" \n "));
|
||||
Assert.assertFalse(Validation.isBlank("a"));
|
||||
Assert.assertFalse(Validation.isBlank(" a "));
|
||||
Assert.assertFalse(Validation.isBlank("asgadfgedfs"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class IdentityProviderTest extends AbstractClientTest {
|
|||
assertEquals("clientSecret", representation.getConfig().get("clientSecret"));
|
||||
assertTrue(representation.isEnabled());
|
||||
assertFalse(representation.isStoreToken());
|
||||
assertTrue(representation.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_ON, representation.getUpdateProfileFirstLoginMode());
|
||||
assertFalse(representation.isTrustEmail());
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.keycloak.models.RoleModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserModel.RequiredAction;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.services.Urls;
|
||||
import org.keycloak.testsuite.MailUtil;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
|
@ -136,18 +137,34 @@ public abstract class AbstractIdentityProviderTest {
|
|||
@Test
|
||||
public void testSuccessfulAuthentication() {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
identityProviderModel.setUpdateProfileFirstLogin(true);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON);
|
||||
|
||||
UserModel user = assertSuccessfulAuthentication(identityProviderModel, "test-user", "new@email.com");
|
||||
UserModel user = assertSuccessfulAuthentication(identityProviderModel, "test-user", "new@email.com", true);
|
||||
Assert.assertEquals("617-666-7777", user.getAttribute("mobile"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
|
||||
|
||||
assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationUpdateProfileOnMissing_missingEmail() {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
|
||||
|
||||
assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", "new@email.com", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationWithoutUpdateProfile() {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
|
||||
assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost");
|
||||
assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,10 +181,10 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
try {
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
identityProviderModel.setTrustEmail(false);
|
||||
|
||||
UserModel federatedUser = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "test-user@localhost");
|
||||
UserModel federatedUser = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "test-user@localhost", false);
|
||||
|
||||
// email is verified now
|
||||
assertFalse(federatedUser.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
|
||||
|
@ -177,9 +194,10 @@ public abstract class AbstractIdentityProviderTest {
|
|||
}
|
||||
}
|
||||
|
||||
private UserModel assertSuccessfulAuthenticationWithEmailVerification(IdentityProviderModel identityProviderModel, String username, String expectedEmail)
|
||||
private UserModel assertSuccessfulAuthenticationWithEmailVerification(IdentityProviderModel identityProviderModel, String username, String expectedEmail,
|
||||
boolean isProfileUpdateExpected)
|
||||
throws IOException, MessagingException {
|
||||
authenticateWithIdentityProvider(identityProviderModel, username);
|
||||
authenticateWithIdentityProvider(identityProviderModel, username, isProfileUpdateExpected);
|
||||
|
||||
// verify email is sent
|
||||
Assert.assertTrue(verifyEmailPage.isCurrent());
|
||||
|
@ -199,7 +217,7 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
assertNotNull(federatedUser);
|
||||
|
||||
doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail);
|
||||
doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
|
||||
|
||||
brokerServerRule.stopSession(session, true);
|
||||
session = brokerServerRule.startSession();
|
||||
|
@ -233,9 +251,9 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
try {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
|
||||
UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", null);
|
||||
UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user-noemail", null, false);
|
||||
|
||||
assertTrue(federatedUser.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
|
||||
|
||||
|
@ -255,10 +273,10 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
try {
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
identityProviderModel.setTrustEmail(true);
|
||||
|
||||
UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost");
|
||||
UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost", false);
|
||||
|
||||
assertFalse(federatedUser.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
|
||||
|
||||
|
@ -282,10 +300,10 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
try {
|
||||
identityProviderModel.setUpdateProfileFirstLogin(true);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON);
|
||||
identityProviderModel.setTrustEmail(true);
|
||||
|
||||
UserModel user = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "new@email.com");
|
||||
UserModel user = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "new@email.com", true);
|
||||
Assert.assertEquals("617-666-7777", user.getAttribute("mobile"));
|
||||
} finally {
|
||||
identityProviderModel.setTrustEmail(false);
|
||||
|
@ -302,9 +320,9 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
try {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
|
||||
authenticateWithIdentityProvider(identityProviderModel, "test-user");
|
||||
authenticateWithIdentityProvider(identityProviderModel, "test-user", false);
|
||||
|
||||
// authenticated and redirected to app
|
||||
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/test-app"));
|
||||
|
@ -321,7 +339,7 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
assertEquals("test-user@localhost", federatedUser.getUsername());
|
||||
|
||||
doAssertFederatedUser(federatedUser, identityProviderModel, "test-user@localhost");
|
||||
doAssertFederatedUser(federatedUser, identityProviderModel, "test-user@localhost", false);
|
||||
|
||||
Set<FederatedIdentityModel> federatedIdentities = this.session.users().getFederatedIdentities(federatedUser, realm);
|
||||
|
||||
|
@ -350,9 +368,9 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
try {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
|
||||
authenticateWithIdentityProvider(identityProviderModel, "test-user-noemail");
|
||||
authenticateWithIdentityProvider(identityProviderModel, "test-user-noemail", false);
|
||||
|
||||
brokerServerRule.stopSession(session, true);
|
||||
session = brokerServerRule.startSession();
|
||||
|
@ -455,7 +473,7 @@ public abstract class AbstractIdentityProviderTest {
|
|||
public void testUserAlreadyExistsWhenNotUpdatingProfile() {
|
||||
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
|
||||
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
|
||||
this.driver.navigate().to("http://localhost:8081/test-app/");
|
||||
|
||||
|
@ -593,7 +611,7 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
identityProviderModel.setStoreToken(true);
|
||||
|
||||
authenticateWithIdentityProvider(identityProviderModel, "test-user");
|
||||
authenticateWithIdentityProvider(identityProviderModel, "test-user", true);
|
||||
|
||||
UserModel federatedUser = getFederatedUser();
|
||||
RealmModel realm = getRealm();
|
||||
|
@ -658,17 +676,18 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
protected abstract void doAssertTokenRetrieval(String pageSource);
|
||||
|
||||
private UserModel assertSuccessfulAuthentication(IdentityProviderModel identityProviderModel, String username, String expectedEmail) {
|
||||
authenticateWithIdentityProvider(identityProviderModel, username);
|
||||
private UserModel assertSuccessfulAuthentication(IdentityProviderModel identityProviderModel, String username, String expectedEmail, boolean isProfileUpdateExpected) {
|
||||
authenticateWithIdentityProvider(identityProviderModel, username, isProfileUpdateExpected);
|
||||
|
||||
// authenticated and redirected to app
|
||||
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/test-app"));
|
||||
assertTrue("Bad current URL " + this.driver.getCurrentUrl() + " and page source: " + this.driver.getPageSource(),
|
||||
this.driver.getCurrentUrl().startsWith("http://localhost:8081/test-app"));
|
||||
|
||||
UserModel federatedUser = getFederatedUser();
|
||||
|
||||
assertNotNull(federatedUser);
|
||||
|
||||
doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail);
|
||||
doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
|
||||
|
||||
brokerServerRule.stopSession(session, true);
|
||||
session = brokerServerRule.startSession();
|
||||
|
@ -691,11 +710,11 @@ public abstract class AbstractIdentityProviderTest {
|
|||
return federatedUser;
|
||||
}
|
||||
|
||||
private void authenticateWithIdentityProvider(IdentityProviderModel identityProviderModel, String username) {
|
||||
private void authenticateWithIdentityProvider(IdentityProviderModel identityProviderModel, String username, boolean isProfileUpdateExpected) {
|
||||
loginIDP(username);
|
||||
|
||||
|
||||
if (identityProviderModel.isUpdateProfileFirstLogin()) {
|
||||
if (isProfileUpdateExpected) {
|
||||
String userEmail = "new@email.com";
|
||||
String userFirstName = "New first";
|
||||
String userLastName = "New last";
|
||||
|
@ -704,6 +723,7 @@ public abstract class AbstractIdentityProviderTest {
|
|||
this.updateProfilePage.assertCurrent();
|
||||
this.updateProfilePage.update(userFirstName, userLastName, userEmail);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void loginIDP(String username) {
|
||||
|
@ -749,7 +769,7 @@ public abstract class AbstractIdentityProviderTest {
|
|||
|
||||
assertNotNull(identityProviderModel);
|
||||
|
||||
identityProviderModel.setUpdateProfileFirstLogin(true);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_ON);
|
||||
identityProviderModel.setEnabled(true);
|
||||
|
||||
return identityProviderModel;
|
||||
|
@ -759,8 +779,8 @@ public abstract class AbstractIdentityProviderTest {
|
|||
return this.session.realms().getRealm("realm-with-broker");
|
||||
}
|
||||
|
||||
protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail) {
|
||||
if (identityProviderModel.isUpdateProfileFirstLogin()) {
|
||||
protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail, boolean isProfileUpdateExpected) {
|
||||
if (isProfileUpdateExpected) {
|
||||
String userFirstName = "New first";
|
||||
String userLastName = "New last";
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
|
|||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.social.facebook.FacebookIdentityProvider;
|
||||
import org.keycloak.social.facebook.FacebookIdentityProviderFactory;
|
||||
|
@ -80,7 +81,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
|
||||
identityProviderModel.getConfig().put("config-added", "value-added");
|
||||
identityProviderModel.setEnabled(false);
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_OFF);
|
||||
identityProviderModel.setTrustEmail(true);
|
||||
identityProviderModel.setStoreToken(true);
|
||||
identityProviderModel.setAuthenticateByDefault(true);
|
||||
|
@ -95,14 +96,14 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
|
||||
assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
|
||||
assertFalse(identityProviderModel.isEnabled());
|
||||
assertFalse(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, identityProviderModel.getUpdateProfileFirstLoginMode());
|
||||
assertTrue(identityProviderModel.isTrustEmail());
|
||||
assertTrue(identityProviderModel.isStoreToken());
|
||||
assertTrue(identityProviderModel.isAuthenticateByDefault());
|
||||
|
||||
identityProviderModel.getConfig().remove("config-added");
|
||||
identityProviderModel.setEnabled(true);
|
||||
identityProviderModel.setUpdateProfileFirstLogin(true);
|
||||
identityProviderModel.setUpdateProfileFirstLoginMode(IdentityProviderRepresentation.UPFLM_MISSING);
|
||||
identityProviderModel.setTrustEmail(false);
|
||||
identityProviderModel.setAuthenticateByDefault(false);
|
||||
|
||||
|
@ -115,7 +116,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
|
||||
assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
|
||||
assertTrue(identityProviderModel.isEnabled());
|
||||
assertTrue(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, identityProviderModel.getUpdateProfileFirstLoginMode());
|
||||
assertFalse(identityProviderModel.isTrustEmail());
|
||||
assertFalse(identityProviderModel.isAuthenticateByDefault());
|
||||
this.realmManager.removeRealm(realm);
|
||||
|
@ -164,7 +165,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-google", config.getAlias());
|
||||
assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(true, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(true, config.isStoreToken());
|
||||
|
@ -183,7 +184,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-saml-signed-idp", config.getAlias());
|
||||
assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
|
@ -204,7 +205,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-oidc-idp", config.getAlias());
|
||||
assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(false, config.isEnabled());
|
||||
assertEquals(false, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
|
@ -219,7 +220,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-facebook", config.getAlias());
|
||||
assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
|
@ -237,7 +238,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-github", config.getAlias());
|
||||
assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_ON, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
|
@ -255,7 +256,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-linkedin", config.getAlias());
|
||||
assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_MISSING, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
|
@ -273,7 +274,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-stackoverflow", config.getAlias());
|
||||
assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(false, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
|
@ -292,7 +293,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals("model-twitter", config.getAlias());
|
||||
assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(IdentityProviderRepresentation.UPFLM_OFF, config.getUpdateProfileFirstLoginMode());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(true, config.isStoreToken());
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.IdentityProviderModel;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
import org.keycloak.testsuite.KeycloakServer;
|
||||
|
@ -50,9 +51,9 @@ public class SAMLKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail) {
|
||||
if (identityProviderModel.isUpdateProfileFirstLogin()) {
|
||||
super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail);
|
||||
protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail, boolean isProfileUpdateExpected) {
|
||||
if (isProfileUpdateExpected) {
|
||||
super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
|
||||
} else {
|
||||
if (expectedEmail == null) {
|
||||
// Need to handle differences for various databases (like Oracle)
|
||||
|
@ -114,4 +115,9 @@ public class SAMLKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT
|
|||
public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() {
|
||||
super.testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
|
||||
// skip this test as this provider do not return name and surname so something is missing always
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.IdentityProviderModel;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
import org.keycloak.testsuite.KeycloakServer;
|
||||
|
@ -50,9 +51,9 @@ public class SAMLKeyCloakServerBrokerWithSignatureTest extends AbstractIdentityP
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail) {
|
||||
if (identityProviderModel.isUpdateProfileFirstLogin()) {
|
||||
super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail);
|
||||
protected void doAssertFederatedUser(UserModel federatedUser, IdentityProviderModel identityProviderModel, String expectedEmail, boolean isProfileUpdateExpected) {
|
||||
if (isProfileUpdateExpected) {
|
||||
super.doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail, isProfileUpdateExpected);
|
||||
} else {
|
||||
if (expectedEmail == null) {
|
||||
// Need to handle differences for various databases (like Oracle)
|
||||
|
@ -102,4 +103,9 @@ public class SAMLKeyCloakServerBrokerWithSignatureTest extends AbstractIdentityP
|
|||
public void testAccountManagementLinkIdentity() {
|
||||
super.testAccountManagementLinkIdentity();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccessfulAuthenticationUpdateProfileOnMissing_nothingMissing() {
|
||||
// skip this test as this provider do not return name and surname so something is missing always
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"alias" : "model-facebook",
|
||||
"providerId" : "facebook",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : "true",
|
||||
"updateProfileFirstLogin" : "false",
|
||||
"config": {
|
||||
"authorizationUrl": "authorizationUrl",
|
||||
"tokenUrl": "tokenUrl",
|
||||
|
@ -42,7 +42,7 @@
|
|||
"alias" : "model-github",
|
||||
"providerId" : "github",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : "true",
|
||||
"updateProfileFirstLoginMode" : "on",
|
||||
"storeToken": "false",
|
||||
"config": {
|
||||
"authorizationUrl": "authorizationUrl",
|
||||
|
@ -56,7 +56,7 @@
|
|||
"alias" : "model-twitter",
|
||||
"providerId" : "twitter",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : "true",
|
||||
"updateProfileFirstLoginMode" : "off",
|
||||
"storeToken": true,
|
||||
"config": {
|
||||
"authorizationUrl": "authorizationUrl",
|
||||
|
@ -70,7 +70,7 @@
|
|||
"alias" : "model-linkedin",
|
||||
"providerId" : "linkedin",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : "true",
|
||||
"updateProfileFirstLoginMode" : "missing",
|
||||
"storeToken": false,
|
||||
"config": {
|
||||
"authorizationUrl": "authorizationUrl",
|
||||
|
@ -84,7 +84,7 @@
|
|||
"alias" : "model-stackoverflow",
|
||||
"providerId" : "stackoverflow",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : "false",
|
||||
"updateProfileFirstLoginMode" : "off",
|
||||
"storeToken": false,
|
||||
"config": {
|
||||
"key": "keyValue",
|
||||
|
@ -99,7 +99,7 @@
|
|||
"alias" : "model-saml-signed-idp",
|
||||
"providerId" : "saml",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : "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",
|
||||
|
@ -115,7 +115,7 @@
|
|||
"alias" : "kc-saml-signed-idp",
|
||||
"providerId" : "saml",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : true,
|
||||
"updateProfileFirstLoginMode" : "on",
|
||||
"addReadTokenRoleOnCreate": true,
|
||||
"config": {
|
||||
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-signed-idp/protocol/saml",
|
||||
|
@ -134,7 +134,7 @@
|
|||
"alias" : "kc-saml-idp-basic",
|
||||
"providerId" : "saml",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : true,
|
||||
"updateProfileFirstLoginMode" : "on",
|
||||
"trustEmail" : false,
|
||||
"addReadTokenRoleOnCreate": true,
|
||||
"config": {
|
||||
|
@ -150,7 +150,7 @@
|
|||
"alias" : "model-oidc-idp",
|
||||
"providerId" : "oidc",
|
||||
"enabled": false,
|
||||
"updateProfileFirstLogin" : "false",
|
||||
"updateProfileFirstLoginMode" : "off",
|
||||
"authenticateByDefault" : "false",
|
||||
"config": {
|
||||
"clientId": "clientId",
|
||||
|
@ -166,7 +166,7 @@
|
|||
"alias" : "kc-oidc-idp",
|
||||
"providerId" : "keycloak-oidc",
|
||||
"enabled": true,
|
||||
"updateProfileFirstLogin" : "false",
|
||||
"updateProfileFirstLoginMode" : "off",
|
||||
"storeToken" : true,
|
||||
"addReadTokenRoleOnCreate": true,
|
||||
"config": {
|
||||
|
|
Loading…
Reference in a new issue