Add svr2 credentials to RegistrationLockFailure responses
Add an svr2 credential to 423 responses for: - PUT v2/accounts/number - POST v1/registration Also add some openapi annotations to those endpoints
This commit is contained in:
parent
7395b5760a
commit
8c42199baf
|
@ -525,7 +525,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
config.getDynamoDbTables().getSubscriptions().getTableName(), dynamoDbAsyncClient);
|
config.getDynamoDbTables().getSubscriptions().getTableName(), dynamoDbAsyncClient);
|
||||||
|
|
||||||
final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager(
|
final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager(
|
||||||
accountsManager, clientPresenceManager, backupCredentialsGenerator, registrationRecoveryPasswordsManager, pushNotificationManager, rateLimiters);
|
accountsManager, clientPresenceManager, backupCredentialsGenerator, svr2CredentialsGenerator, registrationRecoveryPasswordsManager, pushNotificationManager, rateLimiters);
|
||||||
final PhoneVerificationTokenManager phoneVerificationTokenManager = new PhoneVerificationTokenManager(
|
final PhoneVerificationTokenManager phoneVerificationTokenManager = new PhoneVerificationTokenManager(
|
||||||
registrationServiceClient, registrationRecoveryPasswordsManager);
|
registrationServiceClient, registrationRecoveryPasswordsManager);
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,16 @@ package org.whispersystems.textsecuregcm.auth;
|
||||||
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
|
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import io.micrometer.core.instrument.DistributionSummary;
|
import io.micrometer.core.instrument.DistributionSummary;
|
||||||
import io.micrometer.core.instrument.Metrics;
|
import io.micrometer.core.instrument.Metrics;
|
||||||
import io.micrometer.core.instrument.Tag;
|
import io.micrometer.core.instrument.Tag;
|
||||||
import io.micrometer.core.instrument.Tags;
|
import io.micrometer.core.instrument.Tags;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.RegistrationLockFailure;
|
import org.whispersystems.textsecuregcm.entities.RegistrationLockFailure;
|
||||||
|
@ -28,9 +31,6 @@ import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||||
import org.whispersystems.textsecuregcm.storage.Device;
|
import org.whispersystems.textsecuregcm.storage.Device;
|
||||||
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
|
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
|
||||||
import org.whispersystems.textsecuregcm.util.Util;
|
import org.whispersystems.textsecuregcm.util.Util;
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class RegistrationLockVerificationManager {
|
public class RegistrationLockVerificationManager {
|
||||||
public enum Flow {
|
public enum Flow {
|
||||||
|
@ -54,20 +54,23 @@ public class RegistrationLockVerificationManager {
|
||||||
|
|
||||||
private final AccountsManager accounts;
|
private final AccountsManager accounts;
|
||||||
private final ClientPresenceManager clientPresenceManager;
|
private final ClientPresenceManager clientPresenceManager;
|
||||||
private final ExternalServiceCredentialsGenerator backupServiceCredentialGenerator;
|
private final ExternalServiceCredentialsGenerator svr1CredentialGenerator;
|
||||||
|
private final ExternalServiceCredentialsGenerator svr2CredentialGenerator;
|
||||||
private final RateLimiters rateLimiters;
|
private final RateLimiters rateLimiters;
|
||||||
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager;
|
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager;
|
||||||
private final PushNotificationManager pushNotificationManager;
|
private final PushNotificationManager pushNotificationManager;
|
||||||
|
|
||||||
public RegistrationLockVerificationManager(
|
public RegistrationLockVerificationManager(
|
||||||
final AccountsManager accounts, final ClientPresenceManager clientPresenceManager,
|
final AccountsManager accounts, final ClientPresenceManager clientPresenceManager,
|
||||||
final ExternalServiceCredentialsGenerator backupServiceCredentialGenerator,
|
final ExternalServiceCredentialsGenerator svr1CredentialGenerator,
|
||||||
|
final ExternalServiceCredentialsGenerator svr2CredentialGenerator,
|
||||||
final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager,
|
final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager,
|
||||||
final PushNotificationManager pushNotificationManager,
|
final PushNotificationManager pushNotificationManager,
|
||||||
final RateLimiters rateLimiters) {
|
final RateLimiters rateLimiters) {
|
||||||
this.accounts = accounts;
|
this.accounts = accounts;
|
||||||
this.clientPresenceManager = clientPresenceManager;
|
this.clientPresenceManager = clientPresenceManager;
|
||||||
this.backupServiceCredentialGenerator = backupServiceCredentialGenerator;
|
this.svr1CredentialGenerator = svr1CredentialGenerator;
|
||||||
|
this.svr2CredentialGenerator = svr2CredentialGenerator;
|
||||||
this.registrationRecoveryPasswordsManager = registrationRecoveryPasswordsManager;
|
this.registrationRecoveryPasswordsManager = registrationRecoveryPasswordsManager;
|
||||||
this.pushNotificationManager = pushNotificationManager;
|
this.pushNotificationManager = pushNotificationManager;
|
||||||
this.rateLimiters = rateLimiters;
|
this.rateLimiters = rateLimiters;
|
||||||
|
@ -138,8 +141,8 @@ public class RegistrationLockVerificationManager {
|
||||||
// Freezing the existing account credentials will definitively start the reglock timeout.
|
// Freezing the existing account credentials will definitively start the reglock timeout.
|
||||||
// Until the timeout, the current reglock can still be supplied,
|
// Until the timeout, the current reglock can still be supplied,
|
||||||
// along with phone number verification, to restore access.
|
// along with phone number verification, to restore access.
|
||||||
final ExternalServiceCredentials existingBackupCredentials =
|
final ExternalServiceCredentials existingSvr1Credentials = svr1CredentialGenerator.generateForUuid(account.getUuid());
|
||||||
backupServiceCredentialGenerator.generateForUuid(account.getUuid());
|
final ExternalServiceCredentials existingSvr2Credentials = svr2CredentialGenerator.generateForUuid(account.getUuid());
|
||||||
|
|
||||||
final Account updatedAccount;
|
final Account updatedAccount;
|
||||||
if (!alreadyLocked) {
|
if (!alreadyLocked) {
|
||||||
|
@ -170,7 +173,8 @@ public class RegistrationLockVerificationManager {
|
||||||
|
|
||||||
throw new WebApplicationException(Response.status(FAILURE_HTTP_STATUS)
|
throw new WebApplicationException(Response.status(FAILURE_HTTP_STATUS)
|
||||||
.entity(new RegistrationLockFailure(existingRegistrationLock.getTimeRemaining().toMillis(),
|
.entity(new RegistrationLockFailure(existingRegistrationLock.getTimeRemaining().toMillis(),
|
||||||
existingRegistrationLock.needsFailureCredentials() ? existingBackupCredentials : null))
|
existingRegistrationLock.needsFailureCredentials() ? existingSvr1Credentials : null,
|
||||||
|
existingRegistrationLock.needsFailureCredentials() ? existingSvr2Credentials : null))
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@ import io.micrometer.core.instrument.Metrics;
|
||||||
import io.micrometer.core.instrument.Tag;
|
import io.micrometer.core.instrument.Tag;
|
||||||
import io.micrometer.core.instrument.Tags;
|
import io.micrometer.core.instrument.Tags;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.headers.Header;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -39,8 +42,9 @@ import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.ChangeNumberRequest;
|
import org.whispersystems.textsecuregcm.entities.ChangeNumberRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.MismatchedDevices;
|
import org.whispersystems.textsecuregcm.entities.MismatchedDevices;
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneNumberDiscoverabilityRequest;
|
import org.whispersystems.textsecuregcm.entities.PhoneNumberDiscoverabilityRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest;
|
import org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest;
|
||||||
|
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
||||||
|
import org.whispersystems.textsecuregcm.entities.RegistrationLockFailure;
|
||||||
import org.whispersystems.textsecuregcm.entities.StaleDevices;
|
import org.whispersystems.textsecuregcm.entities.StaleDevices;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||||
|
@ -77,6 +81,16 @@ public class AccountControllerV2 {
|
||||||
@Path("/number")
|
@Path("/number")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Operation(summary = "Change number", description = "Changes a phone number for an existing account.")
|
||||||
|
@ApiResponse(responseCode = "200", description = "The phone number associated with the authenticated account was changed successfully", useReturnTypeSchema = true)
|
||||||
|
@ApiResponse(responseCode = "403", description = "Verification failed for the provided Registration Recovery Password")
|
||||||
|
@ApiResponse(responseCode = "409", description = "Mismatched number of devices or device ids in 'devices to notify' list", content = @Content(schema = @Schema(implementation = MismatchedDevices.class)))
|
||||||
|
@ApiResponse(responseCode = "410", description = "Mismatched registration ids in 'devices to notify' list", content = @Content(schema = @Schema(implementation = StaleDevices.class)))
|
||||||
|
@ApiResponse(responseCode = "422", description = "The request did not pass validation")
|
||||||
|
@ApiResponse(responseCode = "423", content = @Content(schema = @Schema(implementation = RegistrationLockFailure.class)))
|
||||||
|
@ApiResponse(responseCode = "429", description = "Too many attempts", headers = @Header(
|
||||||
|
name = "Retry-After",
|
||||||
|
description = "If present, an positive integer indicating the number of seconds before a subsequent attempt could succeed"))
|
||||||
public AccountIdentityResponse changeNumber(@Auth final AuthenticatedAccount authenticatedAccount,
|
public AccountIdentityResponse changeNumber(@Auth final AuthenticatedAccount authenticatedAccount,
|
||||||
@NotNull @Valid final ChangeNumberRequest request, @HeaderParam(HttpHeaders.USER_AGENT) final String userAgent)
|
@NotNull @Valid final ChangeNumberRequest request, @HeaderParam(HttpHeaders.USER_AGENT) final String userAgent)
|
||||||
throws RateLimitExceededException, InterruptedException {
|
throws RateLimitExceededException, InterruptedException {
|
||||||
|
|
|
@ -13,6 +13,11 @@ import io.micrometer.core.instrument.DistributionSummary;
|
||||||
import io.micrometer.core.instrument.Metrics;
|
import io.micrometer.core.instrument.Metrics;
|
||||||
import io.micrometer.core.instrument.Tag;
|
import io.micrometer.core.instrument.Tag;
|
||||||
import io.micrometer.core.instrument.Tags;
|
import io.micrometer.core.instrument.Tags;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.headers.Header;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -34,6 +39,7 @@ import org.whispersystems.textsecuregcm.auth.PhoneVerificationTokenManager;
|
||||||
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
import org.whispersystems.textsecuregcm.entities.PhoneVerificationRequest;
|
||||||
|
import org.whispersystems.textsecuregcm.entities.RegistrationLockFailure;
|
||||||
import org.whispersystems.textsecuregcm.entities.RegistrationRequest;
|
import org.whispersystems.textsecuregcm.entities.RegistrationRequest;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||||
|
@ -78,6 +84,22 @@ public class RegistrationController {
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Operation(summary = "Registers an account",
|
||||||
|
description = """
|
||||||
|
Registers a new account or attempts to “re-register” an existing account. It is expected that a well-behaved client
|
||||||
|
could make up to three consecutive calls to this API:
|
||||||
|
1. gets 423 from existing registration lock \n
|
||||||
|
2. gets 409 from device available for transfer \n
|
||||||
|
3. success \n
|
||||||
|
""")
|
||||||
|
@ApiResponse(responseCode = "200", description = "The phone number associated with the authenticated account was changed successfully", useReturnTypeSchema = true)
|
||||||
|
@ApiResponse(responseCode = "403", description = "Verification failed for the provided Registration Recovery Password")
|
||||||
|
@ApiResponse(responseCode = "409", description = "The caller has not explicitly elected to skip transferring data from another device, but a device transfer is technically possible")
|
||||||
|
@ApiResponse(responseCode = "422", description = "The request did not pass validation")
|
||||||
|
@ApiResponse(responseCode = "423", content = @Content(schema = @Schema(implementation = RegistrationLockFailure.class)))
|
||||||
|
@ApiResponse(responseCode = "429", description = "Too many attempts", headers = @Header(
|
||||||
|
name = "Retry-After",
|
||||||
|
description = "If present, an positive integer indicating the number of seconds before a subsequent attempt could succeed"))
|
||||||
public AccountIdentityResponse register(
|
public AccountIdentityResponse register(
|
||||||
@HeaderParam(HttpHeaders.AUTHORIZATION) @NotNull final BasicAuthorizationHeader authorizationHeader,
|
@HeaderParam(HttpHeaders.AUTHORIZATION) @NotNull final BasicAuthorizationHeader authorizationHeader,
|
||||||
@HeaderParam(HeaderUtils.X_SIGNAL_AGENT) final String signalAgent,
|
@HeaderParam(HeaderUtils.X_SIGNAL_AGENT) final String signalAgent,
|
||||||
|
|
|
@ -7,15 +7,18 @@ package org.whispersystems.textsecuregcm.entities;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MismatchedDevices {
|
public class MismatchedDevices {
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
|
@Schema(description = "Devices present on the account but absent in the request")
|
||||||
public List<Long> missingDevices;
|
public List<Long> missingDevices;
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
|
@Schema(description = "Devices absent on the request but present in the account")
|
||||||
public List<Long> extraDevices;
|
public List<Long> extraDevices;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
|
@ -5,8 +5,16 @@
|
||||||
|
|
||||||
package org.whispersystems.textsecuregcm.entities;
|
package org.whispersystems.textsecuregcm.entities;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
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) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,14 @@
|
||||||
package org.whispersystems.textsecuregcm.entities;
|
package org.whispersystems.textsecuregcm.entities;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class StaleDevices {
|
public class StaleDevices {
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
|
@Schema(description = "Devices that are no longer active")
|
||||||
private List<Long> staleDevices;
|
private List<Long> staleDevices;
|
||||||
|
|
||||||
public StaleDevices() {}
|
public StaleDevices() {}
|
||||||
|
|
|
@ -47,14 +47,16 @@ class RegistrationLockVerificationManagerTest {
|
||||||
|
|
||||||
private final AccountsManager accountsManager = mock(AccountsManager.class);
|
private final AccountsManager accountsManager = mock(AccountsManager.class);
|
||||||
private final ClientPresenceManager clientPresenceManager = mock(ClientPresenceManager.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);
|
ExternalServiceCredentialsGenerator.class);
|
||||||
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager = mock(
|
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager = mock(
|
||||||
RegistrationRecoveryPasswordsManager.class);
|
RegistrationRecoveryPasswordsManager.class);
|
||||||
private static PushNotificationManager pushNotificationManager = mock(PushNotificationManager.class);
|
private static PushNotificationManager pushNotificationManager = mock(PushNotificationManager.class);
|
||||||
private final RateLimiters rateLimiters = mock(RateLimiters.class);
|
private final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||||
private final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager(
|
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);
|
private final RateLimiter pinLimiter = mock(RateLimiter.class);
|
||||||
|
|
||||||
|
@ -65,7 +67,9 @@ class RegistrationLockVerificationManagerTest {
|
||||||
void setUp() {
|
void setUp() {
|
||||||
clearInvocations(pushNotificationManager);
|
clearInvocations(pushNotificationManager);
|
||||||
when(rateLimiters.getPinLimiter()).thenReturn(pinLimiter);
|
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));
|
.thenReturn(mock(ExternalServiceCredentials.class));
|
||||||
|
|
||||||
final Device device = mock(Device.class);
|
final Device device = mock(Device.class);
|
||||||
|
|
|
@ -72,6 +72,7 @@ import org.signal.libsignal.protocol.ecc.ECKeyPair;
|
||||||
import org.signal.libsignal.usernames.BaseUsernameException;
|
import org.signal.libsignal.usernames.BaseUsernameException;
|
||||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
||||||
import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount;
|
import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount;
|
||||||
|
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
||||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator;
|
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator;
|
||||||
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager;
|
||||||
import org.whispersystems.textsecuregcm.auth.SaltedTokenHash;
|
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.CaptchaChecker;
|
||||||
import org.whispersystems.textsecuregcm.captcha.RegistrationCaptchaManager;
|
import org.whispersystems.textsecuregcm.captcha.RegistrationCaptchaManager;
|
||||||
import org.whispersystems.textsecuregcm.configuration.SecureBackupServiceConfiguration;
|
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.DynamicCaptchaConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
import org.whispersystems.textsecuregcm.entities.AccountAttributes;
|
||||||
|
@ -199,15 +201,25 @@ class AccountControllerTest {
|
||||||
private static DynamicConfigurationManager dynamicConfigurationManager = mock(DynamicConfigurationManager.class);
|
private static DynamicConfigurationManager dynamicConfigurationManager = mock(DynamicConfigurationManager.class);
|
||||||
private byte[] registration_lock_key = new byte[32];
|
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,
|
SecureBackupServiceConfiguration.class,
|
||||||
cfg -> when(cfg.getUserAuthenticationTokenSharedSecret()).thenReturn(new byte[32]));
|
cfg -> when(cfg.getUserAuthenticationTokenSharedSecret()).thenReturn(new byte[32]));
|
||||||
|
|
||||||
private static final ExternalServiceCredentialsGenerator backupCredentialsGenerator = SecureBackupController.credentialsGenerator(
|
private static final SecureValueRecovery2Configuration SVR2_CFG = MockUtils.buildMock(
|
||||||
BACKUP_CFG);
|
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(
|
private static final RegistrationLockVerificationManager registrationLockVerificationManager = new RegistrationLockVerificationManager(
|
||||||
accountsManager, clientPresenceManager, backupCredentialsGenerator, registrationRecoveryPasswordsManager,
|
accountsManager, clientPresenceManager, svr1CredentialsGenerator, svr2CredentialsGenerator, registrationRecoveryPasswordsManager,
|
||||||
pushNotificationManager, rateLimiters);
|
pushNotificationManager, rateLimiters);
|
||||||
private static final RegistrationCaptchaManager registrationCaptchaManager = new RegistrationCaptchaManager(
|
private static final RegistrationCaptchaManager registrationCaptchaManager = new RegistrationCaptchaManager(
|
||||||
captchaChecker, rateLimiters, Map.of(TEST_NUMBER, 123456), dynamicConfigurationManager);
|
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().username()).isEqualTo(SENDER_REG_LOCK_UUID.toString());
|
||||||
assertThat(failure.backupCredentials().password()).isNotEmpty();
|
assertThat(failure.backupCredentials().password()).isNotEmpty();
|
||||||
assertThat(failure.backupCredentials().password().startsWith(SENDER_REG_LOCK_UUID.toString())).isTrue();
|
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);
|
assertThat(failure.timeRemaining()).isGreaterThan(0);
|
||||||
|
|
||||||
// verify(senderRegLockAccount).lockAuthenticationCredentials();
|
// verify(senderRegLockAccount).lockAuthenticationCredentials();
|
||||||
|
|
|
@ -71,7 +71,6 @@ import org.whispersystems.textsecuregcm.entities.AccountDataReportResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
import org.whispersystems.textsecuregcm.entities.AccountIdentityResponse;
|
||||||
import org.whispersystems.textsecuregcm.entities.ChangeNumberRequest;
|
import org.whispersystems.textsecuregcm.entities.ChangeNumberRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneNumberDiscoverabilityRequest;
|
import org.whispersystems.textsecuregcm.entities.PhoneNumberDiscoverabilityRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.PhoneNumberIdentityKeyDistributionRequest;
|
|
||||||
import org.whispersystems.textsecuregcm.entities.RegistrationServiceSession;
|
import org.whispersystems.textsecuregcm.entities.RegistrationServiceSession;
|
||||||
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
import org.whispersystems.textsecuregcm.entities.SignedPreKey;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||||
|
|
Loading…
Reference in New Issue