mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-21 22:18:05 +01:00
Look for registration service errors in response bodies in addition to status responses
This commit is contained in:
committed by
Jon Chambers
parent
52d40c2321
commit
cf738a1c14
@@ -361,11 +361,7 @@ public class AccountController {
|
||||
final byte[] sessionId = maybeStoredVerificationCode.isPresent() && maybeStoredVerificationCode.get().sessionId() != null ?
|
||||
maybeStoredVerificationCode.get().sessionId() : createRegistrationSession(phoneNumber);
|
||||
|
||||
registrationServiceClient.sendRegistrationCode(sessionId,
|
||||
messageTransport,
|
||||
clientType,
|
||||
acceptLanguage.orElse(null),
|
||||
REGISTRATION_RPC_TIMEOUT).join();
|
||||
sendVerificationCode(sessionId, messageTransport, clientType, acceptLanguage);
|
||||
|
||||
final StoredVerificationCode storedVerificationCode = new StoredVerificationCode(null,
|
||||
clock.millis(),
|
||||
@@ -405,10 +401,14 @@ public class AccountController {
|
||||
// Note that successful verification depends on being able to find a stored verification code for the given number.
|
||||
// We check that numbers are normalized before we store verification codes, and so don't need to re-assert
|
||||
// normalization here.
|
||||
final boolean codeVerified = pendingAccounts.getCodeForNumber(number).map(storedVerificationCode ->
|
||||
registrationServiceClient.checkVerificationCode(storedVerificationCode.sessionId(),
|
||||
verificationCode, REGISTRATION_RPC_TIMEOUT).join())
|
||||
.orElse(false);
|
||||
final boolean codeVerified;
|
||||
final Optional<StoredVerificationCode> maybeStoredVerificationCode = pendingAccounts.getCodeForNumber(number);
|
||||
|
||||
if (maybeStoredVerificationCode.isPresent()) {
|
||||
codeVerified = checkVerificationCode(maybeStoredVerificationCode.get().sessionId(), verificationCode);
|
||||
} else {
|
||||
codeVerified = false;
|
||||
}
|
||||
|
||||
if (!codeVerified) {
|
||||
throw new WebApplicationException(Response.status(403).build());
|
||||
@@ -471,10 +471,14 @@ public class AccountController {
|
||||
|
||||
rateLimiters.getVerifyLimiter().validate(number);
|
||||
|
||||
final boolean codeVerified = pendingAccounts.getCodeForNumber(number).map(storedVerificationCode ->
|
||||
registrationServiceClient.checkVerificationCode(storedVerificationCode.sessionId(),
|
||||
request.code(), REGISTRATION_RPC_TIMEOUT).join())
|
||||
.orElse(false);
|
||||
final boolean codeVerified;
|
||||
final Optional<StoredVerificationCode> maybeStoredVerificationCode = pendingAccounts.getCodeForNumber(number);
|
||||
|
||||
if (maybeStoredVerificationCode.isPresent()) {
|
||||
codeVerified = checkVerificationCode(maybeStoredVerificationCode.get().sessionId(), request.code());
|
||||
} else {
|
||||
codeVerified = false;
|
||||
}
|
||||
|
||||
if (!codeVerified) {
|
||||
throw new ForbiddenException();
|
||||
@@ -964,17 +968,50 @@ public class AccountController {
|
||||
try {
|
||||
return registrationServiceClient.createRegistrationSession(phoneNumber, REGISTRATION_RPC_TIMEOUT).join();
|
||||
} catch (final CompletionException e) {
|
||||
Throwable cause = e;
|
||||
|
||||
while (cause instanceof CompletionException) {
|
||||
cause = cause.getCause();
|
||||
}
|
||||
|
||||
if (cause instanceof RateLimitExceededException rateLimitExceededException) {
|
||||
throw rateLimitExceededException;
|
||||
}
|
||||
|
||||
rethrowRateLimitException(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendVerificationCode(final byte[] sessionId,
|
||||
final MessageTransport messageTransport,
|
||||
final ClientType clientType,
|
||||
final Optional<String> acceptLanguage) throws RateLimitExceededException {
|
||||
|
||||
try {
|
||||
registrationServiceClient.sendRegistrationCode(sessionId,
|
||||
messageTransport,
|
||||
clientType,
|
||||
acceptLanguage.orElse(null),
|
||||
REGISTRATION_RPC_TIMEOUT).join();
|
||||
} catch (final CompletionException e) {
|
||||
rethrowRateLimitException(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkVerificationCode(final byte[] sessionId, final String verificationCode)
|
||||
throws RateLimitExceededException {
|
||||
|
||||
try {
|
||||
return registrationServiceClient.checkVerificationCode(sessionId, verificationCode, REGISTRATION_RPC_TIMEOUT).join();
|
||||
} catch (final CompletionException e) {
|
||||
rethrowRateLimitException(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void rethrowRateLimitException(final CompletionException completionException)
|
||||
throws RateLimitExceededException {
|
||||
|
||||
Throwable cause = completionException;
|
||||
|
||||
while (cause instanceof CompletionException) {
|
||||
cause = cause.getCause();
|
||||
}
|
||||
|
||||
if (cause instanceof RateLimitExceededException rateLimitExceededException) {
|
||||
throw rateLimitExceededException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ public class RegistrationServiceClient implements Managed {
|
||||
|
||||
case ERROR -> {
|
||||
switch (response.getError().getErrorType()) {
|
||||
case ERROR_TYPE_RATE_LIMITED -> throw new CompletionException(new RateLimitExceededException(Duration.ofSeconds(response.getError().getRetryAfterSeconds())));
|
||||
case CREATE_REGISTRATION_SESSION_ERROR_TYPE_RATE_LIMITED -> throw new CompletionException(new RateLimitExceededException(Duration.ofSeconds(response.getError().getRetryAfterSeconds())));
|
||||
case CREATE_REGISTRATION_SESSION_ERROR_TYPE_ILLEGAL_PHONE_NUMBER -> throw new IllegalArgumentException();
|
||||
default -> throw new RuntimeException("Unrecognized error type from registration service: " + response.getError().getErrorType());
|
||||
}
|
||||
}
|
||||
@@ -95,7 +96,18 @@ public class RegistrationServiceClient implements Managed {
|
||||
|
||||
return toCompletableFuture(stub.withDeadline(toDeadline(timeout))
|
||||
.sendVerificationCode(requestBuilder.build()))
|
||||
.thenApply(response -> response.getSessionId().toByteArray());
|
||||
.thenApply(response -> {
|
||||
if (response.hasError()) {
|
||||
switch (response.getError().getErrorType()) {
|
||||
case SEND_VERIFICATION_CODE_ERROR_TYPE_RATE_LIMITED ->
|
||||
throw new CompletionException(new RateLimitExceededException(Duration.ofSeconds(response.getError().getRetryAfterSeconds())));
|
||||
|
||||
default -> throw new CompletionException(new RuntimeException("Failed to send verification code: " + response.getError().getErrorType()));
|
||||
}
|
||||
} else {
|
||||
return response.getSessionId().toByteArray();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> checkVerificationCode(final byte[] sessionId,
|
||||
@@ -107,7 +119,18 @@ public class RegistrationServiceClient implements Managed {
|
||||
.setSessionId(ByteString.copyFrom(sessionId))
|
||||
.setVerificationCode(verificationCode)
|
||||
.build()))
|
||||
.thenApply(CheckVerificationCodeResponse::getVerified);
|
||||
.thenApply(response -> {
|
||||
if (response.hasError()) {
|
||||
switch (response.getError().getErrorType()) {
|
||||
case CHECK_VERIFICATION_CODE_ERROR_TYPE_RATE_LIMITED ->
|
||||
throw new CompletionException(new RateLimitExceededException(Duration.ofSeconds(response.getError().getRetryAfterSeconds())));
|
||||
|
||||
default -> throw new CompletionException(new RuntimeException("Failed to check verification code: " + response.getError().getErrorType()));
|
||||
}
|
||||
} else {
|
||||
return response.getSessionMetadata().getVerified();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Deadline toDeadline(final Duration timeout) {
|
||||
|
||||
Reference in New Issue
Block a user