Skip to content

Commit

Permalink
KEYCLOAK-1371 - Perform "Update Profile on First Login" only if some of
Browse files Browse the repository at this point in the history
mandatory user profile fields is missing from identity provider
  • Loading branch information
velias committed Jun 3, 2015
1 parent fb60ca1 commit dcc19a3
Show file tree
Hide file tree
Showing 27 changed files with 293 additions and 127 deletions.
Expand Up @@ -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"/>
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -76,12 +94,29 @@ public void setEnabled(boolean enabled) {
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;
}

/**
* @return see {@link #updateProfileFirstLoginMode}
*/
public String getUpdateProfileFirstLoginMode() {
return updateProfileFirstLoginMode;
}

public void setUpdateProfileFirstLogin(boolean updateProfileFirstLogin) {
this.updateProfileFirstLogin = updateProfileFirstLogin;
/**
* @param updateProfileFirstLoginMode see {@link #updateProfileFirstLoginMode}
*/
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}

public boolean isAuthenticateByDefault() {
Expand Down
6 changes: 4 additions & 2 deletions docbook/reference/en/en-US/modules/identity-broker.xml
Expand Up @@ -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>
Expand Down
Expand Up @@ -597,7 +597,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload
if (instance && instance.alias) {

} else {
$scope.identityProvider.updateProfileFirstLogin = false;
$scope.identityProvider.updateProfileFirstLoginMode = "on";
}

};
Expand Down Expand Up @@ -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";
}
}

Expand All @@ -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;
}
Expand Down
Expand Up @@ -59,11 +59,17 @@ <h1 data-ng-show="create"><strong>Add OpenID Connect Identity Provider</strong><
<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>
Expand Down
Expand Up @@ -60,11 +60,17 @@ <h1 data-ng-show="create"><strong>Add SAML Identity Provider</strong></h1>
<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>
Expand Down
Expand Up @@ -70,11 +70,17 @@ <h1 data-ng-show="create"><strong>Add Social Identity Provider</strong></h1>
<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>
Expand Down
Expand Up @@ -8,7 +8,7 @@ <h1><strong>Identity Providers</strong> {{realm.realm|capitalize}}</h1>
<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"
Expand All @@ -21,6 +21,7 @@ <h1><strong>Identity Providers</strong> {{realm.realm|capitalize}}</h1>
<tr ng-show="configuredProviders.length > 0">
<th>Name</th>
<th>Provider</th>
<th>Enabled</th>
<th width="15%">GUI order</th>
</tr>
</thead>
Expand All @@ -30,6 +31,7 @@ <h1><strong>Identity Providers</strong> {{realm.realm|capitalize}}</h1>
<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>
Expand Down
Expand Up @@ -20,6 +20,8 @@
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>
Expand All @@ -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;

Expand All @@ -70,7 +78,7 @@ public IdentityProviderModel(IdentityProviderModel model) {
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();
Expand Down Expand Up @@ -109,12 +117,18 @@ public void setEnabled(boolean enabled) {
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() {
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -62,12 +62,12 @@ public void setEnabled(boolean enabled) {
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() {
Expand Down
Expand Up @@ -325,7 +325,7 @@ public static IdentityProviderRepresentation toRepresentation(IdentityProviderMo
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());
Expand Down
Expand Up @@ -919,7 +919,7 @@ public static IdentityProviderModel toModel(IdentityProviderRepresentation repre
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());
Expand Down
Expand Up @@ -1164,7 +1164,7 @@ public List<IdentityProviderModel> getIdentityProviders() {
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());
Expand Down Expand Up @@ -1197,7 +1197,7 @@ public void addIdentityProvider(IdentityProviderModel identityProvider) {
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());
Expand All @@ -1224,7 +1224,7 @@ public void updateIdentityProvider(IdentityProviderModel identityProvider) {
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());
Expand Down

0 comments on commit dcc19a3

Please sign in to comment.