keycloak-aplcache
Changes
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html 4(+3 -1)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html 14(+10 -4)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html 14(+10 -4)
forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html 14(+10 -4)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java 82(+51 -31)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java 25(+13 -12)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java 12(+9 -3)
Details
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.3.0.Beta1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.3.0.Beta1.xml
index 9f880e5..864676a 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.3.0.Beta1.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.3.0.Beta1.xml
@@ -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"/>
diff --git a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
index 8d9a14e..1e74002 100755
--- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java
@@ -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;
+ }
+
+ /**
+ * @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() {
diff --git a/docbook/reference/en/en-US/modules/identity-broker.xml b/docbook/reference/en/en-US/modules/identity-broker.xml
index 11460ea..75df2c7 100755
--- a/docbook/reference/en/en-US/modules/identity-broker.xml
+++ b/docbook/reference/en/en-US/modules/identity-broker.xml
@@ -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>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index f60e20e..53ad7ae 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -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;
}
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
index c826a16..9a2a28f 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider.html
@@ -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>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 40c0cab..d2a267b 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -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>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index 1588151..d2aaf4e 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -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>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
index 2466772..623bcf0 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html
@@ -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>
diff --git a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
index f4c3271..c4cdd62 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/IdentityProviderEntity.java
@@ -30,7 +30,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() {
diff --git a/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java b/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
index 56f73c3..0c34e4b 100755
--- a/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
+++ b/model/api/src/main/java/org/keycloak/models/IdentityProviderModel.java
@@ -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() {
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 38b125d..9d45152 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -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());
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index bfbfda5..43524c3 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -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());
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
index 2ad8e87..4cfefb4 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/IdentityProviderEntity.java
@@ -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() {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 3f2a00d..0f9a5b0 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -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());
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index 673477d..279114a 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -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());
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 3ada879..e76ab3a 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -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
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 39f6299..697a28f 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -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);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index 0127956..e1d6bfa 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -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();
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 3af66d3..c2571d9 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -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);
diff --git a/services/src/main/java/org/keycloak/services/validation/Validation.java b/services/src/main/java/org/keycloak/services/validation/Validation.java
index fefe74e..d3abc4d 100755
--- a/services/src/main/java/org/keycloak/services/validation/Validation.java
+++ b/services/src/main/java/org/keycloak/services/validation/Validation.java
@@ -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();
diff --git a/services/src/test/java/org/keycloak/test/ValidationTest.java b/services/src/test/java/org/keycloak/test/ValidationTest.java
index 0da7dfa..72f5926 100644
--- a/services/src/test/java/org/keycloak/test/ValidationTest.java
+++ b/services/src/test/java/org/keycloak/test/ValidationTest.java
@@ -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"));
+ }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
index 9b72cd9..a7bae96 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java
@@ -52,7 +52,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());
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
index e82744f..14d083f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
@@ -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";
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
index 7b8c7a5..b2e3605 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
@@ -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());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java
index 46bfa3d..c0ffd00 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerBasicTest.java
@@ -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
+ }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java
index 821fc0e..34c10d5 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/SAMLKeyCloakServerBrokerWithSignatureTest.java
@@ -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
+ }
}
diff --git a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
index 3da5f75..a6ace52 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
@@ -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": {