Support configurable verification code sender overrides

This commit is contained in:
Ravi Khadiwala 2024-01-17 11:01:25 -06:00 committed by ravi-signal
parent db4aa99ce0
commit f5080f9bd6
12 changed files with 244 additions and 53 deletions

View File

@ -172,6 +172,7 @@ import org.whispersystems.textsecuregcm.spam.PushChallengeConfigProvider;
import org.whispersystems.textsecuregcm.spam.RateLimitChallengeListener; import org.whispersystems.textsecuregcm.spam.RateLimitChallengeListener;
import org.whispersystems.textsecuregcm.spam.ReportSpamTokenProvider; import org.whispersystems.textsecuregcm.spam.ReportSpamTokenProvider;
import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider; import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider;
import org.whispersystems.textsecuregcm.spam.SenderOverrideProvider;
import org.whispersystems.textsecuregcm.spam.SpamFilter; import org.whispersystems.textsecuregcm.spam.SpamFilter;
import org.whispersystems.textsecuregcm.storage.AccountLockManager; import org.whispersystems.textsecuregcm.storage.AccountLockManager;
import org.whispersystems.textsecuregcm.storage.Accounts; import org.whispersystems.textsecuregcm.storage.Accounts;
@ -886,8 +887,9 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
WebSocketEnvironment<AuthenticatedAccount> webSocketEnvironment, WebSocketEnvironment<AuthenticatedAccount> webSocketEnvironment,
WebSocketEnvironment<AuthenticatedAccount> provisioningEnvironment) { WebSocketEnvironment<AuthenticatedAccount> provisioningEnvironment) {
List.of( List.of(
ScoreThresholdProvider.ScoreThresholdFeature.class, ScoreThresholdProvider.ScoreThresholdFeature.class,
PushChallengeConfigProvider.PushChallengeConfigFeature.class) SenderOverrideProvider.SenderOverrideFeature.class,
PushChallengeConfigProvider.PushChallengeConfigFeature.class)
.forEach(feature -> { .forEach(feature -> {
environment.jersey().register(feature); environment.jersey().register(feature);
webSocketEnvironment.jersey().register(feature); webSocketEnvironment.jersey().register(feature);

View File

@ -82,6 +82,7 @@ import org.whispersystems.textsecuregcm.registration.VerificationSession;
import org.whispersystems.textsecuregcm.spam.Extract; import org.whispersystems.textsecuregcm.spam.Extract;
import org.whispersystems.textsecuregcm.spam.FilterSpam; import org.whispersystems.textsecuregcm.spam.FilterSpam;
import org.whispersystems.textsecuregcm.spam.ScoreThreshold; import org.whispersystems.textsecuregcm.spam.ScoreThreshold;
import org.whispersystems.textsecuregcm.spam.SenderOverride;
import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager; import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
@ -184,7 +185,7 @@ public class VerificationController {
} }
VerificationSession verificationSession = new VerificationSession(null, new ArrayList<>(), VerificationSession verificationSession = new VerificationSession(null, new ArrayList<>(),
Collections.emptyList(), false, Collections.emptyList(), null, null, false,
clock.millis(), clock.millis(), registrationServiceSession.expiration()); clock.millis(), clock.millis(), registrationServiceSession.expiration());
verificationSession = handlePushToken(pushTokenAndType, verificationSession); verificationSession = handlePushToken(pushTokenAndType, verificationSession);
@ -207,7 +208,8 @@ public class VerificationController {
@HeaderParam(HttpHeaders.USER_AGENT) final String userAgent, @HeaderParam(HttpHeaders.USER_AGENT) final String userAgent,
@Context HttpServletRequest request, @Context HttpServletRequest request,
@NotNull @Valid final UpdateVerificationSessionRequest updateVerificationSessionRequest, @NotNull @Valid final UpdateVerificationSessionRequest updateVerificationSessionRequest,
@NotNull @Extract final ScoreThreshold captchaScoreThreshold) { @NotNull @Extract final ScoreThreshold scoreThreshold,
@NotNull @Extract final SenderOverride senderOverride) {
final String sourceHost = useRemoteAddress final String sourceHost = useRemoteAddress
? request.getRemoteAddr() ? request.getRemoteAddr()
@ -221,13 +223,16 @@ public class VerificationController {
try { try {
// these handle* methods ordered from least likely to fail to most, so take care when considering a change // these handle* methods ordered from least likely to fail to most, so take care when considering a change
verificationSession = handleSenderOverrides(verificationSession, senderOverride);
verificationSession = handlePushToken(pushTokenAndType, verificationSession); verificationSession = handlePushToken(pushTokenAndType, verificationSession);
verificationSession = handlePushChallenge(updateVerificationSessionRequest, registrationServiceSession, verificationSession = handlePushChallenge(updateVerificationSessionRequest, registrationServiceSession,
verificationSession); verificationSession);
verificationSession = handleCaptcha(sourceHost, updateVerificationSessionRequest, registrationServiceSession, verificationSession = handleCaptcha(sourceHost, updateVerificationSessionRequest, registrationServiceSession,
verificationSession, userAgent, captchaScoreThreshold.getScoreThreshold()); verificationSession, userAgent, scoreThreshold.getScoreThreshold());
} catch (final RateLimitExceededException e) { } catch (final RateLimitExceededException e) {
final Response response = buildResponseForRateLimitExceeded(verificationSession, registrationServiceSession, final Response response = buildResponseForRateLimitExceeded(verificationSession, registrationServiceSession,
@ -280,7 +285,8 @@ public class VerificationController {
requestedInformation.addAll(verificationSession.requestedInformation()); requestedInformation.addAll(verificationSession.requestedInformation());
verificationSession = new VerificationSession(generatePushChallenge(), requestedInformation, verificationSession = new VerificationSession(generatePushChallenge(), requestedInformation,
verificationSession.submittedInformation(), verificationSession.allowedToRequestCode(), verificationSession.submittedInformation(), verificationSession.smsSenderOverride(),
verificationSession.voiceSenderOverride(), verificationSession.allowedToRequestCode(),
verificationSession.createdTimestamp(), clock.millis(), verificationSession.remoteExpirationSeconds() verificationSession.createdTimestamp(), clock.millis(), verificationSession.remoteExpirationSeconds()
); );
} }
@ -348,7 +354,8 @@ public class VerificationController {
&& requestedInformation.isEmpty(); && requestedInformation.isEmpty();
verificationSession = new VerificationSession(verificationSession.pushChallenge(), requestedInformation, verificationSession = new VerificationSession(verificationSession.pushChallenge(), requestedInformation,
submittedInformation, allowedToRequestCode, verificationSession.createdTimestamp(), clock.millis(), submittedInformation, verificationSession.smsSenderOverride(), verificationSession.voiceSenderOverride(),
allowedToRequestCode, verificationSession.createdTimestamp(), clock.millis(),
verificationSession.remoteExpirationSeconds()); verificationSession.remoteExpirationSeconds());
} else if (pushChallengePresent) { } else if (pushChallengePresent) {
@ -413,7 +420,8 @@ public class VerificationController {
&& requestedInformation.isEmpty(); && requestedInformation.isEmpty();
verificationSession = new VerificationSession(verificationSession.pushChallenge(), requestedInformation, verificationSession = new VerificationSession(verificationSession.pushChallenge(), requestedInformation,
submittedInformation, allowedToRequestCode, verificationSession.createdTimestamp(), clock.millis(), submittedInformation, verificationSession.smsSenderOverride(), verificationSession.voiceSenderOverride(),
allowedToRequestCode, verificationSession.createdTimestamp(), clock.millis(),
verificationSession.remoteExpirationSeconds()); verificationSession.remoteExpirationSeconds());
} else { } else {
throw new ForbiddenException(); throw new ForbiddenException();
@ -422,6 +430,31 @@ public class VerificationController {
return verificationSession; return verificationSession;
} }
/**
* Update the verification session with explicit sender overrides if present. When the session is used to send
* verification codes, these overrides will be used.
*
* @param verificationSession the session to update
* @param senderOverride configured sender overrides
* @return An updated {@link VerificationSession}
*/
private VerificationSession handleSenderOverrides(
VerificationSession verificationSession,
SenderOverride senderOverride) {
return new VerificationSession(
verificationSession.pushChallenge(),
verificationSession.requestedInformation(),
verificationSession.submittedInformation(),
Optional.ofNullable(verificationSession.smsSenderOverride())
.or(senderOverride::getSmsSenderOverride).orElse(null),
Optional.ofNullable(verificationSession.voiceSenderOverride())
.or(senderOverride::getVoiceSenderOverride)
.orElse(null), verificationSession.allowedToRequestCode(),
verificationSession.createdTimestamp(),
clock.millis(),
verificationSession.remoteExpirationSeconds());
}
@GET @GET
@Path("/session/{sessionId}") @Path("/session/{sessionId}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@ -476,12 +509,19 @@ public class VerificationController {
} }
}; };
final String senderOverride = switch (messageTransport) {
case SMS -> verificationSession.smsSenderOverride();
case VOICE -> verificationSession.voiceSenderOverride();
};
final RegistrationServiceSession resultSession; final RegistrationServiceSession resultSession;
try { try {
resultSession = registrationServiceClient.sendVerificationCode(registrationServiceSession.id(), resultSession = registrationServiceClient.sendVerificationCode(registrationServiceSession.id(),
messageTransport, messageTransport,
clientType, clientType,
acceptLanguage.orElse(null), REGISTRATION_RPC_TIMEOUT).join(); acceptLanguage.orElse(null),
senderOverride,
REGISTRATION_RPC_TIMEOUT).join();
} catch (final CancellationException e) { } catch (final CancellationException e) {
throw new ServerErrorException("registration service unavailable", Response.Status.SERVICE_UNAVAILABLE); throw new ServerErrorException("registration service unavailable", Response.Status.SERVICE_UNAVAILABLE);
} catch (final CompletionException e) { } catch (final CompletionException e) {

View File

@ -114,6 +114,7 @@ public class RegistrationServiceClient implements Managed {
final MessageTransport messageTransport, final MessageTransport messageTransport,
final ClientType clientType, final ClientType clientType,
@Nullable final String acceptLanguage, @Nullable final String acceptLanguage,
@Nullable final String senderOverride,
final Duration timeout) { final Duration timeout) {
final SendVerificationCodeRequest.Builder requestBuilder = SendVerificationCodeRequest.newBuilder() final SendVerificationCodeRequest.Builder requestBuilder = SendVerificationCodeRequest.newBuilder()
@ -125,6 +126,10 @@ public class RegistrationServiceClient implements Managed {
requestBuilder.setAcceptLanguage(acceptLanguage); requestBuilder.setAcceptLanguage(acceptLanguage);
} }
if (StringUtils.isNotBlank(senderOverride)) {
requestBuilder.setSenderName(senderOverride);
}
return toCompletableFuture(stub.withDeadline(toDeadline(timeout)) return toCompletableFuture(stub.withDeadline(toDeadline(timeout))
.sendVerificationCode(requestBuilder.build())) .sendVerificationCode(requestBuilder.build()))
.thenApply(response -> { .thenApply(response -> {

View File

@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.registration;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.whispersystems.textsecuregcm.storage.SerializedExpireableJsonDynamoStore; import org.whispersystems.textsecuregcm.storage.SerializedExpireableJsonDynamoStore;
@ -20,6 +21,10 @@ import org.whispersystems.textsecuregcm.storage.SerializedExpireableJsonDynamoSt
* @param pushChallenge the value of a push challenge sent to a client, after it submitted a push token * @param pushChallenge the value of a push challenge sent to a client, after it submitted a push token
* @param requestedInformation information requested that a client send to the server * @param requestedInformation information requested that a client send to the server
* @param submittedInformation information that a client has submitted and that the server has verified * @param submittedInformation information that a client has submitted and that the server has verified
* @param smsSenderOverride if present, indicates a sender override argument that should be forwarded to the
* Registration Service when requesting a code
* @param voiceSenderOverride if present, indicates a sender override argument that should be forwarded to the
* Registration Service when requesting a code
* @param allowedToRequestCode whether the client is allowed to request a code. This request will be forwarded to * @param allowedToRequestCode whether the client is allowed to request a code. This request will be forwarded to
* Registration Service * Registration Service
* @param createdTimestamp when this session was created * @param createdTimestamp when this session was created
@ -29,11 +34,16 @@ import org.whispersystems.textsecuregcm.storage.SerializedExpireableJsonDynamoSt
* @see org.whispersystems.textsecuregcm.entities.RegistrationServiceSession * @see org.whispersystems.textsecuregcm.entities.RegistrationServiceSession
* @see org.whispersystems.textsecuregcm.entities.VerificationSessionResponse * @see org.whispersystems.textsecuregcm.entities.VerificationSessionResponse
*/ */
public record VerificationSession(@Nullable String pushChallenge, public record VerificationSession(
List<Information> requestedInformation, List<Information> submittedInformation, @Nullable String pushChallenge,
boolean allowedToRequestCode, long createdTimestamp, long updatedTimestamp, List<Information> requestedInformation,
long remoteExpirationSeconds) implements List<Information> submittedInformation,
SerializedExpireableJsonDynamoStore.Expireable { @Nullable String smsSenderOverride,
@Nullable String voiceSenderOverride,
boolean allowedToRequestCode,
long createdTimestamp,
long updatedTimestamp,
long remoteExpirationSeconds) implements SerializedExpireableJsonDynamoStore.Expireable {
@Override @Override
public long getExpirationEpochSeconds() { public long getExpirationEpochSeconds() {

View File

@ -12,10 +12,11 @@ import java.util.Optional;
/** /**
* A ScoreThreshold may be provided by an upstream request filter. If request contains a property for * A ScoreThreshold may be provided by an upstream request filter. If request contains a property for
* SCORE_THRESHOLD_PROPERTY_NAME it can be forwarded to a downstream filter to indicate it can use * {@link #PROPERTY_NAME} it can be forwarded to a downstream filter to indicate it can use a more or less strict
* a more or less strict score threshold when evaluating whether a request should be allowed to continue. * score threshold when evaluating whether a request should be allowed to continue.
*/ */
public class ScoreThreshold { public class ScoreThreshold {
private static final Logger logger = LoggerFactory.getLogger(ScoreThreshold.class); private static final Logger logger = LoggerFactory.getLogger(ScoreThreshold.class);
public static final String PROPERTY_NAME = "scoreThreshold"; public static final String PROPERTY_NAME = "scoreThreshold";

View File

@ -1,3 +1,7 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.spam; package org.whispersystems.textsecuregcm.spam;
import java.util.function.Function; import java.util.function.Function;
@ -11,11 +15,11 @@ import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
/** /**
* Parses a {@link ScoreThreshold} out of a {@link ContainerRequest} to provide to jersey resources. * Parses a {@link ScoreThreshold} out of a {@link ContainerRequest} to provide to jersey resources.
* * <p>
* A request filter may enrich a ContainerRequest with a scoreThreshold by providing a float property with the name * A request filter may enrich a ContainerRequest with a scoreThreshold by providing a float property with the name
* {@link ScoreThreshold#PROPERTY_NAME}. This indicates the desired scoreThreshold to use when evaluating whether a * {@link ScoreThreshold#PROPERTY_NAME}. This indicates the desired scoreThreshold to use when evaluating whether a
* request should proceed. * request should proceed.
* * <p>
* A resource can consume a ScoreThreshold with by annotating a ScoreThreshold parameter with {@link Extract} * A resource can consume a ScoreThreshold with by annotating a ScoreThreshold parameter with {@link Extract}
*/ */
public class ScoreThresholdProvider implements ValueParamProvider { public class ScoreThresholdProvider implements ValueParamProvider {
@ -24,6 +28,7 @@ public class ScoreThresholdProvider implements ValueParamProvider {
* Configures the ScoreThresholdProvider * Configures the ScoreThresholdProvider
*/ */
public static class ScoreThresholdFeature implements Feature { public static class ScoreThresholdFeature implements Feature {
@Override @Override
public boolean configure(FeatureContext context) { public boolean configure(FeatureContext context) {
context.register(new AbstractBinder() { context.register(new AbstractBinder() {

View File

@ -0,0 +1,61 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.spam;
import org.glassfish.jersey.server.ContainerRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Optional;
/**
* A SenderOverride may be provided by an upstream request filter. If request contains a property for
* {@link #SMS_SENDER_OVERRIDE_PROPERTY_NAME} or {@link #VOICE_SENDER_OVERRIDE_PROPERTY_NAME} it can be
* forwarded to a downstream filter to indicate a specific sender should be used when sending verification codes.
*/
public class SenderOverride {
private static final Logger logger = LoggerFactory.getLogger(SenderOverride.class);
public static final String SMS_SENDER_OVERRIDE_PROPERTY_NAME = "smsSenderOverride";
public static final String VOICE_SENDER_OVERRIDE_PROPERTY_NAME = "voiceSenderOverride";
/**
* The name of the sender to use to deliver a verification code via SMS
*/
private final Optional<String> smsSenderOverride;
/**
* The name of the sender to use to deliver a verification code via voice
*/
private final Optional<String> voiceSenderOverride;
public SenderOverride(final ContainerRequest containerRequest) {
this.smsSenderOverride = parse(String.class, SMS_SENDER_OVERRIDE_PROPERTY_NAME, containerRequest);
this.voiceSenderOverride = parse(String.class, VOICE_SENDER_OVERRIDE_PROPERTY_NAME, containerRequest);
}
private static <T> Optional<T> parse(Class<T> type, final String propertyName,
final ContainerRequest containerRequest) {
return Optional
.ofNullable(containerRequest.getProperty(propertyName))
.flatMap(obj -> {
if (type.isInstance(obj)) {
return Optional.of(type.cast(obj));
}
logger.warn("invalid format for filter provided property {}: {}", propertyName, obj);
return Optional.empty();
});
}
public Optional<String> getSmsSenderOverride() {
return smsSenderOverride;
}
public Optional<String> getVoiceSenderOverride() {
return voiceSenderOverride;
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.spam;
import java.util.function.Function;
import javax.inject.Singleton;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.model.Parameter;
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
/**
* Parses a {@link SenderOverride} out of a {@link ContainerRequest} to provide to jersey resources.
* <p>
* A request filter may enrich a ContainerRequest with senderOverrides by providing a string property names defined in
* {@link SenderOverride}. This indicates the desired senderOverride to use when sending verification codes.
* <p>
* A resource can consume a SenderOverride with by annotating a SenderOverride parameter with {@link Extract}
*/
public class SenderOverrideProvider implements ValueParamProvider {
/**
* Configures the SenderOverrideProvider
*/
public static class SenderOverrideFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
context.register(new AbstractBinder() {
@Override
protected void configure() {
bind(SenderOverrideProvider.class)
.to(ValueParamProvider.class)
.in(Singleton.class);
}
});
return true;
}
}
@Override
public Function<ContainerRequest, ?> getValueProvider(final Parameter parameter) {
if (parameter.getRawType().equals(SenderOverride.class)
&& parameter.isAnnotationPresent(Extract.class)) {
return SenderOverride::new;
}
return null;
}
@Override
public PriorityType getPriority() {
return Priority.HIGH;
}
}

View File

@ -79,6 +79,7 @@ import org.whispersystems.textsecuregcm.mappers.JsonMappingExceptionMapper;
import org.whispersystems.textsecuregcm.mappers.NonNormalizedPhoneNumberExceptionMapper; import org.whispersystems.textsecuregcm.mappers.NonNormalizedPhoneNumberExceptionMapper;
import org.whispersystems.textsecuregcm.mappers.RateLimitExceededExceptionMapper; import org.whispersystems.textsecuregcm.mappers.RateLimitExceededExceptionMapper;
import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider; import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider;
import org.whispersystems.textsecuregcm.spam.SenderOverrideProvider;
import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager; import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
@ -149,6 +150,7 @@ class AccountControllerTest {
.addProvider(new NonNormalizedPhoneNumberExceptionMapper()) .addProvider(new NonNormalizedPhoneNumberExceptionMapper())
.addProvider(new RateLimitByIpFilter(rateLimiters, true)) .addProvider(new RateLimitByIpFilter(rateLimiters, true))
.addProvider(ScoreThresholdProvider.ScoreThresholdFeature.class) .addProvider(ScoreThresholdProvider.ScoreThresholdFeature.class)
.addProvider(SenderOverrideProvider.SenderOverrideFeature.class)
.setMapper(SystemMapper.jsonMapper()) .setMapper(SystemMapper.jsonMapper())
.setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory())
.addResource(new AccountController( .addResource(new AccountController(

View File

@ -43,6 +43,8 @@ import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
import org.whispersystems.textsecuregcm.spam.PushChallengeConfigProvider; import org.whispersystems.textsecuregcm.spam.PushChallengeConfigProvider;
import org.whispersystems.textsecuregcm.spam.ScoreThreshold; import org.whispersystems.textsecuregcm.spam.ScoreThreshold;
import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider; import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider;
import org.whispersystems.textsecuregcm.spam.SenderOverride;
import org.whispersystems.textsecuregcm.spam.SenderOverrideProvider;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper; import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import org.whispersystems.textsecuregcm.util.SystemMapper; import org.whispersystems.textsecuregcm.util.SystemMapper;

View File

@ -74,6 +74,7 @@ import org.whispersystems.textsecuregcm.registration.RegistrationServiceSenderEx
import org.whispersystems.textsecuregcm.registration.TransportNotAllowedException; import org.whispersystems.textsecuregcm.registration.TransportNotAllowedException;
import org.whispersystems.textsecuregcm.registration.VerificationSession; import org.whispersystems.textsecuregcm.registration.VerificationSession;
import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider; import org.whispersystems.textsecuregcm.spam.ScoreThresholdProvider;
import org.whispersystems.textsecuregcm.spam.SenderOverrideProvider;
import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager; import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
@ -112,6 +113,7 @@ class VerificationControllerTest {
.addProvider(new NonNormalizedPhoneNumberExceptionMapper()) .addProvider(new NonNormalizedPhoneNumberExceptionMapper())
.addProvider(new RegistrationServiceSenderExceptionMapper()) .addProvider(new RegistrationServiceSenderExceptionMapper())
.addProvider(ScoreThresholdProvider.ScoreThresholdFeature.class) .addProvider(ScoreThresholdProvider.ScoreThresholdFeature.class)
.addProvider(SenderOverrideProvider.SenderOverrideFeature.class)
.setMapper(SystemMapper.jsonMapper()) .setMapper(SystemMapper.jsonMapper())
.setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory())
.addResource( .addResource(
@ -313,7 +315,7 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of( Optional.of(
new VerificationSession(null, List.of(VerificationSession.Information.CAPTCHA), Collections.emptyList(), new VerificationSession(null, List.of(VerificationSession.Information.CAPTCHA), Collections.emptyList(),
false, clock.millis(), clock.millis(), registrationServiceSession.expiration())))); null, null, false, clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(verificationSessionManager.update(any(), any())) when(verificationSessionManager.update(any(), any()))
.thenReturn(CompletableFuture.completedFuture(null)); .thenReturn(CompletableFuture.completedFuture(null));
@ -356,7 +358,7 @@ class VerificationControllerTest {
registrationServiceSession))); registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), false, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, false,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(verificationSessionManager.update(any(), any())) when(verificationSessionManager.update(any(), any()))
@ -392,7 +394,7 @@ class VerificationControllerTest {
registrationServiceSession))); registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), false, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, false,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(verificationSessionManager.update(any(), any())) when(verificationSessionManager.update(any(), any()))
@ -429,7 +431,7 @@ class VerificationControllerTest {
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession("challenge", List.of(VerificationSession.Information.PUSH_CHALLENGE), Optional.of(new VerificationSession("challenge", List.of(VerificationSession.Information.PUSH_CHALLENGE),
Collections.emptyList(), false, clock.millis(), clock.millis(), Collections.emptyList(), null, null, false, clock.millis(), clock.millis(),
registrationServiceSession.expiration())))); registrationServiceSession.expiration()))));
when(verificationSessionManager.update(any(), any())) when(verificationSessionManager.update(any(), any()))
.thenReturn(CompletableFuture.completedFuture(null)); .thenReturn(CompletableFuture.completedFuture(null));
@ -463,7 +465,7 @@ class VerificationControllerTest {
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, List.of(VerificationSession.Information.CAPTCHA), Optional.of(new VerificationSession(null, List.of(VerificationSession.Information.CAPTCHA),
Collections.emptyList(), false, clock.millis(), clock.millis(), Collections.emptyList(), null, null, false, clock.millis(), clock.millis(),
registrationServiceSession.expiration())))); registrationServiceSession.expiration()))));
when(registrationCaptchaManager.assessCaptcha(any(), any())) when(registrationCaptchaManager.assessCaptcha(any(), any()))
@ -511,7 +513,8 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession("challenge", Optional.of(new VerificationSession("challenge",
List.of(VerificationSession.Information.CAPTCHA), List.of(VerificationSession.Information.CAPTCHA),
List.of(VerificationSession.Information.PUSH_CHALLENGE), false, List.of(VerificationSession.Information.PUSH_CHALLENGE),
null, null, false,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(verificationSessionManager.update(any(), any())) when(verificationSessionManager.update(any(), any()))
.thenReturn(CompletableFuture.completedFuture(null)); .thenReturn(CompletableFuture.completedFuture(null));
@ -553,8 +556,8 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession("challenge", List.of(), List.of(), true, clock.millis(), clock.millis(), Optional.of(new VerificationSession("challenge", List.of(), List.of(), null, null, true,
registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(verificationSessionManager.update(any(), any())) when(verificationSessionManager.update(any(), any()))
.thenReturn(CompletableFuture.completedFuture(null)); .thenReturn(CompletableFuture.completedFuture(null));
@ -591,7 +594,7 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession("challenge", Optional.of(new VerificationSession("challenge",
List.of(VerificationSession.Information.PUSH_CHALLENGE, VerificationSession.Information.CAPTCHA), List.of(VerificationSession.Information.PUSH_CHALLENGE, VerificationSession.Information.CAPTCHA),
Collections.emptyList(), false, clock.millis(), clock.millis(), Collections.emptyList(), null, null, false, clock.millis(), clock.millis(),
registrationServiceSession.expiration())))); registrationServiceSession.expiration()))));
when(verificationSessionManager.update(any(), any())) when(verificationSessionManager.update(any(), any()))
.thenReturn(CompletableFuture.completedFuture(null)); .thenReturn(CompletableFuture.completedFuture(null));
@ -634,7 +637,7 @@ class VerificationControllerTest {
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, List.of(VerificationSession.Information.CAPTCHA), Optional.of(new VerificationSession(null, List.of(VerificationSession.Information.CAPTCHA),
Collections.emptyList(), false, clock.millis(), clock.millis(), Collections.emptyList(), null, null, false, clock.millis(), clock.millis(),
registrationServiceSession.expiration())))); registrationServiceSession.expiration()))));
when(registrationCaptchaManager.assessCaptcha(any(), any())) when(registrationCaptchaManager.assessCaptcha(any(), any()))
@ -682,7 +685,7 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession("challenge", Optional.of(new VerificationSession("challenge",
List.of(VerificationSession.Information.CAPTCHA, VerificationSession.Information.CAPTCHA), List.of(VerificationSession.Information.CAPTCHA, VerificationSession.Information.CAPTCHA),
Collections.emptyList(), false, clock.millis(), clock.millis(), Collections.emptyList(), null, null, false, clock.millis(), clock.millis(),
registrationServiceSession.expiration())))); registrationServiceSession.expiration()))));
when(registrationCaptchaManager.assessCaptcha(any(), any())) when(registrationCaptchaManager.assessCaptcha(any(), any()))
@ -729,7 +732,7 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Optional.of(new VerificationSession(null,
List.of(VerificationSession.Information.CAPTCHA), List.of(VerificationSession.Information.CAPTCHA),
Collections.emptyList(), false, clock.millis(), clock.millis(), Collections.emptyList(), null, null, false, clock.millis(), clock.millis(),
registrationServiceSession.expiration())))); registrationServiceSession.expiration()))));
when(registrationCaptchaManager.assessCaptcha(any(), any())) when(registrationCaptchaManager.assessCaptcha(any(), any()))
@ -884,9 +887,9 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession))); .thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any())) when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any(), any()))
.thenReturn(CompletableFuture.completedFuture(registrationServiceSession)); .thenReturn(CompletableFuture.completedFuture(registrationServiceSession));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -915,7 +918,7 @@ class VerificationControllerTest {
registrationServiceSession))); registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture(Optional.of(new VerificationSession(null, List.of( .thenReturn(CompletableFuture.completedFuture(Optional.of(new VerificationSession(null, List.of(
VerificationSession.Information.CAPTCHA), Collections.emptyList(), false, clock.millis(), clock.millis(), VerificationSession.Information.CAPTCHA), Collections.emptyList(), null, null, false, clock.millis(), clock.millis(),
registrationServiceSession.expiration())))); registrationServiceSession.expiration()))));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -946,7 +949,7 @@ class VerificationControllerTest {
registrationServiceSession))); registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), false, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, false,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -974,9 +977,9 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession))); .thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any())) when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any(), any()))
.thenReturn(CompletableFuture.failedFuture( .thenReturn(CompletableFuture.failedFuture(
new CompletionException(new VerificationSessionRateLimitExceededException(registrationServiceSession, new CompletionException(new VerificationSessionRateLimitExceededException(registrationServiceSession,
Duration.ofMinutes(1), true)))); Duration.ofMinutes(1), true))));
@ -1006,9 +1009,9 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession))); .thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any())) when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any(), any()))
.thenReturn(CompletableFuture.failedFuture( .thenReturn(CompletableFuture.failedFuture(
new CompletionException(new TransportNotAllowedException(registrationServiceSession)))); new CompletionException(new TransportNotAllowedException(registrationServiceSession))));
@ -1038,9 +1041,9 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession))); .thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any())) when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any(), any()))
.thenReturn(CompletableFuture.completedFuture(registrationServiceSession)); .thenReturn(CompletableFuture.completedFuture(registrationServiceSession));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -1071,10 +1074,10 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any())) when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any(), any()))
.thenReturn( .thenReturn(
CompletableFuture.failedFuture(new CompletionException(exception))); CompletableFuture.failedFuture(new CompletionException(exception)));
@ -1115,10 +1118,10 @@ class VerificationControllerTest {
.thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession))); .thenReturn(CompletableFuture.completedFuture(Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any())) when(registrationServiceClient.sendVerificationCode(any(), any(), any(), any(), any(), any()))
.thenReturn(CompletableFuture.failedFuture(new CompletionException( .thenReturn(CompletableFuture.failedFuture(new CompletionException(
new RegistrationFraudException(RegistrationServiceSenderException.rejected(true))))); new RegistrationFraudException(RegistrationServiceSenderException.rejected(true)))));
@ -1149,7 +1152,7 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.checkVerificationCode(any(), any(), any())) when(registrationServiceClient.checkVerificationCode(any(), any(), any()))
@ -1176,7 +1179,7 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
final Invocation.Builder request = resources.getJerseyTest() final Invocation.Builder request = resources.getJerseyTest()
@ -1211,7 +1214,7 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
// There is no explicit indication in the exception that no code has been sent, but we treat all RegistrationServiceExceptions // There is no explicit indication in the exception that no code has been sent, but we treat all RegistrationServiceExceptions
@ -1248,7 +1251,7 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.checkVerificationCode(any(), any(), any())) when(registrationServiceClient.checkVerificationCode(any(), any(), any()))
@ -1274,7 +1277,7 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
when(registrationServiceClient.checkVerificationCode(any(), any(), any())) when(registrationServiceClient.checkVerificationCode(any(), any(), any()))
.thenReturn(CompletableFuture.failedFuture( .thenReturn(CompletableFuture.failedFuture(
@ -1306,7 +1309,7 @@ class VerificationControllerTest {
Optional.of(registrationServiceSession))); Optional.of(registrationServiceSession)));
when(verificationSessionManager.findForId(any())) when(verificationSessionManager.findForId(any()))
.thenReturn(CompletableFuture.completedFuture( .thenReturn(CompletableFuture.completedFuture(
Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), true, Optional.of(new VerificationSession(null, Collections.emptyList(), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), registrationServiceSession.expiration())))); clock.millis(), clock.millis(), registrationServiceSession.expiration()))));
final RegistrationServiceSession verifiedSession = new RegistrationServiceSession(SESSION_ID, NUMBER, true, null, final RegistrationServiceSession verifiedSession = new RegistrationServiceSession(SESSION_ID, NUMBER, true, null,

View File

@ -47,7 +47,7 @@ class VerificationSessionsTest {
final Duration remoteExpiration = Duration.ofMinutes(2); final Duration remoteExpiration = Duration.ofMinutes(2);
final VerificationSession verificationSession = new VerificationSession(null, final VerificationSession verificationSession = new VerificationSession(null,
List.of(VerificationSession.Information.PUSH_CHALLENGE), Collections.emptyList(), true, List.of(VerificationSession.Information.PUSH_CHALLENGE), Collections.emptyList(), null, null, true,
created.toEpochMilli(), updates.toEpochMilli(), remoteExpiration.toSeconds()); created.toEpochMilli(), updates.toEpochMilli(), remoteExpiration.toSeconds());
assertEquals(updates.plus(remoteExpiration).getEpochSecond(), verificationSession.getExpirationEpochSeconds()); assertEquals(updates.plus(remoteExpiration).getEpochSecond(), verificationSession.getExpirationEpochSeconds());
@ -64,7 +64,7 @@ class VerificationSessionsTest {
assertTrue(absentSession.isEmpty()); assertTrue(absentSession.isEmpty());
final VerificationSession session = new VerificationSession(null, final VerificationSession session = new VerificationSession(null,
List.of(VerificationSession.Information.PUSH_CHALLENGE), Collections.emptyList(), true, List.of(VerificationSession.Information.PUSH_CHALLENGE), Collections.emptyList(), null, null, true,
clock.millis(), clock.millis(), Duration.ofMinutes(1).toSeconds()); clock.millis(), clock.millis(), Duration.ofMinutes(1).toSeconds());
verificationSessions.insert(sessionId, session).join(); verificationSessions.insert(sessionId, session).join();
@ -79,7 +79,7 @@ class VerificationSessionsTest {
"inserting with the same key should fail conditional checks"); "inserting with the same key should fail conditional checks");
final VerificationSession updatedSession = new VerificationSession(null, Collections.emptyList(), final VerificationSession updatedSession = new VerificationSession(null, Collections.emptyList(),
List.of(VerificationSession.Information.PUSH_CHALLENGE), true, clock.millis(), clock.millis(), List.of(VerificationSession.Information.PUSH_CHALLENGE), null, null, true, clock.millis(), clock.millis(),
Duration.ofMinutes(2).toSeconds()); Duration.ofMinutes(2).toSeconds());
verificationSessions.update(sessionId, updatedSession).join(); verificationSessions.update(sessionId, updatedSession).join();