Add /v1/payments/auth endpoint
This commit is contained in:
		
							parent
							
								
									da16dfd528
								
							
						
					
					
						commit
						39c09733d3
					
				| 
						 | 
				
			
			@ -140,3 +140,6 @@ featureFlag:
 | 
			
		|||
    - # 2nd authorized token
 | 
			
		||||
    - # ...
 | 
			
		||||
    - # Nth authorized token
 | 
			
		||||
 | 
			
		||||
paymentService:
 | 
			
		||||
  userAuthenticationTokenSharedSecret: # hex-encoded 32-byte secret shared with MobileCoin services used to generate auth tokens for Signal users
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ import org.whispersystems.textsecuregcm.configuration.GcpAttachmentsConfiguratio
 | 
			
		|||
import org.whispersystems.textsecuregcm.configuration.MaxDeviceConfiguration;
 | 
			
		||||
import org.whispersystems.textsecuregcm.configuration.MessageCacheConfiguration;
 | 
			
		||||
import org.whispersystems.textsecuregcm.configuration.MicrometerConfiguration;
 | 
			
		||||
import org.whispersystems.textsecuregcm.configuration.PaymentsServiceConfiguration;
 | 
			
		||||
import org.whispersystems.textsecuregcm.configuration.PushConfiguration;
 | 
			
		||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration;
 | 
			
		||||
import org.whispersystems.textsecuregcm.configuration.RecaptchaConfiguration;
 | 
			
		||||
