Merge pull request #1317 from velias/KEYCLOAK-1372

KEYCLOAK-1372 - do not perform email verification if email is provided by trusted Identity provider
This commit is contained in:
Stian Thorgersen 2015-06-03 10:29:52 +01:00
commit 060a59f982
18 changed files with 244 additions and 9 deletions

View file

@ -107,6 +107,9 @@
<addColumn tableName="CLIENT_SESSION"> <addColumn tableName="CLIENT_SESSION">
<column name="AUTH_USER_ID" type="VARCHAR(36)"/> <column name="AUTH_USER_ID" type="VARCHAR(36)"/>
</addColumn> </addColumn>
<addColumn tableName="IDENTITY_PROVIDER">
<column name="TRUST_EMAIL" type="BOOLEAN" defaultValueBoolean="false"/>
</addColumn>
<addColumn tableName="USER_REQUIRED_ACTION"> <addColumn tableName="USER_REQUIRED_ACTION">
<column name="REQUIRED_ACTION" type="VARCHAR(36)"> <column name="REQUIRED_ACTION" type="VARCHAR(36)">
<constraints nullable="false"/> <constraints nullable="false"/>

View file

@ -30,6 +30,7 @@ public class IdentityProviderRepresentation {
protected String providerId; protected String providerId;
protected boolean enabled = true; protected boolean enabled = true;
protected boolean updateProfileFirstLogin = true; protected boolean updateProfileFirstLogin = true;
protected boolean trustEmail;
protected boolean storeToken; protected boolean storeToken;
protected boolean addReadTokenRoleOnCreate; protected boolean addReadTokenRoleOnCreate;
protected boolean authenticateByDefault; protected boolean authenticateByDefault;
@ -106,4 +107,13 @@ public class IdentityProviderRepresentation {
public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) { public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) {
this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate; this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate;
} }
public boolean isTrustEmail() {
return trustEmail;
}
public void setTrustEmail(boolean trustEmail) {
this.trustEmail = trustEmail;
}
} }

View file

@ -305,6 +305,16 @@
during the authentication process. during the authentication process.
</entry> </entry>
</row> </row>
<row>
<entry>
<literal>Trust email</literal>
</entry>
<entry>
Allows you to trust email address returned from the social provider. If enabled then email address returned by the provider
is marked as 'verified' in the Keycloak user profile. This means that email verification step is skipped even
if "Verify email" feature is enabled in realm settings.
</entry>
</row>
<row> <row>
<entry> <entry>
<literal>GUI order</literal> <literal>GUI order</literal>

View file

@ -65,6 +65,13 @@
</div> </div>
<kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip> <kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip>
</div> </div>
<div class="form-group">
<label class="col-md-2 control-label" for="trustEmail">Trust email</label>
<div class="col-md-6">
<input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
</div>
<kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
</div>
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="guiOrder">GUI order</label> <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
<div class="col-md-6"> <div class="col-md-6">

View file

@ -66,6 +66,13 @@
</div> </div>
<kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip> <kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip>
</div> </div>
<div class="form-group">
<label class="col-md-2 control-label" for="trustEmail">Trust email</label>
<div class="col-md-6">
<input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
</div>
<kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
</div>
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="guiOrder">GUI order</label> <label class="col-md-2 control-label" for="guiOrder">GUI order</label>
<div class="col-md-6"> <div class="col-md-6">

View file

@ -76,6 +76,13 @@
</div> </div>
<kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip> <kc-tooltip>Indicates if user must update his profile right after the first login.</kc-tooltip>
</div> </div>
<div class="form-group">
<label class="col-md-2 control-label" for="trustEmail">Trust email</label>
<div class="col-md-6">
<input ng-model="identityProvider.trustEmail" name="identityProvider.trustEmail" id="trustEmail" onoffswitch />
</div>
<kc-tooltip>If enabled then email provided by this provider is not verified even if verification is enabled for the realm.</kc-tooltip>
</div>
<div class="form-group"> <div class="form-group">
<label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label> <label class="col-md-2 control-label" for="authenticateByDefault">Authenticate By Default</label>
<div class="col-md-6"> <div class="col-md-6">

View file

