@Override public void storeHashPassword(UserDto user, String password) { requireNonNull(password, "Password cannot be null"); byte[] saltRandom = new byte[20]; SECURE_RANDOM.nextBytes(saltRandom); String salt = DigestUtils.sha1Hex(saltRandom); user.setHashMethod(HashMethod.SHA1.name()) .setCryptedPassword(hash(salt, password)) .setSalt(salt); }
@Override public void storeHashPassword(UserDto user, String password) { requireNonNull(password, "Password cannot be null"); user.setHashMethod(HashMethod.BCRYPT.name()) .setCryptedPassword(BCrypt.hashpw(password, BCrypt.gensalt(12))) .setSalt(null); } }
@Test public void update_only_scm_accounts() { UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr") .setScmAccounts(asList("ma", "marius33")) .setSalt("salt") .setCryptedPassword("crypted password")); createDefaultGroup(); underTest.updateAndCommit(session, user, new UpdateUser() .setScmAccounts(asList("ma2")), u -> { }); UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getScmAccountsAsList()).containsOnly("ma2"); // Following fields has not changed assertThat(dto.getName()).isEqualTo("Marius"); assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr"); assertThat(dto.getSalt()).isEqualTo("salt"); assertThat(dto.getCryptedPassword()).isEqualTo("crypted password"); }
@Test public void update_only_user_email() { UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr") .setScmAccounts(asList("ma", "marius33")) .setSalt("salt") .setCryptedPassword("crypted password")); createDefaultGroup(); underTest.updateAndCommit(session, user, new UpdateUser() .setEmail("marius2@mail.com"), u -> { }); UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getEmail()).isEqualTo("marius2@mail.com"); // Following fields has not changed assertThat(dto.getName()).isEqualTo("Marius"); assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33"); assertThat(dto.getSalt()).isEqualTo("salt"); assertThat(dto.getCryptedPassword()).isEqualTo("crypted password"); }
@Test public void update_only_user_name() { UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr") .setScmAccounts(asList("ma", "marius33")) .setSalt("salt") .setCryptedPassword("crypted password")); createDefaultGroup(); underTest.updateAndCommit(session, user, new UpdateUser() .setName("Marius2"), u -> { }); UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getName()).isEqualTo("Marius2"); // Following fields has not changed assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr"); assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33"); assertThat(dto.getSalt()).isEqualTo("salt"); assertThat(dto.getCryptedPassword()).isEqualTo("crypted password"); }
public static UserDto newDisabledUser() { return newUserDto() .setActive(false) // All these fields are reset when disabling a user .setScmAccounts((String) null) .setEmail(null) .setCryptedPassword(null) .setSalt(null); }
private void setExternalIdentity(DbSession dbSession, UserDto dto, @Nullable ExternalIdentity externalIdentity) { if (externalIdentity == null) { dto.setExternalLogin(dto.getLogin()); dto.setExternalIdentityProvider(SQ_AUTHORITY); dto.setExternalId(dto.getLogin()); dto.setLocal(true); } else { dto.setExternalLogin(externalIdentity.getLogin()); dto.setExternalIdentityProvider(externalIdentity.getProvider()); dto.setExternalId(externalIdentity.getId()); dto.setLocal(false); dto.setSalt(null); dto.setCryptedPassword(null); } UserDto existingUser = dbClient.userDao().selectByExternalIdAndIdentityProvider(dbSession, dto.getExternalId(), dto.getExternalIdentityProvider()); checkArgument(existingUser == null || Objects.equals(dto.getUuid(), existingUser.getUuid()), "A user with provider id '%s' and identity provider '%s' already exists", dto.getExternalId(), dto.getExternalIdentityProvider()); }
@Test public void authenticate_local_user() { insertUser(newUserDto() .setLogin(LOGIN) .setCryptedPassword(ENCRYPTED_PASSWORD) .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name()) .setSalt(SALT) .setLocal(true)); UserDto userDto = executeAuthenticate(BASIC); assertThat(userDto.getLogin()).isEqualTo(LOGIN); verify(authenticationEvent).loginSuccess(request, LOGIN, Source.local(BASIC)); }
@Test public void update_only_user_password() { UserDto user = db.users().insertUser(newLocalUser(DEFAULT_LOGIN, "Marius", "marius@lesbronzes.fr") .setScmAccounts(asList("ma", "marius33")) .setSalt("salt") .setCryptedPassword("crypted password")); createDefaultGroup(); underTest.updateAndCommit(session, user, new UpdateUser() .setPassword("password2"), u -> { }); UserDto dto = dbClient.userDao().selectByLogin(session, DEFAULT_LOGIN); assertThat(dto.getSalt()).isNotEqualTo("salt"); assertThat(dto.getCryptedPassword()).isNotEqualTo("crypted password"); // Following fields has not changed assertThat(dto.getName()).isEqualTo("Marius"); assertThat(dto.getScmAccountsAsList()).containsOnly("ma", "marius33"); assertThat(dto.getEmail()).isEqualTo("marius@lesbronzes.fr"); }
@Test public void reactivate_user_not_having_password() { UserDto user = db.users().insertDisabledUser(u -> u.setSalt(null).setCryptedPassword(null)); createDefaultGroup(); UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder() .setLogin(user.getLogin()) .setName(user.getName()) .build(), u -> { }); assertThat(dto.isActive()).isTrue(); assertThat(dto.getName()).isEqualTo(user.getName()); assertThat(dto.getScmAccounts()).isNull(); assertThat(dto.getSalt()).isNull(); assertThat(dto.getCryptedPassword()).isNull(); assertThat(dto.getCreatedAt()).isEqualTo(user.getCreatedAt()); assertThat(dto.getUpdatedAt()).isGreaterThan(user.getCreatedAt()); }
@Test public void authentication_with_sha1_with_correct_password_should_work() { String password = randomAlphanumeric(60); byte[] saltRandom = new byte[20]; RANDOM.nextBytes(saltRandom); String salt = DigestUtils.sha1Hex(saltRandom); UserDto user = newUserDto() .setHashMethod(SHA1.name()) .setCryptedPassword(DigestUtils.sha1Hex("--" + salt + "--" + password + "--")) .setSalt(salt); underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); }
@Test public void authentication_with_sha1_with_empty_password_should_throw_AuthenticationException() { byte[] saltRandom = new byte[20]; RANDOM.nextBytes(saltRandom); String salt = DigestUtils.sha1Hex(saltRandom); UserDto user = newUserDto() .setCryptedPassword(null) .setHashMethod(SHA1.name()) .setSalt(salt); expectedException.expect(AuthenticationException.class); expectedException.expectMessage("null password in DB"); underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC); }
@Test public void authentication_upgrade_hash_function_when_SHA1_was_used() { String password = randomAlphanumeric(60); byte[] saltRandom = new byte[20]; RANDOM.nextBytes(saltRandom); String salt = DigestUtils.sha1Hex(saltRandom); UserDto user = newUserDto() .setLogin("myself") .setHashMethod(SHA1.name()) .setCryptedPassword(DigestUtils.sha1Hex("--" + salt + "--" + password + "--")) .setSalt(salt); db.users().insertUser(user); underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); Optional<UserDto> myself = db.users().selectUserByLogin("myself"); assertThat(myself).isPresent(); assertThat(myself.get().getHashMethod()).isEqualTo(BCRYPT.name()); assertThat(myself.get().getSalt()).isNull(); // authentication must work with upgraded hash method underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); } }
@Test public void update_login_from_external_account() { userSession.logIn().setSystemAdministrator(); UserDto user = db.users().insertUser(u -> u .setLogin("old_login") .setLocal(false) .setExternalIdentityProvider("github") .setExternalLogin("github_login") .setExternalId("github_id") .setCryptedPassword(null) .setSalt(null)); ws.newRequest() .setParam("login", user.getLogin()) .setParam("newLogin", "new_login") .execute(); UserDto userReloaded = db.getDbClient().userDao().selectByUuid(db.getSession(), user.getUuid()); assertThat(userReloaded.getLogin()).isEqualTo("new_login"); assertThat(userReloaded.getExternalLogin()).isEqualTo("github_login"); assertThat(userReloaded.getExternalId()).isEqualTo("github_id"); assertThat(userReloaded.isLocal()).isFalse(); assertThat(userReloaded.getCryptedPassword()).isNull(); assertThat(userReloaded.getSalt()).isNull(); }
@Test public void authentication_with_sha1_with_incorrect_password_should_throw_AuthenticationException() { String password = randomAlphanumeric(60); byte[] saltRandom = new byte[20]; RANDOM.nextBytes(saltRandom); String salt = DigestUtils.sha1Hex(saltRandom); UserDto user = newUserDto() .setHashMethod(SHA1.name()) .setCryptedPassword(DigestUtils.sha1Hex("--" + salt + "--" + password + "--")) .setSalt(salt); expectedException.expect(AuthenticationException.class); expectedException.expectMessage("wrong password"); underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC); }
@Test public void authentication_with_sha1_with_empty_salt_should_throw_AuthenticationException() { String password = randomAlphanumeric(60); UserDto user = newUserDto() .setHashMethod(SHA1.name()) .setCryptedPassword(DigestUtils.sha1Hex("--0242b0b4c0a93ddfe09dd886de50bc25ba000b51--" + password + "--")) .setSalt(null); expectedException.expect(AuthenticationException.class); expectedException.expectMessage("null salt"); underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC); }
@Test public void fail_to_authenticate_local_user_that_have_no_salt() { insertUser(newUserDto() .setLogin(LOGIN) .setCryptedPassword(ENCRYPTED_PASSWORD) .setSalt(null) .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name()) .setLocal(true)); expectedException.expect(authenticationException().from(Source.local(BASIC_TOKEN)).withLogin(LOGIN).andNoPublicMessage()); expectedException.expectMessage("null salt"); try { executeAuthenticate(BASIC_TOKEN); } finally { verifyZeroInteractions(authenticationEvent); } }
@Test public void fail_to_authenticate_local_user_when_password_is_wrong() { insertUser(newUserDto() .setLogin(LOGIN) .setCryptedPassword("Wrong password") .setSalt("Wrong salt") .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name()) .setLocal(true)); expectedException.expect(authenticationException().from(Source.local(BASIC)).withLogin(LOGIN).andNoPublicMessage()); expectedException.expectMessage("wrong password"); try { executeAuthenticate(BASIC); } finally { verifyZeroInteractions(authenticationEvent); } }
@Test public void fail_to_authenticate_local_user_that_have_no_password() { insertUser(newUserDto() .setLogin(LOGIN) .setCryptedPassword(null) .setSalt(SALT) .setHashMethod(CredentialsLocalAuthentication.HashMethod.SHA1.name()) .setLocal(true)); expectedException.expect(authenticationException().from(Source.local(BASIC)).withLogin(LOGIN).andNoPublicMessage()); expectedException.expectMessage("null password in DB"); try { executeAuthenticate(BASIC); } finally { verifyZeroInteractions(authenticationEvent); } }
public static UserDto newUserDto() { return new UserDto() .setId(nextInt()) .setUuid(randomAlphanumeric(40)) .setActive(true) .setLocal(nextBoolean()) .setLogin(randomAlphanumeric(30)) .setName(randomAlphanumeric(30)) .setEmail(randomAlphanumeric(30)) .setOnboarded(nextBoolean()) .setScmAccounts(singletonList(randomAlphanumeric(40))) .setExternalId(randomAlphanumeric(40)) .setExternalLogin(randomAlphanumeric(40)) .setExternalIdentityProvider(randomAlphanumeric(40)) .setSalt(randomAlphanumeric(40)) .setCryptedPassword(randomAlphanumeric(40)) .setCreatedAt(nextLong()) .setUpdatedAt(nextLong()); }