diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 9a5fa2516..1bd99a891 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -525,7 +525,7 @@ public class WhisperServerService extends Application missingDevices; @JsonProperty + @Schema(description = "Devices absent on the request but present in the account") public List extraDevices; @VisibleForTesting diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java b/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java index 0872a8649..b3074b158 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/entities/RegistrationLockFailure.java @@ -5,8 +5,16 @@ package org.whispersystems.textsecuregcm.entities; +import io.swagger.v3.oas.annotations.media.Schema; import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials; -public record RegistrationLockFailure(long timeRemaining, ExternalServiceCredentials backupCredentials) { +@Schema(description = "A token provided to the client via a push payload") +public record RegistrationLockFailure( + @Schema(description = "Time remaining in milliseconds before the existing registration lock expires") + long timeRemaining, + @Schema(description = "Credentials that can be used with SVR1") + ExternalServiceCredentials backupCredentials, + @Schema(description = "Credentials that can be used with SVR2") + ExternalServiceCredentials svr2Credentials) { } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/entities/StaleDevices.java b/service/src/main/java/org/whispersystems/textsecuregcm/entities/StaleDevices.java index 98be70197..5cef6fa75 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/entities/StaleDevices.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/entities/StaleDevices.java @@ -6,12 +6,14 @@ package org.whispersystems.textsecuregcm.entities; import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; import java.util.List; public class StaleDevices { @JsonProperty + @Schema(description = "Devices that are no longer active") private List staleDevices; public StaleDevices() {} diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java index 98adeb5ca..943b46aa0 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/RegistrationLockVerificationManagerTest.java @@ -47,14 +47,16 @@ class RegistrationLockVerificationManagerTest { private final AccountsManager accountsManager = mock(AccountsManager.class); private final ClientPresenceManager clientPresenceManager = mock(ClientPresenceManager.class); - private final ExternalServiceCredentialsGenerator backupServiceCredentialsGeneraor = mock( + private final ExternalServiceCredentialsGenerator svr1CredentialsGenerator = mock( + ExternalServiceCredentialsGenerator.class); + private final ExternalServiceCredentialsGenerator svr2CredentialsGenerator = mock( ExternalServiceCredentialsGenerator.class); private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager = mock( RegistrationRecoveryPasswordsManager.class); private static PushNotificationManager pushNotificationManager = mock(PushNotificationManager.class); private final RateLimiters rateLimiters = mock(RateLimiters.class); private final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager( - accountsManager, clientPresenceManager, backupServiceCredentialsGeneraor, registrationRecoveryPasswordsManager, pushNotificationManager, rateLimiters); + accountsManager, clientPresenceManager, svr1CredentialsGenerator, svr2CredentialsGenerator, registrationRecoveryPasswordsManager, pushNotificationManager, rateLimiters); private final RateLimiter pinLimiter = mock(RateLimiter.class); @@ -65,7 +67,9 @@ class RegistrationLockVerificationManagerTest { void setUp() { clearInvocations(pushNotificationManager); when(rateLimiters.getPinLimiter()).thenReturn(pinLimiter); - when(backupServiceCredentialsGeneraor.generateForUuid(any())) + when(svr1CredentialsGenerator.generateForUuid(any())) + .thenReturn(mock(ExternalServiceCredentials.class)); + when(svr2CredentialsGenerator.generateForUuid(any())) .thenReturn(mock(ExternalServiceCredentials.class)); final Device device = mock(Device.class); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java index bdf28d888..d5a5308c9 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java @@ -72,6 +72,7 @@ import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.signal.libsignal.usernames.BaseUsernameException; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; +import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials; import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator; import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager; import org.whispersystems.textsecuregcm.auth.SaltedTokenHash; @@ -83,6 +84,7 @@ import org.whispersystems.textsecuregcm.captcha.AssessmentResult; import org.whispersystems.textsecuregcm.captcha.CaptchaChecker; import org.whispersystems.textsecuregcm.captcha.RegistrationCaptchaManager; import org.whispersystems.textsecuregcm.configuration.SecureBackupServiceConfiguration; +import org.whispersystems.textsecuregcm.configuration.SecureValueRecovery2Configuration; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicCaptchaConfiguration; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.entities.AccountAttributes; @@ -199,15 +201,25 @@ class AccountControllerTest { private static DynamicConfigurationManager dynamicConfigurationManager = mock(DynamicConfigurationManager.class); private byte[] registration_lock_key = new byte[32]; - private static final SecureBackupServiceConfiguration BACKUP_CFG = MockUtils.buildMock( + private static final SecureBackupServiceConfiguration SVR1_CFG = MockUtils.buildMock( SecureBackupServiceConfiguration.class, cfg -> when(cfg.getUserAuthenticationTokenSharedSecret()).thenReturn(new byte[32])); - private static final ExternalServiceCredentialsGenerator backupCredentialsGenerator = SecureBackupController.credentialsGenerator( - BACKUP_CFG); + private static final SecureValueRecovery2Configuration SVR2_CFG = MockUtils.buildMock( + SecureValueRecovery2Configuration.class, + cfg -> { + when(cfg.userAuthenticationTokenSharedSecret()).thenReturn(new byte[32]); + when(cfg.userIdTokenSharedSecret()).thenReturn(new byte[32]); + }); + + private static final ExternalServiceCredentialsGenerator svr1CredentialsGenerator = SecureBackupController.credentialsGenerator( + SVR1_CFG); + + private static final ExternalServiceCredentialsGenerator svr2CredentialsGenerator = SecureValueRecovery2Controller.credentialsGenerator( + SVR2_CFG); private static final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager( - accountsManager, clientPresenceManager, backupCredentialsGenerator, registrationRecoveryPasswordsManager, + accountsManager, clientPresenceManager, svr1CredentialsGenerator, svr2CredentialsGenerator, registrationRecoveryPasswordsManager, pushNotificationManager, rateLimiters); private static final RegistrationCaptchaManager registrationCaptchaManager = new RegistrationCaptchaManager( captchaChecker, rateLimiters, Map.of(TEST_NUMBER, 123456), dynamicConfigurationManager); @@ -1268,6 +1280,8 @@ class AccountControllerTest { assertThat(failure.backupCredentials().username()).isEqualTo(SENDER_REG_LOCK_UUID.toString()); assertThat(failure.backupCredentials().password()).isNotEmpty(); assertThat(failure.backupCredentials().password().startsWith(SENDER_REG_LOCK_UUID.toString())).isTrue(); + assertThat(failure.svr2Credentials()).isNotNull(); + assertThat(failure.svr2Credentials()).isEqualTo(svr2CredentialsGenerator.generateFor(SENDER_REG_LOCK_UUID.toString())); assertThat(failure.timeRemaining()).isGreaterThan(0); // verify(senderRegLockAccount).lockAuthenticationCredentials(); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java index 246fb817b..d9bd36f77 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java @@ -71,7 +71,6 @@ import org.whispersystems.textsecuregcm.entities.AccountDataReportResponse; import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse; import org.whispersystems.textsecuregcm.entities.ChangeNumberRequest; import org.whispersystems.textsecuregcm.entities.PhoneNumberDiscoverabilityRequest; -import org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest; import org.whispersystems.textsecuregcm.entities.RegistrationServiceSession; import org.whispersystems.textsecuregcm.entities.SignedPreKey; import org.whispersystems.textsecuregcm.limits.RateLimiter;