Improve captcha response error handling

This commit is contained in:
Ameya Lokare
2026-02-12 11:57:27 -08:00
parent 8fa1f85924
commit f5a3b93849
2 changed files with 12 additions and 5 deletions

View File

@@ -31,6 +31,8 @@ import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.auth.AuthenticatedDevice;
import org.whispersystems.textsecuregcm.entities.AnswerCaptchaChallengeRequest;
import org.whispersystems.textsecuregcm.entities.AnswerChallengeRequest;
@@ -52,6 +54,8 @@ public class ChallengeController {
private final RateLimitChallengeManager rateLimitChallengeManager;
private final ChallengeConstraintChecker challengeConstraintChecker;
private static final Logger logger = LoggerFactory.getLogger(ChallengeController.class);
private static final String CHALLENGE_RESPONSE_COUNTER_NAME = name(ChallengeController.class, "challengeResponse");
private static final String CHALLENGE_TYPE_TAG = "type";
@@ -85,8 +89,8 @@ public class ChallengeController {
description = "If present, an positive integer indicating the number of seconds before a subsequent attempt could succeed"))
public Response handleChallengeResponse(@Auth final AuthenticatedDevice auth,
@Valid final AnswerChallengeRequest answerRequest,
@Context ContainerRequestContext requestContext,
@HeaderParam(HttpHeaders.USER_AGENT) final String userAgent) throws RateLimitExceededException, IOException {
@Context final ContainerRequestContext requestContext,
@HeaderParam(HttpHeaders.USER_AGENT) final String userAgent) throws RateLimitExceededException {
final Account account = accountsManager.getByAccountIdentifier(auth.accountIdentifier())
.orElseThrow(() -> new WebApplicationException(Response.Status.UNAUTHORIZED));
@@ -103,12 +107,12 @@ public class ChallengeController {
return Response.status(429).build();
}
rateLimitChallengeManager.answerPushChallenge(account, pushChallengeRequest.getChallenge());
} else if (answerRequest instanceof AnswerCaptchaChallengeRequest captchaChallengeRequest) {
} else if (answerRequest instanceof final AnswerCaptchaChallengeRequest captchaChallengeRequest) {
tags = tags.and(CHALLENGE_TYPE_TAG, "captcha");
final String remoteAddress = (String) requestContext.getProperty(
RemoteAddressFilter.REMOTE_ADDRESS_ATTRIBUTE_NAME);
boolean success = rateLimitChallengeManager.answerCaptchaChallenge(
final boolean success = rateLimitChallengeManager.answerCaptchaChallenge(
account,
captchaChallengeRequest.getCaptcha(),
remoteAddress,
@@ -122,6 +126,9 @@ public class ChallengeController {
} else {
tags = tags.and(CHALLENGE_TYPE_TAG, "unrecognized");
}
} catch (final IOException e) {
logger.error("error assessing captcha during challenge response handling", e);
return Response.status(Response.Status.SERVICE_UNAVAILABLE).build();
} finally {
Metrics.counter(CHALLENGE_RESPONSE_COUNTER_NAME, tags).increment();
}

View File

@@ -493,7 +493,7 @@ public class VerificationController {
.increment();
} catch (final IOException e) {
logger.error("error assessing captcha", e);
logger.error("error assessing captcha during registration verification", e);
throw new ServerErrorException(Response.Status.SERVICE_UNAVAILABLE, e);
}