diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index 4019efe8ee..5e62bff43f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -170,7 +170,7 @@ public class AdminController extends BaseController { @ResponseBody public SecuritySettings getSecuritySettings() throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); - return checkNotNull(systemSecurityService.getSecuritySettings(TenantId.SYS_TENANT_ID)); + return checkNotNull(systemSecurityService.getSecuritySettings()); } @ApiOperation(value = "Update Security Settings (saveSecuritySettings)", @@ -182,7 +182,7 @@ public class AdminController extends BaseController { @ApiParam(value = "A JSON value representing the Security Settings.") @RequestBody SecuritySettings securitySettings) throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); - securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(TenantId.SYS_TENANT_ID, securitySettings)); + securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(securitySettings)); return securitySettings; } diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index ac024093c6..efb05cfdc3 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -115,7 +115,7 @@ public class AuthController extends BaseController { if (!passwordEncoder.matches(currentPassword, userCredentials.getPassword())) { throw new ThingsboardException("Current password doesn't match!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); } - systemSecurityService.validatePassword(securityUser.getTenantId(), newPassword, userCredentials); + systemSecurityService.validatePassword(newPassword, userCredentials); if (passwordEncoder.matches(newPassword, userCredentials.getPassword())) { throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); } @@ -135,7 +135,7 @@ public class AuthController extends BaseController { @ResponseBody public UserPasswordPolicy getUserPasswordPolicy() throws ThingsboardException { SecuritySettings securitySettings = - checkNotNull(systemSecurityService.getSecuritySettings(TenantId.SYS_TENANT_ID)); + checkNotNull(systemSecurityService.getSecuritySettings()); return securitySettings.getPasswordPolicy(); } @@ -237,7 +237,7 @@ public class AuthController extends BaseController { HttpServletRequest request) throws ThingsboardException { String activateToken = activateRequest.getActivateToken(); String password = activateRequest.getPassword(); - systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, null); + systemSecurityService.validatePassword(password, null); String encodedPassword = passwordEncoder.encode(password); UserCredentials credentials = userService.activateUserCredentials(TenantId.SYS_TENANT_ID, activateToken, encodedPassword); User user = userService.findUserById(TenantId.SYS_TENANT_ID, credentials.getUserId()); @@ -274,7 +274,7 @@ public class AuthController extends BaseController { String password = resetPasswordRequest.getPassword(); UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); if (userCredentials != null) { - systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, userCredentials); + systemSecurityService.validatePassword(password, userCredentials); if (passwordEncoder.matches(password, userCredentials.getPassword())) { throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java index 7d612fef25..1b28457792 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java @@ -36,11 +36,15 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; +import org.thingsboard.server.common.data.security.model.SecuritySettings; +import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.dao.customer.CustomerService; +import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.MfaAuthenticationToken; import org.thingsboard.server.service.security.auth.mfa.TwoFactorAuthService; +import org.thingsboard.server.service.security.exception.UserPasswordNotValidException; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.security.system.SystemSecurityService; @@ -83,6 +87,17 @@ public class RestAuthenticationProvider implements AuthenticationProvider { if (userPrincipal.getType() == UserPrincipal.Type.USER_NAME) { String username = userPrincipal.getValue(); String password = (String) authentication.getCredentials(); + + SecuritySettings securitySettings = systemSecurityService.getSecuritySettings(); + UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); + if (Boolean.TRUE.equals(passwordPolicy.getForceUserToResetPasswordIfNotValid())) { + try { + systemSecurityService.validatePasswordByPolicy(password, passwordPolicy); + } catch (DataValidationException e) { + throw new UserPasswordNotValidException("The entered password violates our policies. If this is your real password, please reset it."); + } + } + securityUser = authenticateByUsernameAndPassword(authentication, userPrincipal, username, password); if (twoFactorAuthService.isTwoFaEnabled(securityUser.getTenantId(), securityUser.getId())) { return new MfaAuthenticationToken(securityUser); diff --git a/application/src/main/java/org/thingsboard/server/service/security/exception/UserPasswordNotValidException.java b/application/src/main/java/org/thingsboard/server/service/security/exception/UserPasswordNotValidException.java index 7cd01be7d5..2c1488bcbf 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/exception/UserPasswordNotValidException.java +++ b/application/src/main/java/org/thingsboard/server/service/security/exception/UserPasswordNotValidException.java @@ -15,9 +15,9 @@ */ package org.thingsboard.server.service.security.exception; -import org.springframework.security.core.AuthenticationException; +import org.springframework.security.authentication.AccountStatusException; -public class UserPasswordNotValidException extends AuthenticationException { +public class UserPasswordNotValidException extends AccountStatusException { public UserPasswordNotValidException(String msg) { super(msg); diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java index 5dacefc924..36e580c087 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java @@ -95,9 +95,9 @@ public class DefaultSystemSecurityService implements SystemSecurityService { @Cacheable(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") @Override - public SecuritySettings getSecuritySettings(TenantId tenantId) { + public SecuritySettings getSecuritySettings() { SecuritySettings securitySettings = null; - AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, "securitySettings"); + AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); if (adminSettings != null) { try { securitySettings = JacksonUtil.convertValue(adminSettings.getJsonValue(), SecuritySettings.class); @@ -115,15 +115,15 @@ public class DefaultSystemSecurityService implements SystemSecurityService { @CacheEvict(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") @Override - public SecuritySettings saveSecuritySettings(TenantId tenantId, SecuritySettings securitySettings) { - AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, "securitySettings"); + public SecuritySettings saveSecuritySettings(SecuritySettings securitySettings) { + AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); if (adminSettings == null) { adminSettings = new AdminSettings(); - adminSettings.setTenantId(tenantId); + adminSettings.setTenantId(TenantId.SYS_TENANT_ID); adminSettings.setKey("securitySettings"); } adminSettings.setJsonValue(JacksonUtil.valueToTree(securitySettings)); - AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(tenantId, adminSettings); + AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings); try { return JacksonUtil.convertValue(savedAdminSettings.getJsonValue(), SecuritySettings.class); } catch (Exception e) { @@ -133,19 +133,9 @@ public class DefaultSystemSecurityService implements SystemSecurityService { @Override public void validateUserCredentials(TenantId tenantId, UserCredentials userCredentials, String username, String password) throws AuthenticationException { - SecuritySettings securitySettings = self.getSecuritySettings(tenantId); - UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); - - if (!tenantId.isSysTenantId() && Boolean.TRUE.equals(passwordPolicy.getForceUserToResetPasswordIfNotValid())) { - try { - validatePasswordByPolicy(password, passwordPolicy); - } catch (DataValidationException e) { - throw new UserPasswordNotValidException("The entered password violates our policies. If this is your real password, please reset it."); - - } - } if (!encoder.matches(password, userCredentials.getPassword())) { int failedLoginAttempts = userService.increaseFailedLoginAttempts(tenantId, userCredentials.getUserId()); + SecuritySettings securitySettings = self.getSecuritySettings(); if (securitySettings.getMaxFailedLoginAttempts() != null && securitySettings.getMaxFailedLoginAttempts() > 0) { if (failedLoginAttempts > securitySettings.getMaxFailedLoginAttempts() && userCredentials.isEnabled()) { lockAccount(userCredentials.getUserId(), username, securitySettings.getUserLockoutNotificationEmail(), securitySettings.getMaxFailedLoginAttempts()); @@ -161,6 +151,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { userService.resetFailedLoginAttempts(tenantId, userCredentials.getUserId()); + SecuritySettings securitySettings = self.getSecuritySettings(); if (isPositiveInteger(securitySettings.getPasswordPolicy().getPasswordExpirationPeriodDays())) { if ((userCredentials.getCreatedTime() + TimeUnit.DAYS.toMillis(securitySettings.getPasswordPolicy().getPasswordExpirationPeriodDays())) @@ -188,7 +179,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { if (maxVerificationFailures != null && maxVerificationFailures > 0 && failedVerificationAttempts >= maxVerificationFailures) { userService.setUserCredentialsEnabled(TenantId.SYS_TENANT_ID, userId, false); - SecuritySettings securitySettings = self.getSecuritySettings(tenantId); + SecuritySettings securitySettings = self.getSecuritySettings(); lockAccount(userId, securityUser.getEmail(), securitySettings.getUserLockoutNotificationEmail(), maxVerificationFailures); throw new LockedException("User account was locked due to exceeded 2FA verification attempts"); } @@ -206,8 +197,8 @@ public class DefaultSystemSecurityService implements SystemSecurityService { } @Override - public void validatePassword(TenantId tenantId, String password, UserCredentials userCredentials) throws DataValidationException { - SecuritySettings securitySettings = self.getSecuritySettings(tenantId); + public void validatePassword(String password, UserCredentials userCredentials) throws DataValidationException { + SecuritySettings securitySettings = self.getSecuritySettings(); UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); validatePasswordByPolicy(password, passwordPolicy); @@ -227,7 +218,8 @@ public class DefaultSystemSecurityService implements SystemSecurityService { } } - private void validatePasswordByPolicy(String password, UserPasswordPolicy passwordPolicy) { + @Override + public void validatePasswordByPolicy(String password, UserPasswordPolicy passwordPolicy) { List passwordRules = new ArrayList<>(); Integer maximumLength = passwordPolicy.getMaximumLength(); diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java index 64550c438e..103a874bd7 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.model.SecuritySettings; +import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettings; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.service.security.model.SecurityUser; @@ -30,15 +31,17 @@ import javax.servlet.http.HttpServletRequest; public interface SystemSecurityService { - SecuritySettings getSecuritySettings(TenantId tenantId); + SecuritySettings getSecuritySettings(); - SecuritySettings saveSecuritySettings(TenantId tenantId, SecuritySettings securitySettings); + SecuritySettings saveSecuritySettings(SecuritySettings securitySettings); + + void validatePasswordByPolicy(String password, UserPasswordPolicy passwordPolicy); void validateUserCredentials(TenantId tenantId, UserCredentials userCredentials, String username, String password) throws AuthenticationException; void validateTwoFaVerification(SecurityUser securityUser, boolean verificationSuccess, PlatformTwoFaSettings twoFaSettings); - void validatePassword(TenantId tenantId, String password, UserCredentials userCredentials) throws DataValidationException; + void validatePassword(String password, UserCredentials userCredentials) throws DataValidationException; String getBaseUrl(TenantId tenantId, CustomerId customerId, HttpServletRequest httpServletRequest);