added new type of error - UserPasswordNotValidException to correctly handle it on UI

This commit is contained in:
dashevchenko 2023-12-07 17:35:49 +02:00
parent bdf8c6d3db
commit 8b6b1dd7d7
5 changed files with 71 additions and 6 deletions

View File

@ -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);
}
}

View File

@ -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.AuthMethodNotSupportedException;
import org.thingsboard.server.service.security.exception.JwtExpiredTokenException; import org.thingsboard.server.service.security.exception.JwtExpiredTokenException;
import org.thingsboard.server.service.security.exception.UserPasswordExpiredException; import org.thingsboard.server.service.security.exception.UserPasswordExpiredException;
import org.thingsboard.server.service.security.exception.UserPasswordNotValidException;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -178,8 +179,7 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand
private void handleAuthenticationException(AuthenticationException authenticationException, HttpServletResponse response) throws IOException { private void handleAuthenticationException(AuthenticationException authenticationException, HttpServletResponse response) throws IOException {
response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.setStatus(HttpStatus.UNAUTHORIZED.value());
if (authenticationException instanceof BadCredentialsException || authenticationException instanceof UsernameNotFoundException) { 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("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED));
JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of(message, ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED));
} else if (authenticationException instanceof DisabledException) { } else if (authenticationException instanceof DisabledException) {
JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED));
} else if (authenticationException instanceof LockedException) { } else if (authenticationException instanceof LockedException) {
@ -192,6 +192,9 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand
UserPasswordExpiredException expiredException = (UserPasswordExpiredException) authenticationException; UserPasswordExpiredException expiredException = (UserPasswordExpiredException) authenticationException;
String resetToken = expiredException.getResetToken(); String resetToken = expiredException.getResetToken();
JacksonUtil.writeValue(response.getWriter(), ThingsboardCredentialsExpiredResponse.of(expiredException.getMessage(), resetToken)); 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 { } else {
JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)); JacksonUtil.writeValue(response.getWriter(), ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED));
} }

View File

@ -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);
}
}

View File

@ -57,6 +57,7 @@ import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.dao.user.UserServiceImpl; import org.thingsboard.server.dao.user.UserServiceImpl;
import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails;
import org.thingsboard.server.service.security.exception.UserPasswordExpiredException; 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.service.security.model.SecurityUser;
import org.thingsboard.server.utils.MiscUtils; import org.thingsboard.server.utils.MiscUtils;
import ua_parser.Client; import ua_parser.Client;
@ -135,11 +136,12 @@ public class DefaultSystemSecurityService implements SystemSecurityService {
SecuritySettings securitySettings = self.getSecuritySettings(tenantId); SecuritySettings securitySettings = self.getSecuritySettings(tenantId);
UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy();
if (Boolean.TRUE.equals(passwordPolicy.getForceUserToResetPasswordIfNotValid())) { if (!tenantId.isSysTenantId() && Boolean.TRUE.equals(passwordPolicy.getForceUserToResetPasswordIfNotValid())) {
try { try {
validatePasswordByPolicy(password, passwordPolicy); validatePasswordByPolicy(password, passwordPolicy);
} catch (DataValidationException e) { } 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())) { 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 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()) { if (!userCredentials.isEnabled()) {

View File

@ -29,7 +29,8 @@ public enum ThingsboardErrorCode {
ITEM_NOT_FOUND(32), ITEM_NOT_FOUND(32),
TOO_MANY_REQUESTS(33), TOO_MANY_REQUESTS(33),
TOO_MANY_UPDATES(34), TOO_MANY_UPDATES(34),
SUBSCRIPTION_VIOLATION(40); SUBSCRIPTION_VIOLATION(40),
PASSWORD_VIOLATION(45);
private int errorCode; private int errorCode;