Enable verify profile required action by default for new realms

Closes #25985

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2024-01-13 00:17:35 +01:00 committed by Marek Posolda
parent e7363905fa
commit 7f195acc14
22 changed files with 231 additions and 50 deletions

View file

@ -48,6 +48,8 @@ import org.keycloak.quarkus.runtime.cli.command.Start;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.utils.EmailValidationUtil;
import org.keycloak.utils.StringUtil;
import io.quarkus.runtime.QuarkusApplication;
import io.quarkus.runtime.annotations.QuarkusMain;
@ -59,8 +61,13 @@ import io.quarkus.runtime.annotations.QuarkusMain;
@ApplicationScoped
public class KeycloakMain implements QuarkusApplication {
private static final Logger log = Logger.getLogger(KeycloakMain.class);
private static final String KEYCLOAK_ADMIN_ENV_VAR = "KEYCLOAK_ADMIN";
private static final String KEYCLOAK_ADMIN_PASSWORD_ENV_VAR = "KEYCLOAK_ADMIN_PASSWORD";
private static final String KEYCLOAK_ADMIN_FIRSTNAME_ENV_VAR = "KEYCLOAK_ADMIN_FIRSTNAME";
private static final String KEYCLOAK_ADMIN_LASTNAME_ENV_VAR = "KEYCLOAK_ADMIN_LASTNAME";
private static final String KEYCLOAK_ADMIN_EMAIL_ENV_VAR = "KEYCLOAK_ADMIN_EMAIL";
private static final String KEYCLOAK_ADMIN_DEFAULT_EMAIL_DOMAIN = "keycloak.test";
public static void main(String[] args) {
System.setProperty("kc.version", Version.VERSION);
@ -164,17 +171,43 @@ public class KeycloakMain implements QuarkusApplication {
private void createAdminUser() {
String adminUserName = System.getenv(KEYCLOAK_ADMIN_ENV_VAR);
String adminPassword = System.getenv(KEYCLOAK_ADMIN_PASSWORD_ENV_VAR);
String tmpFirstName = System.getenv(KEYCLOAK_ADMIN_FIRSTNAME_ENV_VAR);
String tmpLastName = System.getenv(KEYCLOAK_ADMIN_LASTNAME_ENV_VAR);
String tmpEmail = System.getenv(KEYCLOAK_ADMIN_EMAIL_ENV_VAR);
if ((adminUserName == null || adminUserName.trim().length() == 0)
|| (adminPassword == null || adminPassword.trim().length() == 0)) {
if (StringUtil.isBlank(adminUserName) || StringUtil.isBlank(adminPassword)) {
return;
}
// try to create admin user only with username and password
if (StringUtil.isBlank(tmpFirstName)) {
tmpFirstName = adminUserName;
}
if (StringUtil.isBlank(tmpLastName)) {
tmpLastName = adminUserName;
}
if (StringUtil.isBlank(tmpEmail)) {
tmpEmail = adminUserName + "@" + KEYCLOAK_ADMIN_DEFAULT_EMAIL_DOMAIN;
}
if (!EmailValidationUtil.isValidEmail(tmpEmail)) {
log.errorf("The admin user %s is not created because the associated email is invalid: %s. "
+ "Please set a valid email in the KEYCLOAK_ADMIN_EMAIL environment variable.", adminUserName, tmpEmail);
return;
}
final String adminFirstName = tmpFirstName;
final String adminLastName = tmpLastName;
final String adminEmail = tmpEmail;
KeycloakSessionFactory sessionFactory = KeycloakApplication.getSessionFactory();
try {
KeycloakModelUtils.runJobInTransaction(sessionFactory, session -> {
new ApplianceBootstrap(session).createMasterRealmUser(adminUserName, adminPassword);
new ApplianceBootstrap(session).createMasterRealmUser(adminUserName,
adminPassword, adminFirstName, adminLastName, adminEmail);
});
} catch (Throwable t) {
ServicesLogger.LOGGER.addUserFailed(t, adminUserName, Config.getAdminRealm());

View file

@ -81,7 +81,8 @@ public class DefaultRequiredActions {
UPDATE_EMAIL(UserModel.RequiredAction.UPDATE_EMAIL.name(), DefaultRequiredActions::addUpdateEmailAction, () -> isFeatureEnabled(Profile.Feature.UPDATE_EMAIL)),
CONFIGURE_RECOVERY_AUTHN_CODES(UserModel.RequiredAction.CONFIGURE_RECOVERY_AUTHN_CODES.name(), DefaultRequiredActions::addRecoveryAuthnCodesAction, () -> isFeatureEnabled(Profile.Feature.RECOVERY_CODES)),
WEBAUTHN_REGISTER("webauthn-register", DefaultRequiredActions::addWebAuthnRegisterAction, () -> isFeatureEnabled(Profile.Feature.WEB_AUTHN)),
WEBAUTHN_PASSWORDLESS_REGISTER("webauthn-register-passwordless", DefaultRequiredActions::addWebAuthnPasswordlessRegisterAction, () -> isFeatureEnabled(Profile.Feature.WEB_AUTHN));
WEBAUTHN_PASSWORDLESS_REGISTER("webauthn-register-passwordless", DefaultRequiredActions::addWebAuthnPasswordlessRegisterAction, () -> isFeatureEnabled(Profile.Feature.WEB_AUTHN)),
VERIFY_USER_PROFILE(UserModel.RequiredAction.VERIFY_PROFILE.name(), DefaultRequiredActions::addVerifyProfile);
private final String alias;
private final Consumer<RealmModel> addAction;
@ -182,6 +183,19 @@ public class DefaultRequiredActions {
}
}
public static void addVerifyProfile(RealmModel realm) {
if (realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.VERIFY_PROFILE.name()) == null) {
RequiredActionProviderModel termsAndConditions = new RequiredActionProviderModel();
termsAndConditions.setEnabled(true);
termsAndConditions.setAlias(UserModel.RequiredAction.VERIFY_PROFILE.name());
termsAndConditions.setName("Verify Profile");
termsAndConditions.setProviderId(UserModel.RequiredAction.VERIFY_PROFILE.name());
termsAndConditions.setDefaultAction(false);
termsAndConditions.setPriority(90);
realm.addRequiredActionProvider(termsAndConditions);
}
}
public static void addDeleteAccountAction(RealmModel realm) {
if (realm.getRequiredActionProviderByAlias("delete_account") == null) {
RequiredActionProviderModel deleteAccount = new RequiredActionProviderModel();

View file

@ -92,7 +92,7 @@ public class ApplianceBootstrap {
return true;
}
public void createMasterRealmUser(String username, String password) {
public void createMasterRealmUser(String username, String password, String firstName, String lastName, String email) {
RealmModel realm = session.realms().getRealmByName(Config.getAdminRealm());
session.getContext().setRealm(realm);
@ -103,6 +103,9 @@ public class ApplianceBootstrap {
UserModel adminUser = session.users().addUser(realm, username);
adminUser.setEnabled(true);
adminUser.setFirstName(firstName);
adminUser.setLastName(lastName);
adminUser.setEmail(email);
UserCredentialModel usrCredModel = UserCredentialModel.password(password);
adminUser.credentialManager().updateCredential(usrCredModel);

View file

@ -318,10 +318,7 @@ public class KeycloakApplication extends Application {
if (users.getUserByUsername(realm, userRep.getUsername()) != null) {
ServicesLogger.LOGGER.notCreatingExistingUser(userRep.getUsername());
} else {
UserModel user = users.addUser(realm, userRep.getUsername());
user.setEnabled(userRep.isEnabled());
RepresentationToModel.createCredentials(userRep, session, realm, user, false);
RepresentationToModel.createRoleMappings(userRep, user, realm);
UserModel user = RepresentationToModel.createUser(session, realm, userRep);
ServicesLogger.LOGGER.addUserSuccess(userRep.getUsername(), realmRep.getRealm());
}
});

View file

@ -47,6 +47,7 @@ import org.keycloak.services.util.CookieHelper;
import org.keycloak.theme.Theme;
import org.keycloak.theme.freemarker.FreeMarkerProvider;
import org.keycloak.urls.UrlType;
import org.keycloak.utils.EmailValidationUtil;
import org.keycloak.utils.MediaType;
import java.io.IOException;
@ -113,6 +114,9 @@ public class WelcomeResource {
String username = formData.getFirst("username");
String password = formData.getFirst("password");
String passwordConfirmation = formData.getFirst("passwordConfirmation");
String firstName = formData.getFirst("firstName");
String lastName = formData.getFirst("lastName");
String email = formData.getFirst("email");
if (username != null) {
username = username.trim();
@ -130,10 +134,22 @@ public class WelcomeResource {
return createWelcomePage(null, "Password and confirmation doesn't match");
}
if (firstName == null || firstName.length() == 0) {
return createWelcomePage(null, "FirstName is missing");
}
if (lastName == null || lastName.length() == 0) {
return createWelcomePage(null, "LastName is missing");
}
if (!EmailValidationUtil.isValidEmail(email)) {
return createWelcomePage(null, "Email is invalid");
}
expireCsrfCookie();
ApplianceBootstrap applianceBootstrap = new ApplianceBootstrap(session);
applianceBootstrap.createMasterRealmUser(username, password);
applianceBootstrap.createMasterRealmUser(username, password, firstName, lastName, email);
shouldBootstrap.set(false);
ServicesLogger.LOGGER.createdInitialAdminUser(username);

View file

@ -235,7 +235,7 @@ public class KeycloakOnUndertow implements DeployableContainer<KeycloakOnUnderto
try (KeycloakSession session = sessionFactory.create()) {
session.getTransactionManager().begin();
if (new ApplianceBootstrap(session).isNoMasterUser()) {
new ApplianceBootstrap(session).createMasterRealmUser("admin", "admin");
new ApplianceBootstrap(session).createMasterRealmUser("admin", "admin", "admin", "admin", "admin@keycloak.org");
}
}
}

View file

@ -149,6 +149,9 @@ public class KeycloakQuarkusServerDeployableContainer extends AbstractQuarkusDep
if (!StoreProvider.JPA.equals(StoreProvider.getCurrentProvider())) {
builder.environment().put("KEYCLOAK_ADMIN", "admin");
builder.environment().put("KEYCLOAK_ADMIN_FIRSTNAME", "admin");
builder.environment().put("KEYCLOAK_ADMIN_LASTNAME", "admin");
builder.environment().put("KEYCLOAK_ADMIN_EMAIL", "admin@keycloak.org");
builder.environment().put("KEYCLOAK_ADMIN_PASSWORD", "admin");
}

View file

@ -37,7 +37,6 @@ import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.common.util.KeycloakUriBuilder;
import org.keycloak.common.util.Time;
import org.keycloak.models.cache.UserCache;
import org.keycloak.models.utils.TimeBasedOTP;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
import org.keycloak.representations.idm.ClientRepresentation;
@ -79,7 +78,6 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@ -93,6 +91,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import org.keycloak.models.UserModel;
import static org.keycloak.testsuite.admin.Users.setPasswordFor;
import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_HOST;
@ -473,6 +472,10 @@ public abstract class AbstractKeycloakTest {
assertThat(adminClient.realms().findAll().size(), is(equalTo(1)));
}
protected boolean removeVerifyProfileAtImport() {
// remove verify profile by default because most tests are not prepared
return true;
}
public void importRealm(RealmRepresentation realm) {
if (modifyRealmForSSL()) {
@ -511,6 +514,19 @@ public abstract class AbstractKeycloakTest {
// expected when realm does not exist
}
adminClient.realms().create(realm);
if (removeVerifyProfileAtImport()) {
try {
RequiredActionProviderRepresentation vpModel = adminClient.realm(realm.getRealm()).flows()
.getRequiredAction(UserModel.RequiredAction.VERIFY_PROFILE.name());
vpModel.setEnabled(false);
vpModel.setDefaultAction(false);
adminClient.realm(realm.getRealm()).flows().updateRequiredAction(
UserModel.RequiredAction.VERIFY_PROFILE.name(), vpModel);
testingClient.testing().pollAdminEvent(); // remove the event
} catch (NotFoundException ignore) {
}
}
}
public void removeRealm(String realmName) {

View file

@ -83,16 +83,25 @@ public class IllegalAdminUpgradeTest extends AbstractKeycloakTest {
realmUser.credentialManager().updateCredential(UserCredentialModel.password("password"));
UserModel masterUser = session.users().addUser(master, "userAdmin");
masterUser.setFirstName("userAdmin");
masterUser.setLastName("userAdmin");
masterUser.setEmail("userAdmin@keycloak.org");
masterUser.grantRole(masterManageUsers);
masterUser.setEnabled(true);
masterUser.credentialManager().updateCredential(UserCredentialModel.password("password"));
UserModel masterAdmin = session.users().addUser(master, "masterAdmin");
masterAdmin.setFirstName("masterAdmin");
masterAdmin.setLastName("masterAdmin");
masterAdmin.setEmail("masterAdmin@keycloak.org");
masterAdmin.grantRole(masterMasterManageUSers);
masterAdmin.setEnabled(true);
masterAdmin.credentialManager().updateCredential(UserCredentialModel.password("password"));
UserModel user = session.users().addUser(master, "user");
user.setFirstName("user");
user.setLastName("user");
user.setEmail("user@keycloak.org");
user.grantRole(masterManageUsers);
user.setEnabled(true);
user.credentialManager().updateCredential(UserCredentialModel.password("password"));

View file

@ -142,7 +142,12 @@ public class ImpersonationTest extends AbstractKeycloakTest {
@Test
public void testImpersonateByMasterImpersonator() {
String userId;
try (Response response = adminClient.realm("master").users().create(UserBuilder.create().username("master-impersonator").build())) {
try (Response response = adminClient.realm("master").users().create(
UserBuilder.create().username("master-impersonator")
.firstName("master-impersonator")
.lastName("master-impersonator")
.email("master-impersonator@keycloak.org")
.build())) {
userId = ApiUtil.getCreatedId(response);
}
@ -195,7 +200,12 @@ public class ImpersonationTest extends AbstractKeycloakTest {
@Test
public void testImpersonateByMastertBadImpersonator() {
String userId;
try (Response response = adminClient.realm("master").users().create(UserBuilder.create().username("master-bad-impersonator").build())) {
try (Response response = adminClient.realm("master").users().create(
UserBuilder.create().username("master-bad-impersonator")
.firstName("master-bad-impersonator")
.lastName("master-bad-impersonator")
.email("master-bad-impersonator@keycloak.org")
.build())) {
userId = ApiUtil.getCreatedId(response);
}
adminClient.realm("master").users().get(userId).resetPassword(CredentialBuilder.create().password("password").build());

View file

@ -122,27 +122,33 @@ public class PermissionsTest extends AbstractKeycloakTest {
builder.client(ClientBuilder.create().clientId("test-client").publicClient().directAccessGrants());
builder.user(UserBuilder.create()
.username(AdminRoles.REALM_ADMIN)
.username(AdminRoles.REALM_ADMIN).firstName(AdminRoles.REALM_ADMIN)
.lastName(AdminRoles.REALM_ADMIN).email(AdminRoles.REALM_ADMIN + "@keycloak.org")
.role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.REALM_ADMIN)
.addPassword("password"));
builder.user(UserBuilder.create()
.username("multi")
.username("multi").firstName("multi").lastName("multi").email("multi@keycloak.org")
.role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.QUERY_GROUPS)
.role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.MANAGE_REALM)
.role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.VIEW_CLIENTS)
.addPassword("password"));
builder.user(UserBuilder.create().username("none").addPassword("password"));
builder.user(UserBuilder.create().username("none").firstName("none").lastName("none")
.email("none@keycloak.org").addPassword("password"));
for (String role : AdminRoles.ALL_REALM_ROLES) {
builder.user(UserBuilder.create().username(role).role(Constants.REALM_MANAGEMENT_CLIENT_ID, role).addPassword("password"));
builder.user(UserBuilder.create().username(role)
.firstName(role).lastName(role).email(role + "@keycloak.org")
.role(Constants.REALM_MANAGEMENT_CLIENT_ID, role).addPassword("password"));
}
testRealms.add(builder.build());
RealmBuilder builder2 = RealmBuilder.create().name("realm2");
builder2.client(ClientBuilder.create().clientId("test-client").publicClient().directAccessGrants());
builder2.user(UserBuilder.create().username("admin").role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.REALM_ADMIN).addPassword("password"));
builder2.user(UserBuilder.create().username("admin").firstName("admin")
.lastName("admin").email("admin@keycloak.org")
.role(Constants.REALM_MANAGEMENT_CLIENT_ID, AdminRoles.REALM_ADMIN).addPassword("password"));
testRealms.add(builder2.build());
}
@ -161,13 +167,21 @@ public class PermissionsTest extends AbstractKeycloakTest {
private void createTestUsers() {
RealmResource master = adminClient.realm("master");
Response response = master.users().create(UserBuilder.create().username("permissions-test-master-none").build());
Response response = master.users().create(UserBuilder.create()
.username("permissions-test-master-none")
.firstName("permissions-test-master-none")
.lastName("permissions-test-master-none")
.email("permissions-test-master-none@keycloak.org").build());
String userId = ApiUtil.getCreatedId(response);
response.close();
master.users().get(userId).resetPassword(CredentialBuilder.create().password("password").build());
for (String role : AdminRoles.ALL_REALM_ROLES) {
response = master.users().create(UserBuilder.create().username("permissions-test-master-" + role).build());
response = master.users().create(UserBuilder.create()
.username("permissions-test-master-" + role)
.firstName("permissions-test-master-" + role)
.lastName("permissions-test-master-" + role)
.email("permissions-test-master-" + role + "@keycloak.org").build());
userId = ApiUtil.getCreatedId(response);
response.close();
@ -474,6 +488,9 @@ public class PermissionsTest extends AbstractKeycloakTest {
public void attackDetection() {
UserRepresentation newUser = new UserRepresentation();
newUser.setUsername("attacked");
newUser.setFirstName("attacked");
newUser.setLastName("attacked");
newUser.setEmail("attacked@keycloak.org");
newUser.setEnabled(true);
adminClient.realms().realm(REALM_NAME).users().create(newUser);
UserRepresentation user = adminClient.realms().realm(REALM_NAME).users().search("attacked").get(0);
@ -1441,7 +1458,12 @@ public class PermissionsTest extends AbstractKeycloakTest {
public void users() {
invoke(new InvocationWithResponse() {
public void invoke(RealmResource realm, AtomicReference<Response> response) {
response.set(realm.users().create(UserBuilder.create().username("testuser").build()));
response.set(realm.users().create(UserBuilder.create()
.username("testuser")
.firstName("testuser")
.lastName("testuser")
.email("testuser@keycloak.org")
.build()));
}
}, Resource.USER, true);
UserRepresentation user = adminClient.realms().realm(REALM_NAME).users().search("testuser").get(0);

View file

@ -40,6 +40,12 @@ import java.util.Map;
*/
public class RequiredActionsTest extends AbstractAuthenticationTest {
@Override
protected boolean removeVerifyProfileAtImport() {
// do not remove verify profile action for this test
return false;
}
@Test
public void testRequiredActions() {
List<RequiredActionProviderRepresentation> result = authMgmtResource.getRequiredActions();
@ -50,6 +56,7 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
addRequiredAction(expected, "UPDATE_PASSWORD", "Update Password", true, false, null);
addRequiredAction(expected, "UPDATE_PROFILE", "Update Profile", true, false, null);
addRequiredAction(expected, "VERIFY_EMAIL", "Verify Email", true, false, null);
addRequiredAction(expected, "VERIFY_PROFILE", "Verify Profile", true, false, null);
addRequiredAction(expected, "delete_account", "Delete Account", false, false, null);
addRequiredAction(expected, "update_user_locale", "Update User Locale", true, false, null);
addRequiredAction(expected, "webauthn-register", "Webauthn Register", true, false, null);
@ -84,7 +91,7 @@ public class RequiredActionsTest extends AbstractAuthenticationTest {
// Dummy RequiredAction is not registered in the realm and WebAuthn actions
List<RequiredActionProviderSimpleRepresentation> result = authMgmtResource.getUnregisteredRequiredActions();
Assert.assertEquals(2, result.size());
Assert.assertEquals(1, result.size());
RequiredActionProviderSimpleRepresentation action = result.stream().filter(
a -> a.getProviderId().equals(DummyRequiredActionFactory.PROVIDER_ID)
).findFirst().get();

View file

@ -103,7 +103,9 @@ public class AdminEventAuthDetailsTest extends AbstractAuthTest {
masterRealmId = masterRealm.toRepresentation().getId();
masterAdminCliUuid = ApiUtil.findClientByClientId(masterRealm, Constants.ADMIN_CLI_CLIENT_ID).toRepresentation().getId();
masterAdminUserId = ApiUtil.findUserByUsername(masterRealm, "admin").getId();
masterAdminUser2Id = ApiUtil.createUserAndResetPasswordWithAdminClient(masterRealm, UserBuilder.create().username("admin2").build(), "password");
masterAdminUser2Id = ApiUtil.createUserAndResetPasswordWithAdminClient(masterRealm,
UserBuilder.create().username("admin2").firstName("admin2").lastName("admin2").email("admin2@keycloak.org").build(),
"password");
masterRealm.users().get(masterAdminUser2Id).roles().realmLevel().add(Collections.singletonList(masterRealm.roles().get("admin").toRepresentation()));
RealmResource testRealm = adminClient.realm("test");

View file

@ -837,7 +837,7 @@ public class GroupTest extends AbstractGroupTest {
public void noAdminEndpointAccessWhenNoRoleAssigned() {
String userName = "user-" + UUID.randomUUID();
final String realmName = AuthRealm.MASTER;
createUser(realmName, userName, "pwd");
createUser(realmName, userName, "pwd", userName, userName, userName + "@keycloak.org");
try (Keycloak userClient = Keycloak.getInstance(getAuthServerContextRoot() + "/auth",
realmName, userName, "pwd", Constants.ADMIN_CLI_CLIENT_ID, TLSUtils.initializeTLS())) {
@ -862,7 +862,7 @@ public class GroupTest extends AbstractGroupTest {
assertThat(adminRole, notNullValue());
assertThat(adminRole.getId(), notNullValue());
String userId = createUser(realmName, userName, "pwd");
String userId = createUser(realmName, userName, "pwd", userName, userName, userName + "@keycloak.org");
assertThat(userId, notNullValue());
RoleMappingResource mappings = realm.users().get(userId).roles();
@ -891,7 +891,7 @@ public class GroupTest extends AbstractGroupTest {
assertThat(adminRole, notNullValue());
assertThat(adminRole.getId(), notNullValue());
String userId = createUser(realmName, userName, "pwd");
String userId = createUser(realmName, userName, "pwd", userName, userName, userName + "@keycloak.org");
GroupRepresentation group = GroupBuilder.create().name(groupName).build();
try (Response response = realm.groups().add(group)) {
String groupId = ApiUtil.getCreatedId(response);
@ -984,7 +984,7 @@ public class GroupTest extends AbstractGroupTest {
assertThat(adminRole, notNullValue());
assertThat(adminRole.getId(), notNullValue());
String userId = createUser(realmName, userName, "pwd");
String userId = createUser(realmName, userName, "pwd", userName, userName, userName + "@keycloak.org");
GroupRepresentation group = GroupBuilder.create().name(groupName).build();
try (Response response = realm.groups().add(group)) {
String groupId = ApiUtil.getCreatedId(response);

View file

@ -951,7 +951,11 @@ public class RealmTest extends AbstractAdminTest {
oauth.realm(REALM_NAME);
oauth.redirectUri(redirectUri);
UserRepresentation userRep = UserBuilder.create().username("testuser").build();
UserRepresentation userRep = UserBuilder.create().username("testuser")
.firstName("testuser")
.lastName("testuser")
.email("testuser@keycloak.org")
.build();
Response response = realm.users().create(userRep);
String userId = ApiUtil.getCreatedId(response);
response.close();

View file

@ -43,7 +43,7 @@ public class KcAdmSessionTest extends AbstractAdmCliTest {
Assert.assertTrue(exe.stderrLines().get(exe.stderrLines().size() - 1).startsWith("Created "));
// create user
exe = execute("create users --config '" + configFile.getName() + "' -r demorealm -s username=testuser -s enabled=true -i");
exe = execute("create users --config '" + configFile.getName() + "' -r demorealm -s username=testuser -s firstName=testuser -s lastName=testuser -s email=testuser@keycloak.org -s enabled=true -i");
assertExitCodeAndStreamSizes(exe, 0, 1, 0);
String userId = exe.stdoutLines().get(0);

View file

@ -869,7 +869,7 @@ public class UserStorageTest extends AbstractAuthTest {
// Re-create realm
RealmRepresentation repOrig = testContext.getTestRealmReps().get(0);
adminClient.realms().create(repOrig);
importRealm(repOrig);
}
@Test

View file

@ -49,7 +49,6 @@ import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.userprofile.config.UPAttribute;
import org.keycloak.representations.userprofile.config.UPAttributePermissions;
@ -113,6 +112,12 @@ public class VerifyProfileTest extends AbstractTestRealmKeycloakTest {
private static ClientRepresentation client_scope_default;
private static ClientRepresentation client_scope_optional;
@Override
protected boolean removeVerifyProfileAtImport() {
// we need the verify profile action enabled as default
return false;
}
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
UserRepresentation user = UserBuilder.create().id(UUID.randomUUID().toString()).username("login-test").email("login@test.com").enabled(true).password("password").build();
@ -125,17 +130,6 @@ public class VerifyProfileTest extends AbstractTestRealmKeycloakTest {
RealmBuilder.edit(testRealm).user(user).user(user2).user(user3).user(user4).user(user5).user(user6).user(userWithoutEmail);
RequiredActionProviderRepresentation action = new RequiredActionProviderRepresentation();
action.setAlias(UserModel.RequiredAction.VERIFY_PROFILE.name());
action.setProviderId(UserModel.RequiredAction.VERIFY_PROFILE.name());
action.setEnabled(true);
action.setDefaultAction(false);
action.setPriority(10);
List<RequiredActionProviderRepresentation> actions = new ArrayList<>();
actions.add(action);
testRealm.setRequiredActions(actions);
testRealm.setClientScopes(new ArrayList<>());
testRealm.getClientScopes().add(ClientScopeBuilder.create().name(SCOPE_DEPARTMENT).protocol("openid-connect").build());
testRealm.getClientScopes().add(ClientScopeBuilder.create().name("profile").protocol("openid-connect").build());

View file

@ -366,9 +366,17 @@ public class RefreshTokenTest extends AbstractKeycloakTest {
.build());
realmResource.users()
.create(UserBuilder.create().username("alice").password("alice").addRoles("offline_access").build());
.create(UserBuilder.create().username("alice")
.firstName("alice")
.lastName("alice")
.email("alice@keycloak.org")
.password("alice").addRoles("offline_access").build());
realmResource.users()
.create(UserBuilder.create().username("bob").password("bob").addRoles("offline_access").build());
.create(UserBuilder.create().username("bob")
.firstName("bob")
.lastName("bob")
.email("bob@keycloak.org")
.password("bob").addRoles("offline_access").build());
oauth.realm(realmName);
oauth.clientId("public-client");

View file

@ -2,6 +2,9 @@
"realm" : "master",
"users" : [ {
"username" : "admin",
"firstName" : "admin",
"lastName" : "admin",
"email" : "admin@keycloak.org",
"enabled" : true,
"credentials" : [ {
"type" : "password",

View file

@ -396,7 +396,7 @@ public class KeycloakServer {
try (KeycloakSession session = sessionFactory.create()) {
session.getTransactionManager().begin();
if (new ApplianceBootstrap(session).isNoMasterUser()) {
new ApplianceBootstrap(session).createMasterRealmUser("admin", "admin");
new ApplianceBootstrap(session).createMasterRealmUser("admin", "admin", "admin", "admin", "admin@keycloak.org");
log.info("Created master user with credentials admin:admin");
}
}

View file

@ -80,6 +80,46 @@
</span>
</div>
</div>
<div class="pf-v5-c-form__group">
<div class="pf-v5-c-form__group-label">
<label class="pf-v5-c-form__label" for="email">
<span class="pf-v5-c-form__label-text">Email</span>&nbsp;<span class="pf-v5-c-form__label-required" aria-hidden="true">&#42;</span>
</label>
</div>
<div class="pf-v5-c-form__group-control">
<span class="pf-v5-c-form-control pf-m-required">
<input id="email" type="email" name="email" autocomplete="email" required>
</span>
</div>
</div>
<div class="pf-v5-c-form__group">
<div class="pf-v5-c-form__group-label">
<label class="pf-v5-c-form__label" for="firstName">
<span class="pf-v5-c-form__label-text">First name</span>&nbsp;<span class="pf-v5-c-form__label-required" aria-hidden="true">&#42;</span>
</label>
</div>
<div class="pf-v5-c-form__group-control">
<span class="pf-v5-c-form-control pf-m-required">
<input id="firstName" type="text" name="firstName" autocomplete="firstName" required>
</span>
</div>
</div>
<div class="pf-v5-c-form__group">
<div class="pf-v5-c-form__group-label">
<label class="pf-v5-c-form__label" for="lastName">
<span class="pf-v5-c-form__label-text">Last name</span>&nbsp;<span class="pf-v5-c-form__label-required" aria-hidden="true">&#42;</span>
</label>
</div>
<div class="pf-v5-c-form__group-control">
<span class="pf-v5-c-form-control pf-m-required">
<input id="lastName" type="text" name="lastName" autocomplete="lastName" required>
</span>
</div>
</div>
<div class="pf-v5-c-form__group">
<div class="pf-v5-c-form__group-label">
<label class="pf-v5-c-form__label" for="password">
@ -110,7 +150,7 @@
</div>
</form>
<#else>
<p>To create the administrative user open <a href="${localAdminUrl}">${localAdminUrl}</a>, or set the environment variables <code>KEYCLOAK_ADMIN</code> and <code>KEYCLOAK_ADMIN_PASSWORD</code> when starting the server.</p>
<p>To create the administrative user open <a href="${localAdminUrl}">${localAdminUrl}</a>, or set the environment variables <code>KEYCLOAK_ADMIN</code> and <code>KEYCLOAK_ADMIN_PASSWORD</code> when starting the server. <code>KEYCLOAK_ADMIN_FIRSTNAME</code>, <code>KEYCLOAK_ADMIN_LASTNAME</code> and <code>KEYCLOAK_ADMIN_EMAIL</code> variables can also be set but they are automatically filled (if possible) when missed.</p>
</#if>
</#if>
</div>