Remove transitional and legacy client
This commit is contained in:
parent
a984b3640e
commit
2a68d9095d
|
@ -242,9 +242,6 @@ voiceVerification:
|
|||
locales:
|
||||
- en
|
||||
|
||||
recaptcha:
|
||||
secret: unset
|
||||
|
||||
recaptchaV2:
|
||||
projectPath: projects/example
|
||||
credentialConfigurationJson: "{ }" # service account configuration for backend authentication
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.whispersystems.textsecuregcm.configuration.MessageCacheConfiguration;
|
|||
import org.whispersystems.textsecuregcm.configuration.PaymentsServiceConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.PushConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RecaptchaConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RecaptchaV2Configuration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RedisClusterConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RedisConfiguration;
|
||||
|
@ -206,11 +205,6 @@ public class WhisperServerConfiguration extends Configuration {
|
|||
@JsonProperty
|
||||
private VoiceVerificationConfiguration voiceVerification;
|
||||
|
||||
@Valid
|
||||
@NotNull
|
||||
@JsonProperty
|
||||
private RecaptchaConfiguration recaptcha;
|
||||
|
||||
@Valid
|
||||
@NotNull
|
||||
@JsonProperty
|
||||
|
@ -289,10 +283,6 @@ public class WhisperServerConfiguration extends Configuration {
|
|||
return dynamoDbTables;
|
||||
}
|
||||
|
||||
public RecaptchaConfiguration getRecaptchaConfiguration() {
|
||||
return recaptcha;
|
||||
}
|
||||
|
||||
public RecaptchaV2Configuration getRecaptchaV2Configuration() {
|
||||
return recaptchaV2;
|
||||
}
|
||||
|
|
|
@ -151,8 +151,6 @@ import org.whispersystems.textsecuregcm.push.MessageSender;
|
|||
import org.whispersystems.textsecuregcm.push.ProvisioningManager;
|
||||
import org.whispersystems.textsecuregcm.push.ReceiptSender;
|
||||
import org.whispersystems.textsecuregcm.recaptcha.EnterpriseRecaptchaClient;
|
||||
import org.whispersystems.textsecuregcm.recaptcha.LegacyRecaptchaClient;
|
||||
import org.whispersystems.textsecuregcm.recaptcha.TransitionalRecaptchaClient;
|
||||
import org.whispersystems.textsecuregcm.redis.ConnectionEventLogger;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
import org.whispersystems.textsecuregcm.redis.ReplicatedJedisPool;
|
||||
|
@ -474,16 +472,13 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
MessageSender messageSender = new MessageSender(apnFallbackManager, clientPresenceManager, messagesManager, gcmSender, apnSender, pushLatencyManager);
|
||||
ReceiptSender receiptSender = new ReceiptSender(accountsManager, messageSender);
|
||||
TurnTokenGenerator turnTokenGenerator = new TurnTokenGenerator(config.getTurnConfiguration());
|
||||
LegacyRecaptchaClient legacyRecaptchaClient = new LegacyRecaptchaClient(config.getRecaptchaConfiguration().getSecret());
|
||||
EnterpriseRecaptchaClient enterpriseRecaptchaClient = new EnterpriseRecaptchaClient(
|
||||
config.getRecaptchaV2Configuration().getProjectPath(),
|
||||
config.getRecaptchaV2Configuration().getCredentialConfigurationJson(),
|
||||
dynamicConfigurationManager);
|
||||
TransitionalRecaptchaClient transitionalRecaptchaClient = new TransitionalRecaptchaClient(legacyRecaptchaClient,
|
||||
enterpriseRecaptchaClient);
|
||||
PushChallengeManager pushChallengeManager = new PushChallengeManager(apnSender, gcmSender, pushChallengeDynamoDb);
|
||||
RateLimitChallengeManager rateLimitChallengeManager = new RateLimitChallengeManager(pushChallengeManager,
|
||||
transitionalRecaptchaClient, dynamicRateLimiters);
|
||||
enterpriseRecaptchaClient, dynamicRateLimiters);
|
||||
RateLimitChallengeOptionManager rateLimitChallengeOptionManager =
|
||||
new RateLimitChallengeOptionManager(dynamicRateLimiters, dynamicConfigurationManager);
|
||||
|
||||
|
@ -620,7 +615,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
environment.jersey().register(
|
||||
new AccountController(pendingAccountsManager, accountsManager, abusiveHostRules, rateLimiters,
|
||||
smsSender, dynamicConfigurationManager, turnTokenGenerator, config.getTestDevices(),
|
||||
transitionalRecaptchaClient, gcmSender, apnSender, backupCredentialsGenerator,
|
||||
enterpriseRecaptchaClient, gcmSender, apnSender, backupCredentialsGenerator,
|
||||
verifyExperimentEnrollmentManager));
|
||||
environment.jersey().register(new KeysController(rateLimiters, keys, accountsManager));
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.configuration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
public class RecaptchaConfiguration {
|
||||
|
||||
@JsonProperty
|
||||
@NotEmpty
|
||||
private String secret;
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.ws.rs.BadRequestException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
|
||||
|
@ -29,6 +30,8 @@ public class EnterpriseRecaptchaClient implements RecaptchaClient {
|
|||
|
||||
@VisibleForTesting
|
||||
static final String SEPARATOR = ".";
|
||||
@VisibleForTesting
|
||||
static final String V2_PREFIX = "signal-recaptcha-v2" + EnterpriseRecaptchaClient.SEPARATOR;
|
||||
private static final String ASSESSMENTS_COUNTER_NAME = name(EnterpriseRecaptchaClient.class, "assessments");
|
||||
private static final String SCORE_DISTRIBUTION_NAME = name(EnterpriseRecaptchaClient.class, "scoreDistribution");
|
||||
|
||||
|
@ -61,7 +64,7 @@ public class EnterpriseRecaptchaClient implements RecaptchaClient {
|
|||
* don’t need to be strict.
|
||||
*/
|
||||
static String[] parseInputToken(final String input) {
|
||||
String[] keyActionAndToken = input.split("\\" + SEPARATOR, 3);
|
||||
String[] keyActionAndToken = StringUtils.removeStart(input, V2_PREFIX).split("\\" + SEPARATOR, 3);
|
||||
|
||||
if (keyActionAndToken.length == 1) {
|
||||
throw new BadRequestException("too few parts");
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013-2020 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.recaptcha;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
|
||||
import org.glassfish.jersey.client.ClientConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.core.MultivaluedHashMap;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
|
||||
public class LegacyRecaptchaClient implements RecaptchaClient {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(LegacyRecaptchaClient.class);
|
||||
|
||||
private final Client client;
|
||||
private final String recaptchaSecret;
|
||||
|
||||
public LegacyRecaptchaClient(String recaptchaSecret) {
|
||||
this.client = ClientBuilder.newClient(new ClientConfig(new JacksonJaxbJsonProvider().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)));
|
||||
this.recaptchaSecret = recaptchaSecret;
|
||||
}
|
||||
|
||||
public boolean verify(String captchaToken, String ip) {
|
||||
MultivaluedMap<String, String> formData = new MultivaluedHashMap<>();
|
||||
formData.add("secret", recaptchaSecret);
|
||||
formData.add("response", captchaToken);
|
||||
formData.add("remoteip", ip);
|
||||
|
||||
VerifyResponse response = client.target("https://www.google.com/recaptcha/api/siteverify")
|
||||
.request()
|
||||
.post(Entity.form(formData), VerifyResponse.class);
|
||||
|
||||
if (response.success) {
|
||||
logger.debug("Got successful captcha time: " + response.challenge_ts + ", current time: " + System.currentTimeMillis());
|
||||
}
|
||||
|
||||
return response.success;
|
||||
}
|
||||
|
||||
private static class VerifyResponse {
|
||||
@JsonProperty
|
||||
private boolean success;
|
||||
|
||||
@JsonProperty("error-codes")
|
||||
private String[] errorCodes;
|
||||
|
||||
@JsonProperty
|
||||
private String hostname;
|
||||
|
||||
@JsonProperty
|
||||
private String challenge_ts;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "success: " + success + ", errorCodes: " + String.join(", ", errorCodes == null ? new String[0] : errorCodes) + ", hostname: " + hostname + ", challenge_ts: " + challenge_ts;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021-2022 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.recaptcha;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TransitionalRecaptchaClient implements RecaptchaClient {
|
||||
|
||||
@VisibleForTesting
|
||||
static final String V2_PREFIX = "signal-recaptcha-v2" + EnterpriseRecaptchaClient.SEPARATOR;
|
||||
|
||||
private final LegacyRecaptchaClient legacyRecaptchaClient;
|
||||
private final EnterpriseRecaptchaClient enterpriseRecaptchaClient;
|
||||
|
||||
public TransitionalRecaptchaClient(
|
||||
@Nonnull final LegacyRecaptchaClient legacyRecaptchaClient,
|
||||
@Nonnull final EnterpriseRecaptchaClient enterpriseRecaptchaClient) {
|
||||
this.legacyRecaptchaClient = Objects.requireNonNull(legacyRecaptchaClient);
|
||||
this.enterpriseRecaptchaClient = Objects.requireNonNull(enterpriseRecaptchaClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(@Nonnull final String token, @Nonnull final String ip) {
|
||||
if (token.startsWith(V2_PREFIX)) {
|
||||
return enterpriseRecaptchaClient.verify(token.substring(V2_PREFIX.length()), ip);
|
||||
} else {
|
||||
return legacyRecaptchaClient.verify(token, ip);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,8 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||
|
||||
class EnterpriseRecaptchaClientTest {
|
||||
|
||||
private static final String PREFIX = EnterpriseRecaptchaClient.V2_PREFIX.substring(0,
|
||||
EnterpriseRecaptchaClient.V2_PREFIX.lastIndexOf(SEPARATOR));
|
||||
private static final String SITE_KEY = "site-key";
|
||||
private static final String TOKEN = "some-token";
|
||||
|
||||
|
@ -57,6 +59,21 @@ class EnterpriseRecaptchaClientTest {
|
|||
String.join(SEPARATOR, SITE_KEY, "an-action", TOKEN, "something-else"),
|
||||
TOKEN + SEPARATOR + "something-else",
|
||||
SITE_KEY,
|
||||
"an-action"),
|
||||
Arguments.of(
|
||||
String.join(SEPARATOR, PREFIX, SITE_KEY, TOKEN),
|
||||
TOKEN,
|
||||
SITE_KEY,
|
||||
null),
|
||||
Arguments.of(
|
||||
String.join(SEPARATOR, PREFIX, SITE_KEY, "an-action", TOKEN),
|
||||
TOKEN,
|
||||
SITE_KEY,
|
||||
"an-action"),
|
||||
Arguments.of(
|
||||
String.join(SEPARATOR, PREFIX, SITE_KEY, "an-action", TOKEN, "something-else"),
|
||||
TOKEN + SEPARATOR + "something-else",
|
||||
SITE_KEY,
|
||||
"an-action")
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright 2022 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.recaptcha;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.whispersystems.textsecuregcm.recaptcha.EnterpriseRecaptchaClient.SEPARATOR;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class TransitionalRecaptchaClientTest {
|
||||
|
||||
private TransitionalRecaptchaClient transitionalRecaptchaClient;
|
||||
private EnterpriseRecaptchaClient enterpriseRecaptchaClient;
|
||||
private LegacyRecaptchaClient legacyRecaptchaClient;
|
||||
|
||||
private static final String PREFIX = TransitionalRecaptchaClient.V2_PREFIX.substring(0,
|
||||
TransitionalRecaptchaClient.V2_PREFIX.lastIndexOf(SEPARATOR));
|
||||
private static final String TOKEN = "some-token";
|
||||
private static final String IP_ADDRESS = "127.0.0.1";
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
enterpriseRecaptchaClient = mock(EnterpriseRecaptchaClient.class);
|
||||
legacyRecaptchaClient = mock(LegacyRecaptchaClient.class);
|
||||
transitionalRecaptchaClient = new TransitionalRecaptchaClient(legacyRecaptchaClient, enterpriseRecaptchaClient);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
void testVerify(final String inputToken, final boolean expectLegacy, final String expectedToken) {
|
||||
|
||||
transitionalRecaptchaClient.verify(inputToken, IP_ADDRESS);
|
||||
|
||||
if (expectLegacy) {
|
||||
verifyNoInteractions(enterpriseRecaptchaClient);
|
||||
verify(legacyRecaptchaClient).verify(expectedToken, IP_ADDRESS);
|
||||
} else {
|
||||
verifyNoInteractions(legacyRecaptchaClient);
|
||||
verify(enterpriseRecaptchaClient).verify(expectedToken, IP_ADDRESS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static Stream<Arguments> testVerify() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
TOKEN,
|
||||
true,
|
||||
TOKEN),
|
||||
Arguments.of(
|
||||
String.join(SEPARATOR, PREFIX, TOKEN),
|
||||
false,
|
||||
TOKEN),
|
||||
Arguments.of(
|
||||
String.join(SEPARATOR, PREFIX, "site-key", "an-action", TOKEN),
|
||||
false,
|
||||
String.join(SEPARATOR, "site-key", "an-action", TOKEN),
|
||||
"an-action"),
|
||||
Arguments.of(
|
||||
String.join(SEPARATOR, PREFIX, "site-key", "an-action", TOKEN, "something-else"),
|
||||
false,
|
||||
"site-key" + SEPARATOR + "an-action" + SEPARATOR + TOKEN + SEPARATOR + "something-else")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue