Tag captcha attempt metrics with UA platform
This commit is contained in:
parent
5ca89709e3
commit
c048074c31
|
@ -68,7 +68,7 @@ public class ChallengeController {
|
||||||
final String mostRecentProxy = ForwardedIpUtil.getMostRecentProxy(forwardedFor).orElseThrow();
|
final String mostRecentProxy = ForwardedIpUtil.getMostRecentProxy(forwardedFor).orElseThrow();
|
||||||
|
|
||||||
rateLimitChallengeManager.answerRecaptchaChallenge(auth.getAccount(), recaptchaChallengeRequest.getCaptcha(),
|
rateLimitChallengeManager.answerRecaptchaChallenge(auth.getAccount(), recaptchaChallengeRequest.getCaptcha(),
|
||||||
mostRecentProxy);
|
mostRecentProxy, userAgent);
|
||||||
|
|
||||||
} catch (final NoSuchElementException e) {
|
} catch (final NoSuchElementException e) {
|
||||||
return Response.status(400).build();
|
return Response.status(400).build();
|
||||||
|
|
|
@ -6,12 +6,16 @@ import io.micrometer.core.instrument.Metrics;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import io.micrometer.core.instrument.Tag;
|
||||||
|
import io.micrometer.core.instrument.Tags;
|
||||||
import org.whispersystems.textsecuregcm.abuse.RateLimitChallengeListener;
|
import org.whispersystems.textsecuregcm.abuse.RateLimitChallengeListener;
|
||||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||||
|
import org.whispersystems.textsecuregcm.metrics.UserAgentTagUtil;
|
||||||
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
||||||
import org.whispersystems.textsecuregcm.recaptcha.RecaptchaClient;
|
import org.whispersystems.textsecuregcm.recaptcha.RecaptchaClient;
|
||||||
import org.whispersystems.textsecuregcm.storage.Account;
|
import org.whispersystems.textsecuregcm.storage.Account;
|
||||||
import org.whispersystems.textsecuregcm.util.Util;
|
import org.whispersystems.textsecuregcm.util.Util;
|
||||||
|
import org.whispersystems.textsecuregcm.util.ua.ClientPlatform;
|
||||||
|
|
||||||
public class RateLimitChallengeManager {
|
public class RateLimitChallengeManager {
|
||||||
|
|
||||||
|
@ -54,16 +58,20 @@ public class RateLimitChallengeManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void answerRecaptchaChallenge(final Account account, final String captcha, final String mostRecentProxyIp)
|
public void answerRecaptchaChallenge(final Account account, final String captcha, final String mostRecentProxyIp, final String userAgent)
|
||||||
throws RateLimitExceededException {
|
throws RateLimitExceededException {
|
||||||
|
|
||||||
rateLimiters.getRecaptchaChallengeAttemptLimiter().validate(account.getUuid());
|
rateLimiters.getRecaptchaChallengeAttemptLimiter().validate(account.getUuid());
|
||||||
|
|
||||||
final boolean challengeSuccess = recaptchaClient.verify(captcha, mostRecentProxyIp);
|
final boolean challengeSuccess = recaptchaClient.verify(captcha, mostRecentProxyIp);
|
||||||
|
|
||||||
Metrics.counter(RECAPTCHA_ATTEMPT_COUNTER_NAME,
|
final Tags tags = Tags.of(
|
||||||
SOURCE_COUNTRY_TAG_NAME, Util.getCountryCode(account.getNumber()),
|
Tag.of(SOURCE_COUNTRY_TAG_NAME, Util.getCountryCode(account.getNumber())),
|
||||||
SUCCESS_TAG_NAME, String.valueOf(challengeSuccess)).increment();
|
Tag.of(SUCCESS_TAG_NAME, String.valueOf(challengeSuccess)),
|
||||||
|
UserAgentTagUtil.getPlatformTag(userAgent)
|
||||||
|
);
|
||||||
|
|
||||||
|
Metrics.counter(RECAPTCHA_ATTEMPT_COUNTER_NAME, tags).increment();
|
||||||
|
|
||||||
if (challengeSuccess) {
|
if (challengeSuccess) {
|
||||||
rateLimiters.getRecaptchaChallengeSuccessLimiter().validate(account.getUuid());
|
rateLimiters.getRecaptchaChallengeSuccessLimiter().validate(account.getUuid());
|
||||||
|
|
|
@ -7,6 +7,8 @@ package org.whispersystems.textsecuregcm.controllers;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doThrow;
|
import static org.mockito.Mockito.doThrow;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
|
@ -110,7 +112,7 @@ class ChallengeControllerTest {
|
||||||
.put(Entity.json(recaptchaChallengeJson));
|
.put(Entity.json(recaptchaChallengeJson));
|
||||||
|
|
||||||
assertEquals(200, response.getStatus());
|
assertEquals(200, response.getStatus());
|
||||||
verify(rateLimitChallengeManager).answerRecaptchaChallenge(AuthHelper.VALID_ACCOUNT, "The value of the solved captcha token", "10.0.0.1");
|
verify(rateLimitChallengeManager).answerRecaptchaChallenge(eq(AuthHelper.VALID_ACCOUNT), eq("The value of the solved captcha token"), eq("10.0.0.1"), anyString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -124,7 +126,7 @@ class ChallengeControllerTest {
|
||||||
""";
|
""";
|
||||||
|
|
||||||
final Duration retryAfter = Duration.ofMinutes(17);
|
final Duration retryAfter = Duration.ofMinutes(17);
|
||||||
doThrow(new RateLimitExceededException(retryAfter)).when(rateLimitChallengeManager).answerRecaptchaChallenge(any(), any(), any());
|
doThrow(new RateLimitExceededException(retryAfter)).when(rateLimitChallengeManager).answerRecaptchaChallenge(any(), any(), any(), any());
|
||||||
|
|
||||||
final Response response = EXTENSION.target("/v1/challenge")
|
final Response response = EXTENSION.target("/v1/challenge")
|
||||||
.request()
|
.request()
|
||||||
|
|
|
@ -75,7 +75,7 @@ class RateLimitChallengeManagerTest {
|
||||||
when(rateLimiters.getRecaptchaChallengeSuccessLimiter()).thenReturn(mock(RateLimiter.class));
|
when(rateLimiters.getRecaptchaChallengeSuccessLimiter()).thenReturn(mock(RateLimiter.class));
|
||||||
when(rateLimiters.getRateLimitResetLimiter()).thenReturn(mock(RateLimiter.class));
|
when(rateLimiters.getRateLimitResetLimiter()).thenReturn(mock(RateLimiter.class));
|
||||||
|
|
||||||
rateLimitChallengeManager.answerRecaptchaChallenge(account, "captcha", "10.0.0.1");
|
rateLimitChallengeManager.answerRecaptchaChallenge(account, "captcha", "10.0.0.1", "Test User-Agent");
|
||||||
|
|
||||||
if (successfulChallenge) {
|
if (successfulChallenge) {
|
||||||
verify(rateLimitChallengeListener).handleRateLimitChallengeAnswered(account);
|
verify(rateLimitChallengeListener).handleRateLimitChallengeAnswered(account);
|
||||||
|
|
Loading…
Reference in New Issue