mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-19 10:48:04 +01:00
Update credentials and calling gRPC services to new error model
This commit is contained in:
@@ -15,19 +15,16 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.signal.chat.credentials.AuthCheckResult;
|
||||
import org.signal.chat.credentials.CheckSvrCredentialsRequest;
|
||||
import org.signal.chat.credentials.CheckSvrCredentialsResponse;
|
||||
import org.signal.chat.credentials.ReactorExternalServiceCredentialsAnonymousGrpc;
|
||||
import org.signal.chat.credentials.SimpleExternalServiceCredentialsAnonymousGrpc;
|
||||
import org.whispersystems.textsecuregcm.WhisperServerConfiguration;
|
||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator;
|
||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsSelector;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
public class ExternalServiceCredentialsAnonymousGrpcService extends
|
||||
ReactorExternalServiceCredentialsAnonymousGrpc.ExternalServiceCredentialsAnonymousImplBase {
|
||||
SimpleExternalServiceCredentialsAnonymousGrpc.ExternalServiceCredentialsAnonymousImplBase {
|
||||
|
||||
private static final long MAX_SVR_PASSWORD_AGE_SECONDS = TimeUnit.DAYS.toSeconds(30);
|
||||
|
||||
@@ -54,36 +51,34 @@ public class ExternalServiceCredentialsAnonymousGrpcService extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<CheckSvrCredentialsResponse> checkSvrCredentials(final CheckSvrCredentialsRequest request) {
|
||||
public CheckSvrCredentialsResponse checkSvrCredentials(final CheckSvrCredentialsRequest request) {
|
||||
final List<String> tokens = request.getPasswordsList();
|
||||
if (tokens.size() > 10) {
|
||||
throw GrpcExceptions.fieldViolation("passwordsList", "At most 10 passwords may be provided");
|
||||
}
|
||||
final List<ExternalServiceCredentialsSelector.CredentialInfo> credentials = ExternalServiceCredentialsSelector.check(
|
||||
tokens,
|
||||
svrCredentialsGenerator,
|
||||
MAX_SVR_PASSWORD_AGE_SECONDS);
|
||||
|
||||
return Mono.fromFuture(() -> accountsManager.getByE164Async(request.getNumber()))
|
||||
// the username associated with the provided number
|
||||
.map(maybeAccount -> maybeAccount.map(Account::getUuid)
|
||||
.map(svrCredentialsGenerator::generateForUuid)
|
||||
.map(ExternalServiceCredentials::username))
|
||||
.flatMapMany(maybeMatchingUsername -> Flux.fromIterable(credentials)
|
||||
.map(credential -> Tuples.of(maybeMatchingUsername, credential)))
|
||||
.reduce(CheckSvrCredentialsResponse.newBuilder(), ((builder, usernameAndCredentialInfo) -> {
|
||||
final Optional<String> matchingUsername = usernameAndCredentialInfo.getT1();
|
||||
final ExternalServiceCredentialsSelector.CredentialInfo credentialInfo = usernameAndCredentialInfo.getT2();
|
||||
|
||||
final AuthCheckResult authCheckResult;
|
||||
if (!credentialInfo.valid()) {
|
||||
authCheckResult = AuthCheckResult.AUTH_CHECK_RESULT_INVALID;
|
||||
} else {
|
||||
final String username = credentialInfo.credentials().username();
|
||||
// does this credential match the account id for the e164 provided in the request?
|
||||
authCheckResult = matchingUsername.map(username::equals).orElse(false)
|
||||
? AuthCheckResult.AUTH_CHECK_RESULT_MATCH
|
||||
: AuthCheckResult.AUTH_CHECK_RESULT_NO_MATCH;
|
||||
}
|
||||
return builder.putMatches(credentialInfo.token(), authCheckResult);
|
||||
}))
|
||||
.map(CheckSvrCredentialsResponse.Builder::build);
|
||||
// the username associated with the provided number
|
||||
final Optional<String> maybeUsername = accountsManager.getByE164(request.getNumber())
|
||||
.map(Account::getUuid)
|
||||
.map(svrCredentialsGenerator::generateForUuid)
|
||||
.map(ExternalServiceCredentials::username);
|
||||
final CheckSvrCredentialsResponse.Builder builder = CheckSvrCredentialsResponse.newBuilder();
|
||||
for (ExternalServiceCredentialsSelector.CredentialInfo credentialInfo : credentials) {
|
||||
final AuthCheckResult authCheckResult;
|
||||
if (!credentialInfo.valid()) {
|
||||
authCheckResult = AuthCheckResult.AUTH_CHECK_RESULT_INVALID;
|
||||
} else {
|
||||
final String username = credentialInfo.credentials().username();
|
||||
// does this credential match the account id for the e164 provided in the request?
|
||||
authCheckResult = maybeUsername.map(username::equals).orElse(false)
|
||||
? AuthCheckResult.AUTH_CHECK_RESULT_MATCH
|
||||
: AuthCheckResult.AUTH_CHECK_RESULT_NO_MATCH;
|
||||
}
|
||||
builder.putMatches(credentialInfo.token(), authCheckResult);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,22 +8,21 @@ package org.whispersystems.textsecuregcm.grpc;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.grpc.Status;
|
||||
import java.time.Clock;
|
||||
import java.util.Map;
|
||||
import org.signal.chat.credentials.ExternalServiceType;
|
||||
import org.signal.chat.credentials.GetExternalServiceCredentialsRequest;
|
||||
import org.signal.chat.credentials.GetExternalServiceCredentialsResponse;
|
||||
import org.signal.chat.credentials.ReactorExternalServiceCredentialsGrpc;
|
||||
import org.signal.chat.credentials.SimpleExternalServiceCredentialsGrpc;
|
||||
import org.whispersystems.textsecuregcm.WhisperServerConfiguration;
|
||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
|
||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialsGenerator;
|
||||
import org.whispersystems.textsecuregcm.auth.grpc.AuthenticatedDevice;
|
||||
import org.whispersystems.textsecuregcm.auth.grpc.AuthenticationUtil;
|
||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class ExternalServiceCredentialsGrpcService extends ReactorExternalServiceCredentialsGrpc.ExternalServiceCredentialsImplBase {
|
||||
public class ExternalServiceCredentialsGrpcService extends SimpleExternalServiceCredentialsGrpc.ExternalServiceCredentialsImplBase {
|
||||
|
||||
private final Map<ExternalServiceType, ExternalServiceCredentialsGenerator> credentialsGeneratorByType;
|
||||
|
||||
@@ -48,21 +47,20 @@ public class ExternalServiceCredentialsGrpcService extends ReactorExternalServic
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<GetExternalServiceCredentialsResponse> getExternalServiceCredentials(final GetExternalServiceCredentialsRequest request) {
|
||||
public GetExternalServiceCredentialsResponse getExternalServiceCredentials(final GetExternalServiceCredentialsRequest request)
|
||||
throws RateLimitExceededException {
|
||||
final ExternalServiceCredentialsGenerator credentialsGenerator = this.credentialsGeneratorByType
|
||||
.get(request.getExternalService());
|
||||
if (credentialsGenerator == null) {
|
||||
return Mono.error(Status.INVALID_ARGUMENT.asException());
|
||||
throw GrpcExceptions.fieldViolation("externalService", "Invalid external service type");
|
||||
}
|
||||
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
|
||||
return rateLimiters.forDescriptor(RateLimiters.For.EXTERNAL_SERVICE_CREDENTIALS).validateReactive(authenticatedDevice.accountIdentifier())
|
||||
.then(Mono.fromSupplier(() -> {
|
||||
final ExternalServiceCredentials externalServiceCredentials = credentialsGenerator
|
||||
.generateForUuid(authenticatedDevice.accountIdentifier());
|
||||
return GetExternalServiceCredentialsResponse.newBuilder()
|
||||
.setUsername(externalServiceCredentials.username())
|
||||
.setPassword(externalServiceCredentials.password())
|
||||
.build();
|
||||
}));
|
||||
rateLimiters.forDescriptor(RateLimiters.For.EXTERNAL_SERVICE_CREDENTIALS).validate(authenticatedDevice.accountIdentifier());
|
||||
final ExternalServiceCredentials externalServiceCredentials = credentialsGenerator
|
||||
.generateForUuid(authenticatedDevice.accountIdentifier());
|
||||
return GetExternalServiceCredentialsResponse.newBuilder()
|
||||
.setUsername(externalServiceCredentials.username())
|
||||
.setPassword(externalServiceCredentials.password())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user