| 
						 | 
				
			
			@ -202,6 +203,11 @@ public class WhisperServerConfiguration extends Configuration {
 | 
			
		|||
  @JsonProperty
 | 
			
		||||
  private SecureBackupServiceConfiguration backupService;
 | 
			
		||||
 | 
			
		||||
  @Valid
 | 
			
		||||
  @NotNull
 | 
			
		||||
  @JsonProperty
 | 
			
		||||
  private PaymentsServiceConfiguration paymentsService;
 | 
			
		||||
 | 
			
		||||
  @Valid
 | 
			
		||||
  @NotNull
 | 
			
		||||
  @JsonProperty
 | 
			
		||||
| 
						 | 
				
			
			@ -353,6 +359,10 @@ public class WhisperServerConfiguration extends Configuration {
 | 
			
		|||
    return backupService;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public PaymentsServiceConfiguration getPaymentsServiceConfiguration() {
 | 
			
		||||
    return paymentsService;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public ZkConfig getZkConfig() {
 | 
			
		||||
    return zkConfig;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,6 +69,7 @@ import org.whispersystems.textsecuregcm.controllers.FeatureFlagsController;
 | 
			
		|||
import org.whispersystems.textsecuregcm.controllers.KeepAliveController;
 | 
			
		||||
import org.whispersystems.textsecuregcm.controllers.KeysController;
 | 
			
		||||
import org.whispersystems.textsecuregcm.controllers.MessageController;
 | 
			
		||||
import org.whispersystems.textsecuregcm.controllers.PaymentsController;
 | 
			
		||||
import org.whispersystems.textsecuregcm.controllers.ProfileController;
 | 
			
		||||
import org.whispersystems.textsecuregcm.controllers.ProvisioningController;
 | 
			
		||||
import org.whispersystems.textsecuregcm.controllers.RemoteConfigController;
 | 
			
		||||
| 
						 | 
				
			
			@ -315,8 +316,9 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
 | 
			
		|||
                                                                                                              config.getDirectoryConfiguration().getDirectoryClientConfiguration().getUserAuthenticationTokenUserIdSecret(),
 | 
			
		||||
                                                                                                              true);
 | 
			
		||||
 | 
			
		||||
    ExternalServiceCredentialGenerator storageCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getSecureStorageServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
 | 
			
		||||
    ExternalServiceCredentialGenerator backupCredentialsGenerator  = new ExternalServiceCredentialGenerator(config.getSecureBackupServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
 | 
			
		||||
    ExternalServiceCredentialGenerator storageCredentialsGenerator   = new ExternalServiceCredentialGenerator(config.getSecureStorageServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
 | 
			
		||||
    ExternalServiceCredentialGenerator backupCredentialsGenerator    = new ExternalServiceCredentialGenerator(config.getSecureBackupServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
 | 
			
		||||
    ExternalServiceCredentialGenerator paymentsCredentialsGenerator  = new ExternalServiceCredentialGenerator(config.getPaymentsServiceConfiguration().getUserAuthenticationTokenSharedSecret(), new byte[0], false);
 | 
			
		||||
 | 
			
		||||
    ApnFallbackManager       apnFallbackManager = new ApnFallbackManager(pushSchedulerClient, apnSender, accountsManager);
 | 
			
		||||
    TwilioSmsSender          twilioSmsSender    = new TwilioSmsSender(config.getTwilioConfiguration());
 | 
			
		||||
| 
						 | 
				
			
			@ -391,6 +393,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
 | 
			
		|||
    environment.jersey().register(new VoiceVerificationController(config.getVoiceVerificationConfiguration().getUrl(), config.getVoiceVerificationConfiguration().getLocales()));
 | 
			
		||||
    environment.jersey().register(new SecureStorageController(storageCredentialsGenerator));
 | 
			
		||||
    environment.jersey().register(new SecureBackupController(backupCredentialsGenerator));
 | 
			
		||||
    environment.jersey().register(new PaymentsController(paymentsCredentialsGenerator));
 | 
			
		||||
    environment.jersey().register(attachmentControllerV1);
 | 
			
		||||
    environment.jersey().register(attachmentControllerV2);
 | 
			
		||||
    environment.jersey().register(attachmentControllerV3);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
package org.whispersystems.textsecuregcm.configuration;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonProperty;
 | 
			
		||||
import org.apache.commons.codec.DecoderException;
 | 
			
		||||
import org.apache.commons.codec.binary.Hex;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotEmpty;
 | 
			
		||||
 | 
			
		||||
public class PaymentsServiceConfiguration {
 | 
			
		||||
 | 
			
		||||
  @NotEmpty
 | 
			
		||||
  @JsonProperty
 | 
			
		||||
  private String userAuthenticationTokenSharedSecret;
 | 
			
		||||
 | 
			
		||||
  public byte[] getUserAuthenticationTokenSharedSecret() throws DecoderException {
 | 
			
		||||
    return Hex.decodeHex(userAuthenticationTokenSharedSecret.toCharArray());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
package org.whispersystems.textsecuregcm.controllers;
 | 
			
		||||
 | 
			
		||||
import com.codahale.metrics.annotation.Timed;
 | 
			
		||||
import io.dropwizard.auth.Auth;
 | 
			
		||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialGenerator;
 | 
			
		||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
 | 
			
		||||
import org.whispersystems.textsecuregcm.storage.Account;
 | 
			
		||||
 | 
			
		||||
import javax.ws.rs.GET;
 | 
			
		||||
import javax.ws.rs.Path;
 | 
			
		||||
import javax.ws.rs.Produces;
 | 
			
		||||
import javax.ws.rs.core.MediaType;
 | 
			
		||||
 | 
			
		||||
@Path("/v1/payments")
 | 
			
		||||
public class PaymentsController {
 | 
			
		||||
 | 
			
		||||
  private final ExternalServiceCredentialGenerator paymentsServiceCredentialGenerator;
 | 
			
		||||
 | 
			
		||||
  public PaymentsController(ExternalServiceCredentialGenerator paymentsServiceCredentialGenerator) {
 | 
			
		||||
    this.paymentsServiceCredentialGenerator = paymentsServiceCredentialGenerator;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Timed
 | 
			
		||||
  @GET
 | 
			
		||||
  @Path("/auth")
 | 
			
		||||
  @Produces(MediaType.APPLICATION_JSON)
 | 
			
		||||
  public ExternalServiceCredentials getAuth(@Auth Account account) {
 | 
			
		||||
    return paymentsServiceCredentialGenerator.generateFor(account.getUuid().toString());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
package org.whispersystems.textsecuregcm.tests.controllers;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
 | 
			
		||||
import io.dropwizard.testing.junit.ResourceTestRule;
 | 
			
		||||
import org.assertj.core.api.Assertions;
 | 
			
		||||
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.ClassRule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.whispersystems.textsecuregcm.auth.DisabledPermittedAccount;
 | 
			
		||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentialGenerator;
 | 
			
		||||
import org.whispersystems.textsecuregcm.auth.ExternalServiceCredentials;
 | 
			
		||||
import org.whispersystems.textsecuregcm.controllers.PaymentsController;
 | 
			
		||||
import org.whispersystems.textsecuregcm.storage.Account;
 | 
			
		||||
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
 | 
			
		||||
 | 
			
		||||
import javax.ws.rs.core.Response;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.Mockito.*;
 | 
			
		||||
 | 
			
		||||
public class PaymentsControllerTest {
 | 
			
		||||
 | 
			
		||||
  private static final ExternalServiceCredentialGenerator paymentsCredentialGenerator = mock(ExternalServiceCredentialGenerator.class);
 | 
			
		||||
 | 
			
		||||
  private final ExternalServiceCredentials validCredentials = new ExternalServiceCredentials("username", "password");
 | 
			
		||||
 | 
			
		||||
  @ClassRule
 | 
			
		||||
  public static final ResourceTestRule resources = ResourceTestRule.builder()
 | 
			
		||||
                                                                   .addProvider(AuthHelper.getAuthFilter())
 | 
			
		||||
                                                                   .addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>(ImmutableSet.of(Account.class, DisabledPermittedAccount.class)))
 | 
			
		||||
                                                                   .setTestContainerFactory(new GrizzlyWebTestContainerFactory())
 | 
			
		||||
                                                                   .addResource(new PaymentsController(paymentsCredentialGenerator))
 | 
			
		||||
                                                                   .build();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  @Before
 | 
			
		||||
  public void setup() {
 | 
			
		||||
    when(paymentsCredentialGenerator.generateFor(eq(AuthHelper.VALID_UUID.toString()))).thenReturn(validCredentials);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testGetAuthToken() {
 | 
			
		||||
    ExternalServiceCredentials token =
 | 
			
		||||
        resources.getJerseyTest()
 | 
			
		||||
            .target("/v1/payments/auth")
 | 
			
		||||
            .request()
 | 
			
		||||
            .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD))
 | 
			
		||||
            .get(ExternalServiceCredentials.class);
 | 
			
		||||
 | 
			
		||||
    assertThat(token.getUsername()).isEqualTo(validCredentials.getUsername());
 | 
			
		||||
    assertThat(token.getPassword()).isEqualTo(validCredentials.getPassword());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testInvalidAuthGetAuthToken() {
 | 
			
		||||
    Response response =
 | 
			
		||||
        resources.getJerseyTest()
 | 
			
		||||
            .target("/v1/payments/auth")
 | 
			
		||||
            .request()
 | 
			
		||||
            .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.INVVALID_NUMBER, AuthHelper.INVALID_PASSWORD))
 | 
			
		||||
            .get();
 | 
			
		||||
 | 
			
		||||
    assertThat(response.getStatus()).isEqualTo(401);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void testDisabledGetAuthToken() {
 | 
			
		||||
    Response response =
 | 
			
		||||
        resources.getJerseyTest()
 | 
			
		||||
            .target("/v1/payments/auth")
 | 
			
		||||
            .request()
 | 
			
		||||
            .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.DISABLED_NUMBER, AuthHelper.DISABLED_PASSWORD))
 | 
			
		||||
            .get();
 | 
			
		||||
    assertThat(response.getStatus()).isEqualTo(401);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue