From 195f23c347b0e3b2a4c3187375fbadf01ca92daa Mon Sep 17 00:00:00 2001 From: Chris Eager <79161849+eager-signal@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:51:57 -0600 Subject: [PATCH] Add `/v1/accounts` and `/v2/keys` to the WebSocket --- .../org/signal/openapi/OpenApiExtension.java | 13 -- .../org/signal/openapi/OpenApiReader.java | 6 +- .../textsecuregcm/WhisperServerService.java | 41 ++--- .../auth/AccountAuthenticator.java | 142 +++++++++++++- ...hEnablementRefreshRequirementProvider.java | 1 - .../auth/BaseAccountAuthenticator.java | 173 ------------------ .../auth/BasicAuthorizationHeader.java | 2 +- ...DisabledPermittedAccountAuthenticator.java | 26 --- ...DisabledPermittedAuthenticatedAccount.java | 42 ----- ...icCredentialAuthenticationInterceptor.java | 12 +- .../controllers/AccountController.java | 47 +++-- .../controllers/KeysController.java | 7 +- ...est.java => AccountAuthenticatorTest.java} | 56 +++--- ...blementRefreshRequirementProviderTest.java | 16 +- ...edentialAuthenticationInterceptorTest.java | 13 +- .../controllers/AccountControllerTest.java | 82 +++------ .../controllers/AccountControllerV2Test.java | 9 +- .../controllers/ArchiveControllerTest.java | 7 +- .../controllers/ArtControllerTest.java | 7 +- .../controllers/AttachmentControllerTest.java | 40 +--- .../controllers/CallLinkControllerTest.java | 7 +- .../CertificateControllerTest.java | 18 +- .../controllers/ChallengeControllerTest.java | 7 +- .../controllers/DeviceControllerTest.java | 18 +- .../controllers/DonationControllerTest.java | 7 +- .../controllers/KeysControllerTest.java | 50 +---- .../controllers/MessageControllerTest.java | 21 +-- .../controllers/PaymentsControllerTest.java | 18 +- .../controllers/ProfileControllerTest.java | 19 +- .../ProvisioningControllerTest.java | 7 +- .../RemoteConfigControllerTest.java | 9 +- .../SecureStorageControllerTest.java | 7 +- .../controllers/StickerControllerTest.java | 7 +- .../SubscriptionControllerTest.java | 6 +- .../storage/RemoteConfigsTest.java | 1 - .../textsecuregcm/tests/util/AuthHelper.java | 35 +--- spam-filter | 2 +- 37 files changed, 290 insertions(+), 691 deletions(-) delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/auth/BaseAccountAuthenticator.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAccountAuthenticator.java delete mode 100644 service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAuthenticatedAccount.java rename service/src/test/java/org/whispersystems/textsecuregcm/auth/{BaseAccountAuthenticatorTest.java => AccountAuthenticatorTest.java} (85%) diff --git a/api-doc/src/main/java/org/signal/openapi/OpenApiExtension.java b/api-doc/src/main/java/org/signal/openapi/OpenApiExtension.java index 136cbcf62..c0194e7a7 100644 --- a/api-doc/src/main/java/org/signal/openapi/OpenApiExtension.java +++ b/api-doc/src/main/java/org/signal/openapi/OpenApiExtension.java @@ -22,7 +22,6 @@ import java.util.ServiceLoader; import java.util.Set; import javax.ws.rs.Consumes; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; /** * One of the extension mechanisms of Swagger Core library (OpenAPI processor) is via custom implementations @@ -42,10 +41,6 @@ public class OpenApiExtension extends AbstractOpenAPIExtension { public static final ResolvedParameter OPTIONAL_AUTHENTICATED_ACCOUNT = new ResolvedParameter(); - public static final ResolvedParameter DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT = new ResolvedParameter(); - - public static final ResolvedParameter OPTIONAL_DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT = new ResolvedParameter(); - /** * When parsing endpoint methods, Swagger will treat the first parameter not annotated as header/path/query param * as a request body (and will ignore other not annotated parameters). In our case, this behavior conflicts with @@ -70,18 +65,10 @@ public class OpenApiExtension extends AbstractOpenAPIExtension { && simpleType.getRawClass().equals(AuthenticatedAccount.class)) { return AUTHENTICATED_ACCOUNT; } - if (type instanceof SimpleType simpleType - && simpleType.getRawClass().equals(DisabledPermittedAuthenticatedAccount.class)) { - return DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT; - } if (type instanceof SimpleType simpleType && isOptionalOfType(simpleType, AuthenticatedAccount.class)) { return OPTIONAL_AUTHENTICATED_ACCOUNT; } - if (type instanceof SimpleType simpleType - && isOptionalOfType(simpleType, DisabledPermittedAuthenticatedAccount.class)) { - return OPTIONAL_DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT; - } } return super.extractParameters( diff --git a/api-doc/src/main/java/org/signal/openapi/OpenApiReader.java b/api-doc/src/main/java/org/signal/openapi/OpenApiReader.java index 61585efe1..63f199c94 100644 --- a/api-doc/src/main/java/org/signal/openapi/OpenApiReader.java +++ b/api-doc/src/main/java/org/signal/openapi/OpenApiReader.java @@ -7,9 +7,7 @@ package org.signal.openapi; import static com.google.common.base.MoreObjects.firstNonNull; import static org.signal.openapi.OpenApiExtension.AUTHENTICATED_ACCOUNT; -import static org.signal.openapi.OpenApiExtension.DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT; import static org.signal.openapi.OpenApiExtension.OPTIONAL_AUTHENTICATED_ACCOUNT; -import static org.signal.openapi.OpenApiExtension.OPTIONAL_DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT; import com.fasterxml.jackson.annotation.JsonView; import com.google.common.collect.ImmutableList; @@ -54,13 +52,13 @@ public class OpenApiReader extends Reader { final ResolvedParameter resolved = super.getParameters( type, annotations, operation, classConsumes, methodConsumes, jsonViewAnnotation); - if (resolved == AUTHENTICATED_ACCOUNT || resolved == DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT) { + if (resolved == AUTHENTICATED_ACCOUNT) { operation.setSecurity(ImmutableList.builder() .addAll(firstNonNull(operation.getSecurity(), Collections.emptyList())) .add(new SecurityRequirement().addList(AUTHENTICATED_ACCOUNT_AUTH_SCHEMA)) .build()); } - if (resolved == OPTIONAL_AUTHENTICATED_ACCOUNT || resolved == OPTIONAL_DISABLED_PERMITTED_AUTHENTICATED_ACCOUNT) { + if (resolved == OPTIONAL_AUTHENTICATED_ACCOUNT) { operation.setSecurity(ImmutableList.builder() .addAll(firstNonNull(operation.getSecurity(), Collections.emptyList())) .add(new SecurityRequirement().addList(AUTHENTICATED_ACCOUNT_AUTH_SCHEMA)) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index d39c9c82d..362e5f4fd 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -7,12 +7,10 @@ package org.whispersystems.textsecuregcm; import static com.codahale.metrics.MetricRegistry.name; import static java.util.Objects.requireNonNull; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; +import io.dropwizard.auth.AuthDynamicFeature; import io.dropwizard.auth.AuthFilter; -import io.dropwizard.auth.PolymorphicAuthDynamicFeature; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.auth.basic.BasicCredentialAuthFilter; import io.dropwizard.auth.basic.BasicCredentials; import io.dropwizard.core.Application; @@ -61,10 +59,7 @@ import org.whispersystems.textsecuregcm.attachments.GcsAttachmentGenerator; import org.whispersystems.textsecuregcm.attachments.TusAttachmentGenerator; import org.whispersystems.textsecuregcm.auth.AccountAuthenticator; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.BaseAccountAuthenticator; import org.whispersystems.textsecuregcm.auth.CertificateGenerator; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAccountAuthenticator; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator; import org.whispersystems.textsecuregcm.auth.PhoneVerificationTokenManager; import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager; @@ -580,8 +575,6 @@ public class WhisperServerService extends Application accountAuthFilter = new BasicCredentialAuthFilter.Builder().setAuthenticator( - accountAuthenticator).buildAuthFilter(); - AuthFilter disabledPermittedAccountAuthFilter = new BasicCredentialAuthFilter.Builder().setAuthenticator( - disabledPermittedAccountAuthenticator).buildAuthFilter(); - final BasicCredentialAuthenticationInterceptor basicCredentialAuthenticationInterceptor = - new BasicCredentialAuthenticationInterceptor(new BaseAccountAuthenticator(accountsManager)); + new BasicCredentialAuthenticationInterceptor(new AccountAuthenticator(accountsManager)); final ServerBuilder grpcServer = ServerBuilder.forPort(config.getGrpcPort()) .addService(ServerInterceptors.intercept(new AccountsGrpcService(accountsManager, rateLimiters, usernameHashZkProofVerifier, registrationRecoveryPasswordsManager), basicCredentialAuthenticationInterceptor)) @@ -724,14 +712,16 @@ public class WhisperServerService extends Application accountAuthFilter = + new BasicCredentialAuthFilter.Builder() + .setAuthenticator(accountAuthenticator) + .buildAuthFilter(); + environment.jersey().register(new RequestStatisticsFilter(TrafficSource.HTTP)); environment.jersey().register(MultiRecipientMessageProvider.class); environment.jersey().register(new MetricsApplicationEventListener(TrafficSource.HTTP, clientReleaseManager)); - environment.jersey() - .register(new PolymorphicAuthDynamicFeature<>(ImmutableMap.of(AuthenticatedAccount.class, accountAuthFilter, - DisabledPermittedAuthenticatedAccount.class, disabledPermittedAccountAuthFilter))); - environment.jersey().register(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))); + environment.jersey().register(new AuthDynamicFeature(accountAuthFilter)); + environment.jersey().register(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)); environment.jersey().register(new WebsocketRefreshApplicationEventListener(accountsManager, clientPresenceManager)); environment.jersey().register(new TimestampResponseFilter()); @@ -749,14 +739,6 @@ public class WhisperServerService extends Application commonControllers = Lists.newArrayList( + new AccountController(accountsManager, rateLimiters, turnTokenGenerator, registrationRecoveryPasswordsManager, + usernameHashZkProofVerifier), new AccountControllerV2(accountsManager, changeNumberManager, phoneVerificationTokenManager, registrationLockVerificationManager, rateLimiters), new ArtController(rateLimiters, artCredentialsGenerator), @@ -824,6 +808,7 @@ public class WhisperServerService extends Application { +public class AccountAuthenticator implements Authenticator { + + private static final String LEGACY_NAME_PREFIX = "org.whispersystems.textsecuregcm.auth.BaseAccountAuthenticator"; + + private static final String AUTHENTICATION_COUNTER_NAME = name(LEGACY_NAME_PREFIX, "authentication"); + private static final String AUTHENTICATION_SUCCEEDED_TAG_NAME = "succeeded"; + private static final String AUTHENTICATION_FAILURE_REASON_TAG_NAME = "reason"; + + private static final String DAYS_SINCE_LAST_SEEN_DISTRIBUTION_NAME = name(LEGACY_NAME_PREFIX, "daysSinceLastSeen"); + private static final String IS_PRIMARY_DEVICE_TAG = "isPrimary"; + + @VisibleForTesting + static final char DEVICE_ID_SEPARATOR = '.'; + + private final AccountsManager accountsManager; + private final Clock clock; public AccountAuthenticator(AccountsManager accountsManager) { - super(accountsManager); + this(accountsManager, Clock.systemUTC()); + } + + @VisibleForTesting + public AccountAuthenticator(AccountsManager accountsManager, Clock clock) { + this.accountsManager = accountsManager; + this.clock = clock; + } + + static Pair getIdentifierAndDeviceId(final String basicUsername) { + final String identifier; + final byte deviceId; + + final int deviceIdSeparatorIndex = basicUsername.indexOf(DEVICE_ID_SEPARATOR); + + if (deviceIdSeparatorIndex == -1) { + identifier = basicUsername; + deviceId = Device.PRIMARY_ID; + } else { + identifier = basicUsername.substring(0, deviceIdSeparatorIndex); + deviceId = Byte.parseByte(basicUsername.substring(deviceIdSeparatorIndex + 1)); + } + + return new Pair<>(identifier, deviceId); } @Override public Optional authenticate(BasicCredentials basicCredentials) { - return super.authenticate(basicCredentials, true); + boolean succeeded = false; + String failureReason = null; + + try { + final UUID accountUuid; + final byte deviceId; + { + final Pair identifierAndDeviceId = getIdentifierAndDeviceId(basicCredentials.getUsername()); + + accountUuid = UUID.fromString(identifierAndDeviceId.first()); + deviceId = identifierAndDeviceId.second(); + } + + Optional account = accountsManager.getByAccountIdentifier(accountUuid); + + if (account.isEmpty()) { + failureReason = "noSuchAccount"; + return Optional.empty(); + } + + Optional device = account.get().getDevice(deviceId); + + if (device.isEmpty()) { + failureReason = "noSuchDevice"; + return Optional.empty(); + } + + SaltedTokenHash deviceSaltedTokenHash = device.get().getAuthTokenHash(); + if (deviceSaltedTokenHash.verify(basicCredentials.getPassword())) { + succeeded = true; + Account authenticatedAccount = updateLastSeen(account.get(), device.get()); + if (deviceSaltedTokenHash.getVersion() != SaltedTokenHash.CURRENT_VERSION) { + authenticatedAccount = accountsManager.updateDeviceAuthentication( + authenticatedAccount, + device.get(), + SaltedTokenHash.generateFor(basicCredentials.getPassword())); // new credentials have current version + } + return Optional.of(new AuthenticatedAccount( + new RefreshingAccountAndDeviceSupplier(authenticatedAccount, device.get().getId(), accountsManager))); + } + + return Optional.empty(); + } catch (IllegalArgumentException | InvalidAuthorizationHeaderException iae) { + failureReason = "invalidHeader"; + return Optional.empty(); + } finally { + Tags tags = Tags.of( + AUTHENTICATION_SUCCEEDED_TAG_NAME, String.valueOf(succeeded)); + + if (StringUtils.isNotBlank(failureReason)) { + tags = tags.and(AUTHENTICATION_FAILURE_REASON_TAG_NAME, failureReason); + } + + Metrics.counter(AUTHENTICATION_COUNTER_NAME, tags).increment(); + } } + @VisibleForTesting + public Account updateLastSeen(Account account, Device device) { + // compute a non-negative integer between 0 and 86400. + long n = Util.ensureNonNegativeLong(account.getUuid().getLeastSignificantBits()); + final long lastSeenOffsetSeconds = n % ChronoUnit.DAYS.getDuration().toSeconds(); + + // produce a truncated timestamp which is either today at UTC midnight + // or yesterday at UTC midnight, based on per-user randomized offset used. + final long todayInMillisWithOffset = Util.todayInMillisGivenOffsetFromNow(clock, + Duration.ofSeconds(lastSeenOffsetSeconds).negated()); + + // only update the device's last seen time when it falls behind the truncated timestamp. + // this ensures a few things: + // (1) each account will only update last-seen at most once per day + // (2) these updates will occur throughout the day rather than all occurring at UTC midnight. + if (device.getLastSeen() < todayInMillisWithOffset) { + Metrics.summary(DAYS_SINCE_LAST_SEEN_DISTRIBUTION_NAME, IS_PRIMARY_DEVICE_TAG, String.valueOf(device.isPrimary())) + .record(Duration.ofMillis(todayInMillisWithOffset - device.getLastSeen()).toDays()); + + return accountsManager.updateDeviceLastSeen(account, device, Util.todayInMillis(clock)); + } + + return account; + } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProvider.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProvider.java index 6661375fd..25e28b6f1 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProvider.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProvider.java @@ -31,7 +31,6 @@ import org.whispersystems.textsecuregcm.util.Pair; * {@link io.dropwizard.auth.Auth} object with a current device list. * * @see AuthenticatedAccount - * @see DisabledPermittedAuthenticatedAccount */ public class AuthEnablementRefreshRequirementProvider implements WebsocketRefreshRequirementProvider { diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/BaseAccountAuthenticator.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/BaseAccountAuthenticator.java deleted file mode 100644 index 4adab6cb4..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/BaseAccountAuthenticator.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2013 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.auth; - -import static com.codahale.metrics.MetricRegistry.name; - -import com.google.common.annotations.VisibleForTesting; -import io.dropwizard.auth.basic.BasicCredentials; -import io.micrometer.core.instrument.Metrics; -import io.micrometer.core.instrument.Tags; -import java.time.Clock; -import java.time.Duration; -import java.time.temporal.ChronoUnit; -import java.util.Optional; -import java.util.UUID; -import org.apache.commons.lang3.StringUtils; -import org.whispersystems.textsecuregcm.storage.Account; -import org.whispersystems.textsecuregcm.storage.AccountsManager; -import org.whispersystems.textsecuregcm.storage.Device; -import org.whispersystems.textsecuregcm.storage.RefreshingAccountAndDeviceSupplier; -import org.whispersystems.textsecuregcm.util.Pair; -import org.whispersystems.textsecuregcm.util.Util; - -public class BaseAccountAuthenticator { - - private static final String AUTHENTICATION_COUNTER_NAME = name(BaseAccountAuthenticator.class, "authentication"); - private static final String ENABLED_NOT_REQUIRED_AUTHENTICATION_COUNTER_NAME = name(BaseAccountAuthenticator.class, - "enabledNotRequiredAuthentication"); - private static final String AUTHENTICATION_SUCCEEDED_TAG_NAME = "succeeded"; - private static final String AUTHENTICATION_FAILURE_REASON_TAG_NAME = "reason"; - private static final String ENABLED_TAG_NAME = "enabled"; - - private static final String DAYS_SINCE_LAST_SEEN_DISTRIBUTION_NAME = name(BaseAccountAuthenticator.class, "daysSinceLastSeen"); - private static final String IS_PRIMARY_DEVICE_TAG = "isPrimary"; - - @VisibleForTesting - static final char DEVICE_ID_SEPARATOR = '.'; - - private final AccountsManager accountsManager; - private final Clock clock; - - public BaseAccountAuthenticator(AccountsManager accountsManager) { - this(accountsManager, Clock.systemUTC()); - } - - @VisibleForTesting - public BaseAccountAuthenticator(AccountsManager accountsManager, Clock clock) { - this.accountsManager = accountsManager; - this.clock = clock; - } - - static Pair getIdentifierAndDeviceId(final String basicUsername) { - final String identifier; - final byte deviceId; - - final int deviceIdSeparatorIndex = basicUsername.indexOf(DEVICE_ID_SEPARATOR); - - if (deviceIdSeparatorIndex == -1) { - identifier = basicUsername; - deviceId = Device.PRIMARY_ID; - } else { - identifier = basicUsername.substring(0, deviceIdSeparatorIndex); - deviceId = Byte.parseByte(basicUsername.substring(deviceIdSeparatorIndex + 1)); - } - - return new Pair<>(identifier, deviceId); - } - - public Optional authenticate(BasicCredentials basicCredentials, boolean enabledRequired) { - boolean succeeded = false; - String failureReason = null; - - try { - final UUID accountUuid; - final byte deviceId; - { - final Pair identifierAndDeviceId = getIdentifierAndDeviceId(basicCredentials.getUsername()); - - accountUuid = UUID.fromString(identifierAndDeviceId.first()); - deviceId = identifierAndDeviceId.second(); - } - - Optional account = accountsManager.getByAccountIdentifier(accountUuid); - - if (account.isEmpty()) { - failureReason = "noSuchAccount"; - return Optional.empty(); - } - - Optional device = account.get().getDevice(deviceId); - - if (device.isEmpty()) { - failureReason = "noSuchDevice"; - return Optional.empty(); - } - - if (enabledRequired) { - final boolean deviceDisabled = !device.get().isEnabled(); - if (deviceDisabled) { - failureReason = "deviceDisabled"; - } - - final boolean accountDisabled = !account.get().isEnabled(); - if (accountDisabled) { - failureReason = "accountDisabled"; - } - if (accountDisabled || deviceDisabled) { - return Optional.empty(); - } - } else { - Metrics.counter(ENABLED_NOT_REQUIRED_AUTHENTICATION_COUNTER_NAME, - ENABLED_TAG_NAME, String.valueOf(device.get().isEnabled() && account.get().isEnabled()), - IS_PRIMARY_DEVICE_TAG, String.valueOf(device.get().isPrimary())) - .increment(); - } - - SaltedTokenHash deviceSaltedTokenHash = device.get().getAuthTokenHash(); - if (deviceSaltedTokenHash.verify(basicCredentials.getPassword())) { - succeeded = true; - Account authenticatedAccount = updateLastSeen(account.get(), device.get()); - if (deviceSaltedTokenHash.getVersion() != SaltedTokenHash.CURRENT_VERSION) { - authenticatedAccount = accountsManager.updateDeviceAuthentication( - authenticatedAccount, - device.get(), - SaltedTokenHash.generateFor(basicCredentials.getPassword())); // new credentials have current version - } - return Optional.of(new AuthenticatedAccount( - new RefreshingAccountAndDeviceSupplier(authenticatedAccount, device.get().getId(), accountsManager))); - } - - return Optional.empty(); - } catch (IllegalArgumentException | InvalidAuthorizationHeaderException iae) { - failureReason = "invalidHeader"; - return Optional.empty(); - } finally { - Tags tags = Tags.of( - AUTHENTICATION_SUCCEEDED_TAG_NAME, String.valueOf(succeeded)); - - if (StringUtils.isNotBlank(failureReason)) { - tags = tags.and(AUTHENTICATION_FAILURE_REASON_TAG_NAME, failureReason); - } - - Metrics.counter(AUTHENTICATION_COUNTER_NAME, tags).increment(); - } - } - - @VisibleForTesting - public Account updateLastSeen(Account account, Device device) { - // compute a non-negative integer between 0 and 86400. - long n = Util.ensureNonNegativeLong(account.getUuid().getLeastSignificantBits()); - final long lastSeenOffsetSeconds = n % ChronoUnit.DAYS.getDuration().toSeconds(); - - // produce a truncated timestamp which is either today at UTC midnight - // or yesterday at UTC midnight, based on per-user randomized offset used. - final long todayInMillisWithOffset = Util.todayInMillisGivenOffsetFromNow(clock, Duration.ofSeconds(lastSeenOffsetSeconds).negated()); - - // only update the device's last seen time when it falls behind the truncated timestamp. - // this ensure a few things: - // (1) each account will only update last-seen at most once per day - // (2) these updates will occur throughout the day rather than all occurring at UTC midnight. - if (device.getLastSeen() < todayInMillisWithOffset) { - Metrics.summary(DAYS_SINCE_LAST_SEEN_DISTRIBUTION_NAME, IS_PRIMARY_DEVICE_TAG, String.valueOf(device.isPrimary())) - .record(Duration.ofMillis(todayInMillisWithOffset - device.getLastSeen()).toDays()); - - return accountsManager.updateDeviceLastSeen(account, device, Util.todayInMillis(clock)); - } - - return account; - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java index 54f99fe70..3c272ff2d 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/BasicAuthorizationHeader.java @@ -62,7 +62,7 @@ public class BasicAuthorizationHeader { final byte deviceId; { final Pair identifierAndDeviceId = - BaseAccountAuthenticator.getIdentifierAndDeviceId(usernameComponent); + AccountAuthenticator.getIdentifierAndDeviceId(usernameComponent); username = identifierAndDeviceId.first(); deviceId = identifierAndDeviceId.second(); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAccountAuthenticator.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAccountAuthenticator.java deleted file mode 100644 index 03a365ad8..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAccountAuthenticator.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2013-2021 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.auth; - -import io.dropwizard.auth.Authenticator; -import io.dropwizard.auth.basic.BasicCredentials; -import java.util.Optional; -import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager; -import org.whispersystems.textsecuregcm.storage.AccountsManager; - -public class DisabledPermittedAccountAuthenticator extends BaseAccountAuthenticator implements - Authenticator { - - public DisabledPermittedAccountAuthenticator(AccountsManager accountsManager) { - super(accountsManager); - } - - @Override - public Optional authenticate(BasicCredentials credentials) { - Optional account = super.authenticate(credentials, false); - return account.map(DisabledPermittedAuthenticatedAccount::new); - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAuthenticatedAccount.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAuthenticatedAccount.java deleted file mode 100644 index 2b4fd73f1..000000000 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/DisabledPermittedAuthenticatedAccount.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2013-2021 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.textsecuregcm.auth; - -import java.security.Principal; -import javax.security.auth.Subject; -import org.whispersystems.textsecuregcm.storage.Account; -import org.whispersystems.textsecuregcm.storage.Device; - -public class DisabledPermittedAuthenticatedAccount implements Principal, AccountAndAuthenticatedDeviceHolder { - - private final AuthenticatedAccount authenticatedAccount; - - public DisabledPermittedAuthenticatedAccount(final AuthenticatedAccount authenticatedAccount) { - this.authenticatedAccount = authenticatedAccount; - } - - @Override - public Account getAccount() { - return authenticatedAccount.getAccount(); - } - - @Override - public Device getAuthenticatedDevice() { - return authenticatedAccount.getAuthenticatedDevice(); - } - - // Principal implementation - - @Override - public String getName() { - return null; - } - - @Override - public boolean implies(Subject subject) { - return false; - } -} diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptor.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptor.java index 95b66b18a..635c3497b 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptor.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptor.java @@ -17,7 +17,7 @@ import io.grpc.Status; import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.BaseAccountAuthenticator; +import org.whispersystems.textsecuregcm.auth.AccountAuthenticator; import org.whispersystems.textsecuregcm.util.HeaderUtils; /** @@ -32,11 +32,11 @@ import org.whispersystems.textsecuregcm.util.HeaderUtils; * intended to be replaced with a more robust and efficient strategy before widespread client adoption. * * @see AuthenticationUtil - * @see BaseAccountAuthenticator + * @see AccountAuthenticator */ public class BasicCredentialAuthenticationInterceptor implements ServerInterceptor { - private final BaseAccountAuthenticator baseAccountAuthenticator; + private final AccountAuthenticator accountAuthenticator; @VisibleForTesting static final Metadata.Key BASIC_CREDENTIALS = @@ -44,8 +44,8 @@ public class BasicCredentialAuthenticationInterceptor implements ServerIntercept private static final Metadata EMPTY_TRAILERS = new Metadata(); - public BasicCredentialAuthenticationInterceptor(final BaseAccountAuthenticator baseAccountAuthenticator) { - this.baseAccountAuthenticator = baseAccountAuthenticator; + public BasicCredentialAuthenticationInterceptor(final AccountAuthenticator accountAuthenticator) { + this.accountAuthenticator = accountAuthenticator; } @Override @@ -62,7 +62,7 @@ public class BasicCredentialAuthenticationInterceptor implements ServerIntercept call.close(Status.UNAUTHENTICATED.withDescription("Could not parse credentials"), EMPTY_TRAILERS); } else { final Optional maybeAuthenticatedAccount = - baseAccountAuthenticator.authenticate(maybeCredentials.get(), false); + accountAuthenticator.authenticate(maybeCredentials.get()); if (maybeAuthenticatedAccount.isPresent()) { final AuthenticatedAccount authenticatedAccount = maybeAuthenticatedAccount.get(); diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java index 65ed15da0..460324e28 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/AccountController.java @@ -4,10 +4,7 @@ */ package org.whispersystems.textsecuregcm.controllers; -import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name; - import io.dropwizard.auth.Auth; -import io.micrometer.core.instrument.Metrics; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -38,7 +35,6 @@ import org.signal.libsignal.usernames.BaseUsernameException; import org.whispersystems.textsecuregcm.auth.AccountAndAuthenticatedDeviceHolder; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.ChangesDeviceEnabledState; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.SaltedTokenHash; import org.whispersystems.textsecuregcm.auth.TurnToken; import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator; @@ -59,7 +55,6 @@ import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; import org.whispersystems.textsecuregcm.identity.ServiceIdentifier; import org.whispersystems.textsecuregcm.limits.RateLimitedByIp; import org.whispersystems.textsecuregcm.limits.RateLimiters; -import org.whispersystems.textsecuregcm.metrics.UserAgentTagUtil; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.AccountsManager; import org.whispersystems.textsecuregcm.storage.Device; @@ -79,7 +74,6 @@ public class AccountController { public static final int USERNAME_HASH_LENGTH = 32; public static final int MAXIMUM_USERNAME_CIPHERTEXT_LENGTH = 128; - private static final String INVALID_REGISTRATION_ID = name(AccountController.class, "invalidRegistrationId"); private final AccountsManager accounts; private final RateLimiters rateLimiters; private final TurnTokenGenerator turnTokenGenerator; @@ -112,11 +106,11 @@ public class AccountController { @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ChangesDeviceEnabledState - public void setGcmRegistrationId(@Auth DisabledPermittedAuthenticatedAccount disabledPermittedAuth, + public void setGcmRegistrationId(@Auth AuthenticatedAccount auth, @NotNull @Valid GcmRegistrationId registrationId) { - final Account account = disabledPermittedAuth.getAccount(); - final Device device = disabledPermittedAuth.getAuthenticatedDevice(); + final Account account = auth.getAccount(); + final Device device = auth.getAuthenticatedDevice(); if (Objects.equals(device.getGcmId(), registrationId.gcmRegistrationId())) { return; @@ -133,9 +127,9 @@ public class AccountController { @DELETE @Path("/gcm/") @ChangesDeviceEnabledState - public void deleteGcmRegistrationId(@Auth DisabledPermittedAuthenticatedAccount disabledPermittedAuth) { - Account account = disabledPermittedAuth.getAccount(); - Device device = disabledPermittedAuth.getAuthenticatedDevice(); + public void deleteGcmRegistrationId(@Auth AuthenticatedAccount auth) { + Account account = auth.getAccount(); + Device device = auth.getAuthenticatedDevice(); accounts.updateDevice(account, device.getId(), d -> { d.setGcmId(null); @@ -149,11 +143,11 @@ public class AccountController { @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ChangesDeviceEnabledState - public void setApnRegistrationId(@Auth DisabledPermittedAuthenticatedAccount disabledPermittedAuth, + public void setApnRegistrationId(@Auth AuthenticatedAccount auth, @NotNull @Valid ApnRegistrationId registrationId) { - final Account account = disabledPermittedAuth.getAccount(); - final Device device = disabledPermittedAuth.getAuthenticatedDevice(); + final Account account = auth.getAccount(); + final Device device = auth.getAuthenticatedDevice(); if (Objects.equals(device.getApnId(), registrationId.apnRegistrationId()) && Objects.equals(device.getVoipApnId(), registrationId.voipRegistrationId())) { @@ -172,9 +166,9 @@ public class AccountController { @DELETE @Path("/apn/") @ChangesDeviceEnabledState - public void deleteApnRegistrationId(@Auth DisabledPermittedAuthenticatedAccount disabledPermittedAuth) { - Account account = disabledPermittedAuth.getAccount(); - Device device = disabledPermittedAuth.getAuthenticatedDevice(); + public void deleteApnRegistrationId(@Auth AuthenticatedAccount auth) { + Account account = auth.getAccount(); + Device device = auth.getAuthenticatedDevice(); accounts.updateDevice(account, device.getId(), d -> { d.setApnId(null); @@ -206,9 +200,9 @@ public class AccountController { @PUT @Path("/name/") - public void setName(@Auth DisabledPermittedAuthenticatedAccount disabledPermittedAuth, @NotNull @Valid DeviceName deviceName) { - Account account = disabledPermittedAuth.getAccount(); - Device device = disabledPermittedAuth.getAuthenticatedDevice(); + public void setName(@Auth AuthenticatedAccount auth, @NotNull @Valid DeviceName deviceName) { + Account account = auth.getAccount(); + Device device = auth.getAuthenticatedDevice(); accounts.updateDevice(account, device.getId(), d -> d.setName(deviceName.getDeviceName())); } @@ -218,11 +212,11 @@ public class AccountController { @Produces(MediaType.APPLICATION_JSON) @ChangesDeviceEnabledState public void setAccountAttributes( - @Auth DisabledPermittedAuthenticatedAccount disabledPermittedAuth, + @Auth AuthenticatedAccount auth, @HeaderParam(HeaderUtils.X_SIGNAL_AGENT) String userAgent, @NotNull @Valid AccountAttributes attributes) { - final Account account = disabledPermittedAuth.getAccount(); - final byte deviceId = disabledPermittedAuth.getAuthenticatedDevice().getId(); + final Account account = auth.getAccount(); + final byte deviceId = auth.getAuthenticatedDevice().getId(); final Account updatedAccount = accounts.update(account, a -> { a.getDevice(deviceId).ifPresent(d -> { @@ -246,8 +240,9 @@ public class AccountController { @GET @Path("/me") + @Deprecated() // use whoami @Produces(MediaType.APPLICATION_JSON) - public AccountIdentityResponse getMe(@Auth DisabledPermittedAuthenticatedAccount auth) { + public AccountIdentityResponse getMe(@Auth AuthenticatedAccount auth) { return buildAccountIdentityResponse(auth); } @@ -521,7 +516,7 @@ public class AccountController { @DELETE @Path("/me") - public CompletableFuture deleteAccount(@Auth DisabledPermittedAuthenticatedAccount auth) throws InterruptedException { + public CompletableFuture deleteAccount(@Auth AuthenticatedAccount auth) { return accounts.delete(auth.getAccount(), AccountsManager.DeletionReason.USER_REQUEST).thenApply(Util.ASYNC_EMPTY_RESPONSE); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java index 9d9644538..182a5e7f0 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/KeysController.java @@ -42,7 +42,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.textsecuregcm.auth.Anonymous; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.OptionalAccess; import org.whispersystems.textsecuregcm.entities.ECSignedPreKey; import org.whispersystems.textsecuregcm.entities.KEMSignedPreKey; @@ -114,7 +113,7 @@ public class KeysController { @ApiResponse(responseCode = "401", description = "Account authentication check failed.") @ApiResponse(responseCode = "403", description = "Attempt to change identity key from a non-primary device.") @ApiResponse(responseCode = "422", description = "Invalid request format.") - public CompletableFuture setKeys(@Auth final DisabledPermittedAuthenticatedAccount disabledPermittedAuth, + public CompletableFuture setKeys(@Auth final AuthenticatedAccount auth, @RequestBody @NotNull @Valid final SetKeysRequest setKeysRequest, @Parameter(allowEmptyValue=true) @@ -124,8 +123,8 @@ public class KeysController { description="whether this operation applies to the account (aci) or phone-number (pni) identity") @QueryParam("identity") @DefaultValue("aci") final IdentityType identityType) { - final Account account = disabledPermittedAuth.getAccount(); - final Device device = disabledPermittedAuth.getAuthenticatedDevice(); + final Account account = auth.getAccount(); + final Device device = auth.getAuthenticatedDevice(); final UUID identifier = account.getIdentifier(identityType); checkSignedPreKeySignatures(setKeysRequest, account.getIdentityKey(identityType)); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/BaseAccountAuthenticatorTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/AccountAuthenticatorTest.java similarity index 85% rename from service/src/test/java/org/whispersystems/textsecuregcm/auth/BaseAccountAuthenticatorTest.java rename to service/src/test/java/org/whispersystems/textsecuregcm/auth/AccountAuthenticatorTest.java index dcaca875c..c54f5bd17 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/BaseAccountAuthenticatorTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/AccountAuthenticatorTest.java @@ -38,7 +38,7 @@ import org.whispersystems.textsecuregcm.tests.util.AccountsHelper; import org.whispersystems.textsecuregcm.util.Pair; import org.whispersystems.textsecuregcm.util.TestClock; -class BaseAccountAuthenticatorTest { +class AccountAuthenticatorTest { private final long today = 1590451200000L; private final long yesterday = today - 86_400_000L; @@ -46,7 +46,7 @@ class BaseAccountAuthenticatorTest { private final long currentTime = today + 68_000_000L; private AccountsManager accountsManager; - private BaseAccountAuthenticator baseAccountAuthenticator; + private AccountAuthenticator accountAuthenticator; private TestClock clock; private Account acct1; private Account acct2; @@ -56,7 +56,7 @@ class BaseAccountAuthenticatorTest { void setup() { accountsManager = mock(AccountsManager.class); clock = TestClock.now(); - baseAccountAuthenticator = new BaseAccountAuthenticator(accountsManager, clock); + accountAuthenticator = new AccountAuthenticator(accountsManager, clock); // We use static UUIDs here because the UUID affects the "date last seen" offset acct1 = AccountsHelper.generateTestAccount("+14088675309", UUID.fromString("c139cb3e-f70c-4460-b221-815e8bdf778f"), UUID.randomUUID(), List.of(generateTestDevice(yesterday)), null); @@ -81,8 +81,8 @@ class BaseAccountAuthenticatorTest { final Device device1 = acct1.getDevices().stream().findFirst().get(); final Device device2 = acct2.getDevices().stream().findFirst().get(); - final Account updatedAcct1 = baseAccountAuthenticator.updateLastSeen(acct1, device1); - final Account updatedAcct2 = baseAccountAuthenticator.updateLastSeen(acct2, device2); + final Account updatedAcct1 = accountAuthenticator.updateLastSeen(acct1, device1); + final Account updatedAcct2 = accountAuthenticator.updateLastSeen(acct2, device2); verify(accountsManager, never()).updateDeviceLastSeen(eq(acct1), any(), anyLong()); verify(accountsManager).updateDeviceLastSeen(eq(acct2), eq(device2), anyLong()); @@ -101,8 +101,8 @@ class BaseAccountAuthenticatorTest { final Device device1 = acct1.getDevices().stream().findFirst().get(); final Device device2 = acct2.getDevices().stream().findFirst().get(); - final Account updatedAcct1 = baseAccountAuthenticator.updateLastSeen(acct1, device1); - final Account updatedAcct2 = baseAccountAuthenticator.updateLastSeen(acct2, device2); + final Account updatedAcct1 = accountAuthenticator.updateLastSeen(acct1, device1); + final Account updatedAcct2 = accountAuthenticator.updateLastSeen(acct2, device2); verify(accountsManager, never()).updateDeviceLastSeen(eq(acct1), any(), anyLong()); verify(accountsManager, never()).updateDeviceLastSeen(eq(acct2), any(), anyLong()); @@ -121,8 +121,8 @@ class BaseAccountAuthenticatorTest { final Device device1 = acct1.getDevices().stream().findFirst().get(); final Device device2 = acct2.getDevices().stream().findFirst().get(); - final Account updatedAcct1 = baseAccountAuthenticator.updateLastSeen(acct1, device1); - final Account updatedAcct2 = baseAccountAuthenticator.updateLastSeen(acct2, device2); + final Account updatedAcct1 = accountAuthenticator.updateLastSeen(acct1, device1); + final Account updatedAcct2 = accountAuthenticator.updateLastSeen(acct2, device2); verify(accountsManager).updateDeviceLastSeen(eq(acct1), eq(device1), anyLong()); verify(accountsManager).updateDeviceLastSeen(eq(acct2), eq(device2), anyLong()); @@ -140,7 +140,7 @@ class BaseAccountAuthenticatorTest { final Device device = oldAccount.getDevices().stream().findFirst().get(); - baseAccountAuthenticator.updateLastSeen(oldAccount, device); + accountAuthenticator.updateLastSeen(oldAccount, device); verify(accountsManager).updateDeviceLastSeen(eq(oldAccount), eq(device), anyLong()); @@ -169,7 +169,7 @@ class BaseAccountAuthenticatorTest { when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION); final Optional maybeAuthenticatedAccount = - baseAccountAuthenticator.authenticate(new BasicCredentials(uuid.toString(), password), true); + accountAuthenticator.authenticate(new BasicCredentials(uuid.toString(), password)); assertThat(maybeAuthenticatedAccount).isPresent(); assertThat(maybeAuthenticatedAccount.get().getAccount().getUuid()).isEqualTo(uuid); @@ -199,7 +199,7 @@ class BaseAccountAuthenticatorTest { when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION); final Optional maybeAuthenticatedAccount = - baseAccountAuthenticator.authenticate(new BasicCredentials(uuid + "." + deviceId, password), true); + accountAuthenticator.authenticate(new BasicCredentials(uuid + "." + deviceId, password)); assertThat(maybeAuthenticatedAccount).isPresent(); assertThat(maybeAuthenticatedAccount.get().getAccount().getUuid()).isEqualTo(uuid); @@ -208,8 +208,7 @@ class BaseAccountAuthenticatorTest { } @CartesianTest - void testAuthenticateEnabledRequired( - @CartesianTest.Values(booleans = {true, false}) final boolean enabledRequired, + void testAuthenticateEnabled( @CartesianTest.Values(booleans = {true, false}) final boolean accountEnabled, @CartesianTest.Values(booleans = {true, false}) final boolean deviceEnabled, @CartesianTest.Values(booleans = {true, false}) final boolean authenticatedDeviceIsPrimary) { @@ -236,18 +235,15 @@ class BaseAccountAuthenticatorTest { if (authenticatedDeviceIsPrimary) { identifier = uuid.toString(); } else { - identifier = uuid.toString() + BaseAccountAuthenticator.DEVICE_ID_SEPARATOR + deviceId; + identifier = uuid.toString() + AccountAuthenticator.DEVICE_ID_SEPARATOR + deviceId; } final Optional maybeAuthenticatedAccount = - baseAccountAuthenticator.authenticate(new BasicCredentials(identifier, password), enabledRequired); + accountAuthenticator.authenticate(new BasicCredentials(identifier, password)); + + assertThat(maybeAuthenticatedAccount).isPresent(); + assertThat(maybeAuthenticatedAccount.get().getAccount().getUuid()).isEqualTo(uuid); + assertThat(maybeAuthenticatedAccount.get().getAuthenticatedDevice()).isEqualTo(authenticatedDevice); - if (enabledRequired && !(accountEnabled && deviceEnabled)) { - assertThat(maybeAuthenticatedAccount).isEmpty(); - } else { - assertThat(maybeAuthenticatedAccount).isPresent(); - assertThat(maybeAuthenticatedAccount.get().getAccount().getUuid()).isEqualTo(uuid); - assertThat(maybeAuthenticatedAccount.get().getAuthenticatedDevice()).isEqualTo(authenticatedDevice); - } } @Test @@ -272,7 +268,7 @@ class BaseAccountAuthenticatorTest { when(credentials.getVersion()).thenReturn(SaltedTokenHash.Version.V1); final Optional maybeAuthenticatedAccount = - baseAccountAuthenticator.authenticate(new BasicCredentials(uuid.toString(), password), true); + accountAuthenticator.authenticate(new BasicCredentials(uuid.toString(), password)); assertThat(maybeAuthenticatedAccount).isPresent(); assertThat(maybeAuthenticatedAccount.get().getAccount().getUuid()).isEqualTo(uuid); @@ -283,7 +279,7 @@ class BaseAccountAuthenticatorTest { } @Test void testAuthenticateAccountNotFound() { - assertThat(baseAccountAuthenticator.authenticate(new BasicCredentials(UUID.randomUUID().toString(), "password"), true)) + assertThat(accountAuthenticator.authenticate(new BasicCredentials(UUID.randomUUID().toString(), "password"))) .isEmpty(); } @@ -309,7 +305,7 @@ class BaseAccountAuthenticatorTest { when(credentials.getVersion()).thenReturn(SaltedTokenHash.CURRENT_VERSION); final Optional maybeAuthenticatedAccount = - baseAccountAuthenticator.authenticate(new BasicCredentials(uuid + "." + (deviceId + 1), password), true); + accountAuthenticator.authenticate(new BasicCredentials(uuid + "." + (deviceId + 1), password)); assertThat(maybeAuthenticatedAccount).isEmpty(); verify(account).getDevice((byte) (deviceId + 1)); @@ -339,7 +335,7 @@ class BaseAccountAuthenticatorTest { final String incorrectPassword = password + "incorrect"; final Optional maybeAuthenticatedAccount = - baseAccountAuthenticator.authenticate(new BasicCredentials(uuid.toString(), incorrectPassword), true); + accountAuthenticator.authenticate(new BasicCredentials(uuid.toString(), incorrectPassword)); assertThat(maybeAuthenticatedAccount).isEmpty(); verify(credentials).verify(incorrectPassword); @@ -349,7 +345,7 @@ class BaseAccountAuthenticatorTest { @MethodSource void testAuthenticateMalformedCredentials(final String username) { final Optional maybeAuthenticatedAccount = assertDoesNotThrow( - () -> baseAccountAuthenticator.authenticate(new BasicCredentials(username, "password"), true)); + () -> accountAuthenticator.authenticate(new BasicCredentials(username, "password"))); assertThat(maybeAuthenticatedAccount).isEmpty(); verify(accountsManager, never()).getByAccountIdentifier(any(UUID.class)); @@ -367,7 +363,7 @@ class BaseAccountAuthenticatorTest { @MethodSource void testGetIdentifierAndDeviceId(final String username, final String expectedIdentifier, final byte expectedDeviceId) { - final Pair identifierAndDeviceId = BaseAccountAuthenticator.getIdentifierAndDeviceId(username); + final Pair identifierAndDeviceId = AccountAuthenticator.getIdentifierAndDeviceId(username); assertEquals(expectedIdentifier, identifierAndDeviceId.first()); assertEquals(expectedDeviceId, identifierAndDeviceId.second()); @@ -389,6 +385,6 @@ class BaseAccountAuthenticatorTest { }) void testGetIdentifierAndDeviceIdMalformed(final String malformedUsername) { assertThrows(IllegalArgumentException.class, - () -> BaseAccountAuthenticator.getIdentifierAndDeviceId(malformedUsername)); + () -> AccountAuthenticator.getIdentifierAndDeviceId(malformedUsername)); } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java index 711467ecc..58376e1f5 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/AuthEnablementRefreshRequirementProviderTest.java @@ -17,11 +17,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import io.dropwizard.auth.Auth; -import io.dropwizard.auth.PolymorphicAuthDynamicFeature; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthDynamicFeature; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.auth.basic.BasicCredentialAuthFilter; import io.dropwizard.jersey.DropwizardResourceConfig; import io.dropwizard.jersey.jackson.JacksonMessageBodyProvider; @@ -40,7 +38,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; -import java.util.Set; import java.util.UUID; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -97,12 +94,9 @@ class AuthEnablementRefreshRequirementProviderTest { new TestPrincipal("test", account, authenticatedDevice)); private final ResourceExtension resources = ResourceExtension.builder() - .addProvider( - new PolymorphicAuthDynamicFeature<>(ImmutableMap.of( - TestPrincipal.class, - new BasicCredentialAuthFilter.Builder() - .setAuthenticator(c -> principalSupplier.get()).buildAuthFilter()))) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>(ImmutableSet.of(TestPrincipal.class))) + .addProvider(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder() + .setAuthenticator(c -> principalSupplier.get()).buildAuthFilter())) + .addProvider(new AuthValueFactoryProvider.Binder<>(TestPrincipal.class)) .addProvider(applicationEventListener) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new TestResource()) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptorTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptorTest.java index c064c1586..7bda74261 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptorTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/grpc/BasicCredentialAuthenticationInterceptorTest.java @@ -9,7 +9,6 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -35,7 +34,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.signal.chat.rpc.EchoRequest; import org.signal.chat.rpc.EchoServiceGrpc; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.BaseAccountAuthenticator; +import org.whispersystems.textsecuregcm.auth.AccountAuthenticator; import org.whispersystems.textsecuregcm.grpc.EchoServiceImpl; import org.whispersystems.textsecuregcm.storage.Account; import org.whispersystems.textsecuregcm.storage.Device; @@ -47,15 +46,15 @@ class BasicCredentialAuthenticationInterceptorTest { private Server server; private ManagedChannel managedChannel; - private BaseAccountAuthenticator baseAccountAuthenticator; + private AccountAuthenticator accountAuthenticator; @BeforeEach void setUp() throws IOException { - baseAccountAuthenticator = mock(BaseAccountAuthenticator.class); + accountAuthenticator = mock(AccountAuthenticator.class); final BasicCredentialAuthenticationInterceptor authenticationInterceptor = - new BasicCredentialAuthenticationInterceptor(baseAccountAuthenticator); + new BasicCredentialAuthenticationInterceptor(accountAuthenticator); final String serverName = InProcessServerBuilder.generateName(); @@ -87,10 +86,10 @@ class BasicCredentialAuthenticationInterceptorTest { final Device device = mock(Device.class); when(device.getId()).thenReturn(Device.PRIMARY_ID); - when(baseAccountAuthenticator.authenticate(any(), anyBoolean())) + when(accountAuthenticator.authenticate(any())) .thenReturn(Optional.of(new AuthenticatedAccount(() -> new Pair<>(account, device)))); } else { - when(baseAccountAuthenticator.authenticate(any(), anyBoolean())) + when(accountAuthenticator.authenticate(any())) .thenReturn(Optional.empty()); } 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 9f0bfdeb2..c85f65ef5 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerTest.java @@ -23,9 +23,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; import com.google.common.net.HttpHeaders; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.security.SecureRandom; @@ -55,7 +54,6 @@ import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.signal.libsignal.usernames.BaseUsernameException; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.SaltedTokenHash; import org.whispersystems.textsecuregcm.auth.StoredRegistrationLock; import org.whispersystems.textsecuregcm.auth.TurnTokenGenerator; @@ -144,10 +142,7 @@ class AccountControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) .addProvider(AuthHelper.getAuthFilter()) - .addProvider( - new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, - DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(new JsonMappingExceptionMapper()) .addProvider(new RateLimitExceededExceptionMapper()) .addProvider(new ImpossiblePhoneNumberExceptionMapper()) @@ -231,7 +226,7 @@ class AccountControllerTest { senderTransfer, usernameZkProofVerifier); - clearInvocations(AuthHelper.DISABLED_DEVICE); + clearInvocations(AuthHelper.VALID_DEVICE_3_PRIMARY); } @Test @@ -268,31 +263,20 @@ class AccountControllerTest { assertThat(response.getStatus()).isEqualTo(422); } - @Test - void testSetRegistrationLockDisabled() throws Exception { - Response response = - resources.getJerseyTest() - .target("/v1/accounts/registration_lock/") - .request() - .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .put(Entity.json(new RegistrationLock("1234567890123456789012345678901234567890123456789012345678901234"))); - - assertThat(response.getStatus()).isEqualTo(401); - } - @Test void testSetGcmId() { Response response = resources.getJerseyTest() .target("/v1/accounts/gcm/") .request() - .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) + .header(HttpHeaders.AUTHORIZATION, + AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_3, AuthHelper.VALID_PASSWORD_3_PRIMARY)) .put(Entity.json(new GcmRegistrationId("z000"))); assertThat(response.getStatus()).isEqualTo(204); - verify(AuthHelper.DISABLED_DEVICE, times(1)).setGcmId(eq("z000")); - verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.DISABLED_ACCOUNT), anyByte(), any()); + verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setGcmId(eq("z000")); + verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.VALID_ACCOUNT_3), anyByte(), any()); } @Test @@ -301,7 +285,8 @@ class AccountControllerTest { resources.getJerseyTest() .target("/v1/accounts/gcm/") .request() - .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) + .header(HttpHeaders.AUTHORIZATION, + AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_3, AuthHelper.VALID_PASSWORD_3_PRIMARY)) .put(Entity.json("{}")); assertThat(response.getStatus()).isEqualTo(422); @@ -314,14 +299,15 @@ class AccountControllerTest { resources.getJerseyTest() .target("/v1/accounts/apn/") .request() - .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) + .header(HttpHeaders.AUTHORIZATION, + AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_3, AuthHelper.VALID_PASSWORD_3_PRIMARY)) .put(Entity.json(new ApnRegistrationId("first", "second"))); assertThat(response.getStatus()).isEqualTo(204); - verify(AuthHelper.DISABLED_DEVICE, times(1)).setApnId(eq("first")); - verify(AuthHelper.DISABLED_DEVICE, times(1)).setVoipApnId(eq("second")); - verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.DISABLED_ACCOUNT), anyByte(), any()); + verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setApnId(eq("first")); + verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setVoipApnId(eq("second")); + verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.VALID_ACCOUNT_3), anyByte(), any()); } @Test @@ -330,49 +316,31 @@ class AccountControllerTest { resources.getJerseyTest() .target("/v1/accounts/apn/") .request() - .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) + .header(HttpHeaders.AUTHORIZATION, + AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_3, AuthHelper.VALID_PASSWORD_3_PRIMARY)) .put(Entity.json(new ApnRegistrationId("first", null))); assertThat(response.getStatus()).isEqualTo(204); - verify(AuthHelper.DISABLED_DEVICE, times(1)).setApnId(eq("first")); - verify(AuthHelper.DISABLED_DEVICE, times(1)).setVoipApnId(null); - verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.DISABLED_ACCOUNT), anyByte(), any()); + verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setApnId(eq("first")); + verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setVoipApnId(null); + verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.VALID_ACCOUNT_3), anyByte(), any()); } @ParameterizedTest - @MethodSource - void testWhoAmI(final String path, final boolean enabledAccount, final int expectedHttpStatusCode) { - final UUID aci; - final String password; - if (enabledAccount) { - aci = AuthHelper.VALID_UUID; - password = AuthHelper.VALID_PASSWORD; - } else { - aci = AuthHelper.DISABLED_UUID; - password = AuthHelper.DISABLED_PASSWORD; - } + @ValueSource(strings = {"/v1/accounts/whoami", "/v1/accounts/me"}) + void testWhoAmI(final String path) { + final Response response = resources.getJerseyTest() .target(path) .request() - .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(aci, password)) + .header(HttpHeaders.AUTHORIZATION, AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD)) .get(); - assertThat(response.getStatus()).isEqualTo(expectedHttpStatusCode); + assertThat(response.getStatus()).isEqualTo(200); - if (expectedHttpStatusCode == 200) { - assertThat(response.readEntity(AccountIdentityResponse.class).uuid()).isEqualTo(aci); - } - } - - static Stream testWhoAmI() { - return Stream.of( - Arguments.of("/v1/accounts/whoami", true, 200), - Arguments.of("/v1/accounts/whoami", false, 401), - Arguments.of("/v1/accounts/me", true, 200), - Arguments.of("/v1/accounts/me", false, 200) - ); + assertThat(response.readEntity(AccountIdentityResponse.class).uuid()).isEqualTo(AuthHelper.VALID_UUID); } static Stream testSetUsernameLink() { 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 9dd789e83..1f46d0a09 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AccountControllerV2Test.java @@ -19,10 +19,9 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.nio.charset.StandardCharsets; @@ -65,7 +64,6 @@ import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.PhoneVerificationTokenManager; import org.whispersystems.textsecuregcm.auth.RegistrationLockError; import org.whispersystems.textsecuregcm.auth.RegistrationLockVerificationManager; @@ -118,10 +116,7 @@ class AccountControllerV2Test { private final ResourceExtension resources = ResourceExtension.builder() .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) .addProvider(AuthHelper.getAuthFilter()) - .addProvider( - new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, - DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(new RateLimitExceededExceptionMapper()) .addProvider(new ImpossiblePhoneNumberExceptionMapper()) .addProvider(new NonNormalizedPhoneNumberExceptionMapper()) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java index 683f503e7..78942375a 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArchiveControllerTest.java @@ -14,8 +14,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import io.grpc.Status; @@ -52,7 +51,6 @@ import org.signal.libsignal.zkgroup.VerificationFailedException; import org.signal.libsignal.zkgroup.backups.BackupAuthCredentialPresentation; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.AuthenticatedBackupUser; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.backup.BackupAuthManager; import org.whispersystems.textsecuregcm.backup.BackupAuthTestUtil; import org.whispersystems.textsecuregcm.backup.BackupManager; @@ -76,8 +74,7 @@ public class ArchiveControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(new CompletionExceptionMapper()) .addResource(new GrpcStatusRuntimeExceptionMapper()) .addProvider(new RateLimitExceededExceptionMapper()) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArtControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArtControllerTest.java index f3cd583c2..94e8260f5 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArtControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ArtControllerTest.java @@ -9,8 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.whispersystems.textsecuregcm.util.MockUtils.randomSecretBytes; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.time.Duration; @@ -18,7 +17,6 @@ import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; 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.configuration.ArtServiceConfiguration; @@ -36,8 +34,7 @@ class ArtControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new ArtController(rateLimiters, artCredentialsGenerator)) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AttachmentControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AttachmentControllerTest.java index d318ab2a7..8c3f543dc 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AttachmentControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/AttachmentControllerTest.java @@ -9,8 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.io.IOException; @@ -26,7 +25,6 @@ import java.security.spec.InvalidKeySpecException; import java.util.Base64; import java.util.HashMap; import java.util.Map; -import javax.ws.rs.core.Response; import org.assertj.core.api.Assertions; import org.assertj.core.api.Condition; import org.assertj.core.api.InstanceOfAssertFactories; @@ -37,7 +35,6 @@ import org.whispersystems.textsecuregcm.attachments.GcsAttachmentGenerator; import org.whispersystems.textsecuregcm.attachments.TusAttachmentGenerator; import org.whispersystems.textsecuregcm.attachments.TusConfiguration; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes; import org.whispersystems.textsecuregcm.entities.AttachmentDescriptorV2; import org.whispersystems.textsecuregcm.entities.AttachmentDescriptorV3; @@ -93,15 +90,15 @@ class AttachmentControllerTest { "signal@example.com", 1000, "/attach-here", RSA_PRIVATE_KEY_PEM); resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) - .setMapper(SystemMapper.jsonMapper()) - .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) - .addResource(new AttachmentControllerV2(RATE_LIMITERS, "accessKey", "accessSecret", "us-east-1", "attachmentv2-bucket")) - .addResource(new AttachmentControllerV3(RATE_LIMITERS, gcsAttachmentGenerator)) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) + .setMapper(SystemMapper.jsonMapper()) + .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) + .addResource(new AttachmentControllerV2(RATE_LIMITERS, "accessKey", "accessSecret", "us-east-1", + "attachmentv2-bucket")) + .addResource(new AttachmentControllerV3(RATE_LIMITERS, gcsAttachmentGenerator)) .addProvider(new AttachmentControllerV4(RATE_LIMITERS, gcsAttachmentGenerator, - new TusAttachmentGenerator(new TusConfiguration( new SecretBytes(TUS_SECRET), TUS_URL)), + new TusAttachmentGenerator(new TusConfiguration(new SecretBytes(TUS_SECRET), TUS_URL)), EXPERIMENT_MANAGER)) .build(); } catch (IOException | InvalidKeyException | InvalidKeySpecException e) { @@ -194,17 +191,6 @@ class AttachmentControllerTest { assertThat(credentialParts[4]).isEqualTo("goog4_request"); } - @Test - void testV3FormDisabled() { - Response response = resources.getJerseyTest() - .target("/v3/attachments/form/upload") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .get(); - - assertThat(response.getStatus()).isEqualTo(401); - } - @Test void testV2Form() throws IOException { AttachmentDescriptorV2 descriptor = resources.getJerseyTest() @@ -233,14 +219,4 @@ class AttachmentControllerTest { assertThat(new String(Base64.getDecoder().decode(descriptor.policy()))).contains("[\"content-length-range\", 1, 104857600]"); } - @Test - void testV2FormDisabled() { - Response response = resources.getJerseyTest() - .target("/v2/attachments/form/upload") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .get(); - - assertThat(response.getStatus()).isEqualTo(401); - } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallLinkControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallLinkControllerTest.java index acf6cee60..64432c05d 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallLinkControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CallLinkControllerTest.java @@ -10,8 +10,7 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import javax.ws.rs.client.Entity; @@ -24,7 +23,6 @@ import org.signal.libsignal.protocol.util.Hex; import org.signal.libsignal.zkgroup.GenericServerSecretParams; import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialRequestContext; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.entities.GetCreateCallLinkCredentialsRequest; import org.whispersystems.textsecuregcm.limits.RateLimiter; import org.whispersystems.textsecuregcm.limits.RateLimiters; @@ -43,8 +41,7 @@ public class CallLinkControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(new RateLimitExceededExceptionMapper()) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CertificateControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CertificateControllerTest.java index fc1b8b0aa..8ce182f03 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CertificateControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/CertificateControllerTest.java @@ -10,8 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.io.IOException; @@ -41,7 +40,6 @@ import org.signal.libsignal.zkgroup.auth.ServerZkAuthOperations; import org.signal.libsignal.zkgroup.calllinks.CallLinkAuthCredentialResponse; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.CertificateGenerator; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.OptionalAccess; import org.whispersystems.textsecuregcm.entities.DeliveryCertificate; import org.whispersystems.textsecuregcm.entities.GroupCredentials; @@ -81,8 +79,7 @@ class CertificateControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new CertificateController(certificateGenerator, serverZkAuthOperations, genericServerSecretParams, clock)) @@ -207,17 +204,6 @@ class CertificateControllerTest { assertEquals(response.getStatus(), 401); } - @Test - void testDisabledAuthentication() { - Response response = resources.getJerseyTest() - .target("/v1/certificate/delivery") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .get(); - - assertEquals(response.getStatus(), 401); - } - @Test void testGetSingleGroupCredentialWithPniAsAci() { final Instant startOfDay = clock.instant().truncatedTo(ChronoUnit.DAYS); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ChallengeControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ChallengeControllerTest.java index 3a6ccf763..9288cfc89 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ChallengeControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ChallengeControllerTest.java @@ -17,13 +17,12 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import com.google.common.net.HttpHeaders; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.io.IOException; import java.time.Duration; import java.util.Optional; -import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.ws.rs.client.Entity; import javax.ws.rs.container.ContainerRequestContext; @@ -38,7 +37,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.limits.RateLimitChallengeManager; import org.whispersystems.textsecuregcm.mappers.RateLimitExceededExceptionMapper; import org.whispersystems.textsecuregcm.push.NotPushRegisteredException; @@ -60,8 +58,7 @@ class ChallengeControllerTest { private static final ResourceExtension EXTENSION = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - Set.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(ScoreThresholdProvider.ScoreThresholdFeature.class) .addProvider(PushChallengeConfigProvider.PushChallengeConfigFeature.class) .addProvider(new Feature() { diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java index 1423bf7aa..025363455 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DeviceControllerTest.java @@ -18,9 +18,8 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; import com.google.common.net.HttpHeaders; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import io.lettuce.core.cluster.api.async.RedisAdvancedClusterAsyncCommands; @@ -53,7 +52,6 @@ import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.WebsocketRefreshApplicationEventListener; import org.whispersystems.textsecuregcm.entities.AccountAttributes; import org.whispersystems.textsecuregcm.entities.ApnRegistrationId; @@ -117,8 +115,7 @@ class DeviceControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addProvider(new WebsocketRefreshApplicationEventListener(accountsManager, clientPresenceManager)) .addProvider(new DeviceLimitExceededExceptionMapper()) @@ -671,17 +668,6 @@ class DeviceControllerTest { "incorrect-signature".getBytes(StandardCharsets.UTF_8)); } - @Test - void disabledDeviceRegisterTest() { - Response response = resources.getJerseyTest() - .target("/v1/devices/provisioning/code") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .get(); - - assertThat(response.getStatus()).isEqualTo(401); - } - @Test void maxDevicesTest() { final AuthHelper.TestAccount testAccount = AUTH_FILTER_EXTENSION.createTestAccount(); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DonationControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DonationControllerTest.java index 0de5a1170..4b95d308a 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DonationControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/DonationControllerTest.java @@ -13,8 +13,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.ResourceExtension; import java.time.Clock; import java.time.Instant; @@ -34,7 +33,6 @@ import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialPresentation; import org.signal.libsignal.zkgroup.receipts.ReceiptSerial; import org.signal.libsignal.zkgroup.receipts.ServerZkReceiptOperations; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.configuration.BadgeConfiguration; import org.whispersystems.textsecuregcm.configuration.BadgesConfiguration; import org.whispersystems.textsecuregcm.entities.BadgeSvg; @@ -96,8 +94,7 @@ class DonationControllerTest { resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new DonationController(clock, zkReceiptOperations, redeemedReceiptsManager, accountsManager, getBadgesConfiguration(), receiptCredentialPresentationFactory)) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java index c56750fbd..84dc3395f 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/KeysControllerTest.java @@ -22,8 +22,7 @@ import static org.mockito.Mockito.when; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.time.Duration; @@ -49,7 +48,6 @@ import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.OptionalAccess; import org.whispersystems.textsecuregcm.entities.ECPreKey; import org.whispersystems.textsecuregcm.entities.ECSignedPreKey; @@ -135,8 +133,7 @@ class KeysControllerTest { .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) .addProvider(AuthHelper.getAuthFilter()) .addProvider(CompletionExceptionMapper.class) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>(ImmutableSet.of( - AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new ServerRejectedExceptionMapper()) .addResource(new KeysController(rateLimiters, KEYS, accounts)) @@ -340,18 +337,6 @@ class KeysControllerTest { verify(accounts).updateDeviceTransactionallyAsync(eq(AuthHelper.VALID_ACCOUNT), anyByte(), any(), any()); } - @Test - void disabledPutSignedPreKeyV2() { - ECSignedPreKey test = KeysHelper.signedECPreKey(9999, IDENTITY_KEY_PAIR); - Response response = resources.getJerseyTest() - .target("/v2/keys/signed") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .put(Entity.entity(test, MediaType.APPLICATION_JSON_TYPE)); - - assertThat(response.getStatus()).isEqualTo(401); - } - @Test void validSingleRequestTestV2() { PreKeyResponse result = resources.getJerseyTest() @@ -990,35 +975,4 @@ class KeysControllerTest { assertThat(response.getStatus()).isEqualTo(422); } - @Test - void disabledPutKeysTestV2() { - final ECPreKey preKey = KeysHelper.ecPreKey(31337); - final ECKeyPair identityKeyPair = Curve.generateKeyPair(); - final ECSignedPreKey signedPreKey = KeysHelper.signedECPreKey(31338, identityKeyPair); - final IdentityKey identityKey = new IdentityKey(identityKeyPair.getPublicKey()); - - when(AuthHelper.DISABLED_ACCOUNT.getIdentityKey(IdentityType.ACI)).thenReturn(identityKey); - - final SetKeysRequest setKeysRequest = new SetKeysRequest(List.of(preKey), signedPreKey, null, null); - - Response response = - resources.getJerseyTest() - .target("/v2/keys") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .put(Entity.entity(setKeysRequest, MediaType.APPLICATION_JSON_TYPE)); - - assertThat(response.getStatus()).isEqualTo(204); - - ArgumentCaptor> listCaptor = ArgumentCaptor.forClass(List.class); - verify(KEYS).storeEcOneTimePreKeys(eq(AuthHelper.DISABLED_UUID), eq(SAMPLE_DEVICE_ID), listCaptor.capture()); - - List capturedList = listCaptor.getValue(); - assertThat(capturedList.size()).isEqualTo(1); - assertThat(capturedList.get(0).keyId()).isEqualTo(31337); - assertThat(capturedList.get(0).publicKey()).isEqualTo(preKey.publicKey()); - - verify(AuthHelper.DISABLED_DEVICE).setSignedPreKey(eq(signedPreKey)); - verify(accounts).updateDeviceTransactionallyAsync(eq(AuthHelper.DISABLED_ACCOUNT), eq(SAMPLE_DEVICE_ID), any(), any()); - } } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java index 88a6ae3f2..cfaf12d29 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/MessageControllerTest.java @@ -32,10 +32,9 @@ import static org.whispersystems.textsecuregcm.tests.util.JsonHelpers.jsonFixtur import static org.whispersystems.textsecuregcm.util.MockUtils.exactly; import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.MoreExecutors; import com.google.protobuf.ByteString; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands; @@ -85,7 +84,6 @@ import org.mockito.ArgumentCaptor; import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.OptionalAccess; import org.whispersystems.textsecuregcm.auth.UnidentifiedAccessUtil; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; @@ -184,8 +182,7 @@ class MessageControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(RateLimitExceededExceptionMapper.class) .addProvider(MultiRecipientMessageProvider.class) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) @@ -283,20 +280,6 @@ class MessageControllerTest { messageDeliveryScheduler.dispose(); } - @Test - void testSendFromDisabledAccount() throws Exception { - Response response = - resources.getJerseyTest() - .target(String.format("/v1/messages/%s", SINGLE_DEVICE_UUID)) - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .put(Entity.entity(SystemMapper.jsonMapper().readValue(jsonFixture("fixtures/current_message_single_device.json"), - IncomingMessageList.class), - MediaType.APPLICATION_JSON_TYPE)); - - assertThat("Unauthorized response", response.getStatus(), is(equalTo(401))); - } - @Test void testSingleDeviceCurrent() throws Exception { Response response = diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/PaymentsControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/PaymentsControllerTest.java index e7a4d1ca1..6f7393882 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/PaymentsControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/PaymentsControllerTest.java @@ -10,8 +10,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.math.BigDecimal; @@ -24,7 +23,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; 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.currency.CurrencyConversionManager; @@ -42,8 +40,7 @@ class PaymentsControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new PaymentsController(currencyManager, paymentsCredentialsGenerator)) .build(); @@ -90,17 +87,6 @@ class PaymentsControllerTest { assertThat(response.getStatus()).isEqualTo(401); } - @Test - void testDisabledGetAuthToken() { - Response response = - resources.getJerseyTest() - .target("/v1/payments/auth") - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .get(); - assertThat(response.getStatus()).isEqualTo(401); - } - @Test void testGetCurrencyConversions() { CurrencyConversionEntityList conversions = diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java index ca91b2d98..eaeaa3b53 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProfileControllerTest.java @@ -21,8 +21,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.nio.charset.StandardCharsets; @@ -76,7 +75,6 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequest; import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequestContext; import org.signal.libsignal.zkgroup.profiles.ServerZkProfileOperations; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.OptionalAccess; import org.whispersystems.textsecuregcm.configuration.BadgeConfiguration; import org.whispersystems.textsecuregcm.configuration.BadgesConfiguration; @@ -149,8 +147,7 @@ class ProfileControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE) .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(new RateLimitExceededExceptionMapper()) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) @@ -384,18 +381,6 @@ class ProfileControllerTest { assertThat(response.getStatus()).isEqualTo(401); } - - @Test - void testProfileGetDisabled() { - final Response response = resources.getJerseyTest() - .target("/v1/profile/" + AuthHelper.VALID_UUID_TWO) - .request() - .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_UUID, AuthHelper.DISABLED_PASSWORD)) - .get(); - - assertThat(response.getStatus()).isEqualTo(401); - } - @Test void testProfileCapabilities() { final BaseProfileResponse profile = resources.getJerseyTest() diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProvisioningControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProvisioningControllerTest.java index c9728d435..3801a2dec 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProvisioningControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/ProvisioningControllerTest.java @@ -15,8 +15,7 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.nio.charset.StandardCharsets; @@ -32,7 +31,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.entities.ProvisioningMessage; import org.whispersystems.textsecuregcm.limits.RateLimiter; import org.whispersystems.textsecuregcm.limits.RateLimiters; @@ -52,8 +50,7 @@ class ProvisioningControllerTest { private static final ResourceExtension RESOURCE_EXTENSION = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .addProvider(new RateLimitExceededExceptionMapper()) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/RemoteConfigControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/RemoteConfigControllerTest.java index e5957899d..dc368705c 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/RemoteConfigControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/RemoteConfigControllerTest.java @@ -13,8 +13,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.security.MessageDigest; @@ -36,7 +35,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.entities.UserRemoteConfig; import org.whispersystems.textsecuregcm.entities.UserRemoteConfigList; import org.whispersystems.textsecuregcm.mappers.DeviceLimitExceededExceptionMapper; @@ -56,8 +54,7 @@ class RemoteConfigControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addProvider(new DeviceLimitExceededExceptionMapper()) .addResource(new RemoteConfigController(remoteConfigsManager, Map.of("maxGroupSize", "42"), TEST_CLOCK)) @@ -67,7 +64,7 @@ class RemoteConfigControllerTest { @BeforeEach void setup() throws Exception { when(remoteConfigsManager.getAll()).thenReturn(new LinkedList<>() {{ - add(new RemoteConfig("android.stickers", 25, Set.of(AuthHelper.DISABLED_UUID, AuthHelper.INVALID_UUID), null, + add(new RemoteConfig("android.stickers", 25, Set.of(AuthHelper.VALID_UUID_3, AuthHelper.INVALID_UUID), null, null, null)); add(new RemoteConfig("ios.stickers", 50, Set.of(), null, null, null)); add(new RemoteConfig("always.true", 100, Set.of(), null, null, null)); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureStorageControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureStorageControllerTest.java index 1a7c276ac..04157c959 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureStorageControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SecureStorageControllerTest.java @@ -9,8 +9,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.mockito.Mockito.when; import static org.whispersystems.textsecuregcm.util.MockUtils.randomSecretBytes; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import javax.ws.rs.core.Response; @@ -18,7 +17,6 @@ import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; 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.configuration.SecureStorageServiceConfiguration; @@ -38,8 +36,7 @@ class SecureStorageControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new SecureStorageController(STORAGE_CREDENTIAL_GENERATOR)) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/StickerControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/StickerControllerTest.java index 962703473..38403d262 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/StickerControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/StickerControllerTest.java @@ -11,8 +11,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.google.common.collect.ImmutableSet; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.util.Base64; @@ -22,7 +21,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.entities.StickerPackFormUploadAttributes; import org.whispersystems.textsecuregcm.limits.RateLimiter; import org.whispersystems.textsecuregcm.limits.RateLimiters; @@ -37,8 +35,7 @@ class StickerControllerTest { private static final ResourceExtension resources = ResourceExtension.builder() .addProvider(AuthHelper.getAuthFilter()) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>( - ImmutableSet.of(AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(new StickerController(rateLimiters, "foo", "bar", "us-east-1", "mybucket")) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java index a4157e275..ae29d3220 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java @@ -22,7 +22,7 @@ import static org.whispersystems.textsecuregcm.util.AttributeValues.s; import com.fasterxml.jackson.databind.ObjectMapper; import com.stripe.exception.ApiException; import com.stripe.model.PaymentIntent; -import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; +import io.dropwizard.auth.AuthValueFactoryProvider; import io.dropwizard.testing.junit5.DropwizardExtensionsSupport; import io.dropwizard.testing.junit5.ResourceExtension; import java.math.BigDecimal; @@ -56,7 +56,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.signal.libsignal.zkgroup.receipts.ServerZkReceiptOperations; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.badges.BadgeTranslator; import org.whispersystems.textsecuregcm.badges.LevelTranslator; import org.whispersystems.textsecuregcm.configuration.OneTimeDonationConfiguration; @@ -111,8 +110,7 @@ class SubscriptionControllerTest { .addProvider(AuthHelper.getAuthFilter()) .addProvider(CompletionExceptionMapper.class) .addProvider(SubscriptionProcessorExceptionMapper.class) - .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>(Set.of( - AuthenticatedAccount.class, DisabledPermittedAuthenticatedAccount.class))) + .addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedAccount.class)) .setMapper(SystemMapper.jsonMapper()) .setTestContainerFactory(new GrizzlyWebTestContainerFactory()) .addResource(SUBSCRIPTION_CONTROLLER) diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/RemoteConfigsTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/RemoteConfigsTest.java index 92f874d16..4ceff6688 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/RemoteConfigsTest.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/RemoteConfigsTest.java @@ -59,7 +59,6 @@ class RemoteConfigsTest { void testUpdate() { remoteConfigs.set(new RemoteConfig("android.stickers", 50, Set.of(), "FALSE", "TRUE", null)); remoteConfigs.set(new RemoteConfig("value.sometimes", 22, Set.of(), "def", "!", null)); - remoteConfigs.set(new RemoteConfig("ios.stickers", 50, Set.of(AuthHelper.DISABLED_UUID), "FALSE", "TRUE", null)); remoteConfigs.set(new RemoteConfig("ios.stickers", 75, Set.of(), "FALSE", "TRUE", null)); remoteConfigs.set(new RemoteConfig("value.sometimes", 77, Set.of(), "hey", "wut", null)); diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java index 28553d995..65917821b 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/util/AuthHelper.java @@ -32,8 +32,6 @@ import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.whispersystems.textsecuregcm.auth.AccountAuthenticator; import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAccountAuthenticator; -import org.whispersystems.textsecuregcm.auth.DisabledPermittedAuthenticatedAccount; import org.whispersystems.textsecuregcm.auth.SaltedTokenHash; import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier; import org.whispersystems.textsecuregcm.identity.IdentityType; @@ -68,10 +66,6 @@ public class AuthHelper { public static final UUID INVALID_UUID = UUID.randomUUID(); public static final String INVALID_PASSWORD = "bar"; - public static final String DISABLED_NUMBER = "+78888888"; - public static final UUID DISABLED_UUID = UUID.randomUUID(); - public static final String DISABLED_PASSWORD = "poof"; - public static final String UNDISCOVERABLE_NUMBER = "+18005551234"; public static final UUID UNDISCOVERABLE_UUID = UUID.randomUUID(); public static final String UNDISCOVERABLE_PASSWORD = "IT'S A SECRET TO EVERYBODY."; @@ -82,13 +76,11 @@ public class AuthHelper { public static AccountsManager ACCOUNTS_MANAGER = mock(AccountsManager.class); public static Account VALID_ACCOUNT = mock(Account.class ); public static Account VALID_ACCOUNT_TWO = mock(Account.class ); - public static Account DISABLED_ACCOUNT = mock(Account.class ); public static Account UNDISCOVERABLE_ACCOUNT = mock(Account.class ); public static Account VALID_ACCOUNT_3 = mock(Account.class ); public static Device VALID_DEVICE = mock(Device.class); public static Device VALID_DEVICE_TWO = mock(Device.class); - public static Device DISABLED_DEVICE = mock(Device.class); public static Device UNDISCOVERABLE_DEVICE = mock(Device.class); public static Device VALID_DEVICE_3_PRIMARY = mock(Device.class); public static Device VALID_DEVICE_3_LINKED = mock(Device.class); @@ -97,7 +89,6 @@ public class AuthHelper { private static SaltedTokenHash VALID_CREDENTIALS_TWO = mock(SaltedTokenHash.class); private static SaltedTokenHash VALID_CREDENTIALS_3_PRIMARY = mock(SaltedTokenHash.class); private static SaltedTokenHash VALID_CREDENTIALS_3_LINKED = mock(SaltedTokenHash.class); - private static SaltedTokenHash DISABLED_CREDENTIALS = mock(SaltedTokenHash.class); private static SaltedTokenHash UNDISCOVERABLE_CREDENTIALS = mock(SaltedTokenHash.class); private static final Collection EXTENSION_TEST_ACCOUNTS = new HashSet<>(); @@ -107,33 +98,28 @@ public class AuthHelper { when(VALID_CREDENTIALS_TWO.verify("baz")).thenReturn(true); when(VALID_CREDENTIALS_3_PRIMARY.verify(VALID_PASSWORD_3_PRIMARY)).thenReturn(true); when(VALID_CREDENTIALS_3_LINKED.verify(VALID_PASSWORD_3_LINKED)).thenReturn(true); - when(DISABLED_CREDENTIALS.verify(DISABLED_PASSWORD)).thenReturn(true); when(UNDISCOVERABLE_CREDENTIALS.verify(UNDISCOVERABLE_PASSWORD)).thenReturn(true); when(VALID_DEVICE.getAuthTokenHash()).thenReturn(VALID_CREDENTIALS); when(VALID_DEVICE_TWO.getAuthTokenHash()).thenReturn(VALID_CREDENTIALS_TWO); when(VALID_DEVICE_3_PRIMARY.getAuthTokenHash()).thenReturn(VALID_CREDENTIALS_3_PRIMARY); when(VALID_DEVICE_3_LINKED.getAuthTokenHash()).thenReturn(VALID_CREDENTIALS_3_LINKED); - when(DISABLED_DEVICE.getAuthTokenHash()).thenReturn(DISABLED_CREDENTIALS); when(UNDISCOVERABLE_DEVICE.getAuthTokenHash()).thenReturn(UNDISCOVERABLE_CREDENTIALS); when(VALID_DEVICE.isPrimary()).thenReturn(true); when(VALID_DEVICE_TWO.isPrimary()).thenReturn(true); - when(DISABLED_DEVICE.isPrimary()).thenReturn(true); when(UNDISCOVERABLE_DEVICE.isPrimary()).thenReturn(true); when(VALID_DEVICE_3_PRIMARY.isPrimary()).thenReturn(true); when(VALID_DEVICE_3_LINKED.isPrimary()).thenReturn(false); when(VALID_DEVICE.getId()).thenReturn(Device.PRIMARY_ID); when(VALID_DEVICE_TWO.getId()).thenReturn(Device.PRIMARY_ID); - when(DISABLED_DEVICE.getId()).thenReturn(Device.PRIMARY_ID); when(UNDISCOVERABLE_DEVICE.getId()).thenReturn(Device.PRIMARY_ID); when(VALID_DEVICE_3_PRIMARY.getId()).thenReturn(Device.PRIMARY_ID); when(VALID_DEVICE_3_LINKED.getId()).thenReturn((byte) 2); when(VALID_DEVICE.isEnabled()).thenReturn(true); when(VALID_DEVICE_TWO.isEnabled()).thenReturn(true); - when(DISABLED_DEVICE.isEnabled()).thenReturn(false); when(UNDISCOVERABLE_DEVICE.isPrimary()).thenReturn(true); when(VALID_DEVICE_3_PRIMARY.isEnabled()).thenReturn(true); when(VALID_DEVICE_3_LINKED.isEnabled()).thenReturn(true); @@ -142,8 +128,6 @@ public class AuthHelper { when(VALID_ACCOUNT.getPrimaryDevice()).thenReturn(VALID_DEVICE); when(VALID_ACCOUNT_TWO.getDevice(eq(Device.PRIMARY_ID))).thenReturn(Optional.of(VALID_DEVICE_TWO)); when(VALID_ACCOUNT_TWO.getPrimaryDevice()).thenReturn(VALID_DEVICE_TWO); - when(DISABLED_ACCOUNT.getDevice(eq(Device.PRIMARY_ID))).thenReturn(Optional.of(DISABLED_DEVICE)); - when(DISABLED_ACCOUNT.getPrimaryDevice()).thenReturn(DISABLED_DEVICE); when(UNDISCOVERABLE_ACCOUNT.getDevice(eq(Device.PRIMARY_ID))).thenReturn(Optional.of(UNDISCOVERABLE_DEVICE)); when(UNDISCOVERABLE_ACCOUNT.getPrimaryDevice()).thenReturn(UNDISCOVERABLE_DEVICE); when(VALID_ACCOUNT_3.getDevice(Device.PRIMARY_ID)).thenReturn(Optional.of(VALID_DEVICE_3_PRIMARY)); @@ -152,7 +136,6 @@ public class AuthHelper { when(VALID_ACCOUNT.getDevices()).thenReturn(List.of(VALID_DEVICE)); when(VALID_ACCOUNT_TWO.getDevices()).thenReturn(List.of(VALID_DEVICE_TWO)); - when(DISABLED_ACCOUNT.getDevices()).thenReturn(List.of(DISABLED_DEVICE)); when(UNDISCOVERABLE_ACCOUNT.getDevices()).thenReturn(List.of(UNDISCOVERABLE_DEVICE)); when(VALID_ACCOUNT_3.getDevices()).thenReturn(List.of(VALID_DEVICE_3_PRIMARY, VALID_DEVICE_3_LINKED)); @@ -168,9 +151,6 @@ public class AuthHelper { when(VALID_ACCOUNT_TWO.getPhoneNumberIdentifier()).thenReturn(VALID_PNI_TWO); when(VALID_ACCOUNT_TWO.getIdentifier(IdentityType.ACI)).thenReturn(VALID_UUID_TWO); when(VALID_ACCOUNT_TWO.getPhoneNumberIdentifier()).thenReturn(VALID_PNI_TWO); - when(DISABLED_ACCOUNT.getNumber()).thenReturn(DISABLED_NUMBER); - when(DISABLED_ACCOUNT.getUuid()).thenReturn(DISABLED_UUID); - when(DISABLED_ACCOUNT.getIdentifier(IdentityType.ACI)).thenReturn(DISABLED_UUID); when(UNDISCOVERABLE_ACCOUNT.getNumber()).thenReturn(UNDISCOVERABLE_NUMBER); when(UNDISCOVERABLE_ACCOUNT.getUuid()).thenReturn(UNDISCOVERABLE_UUID); when(UNDISCOVERABLE_ACCOUNT.getIdentifier(IdentityType.ACI)).thenReturn(UNDISCOVERABLE_UUID); @@ -182,13 +162,11 @@ public class AuthHelper { when(VALID_ACCOUNT.isEnabled()).thenReturn(true); when(VALID_ACCOUNT_TWO.isEnabled()).thenReturn(true); - when(DISABLED_ACCOUNT.isEnabled()).thenReturn(false); when(UNDISCOVERABLE_ACCOUNT.isEnabled()).thenReturn(true); when(VALID_ACCOUNT_3.isEnabled()).thenReturn(true); when(VALID_ACCOUNT.isDiscoverableByPhoneNumber()).thenReturn(true); when(VALID_ACCOUNT_TWO.isDiscoverableByPhoneNumber()).thenReturn(true); - when(DISABLED_ACCOUNT.isDiscoverableByPhoneNumber()).thenReturn(true); when(UNDISCOVERABLE_ACCOUNT.isDiscoverableByPhoneNumber()).thenReturn(false); when(VALID_ACCOUNT_3.isDiscoverableByPhoneNumber()).thenReturn(true); @@ -196,7 +174,6 @@ public class AuthHelper { when(VALID_ACCOUNT.isIdentifiedBy(new PniServiceIdentifier(VALID_PNI))).thenReturn(true); when(VALID_ACCOUNT_TWO.isIdentifiedBy(new AciServiceIdentifier(VALID_UUID_TWO))).thenReturn(true); when(VALID_ACCOUNT_TWO.isIdentifiedBy(new PniServiceIdentifier(VALID_PNI_TWO))).thenReturn(true); - when(DISABLED_ACCOUNT.isIdentifiedBy(new AciServiceIdentifier(DISABLED_UUID))).thenReturn(true); when(UNDISCOVERABLE_ACCOUNT.isIdentifiedBy(new AciServiceIdentifier(UNDISCOVERABLE_UUID))).thenReturn(true); when(VALID_ACCOUNT_3.isIdentifiedBy(new AciServiceIdentifier(VALID_UUID_3))).thenReturn(true); when(VALID_ACCOUNT_3.isIdentifiedBy(new PniServiceIdentifier(VALID_PNI_3))).thenReturn(true); @@ -213,9 +190,6 @@ public class AuthHelper { when(ACCOUNTS_MANAGER.getByAccountIdentifier(VALID_UUID_TWO)).thenReturn(Optional.of(VALID_ACCOUNT_TWO)); when(ACCOUNTS_MANAGER.getByPhoneNumberIdentifier(VALID_PNI_TWO)).thenReturn(Optional.of(VALID_ACCOUNT_TWO)); - when(ACCOUNTS_MANAGER.getByE164(DISABLED_NUMBER)).thenReturn(Optional.of(DISABLED_ACCOUNT)); - when(ACCOUNTS_MANAGER.getByAccountIdentifier(DISABLED_UUID)).thenReturn(Optional.of(DISABLED_ACCOUNT)); - when(ACCOUNTS_MANAGER.getByE164(UNDISCOVERABLE_NUMBER)).thenReturn(Optional.of(UNDISCOVERABLE_ACCOUNT)); when(ACCOUNTS_MANAGER.getByAccountIdentifier(UNDISCOVERABLE_UUID)).thenReturn(Optional.of(UNDISCOVERABLE_ACCOUNT)); @@ -231,11 +205,8 @@ public class AuthHelper { AuthFilter accountAuthFilter = new BasicCredentialAuthFilter.Builder().setAuthenticator( new AccountAuthenticator(ACCOUNTS_MANAGER)).buildAuthFilter(); - AuthFilter disabledPermittedAccountAuthFilter = new BasicCredentialAuthFilter.Builder().setAuthenticator( - new DisabledPermittedAccountAuthenticator(ACCOUNTS_MANAGER)).buildAuthFilter(); - return new PolymorphicAuthDynamicFeature<>(ImmutableMap.of(AuthenticatedAccount.class, accountAuthFilter, - DisabledPermittedAuthenticatedAccount.class, disabledPermittedAccountAuthFilter)); + return new PolymorphicAuthDynamicFeature<>(ImmutableMap.of(AuthenticatedAccount.class, accountAuthFilter)); } public static String getAuthHeader(UUID uuid, byte deviceId, String password) { @@ -336,9 +307,7 @@ public class AuthHelper { @Override public void afterEach(final ExtensionContext context) { - EXTENSION_TEST_ACCOUNTS.forEach(testAccount -> { - testAccount.teardown(ACCOUNTS_MANAGER); - }); + EXTENSION_TEST_ACCOUNTS.forEach(testAccount -> testAccount.teardown(ACCOUNTS_MANAGER)); EXTENSION_TEST_ACCOUNTS.clear(); } diff --git a/spam-filter b/spam-filter index 5f4622c18..fd935511a 160000 --- a/spam-filter +++ b/spam-filter @@ -1 +1 @@ -Subproject commit 5f4622c184dee3eebb0ec7a909f0992e32596567 +Subproject commit fd935511ac7bacec9465edcb4fa2f844a48df759