@ -44,6 +44,8 @@ public class IdentityProviderModel {
private boolean enabled; private boolean enabled;
private boolean updateProfileFirstLogin = true; private boolean updateProfileFirstLogin = true;
private boolean trustEmail;
private boolean storeToken; private boolean storeToken;
@ -69,6 +71,7 @@ public class IdentityProviderModel {
this.config = new HashMap<String, String>(model.getConfig()); this.config = new HashMap<String, String>(model.getConfig());
this.enabled = model.isEnabled(); this.enabled = model.isEnabled();
this.updateProfileFirstLogin = model.isUpdateProfileFirstLogin(); this.updateProfileFirstLogin = model.isUpdateProfileFirstLogin();
this.trustEmail = model.isTrustEmail();
this.storeToken = model.isStoreToken(); this.storeToken = model.isStoreToken();
this.authenticateByDefault = model.isAuthenticateByDefault(); this.authenticateByDefault = model.isAuthenticateByDefault();
this.addReadTokenRoleOnCreate = model.addReadTokenRoleOnCreate; this.addReadTokenRoleOnCreate = model.addReadTokenRoleOnCreate;
@ -145,4 +148,13 @@ public class IdentityProviderModel {
public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) { public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) {
this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate; this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate;
} }
public boolean isTrustEmail() {
return trustEmail;
}
public void setTrustEmail(boolean trustEmail) {
this.trustEmail = trustEmail;
}
} }

View file

@ -31,6 +31,7 @@ public class IdentityProviderEntity {
private String name; private String name;
private boolean enabled; private boolean enabled;
private boolean updateProfileFirstLogin; private boolean updateProfileFirstLogin;
private boolean trustEmail;
private boolean storeToken; private boolean storeToken;
protected boolean addReadTokenRoleOnCreate; protected boolean addReadTokenRoleOnCreate;
private boolean authenticateByDefault; private boolean authenticateByDefault;
@ -116,4 +117,12 @@ public class IdentityProviderEntity {
public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) { public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) {
this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate; this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate;
} }
public boolean isTrustEmail() {
return trustEmail;
}
public void setTrustEmail(boolean trustEmail) {
this.trustEmail = trustEmail;
}
} }

View file

@ -325,6 +325,7 @@ public class ModelToRepresentation {
providerRep.setEnabled(identityProviderModel.isEnabled()); providerRep.setEnabled(identityProviderModel.isEnabled());
providerRep.setStoreToken(identityProviderModel.isStoreToken()); providerRep.setStoreToken(identityProviderModel.isStoreToken());
providerRep.setUpdateProfileFirstLogin(identityProviderModel.isUpdateProfileFirstLogin()); providerRep.setUpdateProfileFirstLogin(identityProviderModel.isUpdateProfileFirstLogin());
providerRep.setTrustEmail(identityProviderModel.isTrustEmail());
providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault()); providerRep.setAuthenticateByDefault(identityProviderModel.isAuthenticateByDefault());
providerRep.setConfig(identityProviderModel.getConfig()); providerRep.setConfig(identityProviderModel.getConfig());
providerRep.setAddReadTokenRoleOnCreate(identityProviderModel.isAddReadTokenRoleOnCreate()); providerRep.setAddReadTokenRoleOnCreate(identityProviderModel.isAddReadTokenRoleOnCreate());

View file

