Allow clients to request PNI-based group credentials

This commit is contained in:
Jon Chambers 2021-11-03 15:07:28 -04:00 committed by Jon Chambers
parent 9383e7716b
commit fa6e3d3690
2 changed files with 49 additions and 3 deletions

View File

@ -14,7 +14,9 @@ import java.security.InvalidKeyException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@ -70,7 +72,8 @@ public class CertificateController {
@Path("/group/{startRedemptionTime}/{endRedemptionTime}") @Path("/group/{startRedemptionTime}/{endRedemptionTime}")
public GroupCredentials getAuthenticationCredentials(@Auth AuthenticatedAccount auth, public GroupCredentials getAuthenticationCredentials(@Auth AuthenticatedAccount auth,
@PathParam("startRedemptionTime") int startRedemptionTime, @PathParam("startRedemptionTime") int startRedemptionTime,
@PathParam("endRedemptionTime") int endRedemptionTime) { @PathParam("endRedemptionTime") int endRedemptionTime,
@QueryParam("identity") Optional<String> identityType) {
if (startRedemptionTime > endRedemptionTime) { if (startRedemptionTime > endRedemptionTime) {
throw new WebApplicationException(Response.Status.BAD_REQUEST); throw new WebApplicationException(Response.Status.BAD_REQUEST);
} }
@ -83,10 +86,13 @@ public class CertificateController {
List<GroupCredentials.GroupCredential> credentials = new LinkedList<>(); List<GroupCredentials.GroupCredential> credentials = new LinkedList<>();
final UUID identifier = identityType.map(String::toLowerCase).orElse("aci").equals("pni") ?
auth.getAccount().getPhoneNumberIdentifier().orElseThrow(NotFoundException::new) :
auth.getAccount().getUuid();
for (int i = startRedemptionTime; i <= endRedemptionTime; i++) { for (int i = startRedemptionTime; i <= endRedemptionTime; i++) {
credentials.add(new GroupCredentials.GroupCredential( credentials.add(new GroupCredentials.GroupCredential(
serverZkAuthOperations.issueAuthCredential(auth.getAccount().getUuid(), i) serverZkAuthOperations.issueAuthCredential(identifier, i).serialize(),
.serialize(),
i)); i));
} }

View File

@ -7,9 +7,11 @@ package org.whispersystems.textsecuregcm.tests.controllers;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider; import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
@ -17,12 +19,15 @@ import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
import io.dropwizard.testing.junit5.ResourceExtension; import io.dropwizard.testing.junit5.ResourceExtension;
import java.io.IOException; import java.io.IOException;
import java.util.Base64; import java.util.Base64;
import java.util.Optional;
import java.util.UUID;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory; import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.signal.zkgroup.ServerSecretParams; import org.signal.zkgroup.ServerSecretParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.auth.AuthCredentialResponse; import org.signal.zkgroup.auth.AuthCredentialResponse;
import org.signal.zkgroup.auth.ClientZkAuthOperations; import org.signal.zkgroup.auth.ClientZkAuthOperations;
import org.signal.zkgroup.auth.ServerZkAuthOperations; import org.signal.zkgroup.auth.ServerZkAuthOperations;
@ -213,6 +218,41 @@ class CertificateControllerTest {
.doesNotThrowAnyException(); .doesNotThrowAnyException();
} }
@Test
void testGetSingleAuthCredentialByPni() {
when(AuthHelper.VALID_ACCOUNT.getPhoneNumberIdentifier()).thenReturn(Optional.of(UUID.randomUUID()));
GroupCredentials credentials = resources.getJerseyTest()
.target("/v1/certificate/group/" + Util.currentDaysSinceEpoch() + "/" + Util.currentDaysSinceEpoch())
.queryParam("identity", "pni")
.request()
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.get(GroupCredentials.class);
assertThat(credentials.getCredentials().size()).isEqualTo(1);
assertThat(credentials.getCredentials().get(0).getRedemptionTime()).isEqualTo(Util.currentDaysSinceEpoch());
ClientZkAuthOperations clientZkAuthOperations = new ClientZkAuthOperations(serverSecretParams.getPublicParams());
assertThatExceptionOfType(VerificationFailedException.class)
.isThrownBy(() ->
clientZkAuthOperations.receiveAuthCredential(AuthHelper.VALID_UUID, Util.currentDaysSinceEpoch(), new AuthCredentialResponse(credentials.getCredentials().get(0).getCredential())));
}
@Test
void testGetSingleAuthCredentialByPniNotSet() {
when(AuthHelper.VALID_ACCOUNT.getPhoneNumberIdentifier()).thenReturn(Optional.empty());
Response response = resources.getJerseyTest()
.target("/v1/certificate/group/" + Util.currentDaysSinceEpoch() + "/" + Util.currentDaysSinceEpoch())
.queryParam("identity", "pni")
.request()
.header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_UUID, AuthHelper.VALID_PASSWORD))
.get();
assertThat(response.getStatus()).isEqualTo(404);
}
@Test @Test
void testGetWeekLongAuthCredentials() { void testGetWeekLongAuthCredentials() {
GroupCredentials credentials = resources.getJerseyTest() GroupCredentials credentials = resources.getJerseyTest()