diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardCredentialsViolationResponse.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardCredentialsViolationResponse.java new file mode 100644 index 0000000000..421ca04a34 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardCredentialsViolationResponse.java @@ -0,0 +1,33 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.exception; + +import io.swagger.annotations.ApiModel; +import org.springframework.http.HttpStatus; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; + +@ApiModel +public class ThingsboardCredentialsViolationResponse extends ThingsboardErrorResponse { + + protected ThingsboardCredentialsViolationResponse(String message) { + super(message, ThingsboardErrorCode.PASSWORD_VIOLATION, HttpStatus.UNAUTHORIZED); + } + + public static ThingsboardCredentialsViolationResponse of(final String message) { + return new ThingsboardCredentialsViolationResponse(message); + } + +} diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index e05fbe9e43..fbb2f1d8e2 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -41,6 +41,7 @@ import org.thingsboard.server.common.msg.tools.TbRateLimitsException; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; import org.thingsboard.server.service.security.exception.JwtExpiredTokenException; import org.thingsboard.server.service.security.exception.UserPasswordExpiredException; +import org.thingsboard.server.service.security.exception.UserPasswordNotValidException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -178,8 +179,7 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand private void handleAuthenticationException(AuthenticationException authenticationException, HttpServletResponse response) throws IOException { response.setStatus(HttpStatus.UNAUTHORIZED.value()); if (authenticationException instanceof BadCredentialsException || authenticationException instanceof UsernameNotFoundException) { - String message = (authenticationException.getMessage() == null || authenticationException.getMessage().isEmpty()) ? "Invalid username or password" : authenticationException.getMessage(); - JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of(message, ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); + JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } else if (authenticationException instanceof DisabledException) { JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } else if (authenticationException instanceof LockedException) { @@ -192,6 +192,9 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand UserPasswordExpiredException expiredException = (UserPasswordExpiredException) authenticationException; String resetToken = expiredException.getResetToken(); JacksonUtil.writeValue(response.getWriter(), ThingsboardCredentialsExpiredResponse.of(expiredException.getMessage(), resetToken)); + } else if (authenticationException instanceof UserPasswordNotValidException) { + UserPasswordNotValidException expiredException = (UserPasswordNotValidException) authenticationException; + JacksonUtil.writeValue(response.getWriter(), ThingsboardCredentialsViolationResponse.of(expiredException.getMessage())); } else { JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); } 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 new file mode 100644 index 0000000000..7cd01be7d5 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/security/exception/UserPasswordNotValidException.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.security.exception; + +import org.springframework.security.core.AuthenticationException; + +public class UserPasswordNotValidException extends AuthenticationException { + + 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 3e2f6e9018..5dacefc924 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 @@ -57,6 +57,7 @@ import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.user.UserServiceImpl; import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; import org.thingsboard.server.service.security.exception.UserPasswordExpiredException; +import org.thingsboard.server.service.security.exception.UserPasswordNotValidException; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.utils.MiscUtils; import ua_parser.Client; @@ -135,11 +136,12 @@ public class DefaultSystemSecurityService implements SystemSecurityService { SecuritySettings securitySettings = self.getSecuritySettings(tenantId); UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); - if (Boolean.TRUE.equals(passwordPolicy.getForceUserToResetPasswordIfNotValid())) { + if (!tenantId.isSysTenantId() && Boolean.TRUE.equals(passwordPolicy.getForceUserToResetPasswordIfNotValid())) { try { validatePasswordByPolicy(password, passwordPolicy); } catch (DataValidationException e) { - throw new BadCredentialsException("The entered password violates our policies. If this is your real password, please reset it."); + throw new UserPasswordNotValidException("The entered password violates our policies. If this is your real password, please reset it."); + } } if (!encoder.matches(password, userCredentials.getPassword())) { @@ -150,7 +152,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { throw new LockedException("Authentication Failed. Username was locked due to security policy."); } } - throw new BadCredentialsException("Invalid username or Password."); + throw new BadCredentialsException("Authentication Failed. Username or Password not valid."); } if (!userCredentials.isEnabled()) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java index 00ffd655dc..1ab0e3e634 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/exception/ThingsboardErrorCode.java @@ -29,7 +29,8 @@ public enum ThingsboardErrorCode { ITEM_NOT_FOUND(32), TOO_MANY_REQUESTS(33), TOO_MANY_UPDATES(34), - SUBSCRIPTION_VIOLATION(40); + SUBSCRIPTION_VIOLATION(40), + PASSWORD_VIOLATION(45); private int errorCode;