@ -918,6 +918,7 @@ public class RepresentationToModel {
identityProviderModel.setProviderId(representation.getProviderId()); identityProviderModel.setProviderId(representation.getProviderId());
identityProviderModel.setEnabled(representation.isEnabled()); identityProviderModel.setEnabled(representation.isEnabled());
identityProviderModel.setUpdateProfileFirstLogin(representation.isUpdateProfileFirstLogin()); identityProviderModel.setUpdateProfileFirstLogin(representation.isUpdateProfileFirstLogin());
identityProviderModel.setTrustEmail(representation.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault()); identityProviderModel.setAuthenticateByDefault(representation.isAuthenticateByDefault());
identityProviderModel.setStoreToken(representation.isStoreToken()); identityProviderModel.setStoreToken(representation.isStoreToken());
identityProviderModel.setAddReadTokenRoleOnCreate(representation.isAddReadTokenRoleOnCreate()); identityProviderModel.setAddReadTokenRoleOnCreate(representation.isAddReadTokenRoleOnCreate());

View file

@ -1154,6 +1154,7 @@ public class RealmAdapter implements RealmModel {
identityProviderModel.setConfig(entity.getConfig()); identityProviderModel.setConfig(entity.getConfig());
identityProviderModel.setEnabled(entity.isEnabled()); identityProviderModel.setEnabled(entity.isEnabled());
identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin()); identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
identityProviderModel.setTrustEmail(entity.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault()); identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
identityProviderModel.setStoreToken(entity.isStoreToken()); identityProviderModel.setStoreToken(entity.isStoreToken());
identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate()); identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
@ -1186,6 +1187,7 @@ public class RealmAdapter implements RealmModel {
entity.setStoreToken(identityProvider.isStoreToken()); entity.setStoreToken(identityProvider.isStoreToken());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setConfig(identityProvider.getConfig()); entity.setConfig(identityProvider.getConfig());
@ -1212,6 +1214,7 @@ public class RealmAdapter implements RealmModel {
entity.setAlias(identityProvider.getAlias()); entity.setAlias(identityProvider.getAlias());
entity.setEnabled(identityProvider.isEnabled()); entity.setEnabled(identityProvider.isEnabled());
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setStoreToken(identityProvider.isStoreToken()); entity.setStoreToken(identityProvider.isStoreToken());

View file

@ -44,6 +44,9 @@ public class IdentityProviderEntity {
@Column(name="UPDATE_PROFILE_FIRST_LOGIN") @Column(name="UPDATE_PROFILE_FIRST_LOGIN")
private boolean updateProfileFirstLogin; private boolean updateProfileFirstLogin;
@Column(name = "TRUST_EMAIL")
private boolean trustEmail;
@Column(name="STORE_TOKEN") @Column(name="STORE_TOKEN")
private boolean storeToken; private boolean storeToken;
@ -138,4 +141,12 @@ public class IdentityProviderEntity {
public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) { public void setAddReadTokenRoleOnCreate(boolean addReadTokenRoleOnCreate) {
this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate; this.addReadTokenRoleOnCreate = addReadTokenRoleOnCreate;
} }
public boolean isTrustEmail() {
return trustEmail;
}
public void setTrustEmail(boolean trustEmail) {
this.trustEmail = trustEmail;
}
} }

View file

@ -772,6 +772,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
identityProviderModel.setConfig(entity.getConfig()); identityProviderModel.setConfig(entity.getConfig());
identityProviderModel.setEnabled(entity.isEnabled()); identityProviderModel.setEnabled(entity.isEnabled());
identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin()); identityProviderModel.setUpdateProfileFirstLogin(entity.isUpdateProfileFirstLogin());
identityProviderModel.setTrustEmail(entity.isTrustEmail());
identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault()); identityProviderModel.setAuthenticateByDefault(entity.isAuthenticateByDefault());
identityProviderModel.setStoreToken(entity.isStoreToken()); identityProviderModel.setStoreToken(entity.isStoreToken());
identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate()); identityProviderModel.setAddReadTokenRoleOnCreate(entity.isAddReadTokenRoleOnCreate());
@ -802,6 +803,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
entity.setProviderId(identityProvider.getProviderId()); entity.setProviderId(identityProvider.getProviderId());
entity.setEnabled(identityProvider.isEnabled()); entity.setEnabled(identityProvider.isEnabled());
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setStoreToken(identityProvider.isStoreToken()); entity.setStoreToken(identityProvider.isStoreToken());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
@ -830,6 +832,7 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
entity.setAlias(identityProvider.getAlias()); entity.setAlias(identityProvider.getAlias());
entity.setEnabled(identityProvider.isEnabled()); entity.setEnabled(identityProvider.isEnabled());
entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin()); entity.setUpdateProfileFirstLogin(identityProvider.isUpdateProfileFirstLogin());
entity.setTrustEmail(identityProvider.isTrustEmail());
entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault()); entity.setAuthenticateByDefault(identityProvider.isAuthenticateByDefault());
entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate()); entity.setAddReadTokenRoleOnCreate(identityProvider.isAddReadTokenRoleOnCreate());
entity.setStoreToken(identityProvider.isStoreToken()); entity.setStoreToken(identityProvider.isStoreToken());

