3 * Copyright (C) 2009-2018 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.authentication;
22 import java.util.Optional;
23 import java.util.stream.Collectors;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.rules.ExpectedException;
27 import org.sonar.api.config.internal.MapSettings;
28 import org.sonar.api.resources.Qualifiers;
29 import org.sonar.api.resources.ResourceTypes;
30 import org.sonar.api.server.authentication.UserIdentity;
31 import org.sonar.api.utils.System2;
32 import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
33 import org.sonar.core.util.UuidFactoryFast;
34 import org.sonar.core.util.stream.MoreCollectors;
35 import org.sonar.db.DbTester;
36 import org.sonar.db.component.ResourceTypesRule;
37 import org.sonar.db.organization.OrganizationDto;
38 import org.sonar.db.user.GroupDto;
39 import org.sonar.db.user.UserDto;
40 import org.sonar.server.authentication.UserIdentityAuthenticatorParameters.ExistingEmailStrategy;
41 import org.sonar.server.authentication.UserIdentityAuthenticatorParameters.UpdateLoginStrategy;
42 import org.sonar.server.authentication.event.AuthenticationEvent;
43 import org.sonar.server.authentication.event.AuthenticationEvent.Source;
44 import org.sonar.server.authentication.exception.EmailAlreadyExistsRedirectionException;
45 import org.sonar.server.authentication.exception.UpdateLoginRedirectionException;
46 import org.sonar.server.es.EsTester;
47 import org.sonar.server.organization.DefaultOrganizationProvider;
48 import org.sonar.server.organization.OrganizationUpdater;
49 import org.sonar.server.organization.OrganizationUpdaterImpl;
50 import org.sonar.server.organization.OrganizationValidationImpl;
51 import org.sonar.server.organization.TestDefaultOrganizationProvider;
52 import org.sonar.server.organization.TestOrganizationFlags;
53 import org.sonar.server.permission.PermissionService;
54 import org.sonar.server.permission.PermissionServiceImpl;
55 import org.sonar.server.user.NewUserNotifier;
56 import org.sonar.server.user.UserUpdater;
57 import org.sonar.server.user.index.UserIndexer;
58 import org.sonar.server.usergroups.DefaultGroupFinder;
60 import static com.google.common.collect.Sets.newHashSet;
61 import static java.util.Arrays.stream;
62 import static org.assertj.core.api.Assertions.assertThat;
63 import static org.mockito.Mockito.mock;
64 import static org.sonar.core.config.CorePropertyDefinitions.ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS;
65 import static org.sonar.db.user.UserTesting.newUserDto;
66 import static org.sonar.server.authentication.UserIdentityAuthenticatorParameters.ExistingEmailStrategy.FORBID;
67 import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC;
68 import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException;
70 public class UserIdentityAuthenticatorImplTest {
72 private static String USER_LOGIN = "github-johndoo";
74 private static UserIdentity USER_IDENTITY = UserIdentity.builder()
75 .setProviderId("ABCD")
76 .setProviderLogin("johndoo")
79 .setEmail("john@email.com")
82 private static TestIdentityProvider IDENTITY_PROVIDER = new TestIdentityProvider()
84 .setName("name of github")
86 .setAllowsUsersToSignUp(true);
88 private MapSettings settings = new MapSettings();
91 public ExpectedException expectedException = ExpectedException.none();
93 public DbTester db = DbTester.create(new AlwaysIncreasingSystem2());
95 public EsTester es = EsTester.create();
96 private UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client());
97 private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
98 private OrganizationUpdater organizationUpdater = mock(OrganizationUpdater.class);
99 private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
100 private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
101 private UserUpdater userUpdater = new UserUpdater(
102 mock(NewUserNotifier.class),
106 defaultOrganizationProvider,
108 new DefaultGroupFinder(db.getDbClient()),
110 localAuthentication);
112 private ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT);
113 private PermissionService permissionService = new PermissionServiceImpl(resourceTypes);
115 private UserIdentityAuthenticatorImpl underTest = new UserIdentityAuthenticatorImpl(db.getDbClient(), userUpdater, defaultOrganizationProvider, organizationFlags,
116 new OrganizationUpdaterImpl(db.getDbClient(), mock(System2.class), UuidFactoryFast.getInstance(),
117 new OrganizationValidationImpl(), settings.asConfig(), null, null, null, permissionService),
118 new DefaultGroupFinder(db.getDbClient()));
121 public void authenticate_new_user() {
122 organizationFlags.setEnabled(true);
124 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
125 .setUserIdentity(USER_IDENTITY)
126 .setProvider(IDENTITY_PROVIDER)
127 .setSource(Source.realm(BASIC, IDENTITY_PROVIDER.getName()))
128 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
129 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
132 UserDto user = db.users().selectUserByLogin(USER_LOGIN).get();
133 assertThat(user).isNotNull();
134 assertThat(user.isActive()).isTrue();
135 assertThat(user.getName()).isEqualTo("John");
136 assertThat(user.getEmail()).isEqualTo("john@email.com");
137 assertThat(user.getExternalLogin()).isEqualTo("johndoo");
138 assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
139 assertThat(user.getExternalId()).isEqualTo("ABCD");
140 assertThat(user.isRoot()).isFalse();
141 checkGroupMembership(user);
145 public void authenticate_new_user_generate_login_when_no_login_provided() {
146 organizationFlags.setEnabled(true);
148 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
149 .setUserIdentity(UserIdentity.builder()
150 .setProviderId("ABCD")
151 .setProviderLogin("johndoo")
153 .setEmail("john@email.com")
155 .setProvider(IDENTITY_PROVIDER)
156 .setSource(Source.realm(BASIC, IDENTITY_PROVIDER.getName()))
157 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
158 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
161 UserDto user = db.getDbClient().userDao().selectByEmail(db.getSession(), "john@email.com").get(0);
162 assertThat(user).isNotNull();
163 assertThat(user.isActive()).isTrue();
164 assertThat(user.getLogin()).isNotEqualTo("John Doe").startsWith("john-doe");
165 assertThat(user.getEmail()).isEqualTo("john@email.com");
166 assertThat(user.getExternalLogin()).isEqualTo("johndoo");
167 assertThat(user.getExternalIdentityProvider()).isEqualTo("github");
168 assertThat(user.getExternalId()).isEqualTo("ABCD");
172 public void authenticate_new_user_with_groups() {
173 organizationFlags.setEnabled(true);
174 GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
175 GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
177 authenticate(USER_LOGIN, "group1", "group2", "group3");
179 Optional<UserDto> user = db.users().selectUserByLogin(USER_LOGIN);
180 checkGroupMembership(user.get(), group1, group2);
184 public void authenticate_new_user_and_force_default_group_when_organizations_are_disabled() {
185 organizationFlags.setEnabled(false);
186 UserDto user = db.users().insertUser();
187 GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
188 GroupDto defaultGroup = insertDefaultGroup();
189 db.users().insertMember(group1, user);
190 db.users().insertMember(defaultGroup, user);
192 authenticate(user.getLogin(), "group1");
194 checkGroupMembership(user, group1, defaultGroup);
198 public void does_not_force_default_group_when_authenticating_new_user_if_organizations_are_enabled() {
199 organizationFlags.setEnabled(true);
200 UserDto user = db.users().insertUser();
201 GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
202 GroupDto defaultGroup = insertDefaultGroup();
203 db.users().insertMember(group1, user);
204 db.users().insertMember(defaultGroup, user);
206 authenticate(user.getLogin(), "group1");
208 checkGroupMembership(user, group1);
212 public void authenticate_new_user_sets_onboarded_flag_to_false_when_onboarding_setting_is_set_to_true() {
213 organizationFlags.setEnabled(true);
214 settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS, true);
216 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
217 .setUserIdentity(USER_IDENTITY)
218 .setProvider(IDENTITY_PROVIDER)
219 .setSource(Source.local(BASIC))
220 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
221 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
224 assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isFalse();
228 public void authenticate_new_user_sets_onboarded_flag_to_true_when_onboarding_setting_is_set_to_false() {
229 organizationFlags.setEnabled(true);
230 settings.setProperty(ONBOARDING_TUTORIAL_SHOW_TO_NEW_USERS, false);
232 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
233 .setUserIdentity(USER_IDENTITY)
234 .setProvider(IDENTITY_PROVIDER)
235 .setSource(Source.local(BASIC))
236 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
237 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
240 assertThat(db.users().selectUserByLogin(USER_LOGIN).get().isOnboarded()).isTrue();
244 public void external_id_is_set_to_provider_login_when_null() {
245 organizationFlags.setEnabled(true);
246 UserIdentity newUser = UserIdentity.builder()
249 .setProviderLogin("johndoo")
253 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
254 .setUserIdentity(newUser)
255 .setProvider(IDENTITY_PROVIDER)
256 .setSource(Source.local(BASIC))
257 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
258 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
261 assertThat(db.users().selectUserByLogin(newUser.getLogin()).get())
262 .extracting(UserDto::getLogin, UserDto::getExternalId, UserDto::getExternalLogin)
263 .contains("john", "johndoo", "johndoo");
267 public void authenticate_new_user_update_existing_user_email_when_strategy_is_ALLOW() {
268 organizationFlags.setEnabled(true);
269 UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
270 UserIdentity newUser = UserIdentity.builder()
271 .setProviderLogin("johndoo")
272 .setLogin("new_login")
273 .setName(existingUser.getName())
274 .setEmail(existingUser.getEmail())
277 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
278 .setUserIdentity(newUser)
279 .setProvider(IDENTITY_PROVIDER)
280 .setSource(Source.local(BASIC))
281 .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
282 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
285 UserDto newUserReloaded = db.users().selectUserByLogin(newUser.getLogin()).get();
286 assertThat(newUserReloaded.getEmail()).isEqualTo(existingUser.getEmail());
287 UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
288 assertThat(existingUserReloaded.getEmail()).isNull();
292 public void throw_EmailAlreadyExistException_when_authenticating_new_user_when_email_already_exists_and_strategy_is_WARN() {
293 organizationFlags.setEnabled(true);
294 UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
295 UserIdentity newUser = UserIdentity.builder()
296 .setProviderLogin("johndoo")
297 .setLogin("new_login")
298 .setName(existingUser.getName())
299 .setEmail(existingUser.getEmail())
302 expectedException.expect(EmailAlreadyExistsRedirectionException.class);
304 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
305 .setUserIdentity(newUser)
306 .setProvider(IDENTITY_PROVIDER)
307 .setSource(Source.local(BASIC))
308 .setExistingEmailStrategy(ExistingEmailStrategy.WARN)
309 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
314 public void throw_AuthenticationException_when_authenticating_new_user_when_email_already_exists_and_strategy_is_FORBID() {
315 db.users().insertUser(u -> u.setEmail("john@email.com"));
316 Source source = Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName());
318 expectedException.expect(authenticationException().from(source)
319 .withLogin(USER_IDENTITY.getProviderLogin())
320 .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
321 "This means that you probably already registered with another account."));
322 expectedException.expectMessage("Email 'john@email.com' is already used");
324 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
325 .setUserIdentity(USER_IDENTITY)
326 .setProvider(IDENTITY_PROVIDER)
328 .setExistingEmailStrategy(FORBID)
329 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
330 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
335 public void throw_AuthenticationException_when_authenticating_new_user_and_email_already_exists_multiple_times() {
336 db.users().insertUser(u -> u.setEmail("john@email.com"));
337 db.users().insertUser(u -> u.setEmail("john@email.com"));
338 Source source = Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName());
340 expectedException.expect(authenticationException().from(source)
341 .withLogin(USER_IDENTITY.getProviderLogin())
342 .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
343 "This means that you probably already registered with another account."));
344 expectedException.expectMessage("Email 'john@email.com' is already used");
346 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
347 .setUserIdentity(USER_IDENTITY)
348 .setProvider(IDENTITY_PROVIDER)
350 .setExistingEmailStrategy(FORBID)
351 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
352 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
357 public void fail_to_authenticate_new_user_when_allow_users_to_signup_is_false() {
358 TestIdentityProvider identityProvider = new TestIdentityProvider()
362 .setAllowsUsersToSignUp(false);
363 Source source = Source.realm(AuthenticationEvent.Method.FORM, identityProvider.getName());
365 expectedException.expect(authenticationException().from(source).withLogin(USER_IDENTITY.getProviderLogin()).andPublicMessage("'github' users are not allowed to sign up"));
366 expectedException.expectMessage("User signup disabled for provider 'github'");
368 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
369 .setUserIdentity(USER_IDENTITY)
370 .setProvider(identityProvider)
372 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
373 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
378 public void authenticate_and_update_existing_user_matching_login() {
379 db.users().insertUser(u -> u
380 .setLogin(USER_LOGIN)
382 .setEmail("Old email")
383 .setExternalId("old id")
384 .setExternalLogin("old identity")
385 .setExternalIdentityProvider("old provide"));
387 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
388 .setUserIdentity(USER_IDENTITY)
389 .setProvider(IDENTITY_PROVIDER)
390 .setSource(Source.local(BASIC))
391 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
392 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
395 assertThat(db.users().selectUserByLogin(USER_LOGIN).get())
396 .extracting(UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider, UserDto::isActive)
397 .contains("John", "john@email.com", "ABCD", "johndoo", "github", true);
401 public void authenticate_and_update_existing_user_matching_external_id() {
402 UserDto user = db.users().insertUser(u -> u
403 .setLogin("Old login")
405 .setEmail("Old email")
406 .setExternalId(USER_IDENTITY.getProviderId())
407 .setExternalLogin("old identity")
408 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
410 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
411 .setUserIdentity(USER_IDENTITY)
412 .setProvider(IDENTITY_PROVIDER)
413 .setSource(Source.local(BASIC))
414 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
415 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
418 assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
419 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
420 .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
422 .contains(USER_LOGIN, "John", "john@email.com", "ABCD", "johndoo", "github", true);
426 public void authenticate_existing_user_and_update_only_login() {
427 UserDto user = db.users().insertUser(u -> u
428 .setLogin("old login")
429 .setName(USER_IDENTITY.getName())
430 .setEmail(USER_IDENTITY.getEmail())
431 .setExternalId(USER_IDENTITY.getProviderId())
432 .setExternalLogin("old identity")
433 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
435 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
436 .setUserIdentity(USER_IDENTITY)
437 .setProvider(IDENTITY_PROVIDER)
438 .setSource(Source.local(BASIC))
439 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
440 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
443 assertThat(db.users().selectUserByLogin("Old login")).isNotPresent();
444 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
445 .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
447 .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
448 IDENTITY_PROVIDER.getKey(),
453 public void authenticate_existing_user_and_update_only_identity_provider_key() {
454 UserDto user = db.users().insertUser(u -> u
455 .setLogin(USER_LOGIN)
456 .setName(USER_IDENTITY.getName())
457 .setEmail(USER_IDENTITY.getEmail())
458 .setExternalId(USER_IDENTITY.getProviderId())
459 .setExternalLogin(USER_IDENTITY.getProviderLogin())
460 .setExternalIdentityProvider("old identity provider"));
462 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
463 .setUserIdentity(USER_IDENTITY)
464 .setProvider(IDENTITY_PROVIDER)
465 .setSource(Source.local(BASIC))
466 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
467 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
470 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
471 .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
473 .containsExactlyInAnyOrder(USER_LOGIN, USER_IDENTITY.getName(), USER_IDENTITY.getEmail(), USER_IDENTITY.getProviderId(), USER_IDENTITY.getProviderLogin(),
474 IDENTITY_PROVIDER.getKey(),
479 public void authenticate_existing_user_matching_login_when_external_id_is_null() {
480 UserDto user = db.users().insertUser(u -> u
481 .setLogin(USER_LOGIN)
483 .setEmail("Old email")
484 .setExternalId("Old id")
485 .setExternalLogin("old identity")
486 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
488 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
489 .setUserIdentity(UserIdentity.builder()
491 .setProviderLogin("johndoo")
492 .setLogin(USER_LOGIN)
494 .setEmail("john@email.com")
496 .setProvider(IDENTITY_PROVIDER)
497 .setSource(Source.local(BASIC))
498 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
499 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
502 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
503 .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
505 .contains(user.getLogin(), "John", "john@email.com", "johndoo", "johndoo", "github", true);
509 public void authenticate_existing_user_when_login_is_not_provided() {
510 UserDto user = db.users().insertUser(u -> u.setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
512 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
513 .setUserIdentity(UserIdentity.builder()
514 .setProviderId(user.getExternalId())
515 .setProviderLogin(user.getExternalLogin())
517 .setName(user.getName())
518 .setEmail(user.getEmail())
520 .setProvider(IDENTITY_PROVIDER)
521 .setSource(Source.local(BASIC))
522 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
523 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
526 // No new user is created
527 assertThat(db.countRowsOfTable(db.getSession(), "users")).isEqualTo(1);
528 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
529 .extracting(UserDto::getLogin, UserDto::getName, UserDto::getEmail, UserDto::getExternalId, UserDto::getExternalLogin, UserDto::getExternalIdentityProvider,
531 .contains(user.getLogin(), user.getName(), user.getEmail(), user.getExternalId(), user.getExternalLogin(), user.getExternalIdentityProvider(), true);
535 public void authenticate_existing_user_with_login_update_and_strategy_is_ALLOW() {
536 UserDto user = db.users().insertUser(u -> u
537 .setLogin("Old login")
538 .setExternalId(USER_IDENTITY.getProviderId())
539 .setExternalLogin("old identity")
540 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
542 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
543 .setUserIdentity(USER_IDENTITY)
544 .setProvider(IDENTITY_PROVIDER)
545 .setSource(Source.local(BASIC))
546 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
547 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
550 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
551 .extracting(UserDto::getLogin, UserDto::getExternalLogin)
552 .contains(USER_LOGIN, USER_IDENTITY.getProviderLogin());
556 public void authenticate_existing_user_with_login_update_and_personal_org_does_not_exits_and_strategy_is_WARN() {
557 organizationFlags.setEnabled(true);
558 UserDto user = db.users().insertUser(u -> u
559 .setLogin("Old login")
560 .setExternalId(USER_IDENTITY.getProviderId())
561 .setExternalLogin("old identity")
562 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
563 .setOrganizationUuid(null));
565 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
566 .setUserIdentity(USER_IDENTITY)
567 .setProvider(IDENTITY_PROVIDER)
568 .setSource(Source.local(BASIC))
569 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
570 .setUpdateLoginStrategy(UpdateLoginStrategy.WARN)
573 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
574 .extracting(UserDto::getLogin, UserDto::getExternalLogin)
575 .contains(USER_LOGIN, USER_IDENTITY.getProviderLogin());
579 public void throw_UpdateLoginRedirectionException_when_authenticating_with_login_update_and_personal_org_exists_and_strategy_is_WARN() {
580 organizationFlags.setEnabled(true);
581 OrganizationDto organization = db.organizations().insert(o -> o.setKey("Old login"));
582 db.users().insertUser(u -> u
583 .setLogin("Old login")
584 .setExternalId(USER_IDENTITY.getProviderId())
585 .setExternalLogin("old identity")
586 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
587 .setOrganizationUuid(organization.getUuid()));
589 expectedException.expect(UpdateLoginRedirectionException.class);
591 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
592 .setUserIdentity(USER_IDENTITY)
593 .setProvider(IDENTITY_PROVIDER)
594 .setSource(Source.local(BASIC))
595 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
596 .setUpdateLoginStrategy(UpdateLoginStrategy.WARN)
601 public void authenticate_existing_user_and_update_personal_og_key_when_personal_org_exists_and_strategy_is_ALLOW() {
602 organizationFlags.setEnabled(true);
603 OrganizationDto personalOrganization = db.organizations().insert(o -> o.setKey("Old login"));
604 UserDto user = db.users().insertUser(u -> u
605 .setLogin("Old login")
606 .setExternalId(USER_IDENTITY.getProviderId())
607 .setExternalLogin("old identity")
608 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
609 .setOrganizationUuid(personalOrganization.getUuid()));
611 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
612 .setUserIdentity(USER_IDENTITY)
613 .setProvider(IDENTITY_PROVIDER)
614 .setSource(Source.local(BASIC))
615 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
616 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
619 assertThat(db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()))
620 .extracting(UserDto::getLogin, UserDto::getExternalLogin)
621 .contains(USER_LOGIN, USER_IDENTITY.getProviderLogin());
622 OrganizationDto organizationReloaded = db.getDbClient().organizationDao().selectByUuid(db.getSession(), personalOrganization.getUuid()).get();
623 assertThat(organizationReloaded.getKey()).isEqualTo(USER_LOGIN);
627 public void fail_to_authenticate_existing_user_when_personal_org_does_not_exist() {
628 organizationFlags.setEnabled(true);
629 db.users().insertUser(u -> u
630 .setLogin("Old login")
631 .setExternalId(USER_IDENTITY.getProviderId())
632 .setExternalLogin("old identity")
633 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey())
634 .setOrganizationUuid("unknown"));
636 expectedException.expect(IllegalStateException.class);
637 expectedException.expectMessage("Cannot find personal organization uuid 'unknown' for user 'Old login'");
639 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
640 .setUserIdentity(USER_IDENTITY)
641 .setProvider(IDENTITY_PROVIDER)
642 .setSource(Source.local(BASIC))
643 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
644 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
649 public void authenticate_existing_disabled_user() {
650 organizationFlags.setEnabled(true);
651 db.users().insertUser(u -> u
652 .setLogin(USER_LOGIN)
655 .setEmail("Old email")
656 .setExternalId("old id")
657 .setExternalLogin("old identity")
658 .setExternalIdentityProvider("old provide"));
660 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
661 .setUserIdentity(USER_IDENTITY)
662 .setProvider(IDENTITY_PROVIDER)
663 .setSource(Source.local(BASIC))
664 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
665 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
668 UserDto userDto = db.users().selectUserByLogin(USER_LOGIN).get();
669 assertThat(userDto.isActive()).isTrue();
670 assertThat(userDto.getName()).isEqualTo("John");
671 assertThat(userDto.getEmail()).isEqualTo("john@email.com");
672 assertThat(userDto.getExternalId()).isEqualTo("ABCD");
673 assertThat(userDto.getExternalLogin()).isEqualTo("johndoo");
674 assertThat(userDto.getExternalIdentityProvider()).isEqualTo("github");
675 assertThat(userDto.isRoot()).isFalse();
679 public void authenticate_existing_user_when_email_already_exists_and_strategy_is_ALLOW() {
680 organizationFlags.setEnabled(true);
681 UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
682 UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
683 UserIdentity userIdentity = UserIdentity.builder()
684 .setLogin(currentUser.getLogin())
685 .setProviderLogin("johndoo")
687 .setEmail("john@email.com")
690 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
691 .setUserIdentity(userIdentity)
692 .setProvider(IDENTITY_PROVIDER)
693 .setSource(Source.local(BASIC))
694 .setExistingEmailStrategy(ExistingEmailStrategy.ALLOW)
695 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
698 UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
699 assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
700 UserDto existingUserReloaded = db.users().selectUserByLogin(existingUser.getLogin()).get();
701 assertThat(existingUserReloaded.getEmail()).isNull();
705 public void throw_EmailAlreadyExistException_when_authenticating_existing_user_when_email_already_exists_and_strategy_is_WARN() {
706 organizationFlags.setEnabled(true);
707 UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
708 UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
709 UserIdentity userIdentity = UserIdentity.builder()
710 .setLogin(currentUser.getLogin())
711 .setProviderLogin("johndoo")
713 .setEmail("john@email.com")
716 expectedException.expect(EmailAlreadyExistsRedirectionException.class);
718 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
719 .setUserIdentity(userIdentity)
720 .setProvider(IDENTITY_PROVIDER)
721 .setSource(Source.local(BASIC))
722 .setExistingEmailStrategy(ExistingEmailStrategy.WARN)
723 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
728 public void throw_AuthenticationException_when_authenticating_existing_user_when_email_already_exists_and_strategy_is_FORBID() {
729 organizationFlags.setEnabled(true);
730 UserDto existingUser = db.users().insertUser(u -> u.setEmail("john@email.com"));
731 UserDto currentUser = db.users().insertUser(u -> u.setEmail(null));
732 UserIdentity userIdentity = UserIdentity.builder()
733 .setLogin(currentUser.getLogin())
734 .setProviderLogin("johndoo")
736 .setEmail("john@email.com")
739 expectedException.expect(authenticationException().from(Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName()))
740 .withLogin(userIdentity.getProviderLogin())
741 .andPublicMessage("You can't sign up because email 'john@email.com' is already used by an existing user. " +
742 "This means that you probably already registered with another account."));
743 expectedException.expectMessage("Email 'john@email.com' is already used");
745 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
746 .setUserIdentity(userIdentity)
747 .setProvider(IDENTITY_PROVIDER)
748 .setSource(Source.realm(AuthenticationEvent.Method.FORM, IDENTITY_PROVIDER.getName()))
749 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
750 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
755 public void does_not_fail_to_authenticate_user_when_email_has_not_changed_and_strategy_is_FORBID() {
756 organizationFlags.setEnabled(true);
757 UserDto currentUser = db.users().insertUser(u -> u.setEmail("john@email.com")
758 .setExternalIdentityProvider(IDENTITY_PROVIDER.getKey()));
759 UserIdentity userIdentity = UserIdentity.builder()
760 .setLogin(currentUser.getLogin())
761 .setProviderId(currentUser.getExternalId())
762 .setProviderLogin(currentUser.getExternalLogin())
764 .setEmail("john@email.com")
767 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
768 .setUserIdentity(userIdentity)
769 .setProvider(IDENTITY_PROVIDER)
770 .setSource(Source.local(BASIC))
771 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
772 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
775 UserDto currentUserReloaded = db.users().selectUserByLogin(currentUser.getLogin()).get();
776 assertThat(currentUserReloaded.getEmail()).isEqualTo("john@email.com");
780 public void authenticate_existing_user_and_add_new_groups() {
781 organizationFlags.setEnabled(true);
782 UserDto user = db.users().insertUser(newUserDto()
783 .setLogin(USER_LOGIN)
786 GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
787 GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
789 authenticate(USER_LOGIN, "group1", "group2", "group3");
791 checkGroupMembership(user, group1, group2);
795 public void authenticate_existing_user_and_remove_groups() {
796 organizationFlags.setEnabled(true);
797 UserDto user = db.users().insertUser(newUserDto()
798 .setLogin(USER_LOGIN)
801 GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
802 GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
803 db.users().insertMember(group1, user);
804 db.users().insertMember(group2, user);
806 authenticate(USER_LOGIN, "group1");
808 checkGroupMembership(user, group1);
812 public void authenticate_existing_user_and_remove_all_groups_expect_default_when_organizations_are_disabled() {
813 organizationFlags.setEnabled(false);
814 UserDto user = db.users().insertUser();
815 GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
816 GroupDto group2 = db.users().insertGroup(db.getDefaultOrganization(), "group2");
817 GroupDto defaultGroup = insertDefaultGroup();
818 db.users().insertMember(group1, user);
819 db.users().insertMember(group2, user);
820 db.users().insertMember(defaultGroup, user);
822 authenticate(user.getLogin());
824 checkGroupMembership(user, defaultGroup);
828 public void does_not_force_default_group_when_authenticating_existing_user_when_organizations_are_enabled() {
829 organizationFlags.setEnabled(true);
830 UserDto user = db.users().insertUser();
831 GroupDto group1 = db.users().insertGroup(db.getDefaultOrganization(), "group1");
832 GroupDto defaultGroup = insertDefaultGroup();
833 db.users().insertMember(group1, user);
834 db.users().insertMember(defaultGroup, user);
836 authenticate(user.getLogin(), "group1");
838 checkGroupMembership(user, group1);
842 public void ignore_groups_on_non_default_organizations() {
843 organizationFlags.setEnabled(true);
844 OrganizationDto org = db.organizations().insert();
845 UserDto user = db.users().insertUser(newUserDto()
846 .setLogin(USER_LOGIN)
849 String groupName = "a-group";
850 GroupDto groupInDefaultOrg = db.users().insertGroup(db.getDefaultOrganization(), groupName);
851 GroupDto groupInOrg = db.users().insertGroup(org, groupName);
853 // adding a group with the same name than in non-default organization
854 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
855 .setUserIdentity(UserIdentity.builder()
856 .setProviderLogin("johndoo")
857 .setLogin(user.getLogin())
858 .setName(user.getName())
859 .setGroups(newHashSet(groupName))
861 .setProvider(IDENTITY_PROVIDER)
862 .setSource(Source.local(BASIC))
863 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
864 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
867 checkGroupMembership(user, groupInDefaultOrg);
870 private void authenticate(String login, String... groups) {
871 underTest.authenticate(UserIdentityAuthenticatorParameters.builder()
872 .setUserIdentity(UserIdentity.builder()
873 .setProviderLogin("johndoo")
877 .setGroups(stream(groups).collect(MoreCollectors.toSet()))
879 .setProvider(IDENTITY_PROVIDER)
880 .setSource(Source.local(BASIC))
881 .setExistingEmailStrategy(ExistingEmailStrategy.FORBID)
882 .setUpdateLoginStrategy(UpdateLoginStrategy.ALLOW)
886 private void checkGroupMembership(UserDto user, GroupDto... expectedGroups) {
887 assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(stream(expectedGroups).map(GroupDto::getId).collect(Collectors.toList()).toArray(new Integer[] {}));
890 private GroupDto insertDefaultGroup() {
891 return db.users().insertDefaultGroup(db.getDefaultOrganization(), "sonar-users");