Status '410 Gone' when token is expired

This commit is contained in:
ViacheslavKlimov 2024-07-25 11:49:10 +03:00
parent a246032e54
commit 478d20aec7
5 changed files with 47 additions and 44 deletions

View File

@ -21,7 +21,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@ -132,28 +131,28 @@ public class AuthController extends BaseController {
@ApiOperation(value = "Check Activate User Token (checkActivateToken)", @ApiOperation(value = "Check Activate User Token (checkActivateToken)",
notes = "Checks the activation token and forwards user to 'Create Password' page. " + notes = "Checks the activation token and forwards user to 'Create Password' page. " +
"If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Create Password' page and same 'activateToken' specified in the URL parameters. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Create Password' page and same 'activateToken' specified in the URL parameters. " +
"If token is not valid, returns '409 Conflict'.") "If token is not valid, returns '409 Conflict'. " +
"If token is expired, returns '410 Gone'.")
@GetMapping(value = "/noauth/activate", params = {"activateToken"}) @GetMapping(value = "/noauth/activate", params = {"activateToken"})
public ResponseEntity<String> checkActivateToken( public ResponseEntity<?> checkActivateToken(
@Parameter(description = "The activate token string.") @Parameter(description = "The activate token string.")
@RequestParam(value = "activateToken") String activateToken) { @RequestParam(value = "activateToken") String activateToken) {
HttpHeaders headers = new HttpHeaders();
HttpStatus responseStatus;
UserCredentials userCredentials = userService.findUserCredentialsByActivateToken(TenantId.SYS_TENANT_ID, activateToken); UserCredentials userCredentials = userService.findUserCredentialsByActivateToken(TenantId.SYS_TENANT_ID, activateToken);
if (userCredentials != null && !userCredentials.isActivationTokenExpired()) { if (userCredentials == null) {
String createURI = "/login/createPassword"; return response(HttpStatus.CONFLICT);
try { } else if (userCredentials.isActivationTokenExpired()) {
URI location = new URI(createURI + "?activateToken=" + activateToken); return response(HttpStatus.GONE);
headers.setLocation(location); }
responseStatus = HttpStatus.SEE_OTHER;
} catch (URISyntaxException e) { String createURI = "/login/createPassword";
log.error("Unable to create URI with address [{}]", createURI); try {
responseStatus = HttpStatus.BAD_REQUEST; URI location = new URI(createURI + "?activateToken=" + activateToken);
} return ResponseEntity.status(HttpStatus.SEE_OTHER)
} else { .location(location).build();
responseStatus = HttpStatus.CONFLICT; } catch (URISyntaxException e) {
log.error("Unable to create URI with address [{}]", createURI);
return response(HttpStatus.BAD_REQUEST);
} }
return new ResponseEntity<>(headers, responseStatus);
} }
@ApiOperation(value = "Request reset password email (requestResetPasswordByEmail)", @ApiOperation(value = "Request reset password email (requestResetPasswordByEmail)",
@ -181,32 +180,31 @@ public class AuthController extends BaseController {
@ApiOperation(value = "Check password reset token (checkResetToken)", @ApiOperation(value = "Check password reset token (checkResetToken)",
notes = "Checks the password reset token and forwards user to 'Reset Password' page. " + notes = "Checks the password reset token and forwards user to 'Reset Password' page. " +
"If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Reset Password' page and same 'resetToken' specified in the URL parameters. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Reset Password' page and same 'resetToken' specified in the URL parameters. " +
"If token is not valid, returns '409 Conflict'.") "If token is not valid, returns '409 Conflict'. " +
"If token is expired, returns '410 Gone'.")
@GetMapping(value = "/noauth/resetPassword", params = {"resetToken"}) @GetMapping(value = "/noauth/resetPassword", params = {"resetToken"})
public ResponseEntity<String> checkResetToken( public ResponseEntity<?> checkResetToken(
@Parameter(description = "The reset token string.") @Parameter(description = "The reset token string.")
@RequestParam(value = "resetToken") String resetToken) { @RequestParam(value = "resetToken") String resetToken) {
HttpHeaders headers = new HttpHeaders();
HttpStatus responseStatus;
String resetURI = "/login/resetPassword";
UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken);
if (userCredentials == null) {
if (userCredentials != null && !userCredentials.isResetTokenExpired()) { return response(HttpStatus.CONFLICT);
if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) { } else if (userCredentials.isResetTokenExpired()) {
return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).build(); return response(HttpStatus.GONE);
} }
try { if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) {
URI location = new URI(resetURI + "?resetToken=" + resetToken); return response(HttpStatus.TOO_MANY_REQUESTS);
headers.setLocation(location); }
responseStatus = HttpStatus.SEE_OTHER;
} catch (URISyntaxException e) { String resetURI = "/login/resetPassword";
log.error("Unable to create URI with address [{}]", resetURI); try {
responseStatus = HttpStatus.BAD_REQUEST; URI location = new URI(resetURI + "?resetToken=" + resetToken);
} return ResponseEntity.status(HttpStatus.SEE_OTHER)
} else { .location(location).build();
responseStatus = HttpStatus.CONFLICT; } catch (URISyntaxException e) {
log.error("Unable to create URI with address [{}]", resetURI);
return response(HttpStatus.BAD_REQUEST);
} }
return new ResponseEntity<>(headers, responseStatus);
} }
@ApiOperation(value = "Activate User", @ApiOperation(value = "Activate User",

View File

@ -27,7 +27,9 @@ import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MethodArgumentNotValidException;
@ -867,4 +869,8 @@ public abstract class BaseController {
} }
} }
protected <T> ResponseEntity<T> response(HttpStatus status) {
return ResponseEntity.status(status).build();
}
} }