View file

@ -284,6 +284,9 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
} }
federatedUser.addRequiredAction(UPDATE_PROFILE); federatedUser.addRequiredAction(UPDATE_PROFILE);
} }
if(identityProviderConfig.isTrustEmail() && federatedUser.getEmail() != null && federatedUser.getEmail().trim().length()>0){
federatedUser.setEmailVerified(true);
}
} catch (Exception e) { } catch (Exception e) {
return redirectToLoginPage(e, clientCode); return redirectToLoginPage(e, clientCode);
} }

View file

@ -53,6 +53,7 @@ public class IdentityProviderTest extends AbstractClientTest {
assertTrue(representation.isEnabled()); assertTrue(representation.isEnabled());
assertFalse(representation.isStoreToken()); assertFalse(representation.isStoreToken());
assertTrue(representation.isUpdateProfileFirstLogin()); assertTrue(representation.isUpdateProfileFirstLogin());
assertFalse(representation.isTrustEmail());
} }
@Test @Test

View file

@ -35,6 +35,7 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserModel.RequiredAction; import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.representations.IDToken; import org.keycloak.representations.IDToken;
import org.keycloak.services.Urls; import org.keycloak.services.Urls;
import org.keycloak.testsuite.MailUtil;
import org.keycloak.testsuite.OAuthClient; import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.broker.util.UserSessionStatusServlet.UserSessionStatus; import org.keycloak.testsuite.broker.util.UserSessionStatusServlet.UserSessionStatus;
import org.keycloak.testsuite.pages.AccountFederatedIdentityPage; import org.keycloak.testsuite.pages.AccountFederatedIdentityPage;
@ -42,6 +43,8 @@ import org.keycloak.testsuite.pages.AccountPasswordPage;
import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.LoginUpdateProfilePage; import org.keycloak.testsuite.pages.LoginUpdateProfilePage;
import org.keycloak.testsuite.pages.OAuthGrantPage; import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.keycloak.testsuite.pages.VerifyEmailPage;
import org.keycloak.testsuite.rule.GreenMailRule;
import org.keycloak.testsuite.rule.WebResource; import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule; import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.By; import org.openqa.selenium.By;
@ -49,6 +52,8 @@ import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement; import org.openqa.selenium.WebElement;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.ws.rs.client.Client; import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestContext;
@ -58,6 +63,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
@ -91,6 +97,13 @@ public abstract class AbstractIdentityProviderTest {
@WebResource @WebResource
private LoginUpdateProfilePage updateProfilePage; private LoginUpdateProfilePage updateProfilePage;
@WebResource
protected VerifyEmailPage verifyEmailPage;
@Rule
public GreenMailRule greenMail = new GreenMailRule();
@WebResource @WebResource
protected OAuthClient oauth; protected OAuthClient oauth;
@ -123,6 +136,7 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testSuccessfulAuthentication() { public void testSuccessfulAuthentication() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel(); IdentityProviderModel identityProviderModel = getIdentityProviderModel();
identityProviderModel.setUpdateProfileFirstLogin(true);
UserModel user = assertSuccessfulAuthentication(identityProviderModel, "test-user", "new@email.com"); UserModel user = assertSuccessfulAuthentication(identityProviderModel, "test-user", "new@email.com");
Assert.assertEquals("617-666-7777", user.getAttribute("mobile")); Assert.assertEquals("617-666-7777", user.getAttribute("mobile"));
@ -136,6 +150,78 @@ public abstract class AbstractIdentityProviderTest {
assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost"); assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost");
} }
/**
* Test that verify email action is performed if email is provided and email trust is not enabled for the provider
*
* @throws MessagingException
* @throws IOException
*/
@Test
public void testSuccessfulAuthenticationWithoutUpdateProfile_emailProvided_emailVerifyEnabled() throws IOException, MessagingException {
getRealm().setVerifyEmail(true);
brokerServerRule.stopSession(this.session, true);
this.session = brokerServerRule.startSession();
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
try {
identityProviderModel.setUpdateProfileFirstLogin(false);
identityProviderModel.setTrustEmail(false);
UserModel federatedUser = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "test-user@localhost");
// email is verified now
assertFalse(federatedUser.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
} finally {
getRealm().setVerifyEmail(false);
}
}
private UserModel assertSuccessfulAuthenticationWithEmailVerification(IdentityProviderModel identityProviderModel, String username, String expectedEmail)
throws IOException, MessagingException {
authenticateWithIdentityProvider(identityProviderModel, username);
// verify email is sent
Assert.assertTrue(verifyEmailPage.isCurrent());
// read email to take verification link from
Assert.assertEquals(1, greenMail.getReceivedMessages().length);
MimeMessage message = greenMail.getReceivedMessages()[0];
String body = (String) message.getContent();
String verificationUrl = MailUtil.getLink(body);
driver.navigate().to(verificationUrl.trim());
// authenticated and redirected to app
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/test-app"));
UserModel federatedUser = getFederatedUser();
assertNotNull(federatedUser);
doAssertFederatedUser(federatedUser, identityProviderModel, expectedEmail);
brokerServerRule.stopSession(session, true);
session = brokerServerRule.startSession();
RealmModel realm = getRealm();
Set<FederatedIdentityModel> federatedIdentities = this.session.users().getFederatedIdentities(federatedUser, realm);
assertEquals(1, federatedIdentities.size());
FederatedIdentityModel federatedIdentityModel = federatedIdentities.iterator().next();
assertEquals(getProviderId(), federatedIdentityModel.getIdentityProvider());
assertEquals(federatedUser.getUsername(), federatedIdentityModel.getIdentityProvider() + "." + federatedIdentityModel.getUserName());
driver.navigate().to("http://localhost:8081/test-app/logout");
driver.navigate().to("http://localhost:8081/test-app");
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
return federatedUser;
}
/** /**
* Test for KEYCLOAK-1053 - verify email action is not performed if email is not provided, login is normal, but action stays in set to be performed later * Test for KEYCLOAK-1053 - verify email action is not performed if email is not provided, login is normal, but action stays in set to be performed later
*/ */
@ -158,6 +244,55 @@ public abstract class AbstractIdentityProviderTest {
} }
} }
/**
* Test for KEYCLOAK-1372 - verify email action is not performed if email is provided but email trust is enabled for the provider
*/
@Test
public void testSuccessfulAuthenticationWithoutUpdateProfile_emailProvided_emailVerifyEnabled_emailTrustEnabled() {
getRealm().setVerifyEmail(true);
brokerServerRule.stopSession(this.session, true);
this.session = brokerServerRule.startSession();
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
try {
identityProviderModel.setUpdateProfileFirstLogin(false);
identityProviderModel.setTrustEmail(true);
UserModel federatedUser = assertSuccessfulAuthentication(identityProviderModel, "test-user", "test-user@localhost");
assertFalse(federatedUser.getRequiredActions().contains(RequiredAction.VERIFY_EMAIL.name()));
} finally {
identityProviderModel.setTrustEmail(false);
getRealm().setVerifyEmail(false);
}
}
/**
* Test for KEYCLOAK-1372 - verify email action is performed if email is provided and email trust is enabled for the provider, but email is changed on First login update profile page
*
* @throws MessagingException
* @throws IOException
*/
@Test
public void testSuccessfulAuthentication_emailTrustEnabled_emailVerifyEnabled_emailUpdatedOnFirstLogin() throws IOException, MessagingException {
getRealm().setVerifyEmail(true);
brokerServerRule.stopSession(this.session, true);
this.session = brokerServerRule.startSession();
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
try {
identityProviderModel.setUpdateProfileFirstLogin(true);
identityProviderModel.setTrustEmail(true);
UserModel user = assertSuccessfulAuthenticationWithEmailVerification(identityProviderModel, "test-user", "new@email.com");
Assert.assertEquals("617-666-7777", user.getAttribute("mobile"));
} finally {
identityProviderModel.setTrustEmail(false);
getRealm().setVerifyEmail(false);
}
}
@Test @Test
public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() { public void testSuccessfulAuthenticationWithoutUpdateProfile_newUser_emailAsUsername() {
@ -275,15 +410,10 @@ public abstract class AbstractIdentityProviderTest {
@Test @Test
public void testProviderOnLoginPage() { public void testProviderOnLoginPage() {
IdentityProviderModel identityProviderModel = getIdentityProviderModel();
RealmModel realm = getRealm();
ClientModel clientModel = realm.getClientByClientId("test-app");
// Provider button is available on login page // Provider button is available on login page
this.driver.navigate().to("http://localhost:8081/test-app/"); this.driver.navigate().to("http://localhost:8081/test-app/");
assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth")); assertTrue(this.driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/realm-with-broker/protocol/openid-connect/auth"));
loginPage.findSocialButton(getProviderId()); loginPage.findSocialButton(getProviderId());
} }
@Test @Test
@ -390,7 +520,6 @@ public abstract class AbstractIdentityProviderTest {
revokeGrant(); revokeGrant();
// Logout from account management // Logout from account management
String pageSource = driver.getPageSource();
System.out.println("*** logout from account management"); System.out.println("*** logout from account management");
accountFederatedIdentityPage.logout(); accountFederatedIdentityPage.logout();
assertTrue(driver.getTitle().equals("Log in to realm-with-broker")); assertTrue(driver.getTitle().equals("Log in to realm-with-broker"));
@ -400,7 +529,6 @@ public abstract class AbstractIdentityProviderTest {
this.loginPage.clickSocial(identityProviderModel.getAlias()); this.loginPage.clickSocial(identityProviderModel.getAlias());
this.loginPage.login("test-user", "password"); this.loginPage.login("test-user", "password");
doAfterProviderAuthentication(); doAfterProviderAuthentication();
String current = driver.getCurrentUrl();
this.updateProfilePage.assertCurrent(); this.updateProfilePage.assertCurrent();
} }

View file

@ -81,6 +81,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
identityProviderModel.getConfig().put("config-added", "value-added"); identityProviderModel.getConfig().put("config-added", "value-added");
identityProviderModel.setEnabled(false); identityProviderModel.setEnabled(false);
identityProviderModel.setUpdateProfileFirstLogin(false); identityProviderModel.setUpdateProfileFirstLogin(false);
identityProviderModel.setTrustEmail(true);
identityProviderModel.setStoreToken(true); identityProviderModel.setStoreToken(true);
identityProviderModel.setAuthenticateByDefault(true); identityProviderModel.setAuthenticateByDefault(true);
@ -95,12 +96,14 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("value-added", identityProviderModel.getConfig().get("config-added")); assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
assertFalse(identityProviderModel.isEnabled()); assertFalse(identityProviderModel.isEnabled());
assertFalse(identityProviderModel.isUpdateProfileFirstLogin()); assertFalse(identityProviderModel.isUpdateProfileFirstLogin());
assertTrue(identityProviderModel.isTrustEmail());
assertTrue(identityProviderModel.isStoreToken()); assertTrue(identityProviderModel.isStoreToken());
assertTrue(identityProviderModel.isAuthenticateByDefault()); assertTrue(identityProviderModel.isAuthenticateByDefault());
identityProviderModel.getConfig().remove("config-added"); identityProviderModel.getConfig().remove("config-added");
identityProviderModel.setEnabled(true); identityProviderModel.setEnabled(true);
identityProviderModel.setUpdateProfileFirstLogin(true); identityProviderModel.setUpdateProfileFirstLogin(true);
identityProviderModel.setTrustEmail(false);
identityProviderModel.setAuthenticateByDefault(false); identityProviderModel.setAuthenticateByDefault(false);
realm.updateIdentityProvider(identityProviderModel); realm.updateIdentityProvider(identityProviderModel);
@ -113,6 +116,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertFalse(identityProviderModel.getConfig().containsKey("config-added")); assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
assertTrue(identityProviderModel.isEnabled()); assertTrue(identityProviderModel.isEnabled());
assertTrue(identityProviderModel.isUpdateProfileFirstLogin()); assertTrue(identityProviderModel.isUpdateProfileFirstLogin());
assertFalse(identityProviderModel.isTrustEmail());
assertFalse(identityProviderModel.isAuthenticateByDefault()); assertFalse(identityProviderModel.isAuthenticateByDefault());
this.realmManager.removeRealm(realm); this.realmManager.removeRealm(realm);
} }
@ -161,6 +165,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(true, config.isUpdateProfileFirstLogin()); assertEquals(true, config.isUpdateProfileFirstLogin());
assertEquals(true, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(true, config.isStoreToken()); assertEquals(true, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());
@ -180,6 +185,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(true, config.isUpdateProfileFirstLogin()); assertEquals(true, config.isUpdateProfileFirstLogin());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
assertEquals("http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml", config.getSingleSignOnServiceUrl()); assertEquals("http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml", config.getSingleSignOnServiceUrl());
assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", config.getNameIDPolicyFormat()); assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", config.getNameIDPolicyFormat());
@ -199,6 +205,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(false, config.isEnabled()); assertEquals(false, config.isEnabled());
assertEquals(false, config.isUpdateProfileFirstLogin()); assertEquals(false, config.isUpdateProfileFirstLogin());
assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());
@ -213,6 +220,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(true, config.isUpdateProfileFirstLogin()); assertEquals(true, config.isUpdateProfileFirstLogin());
assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());
@ -230,6 +238,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(true, config.isUpdateProfileFirstLogin()); assertEquals(true, config.isUpdateProfileFirstLogin());
assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());
@ -247,6 +256,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(LinkedInIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(true, config.isUpdateProfileFirstLogin()); assertEquals(true, config.isUpdateProfileFirstLogin());
assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());
@ -263,7 +273,8 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals("model-stackoverflow", config.getAlias()); assertEquals("model-stackoverflow", config.getAlias());
assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(StackoverflowIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(true, config.isUpdateProfileFirstLogin()); assertEquals(false, config.isUpdateProfileFirstLogin());
assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(false, config.isStoreToken()); assertEquals(false, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());
@ -282,6 +293,7 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId()); assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
assertEquals(true, config.isEnabled()); assertEquals(true, config.isEnabled());
assertEquals(true, config.isUpdateProfileFirstLogin()); assertEquals(true, config.isUpdateProfileFirstLogin());
assertEquals(false, config.isTrustEmail());
assertEquals(false, config.isAuthenticateByDefault()); assertEquals(false, config.isAuthenticateByDefault());
assertEquals(true, config.isStoreToken()); assertEquals(true, config.isStoreToken());
assertEquals("clientId", config.getClientId()); assertEquals("clientId", config.getClientId());

