Stop checking for stored verification codes when linking devices

This commit is contained in:
Jon Chambers
2023-08-03 18:12:15 -04:00
committed by Jon Chambers
parent c873f62025
commit 625637b888
5 changed files with 13 additions and 129 deletions

View File

@@ -115,14 +115,14 @@ import org.whispersystems.textsecuregcm.controllers.VerificationController;
import org.whispersystems.textsecuregcm.currency.CoinMarketCapClient;
import org.whispersystems.textsecuregcm.currency.CurrencyConversionManager;
import org.whispersystems.textsecuregcm.currency.FixerClient;
import org.whispersystems.textsecuregcm.grpc.GrpcServerManagedWrapper;
import org.whispersystems.textsecuregcm.grpc.UserAgentInterceptor;
import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager;
import org.whispersystems.textsecuregcm.filters.RemoteDeprecationFilter;
import org.whispersystems.textsecuregcm.filters.RequestStatisticsFilter;
import org.whispersystems.textsecuregcm.filters.TimestampResponseFilter;
import org.whispersystems.textsecuregcm.grpc.KeysGrpcService;
import org.whispersystems.textsecuregcm.grpc.GrpcServerManagedWrapper;
import org.whispersystems.textsecuregcm.grpc.KeysAnonymousGrpcService;
import org.whispersystems.textsecuregcm.grpc.KeysGrpcService;
import org.whispersystems.textsecuregcm.grpc.UserAgentInterceptor;
import org.whispersystems.textsecuregcm.limits.CardinalityEstimator;
import org.whispersystems.textsecuregcm.limits.PushChallengeManager;
import org.whispersystems.textsecuregcm.limits.RateLimitChallengeManager;
@@ -189,9 +189,7 @@ import org.whispersystems.textsecuregcm.storage.RemoteConfigs;
import org.whispersystems.textsecuregcm.storage.RemoteConfigsManager;
import org.whispersystems.textsecuregcm.storage.ReportMessageDynamoDb;
import org.whispersystems.textsecuregcm.storage.ReportMessageManager;
import org.whispersystems.textsecuregcm.storage.StoredVerificationCodeManager;
import org.whispersystems.textsecuregcm.storage.SubscriptionManager;
import org.whispersystems.textsecuregcm.storage.VerificationCodeStore;
import org.whispersystems.textsecuregcm.storage.VerificationSessionManager;
import org.whispersystems.textsecuregcm.storage.VerificationSessions;
import org.whispersystems.textsecuregcm.subscriptions.BraintreeManager;
@@ -352,8 +350,6 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
ReportMessageDynamoDb reportMessageDynamoDb = new ReportMessageDynamoDb(dynamoDbClient,
config.getDynamoDbTables().getReportMessage().getTableName(),
config.getReportMessageConfiguration().getReportTtl());
VerificationCodeStore pendingDevices = new VerificationCodeStore(dynamoDbClient,
config.getDynamoDbTables().getPendingDevices().getTableName());
RegistrationRecoveryPasswords registrationRecoveryPasswords = new RegistrationRecoveryPasswords(
config.getDynamoDbTables().getRegistrationRecovery().getTableName(),
config.getDynamoDbTables().getRegistrationRecovery().getExpiration(),
@@ -507,7 +503,6 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
storageServiceExecutor, storageServiceRetryExecutor, config.getSecureStorageServiceConfiguration());
ClientPresenceManager clientPresenceManager = new ClientPresenceManager(clientPresenceCluster, recurringJobExecutor,
keyspaceNotificationDispatchExecutor);
StoredVerificationCodeManager pendingDevicesManager = new StoredVerificationCodeManager(pendingDevices);
ProfilesManager profilesManager = new ProfilesManager(profiles, cacheCluster);
MessagesCache messagesCache = new MessagesCache(messagesCluster, messagesCluster,
keyspaceNotificationDispatchExecutor, messageDeliveryScheduler, messageDeletionAsyncExecutor, clock);
@@ -756,7 +751,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
new CallLinkController(rateLimiters, genericZkSecretParams),
new CertificateController(new CertificateGenerator(config.getDeliveryCertificate().certificate().value(), config.getDeliveryCertificate().ecPrivateKey(), config.getDeliveryCertificate().expiresDays()), zkAuthOperations, genericZkSecretParams, clock),
new ChallengeController(rateLimitChallengeManager),
new DeviceController(pendingDevicesManager, config.getLinkDeviceSecretConfiguration().secret().value(), accountsManager, messagesManager, keys, rateLimiters,
new DeviceController(config.getLinkDeviceSecretConfiguration().secret().value(), accountsManager, messagesManager, keys, rateLimiters,
rateLimitersCluster, config.getMaxDevices(), clock),
new DirectoryV2Controller(directoryV2CredentialsGenerator),
new DonationController(clock, zkReceiptOperations, redeemedReceiptsManager, accountsManager, config.getBadges(),

View File

@@ -56,7 +56,6 @@ public class DynamoDbTables {
private final Table kemKeys;
private final Table kemLastResortKeys;
private final TableWithExpiration messages;
private final Table pendingDevices;
private final Table phoneNumberIdentifiers;
private final Table profiles;
private final Table pushChallenge;
@@ -78,7 +77,6 @@ public class DynamoDbTables {
@JsonProperty("pqKeys") final Table kemKeys,
@JsonProperty("pqLastResortKeys") final Table kemLastResortKeys,
@JsonProperty("messages") final TableWithExpiration messages,
@JsonProperty("pendingDevices") final Table pendingDevices,
@JsonProperty("phoneNumberIdentifiers") final Table phoneNumberIdentifiers,
@JsonProperty("profiles") final Table profiles,
@JsonProperty("pushChallenge") final Table pushChallenge,
@@ -99,7 +97,6 @@ public class DynamoDbTables {
this.kemKeys = kemKeys;
this.kemLastResortKeys = kemLastResortKeys;
this.messages = messages;
this.pendingDevices = pendingDevices;
this.phoneNumberIdentifiers = phoneNumberIdentifiers;
this.profiles = profiles;
this.pushChallenge = pushChallenge;
@@ -171,12 +168,6 @@ public class DynamoDbTables {
return messages;
}
@NotNull
@Valid
public Table getPendingDevices() {
return pendingDevices;
}
@NotNull
@Valid
public Table getPhoneNumberIdentifiers() {

View File

@@ -66,7 +66,6 @@ import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.Device.DeviceCapabilities;
import org.whispersystems.textsecuregcm.storage.KeysManager;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.StoredVerificationCodeManager;
import org.whispersystems.textsecuregcm.util.Pair;
import org.whispersystems.textsecuregcm.util.Util;
import org.whispersystems.textsecuregcm.util.VerificationCode;
@@ -77,7 +76,6 @@ public class DeviceController {
static final int MAX_DEVICES = 6;
private final StoredVerificationCodeManager pendingDevices;
private final Key verificationTokenKey;
private final AccountsManager accounts;
private final MessagesManager messages;
@@ -93,15 +91,13 @@ public class DeviceController {
@VisibleForTesting
static final Duration TOKEN_EXPIRATION_DURATION = Duration.ofMinutes(10);
public DeviceController(StoredVerificationCodeManager pendingDevices,
byte[] linkDeviceSecret,
public DeviceController(byte[] linkDeviceSecret,
AccountsManager accounts,
MessagesManager messages,
KeysManager keys,
RateLimiters rateLimiters,
FaultTolerantRedisCluster usedTokenCluster,
Map<String, Integer> maxDeviceConfiguration, final Clock clock) {
this.pendingDevices = pendingDevices;
this.verificationTokenKey = new SecretKeySpec(linkDeviceSecret, VERIFICATION_TOKEN_ALGORITHM);
this.accounts = accounts;
this.messages = messages;
@@ -202,8 +198,7 @@ public class DeviceController {
@Context ContainerRequest containerRequest)
throws RateLimitExceededException, DeviceLimitExceededException {
final Pair<Account, Device> accountAndDevice = createDevice(authorizationHeader.getUsername(),
authorizationHeader.getPassword(),
final Pair<Account, Device> accountAndDevice = createDevice(authorizationHeader.getPassword(),
verificationCode,
accountAttributes,
containerRequest,
@@ -237,8 +232,7 @@ public class DeviceController {
@Context ContainerRequest containerRequest)
throws RateLimitExceededException, DeviceLimitExceededException {
final Pair<Account, Device> accountAndDevice = createDevice(authorizationHeader.getUsername(),
authorizationHeader.getPassword(),
final Pair<Account, Device> accountAndDevice = createDevice(authorizationHeader.getPassword(),
linkDeviceRequest.verificationCode(),
linkDeviceRequest.accountAttributes(),
containerRequest,
@@ -362,28 +356,20 @@ public class DeviceController {
return isDowngrade;
}
private Pair<Account, Device> createDevice(final String phoneNumber,
final String password,
private Pair<Account, Device> createDevice(final String password,
final String verificationCode,
final AccountAttributes accountAttributes,
final ContainerRequest containerRequest,
final Optional<DeviceActivationRequest> maybeDeviceActivationRequest)
throws RateLimitExceededException, DeviceLimitExceededException {
rateLimiters.getVerifyDeviceLimiter().validate(phoneNumber);
final Optional<UUID> maybeAciFromToken = checkVerificationToken(verificationCode);
final Account account = maybeAciFromToken.flatMap(accounts::getByAccountIdentifier)
.or(() -> {
final boolean verificationCodeValid = pendingDevices.getCodeForNumber(phoneNumber)
.map(storedVerificationCode -> storedVerificationCode.isValid(verificationCode))
.orElse(false);
return verificationCodeValid ? accounts.getByE164(phoneNumber) : Optional.empty();
})
.orElseThrow(ForbiddenException::new);
rateLimiters.getVerifyDeviceLimiter().validate(account.getUuid());
maybeDeviceActivationRequest.ifPresent(deviceActivationRequest -> {
assert deviceActivationRequest.aciSignedPreKey().isPresent();
assert deviceActivationRequest.pniSignedPreKey().isPresent();
@@ -468,8 +454,6 @@ public class DeviceController {
a.addDevice(device);
});
pendingDevices.remove(phoneNumber);
if (maybeAciFromToken.isPresent()) {
usedTokenCluster.useCluster(connection ->
connection.sync().set(getUsedTokenKey(verificationCode), "", new SetArgs().ex(TOKEN_EXPIRATION_DURATION)));