View File

@ -290,7 +290,7 @@ public class ImageController extends BaseController {
if (StringUtils.isNotEmpty(etag)) { if (StringUtils.isNotEmpty(etag)) {
etag = StringUtils.remove(etag, '\"'); // etag is wrapped in double quotes due to HTTP specification etag = StringUtils.remove(etag, '\"'); // etag is wrapped in double quotes due to HTTP specification
if (etag.equals(tbImageService.getETag(cacheKey))) { if (etag.equals(tbImageService.getETag(cacheKey))) {
return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build(); return response(HttpStatus.NOT_MODIFIED);
} }
} }

View File

@ -183,8 +183,7 @@ public class MobileApplicationController extends BaseController {
.header("Location", appStoreLink) .header("Location", appStoreLink)
.build(); .build();
} else { } else {
return ResponseEntity.status(HttpStatus.NOT_FOUND) return response(HttpStatus.NOT_FOUND);
.build();
} }
} }

View File

@ -193,7 +193,7 @@ public class AuthControllerTest extends AbstractControllerTest {
userCredentialsDao.save(tenantId, userCredentials); userCredentialsDao.save(tenantId, userCredentials);
doGet("/api/noauth/resetPassword?resetToken={resetToken}", this.currentResetPasswordToken) doGet("/api/noauth/resetPassword?resetToken={resetToken}", this.currentResetPasswordToken)
.andExpect(status().isConflict()); .andExpect(status().isGone());
JsonNode resetPasswordRequest = JacksonUtil.newObjectNode() JsonNode resetPasswordRequest = JacksonUtil.newObjectNode()
.put("resetToken", this.currentResetPasswordToken) .put("resetToken", this.currentResetPasswordToken)
.put("password", "wefwefe"); .put("password", "wefwefe");
@ -223,7 +223,7 @@ public class AuthControllerTest extends AbstractControllerTest {
userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1); userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1);
userCredentialsDao.save(tenantId, userCredentials); userCredentialsDao.save(tenantId, userCredentials);
doGet("/api/noauth/activate?activateToken={activateToken}", initialActivationToken) doGet("/api/noauth/activate?activateToken={activateToken}", initialActivationToken)
.andExpect(status().isConflict()); .andExpect(status().isGone());
doPost("/api/noauth/activate", JacksonUtil.newObjectNode() doPost("/api/noauth/activate", JacksonUtil.newObjectNode()
.put("activateToken", initialActivationToken) .put("activateToken", initialActivationToken)
.put("password", "wefewe")).andExpect(status().isBadRequest()) .put("password", "wefewe")).andExpect(status().isBadRequest())