View file

@ -7,12 +7,18 @@
"registrationAllowed": true, "registrationAllowed": true,
"privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn", "privateKey": "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eAguHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3IywJYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWwY2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58SMDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfYP/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmqeFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1yltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ381527ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruVXXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0lLcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaaPnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2IY+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUAYqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQCahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDsuqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIOPO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBPspPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GFCp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn",
"publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB", "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
"smtpServer": {
"from": "auto@keycloak.org",
"host": "localhost",
"port":"3025"
},
"identityProviders" : [ "identityProviders" : [
{ {
"alias" : "model-google", "alias" : "model-google",
"providerId" : "google", "providerId" : "google",
"enabled": true, "enabled": true,
"updateProfileFirstLogin" : "true", "updateProfileFirstLogin" : "true",
"trustEmail" : "true",
"storeToken": "true", "storeToken": "true",
"config": { "config": {
"clientId": "clientId", "clientId": "clientId",
@ -78,7 +84,7 @@
"alias" : "model-stackoverflow", "alias" : "model-stackoverflow",
"providerId" : "stackoverflow", "providerId" : "stackoverflow",
"enabled": true, "enabled": true,
"updateProfileFirstLogin" : "true", "updateProfileFirstLogin" : "false",
"storeToken": false, "storeToken": false,
"config": { "config": {
"key": "keyValue", "key": "keyValue",
@ -129,6 +135,7 @@
"providerId" : "saml", "providerId" : "saml",
"enabled": true, "enabled": true,
"updateProfileFirstLogin" : true, "updateProfileFirstLogin" : true,
"trustEmail" : false,
"addReadTokenRoleOnCreate": true, "addReadTokenRoleOnCreate": true,
"config": { "config": {
"singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml", "singleSignOnServiceUrl": "http://localhost:8082/auth/realms/realm-with-saml-idp-basic/protocol/saml",