Add /v1/payments/auth endpoint
This commit is contained in:
parent
da16dfd528
commit
39c09733d3
|
@ -140,3 +140,6 @@ featureFlag:
|
||||||
- # 2nd authorized token
|
- # 2nd authorized token
|
||||||
- # ...
|
- # ...
|
||||||
- # Nth 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.MaxDeviceConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.MessageCacheConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.MessageCacheConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.MicrometerConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.MicrometerConfiguration;
|
||||||
|
import org.whispersystems.textsecuregcm.configuration.PaymentsServiceConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.PushConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.PushConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration;
|
||||||
import org.whispersystems.textsecuregcm.configuration.RecaptchaConfiguration;
|
import org.whispersystems.textsecuregcm.configuration.RecaptchaConfiguration;
|
||||||
|
@ -202,6 +203,11 @@ public class WhisperServerConfiguration extends Configuration {
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private SecureBackupServiceConfiguration backupService;
|
private SecureBackupServiceConfiguration backupService;
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
@NotNull
|
||||||
|
@JsonProperty
|
||||||
|
private PaymentsServiceConfiguration paymentsService;
|
||||||
|
|
||||||
@Valid
|
@Valid
|
||||||
@NotNull
|
@NotNull
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
|
@ -353,6 +359,10 @@ public class WhisperServerConfiguration extends Configuration {
|
||||||
return backupService;
|
return backupService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PaymentsServiceConfiguration getPaymentsServiceConfiguration() {
|
||||||
|
return paymentsService;
|
||||||
|
}
|
||||||
|
|
||||||
public ZkConfig getZkConfig() {
|
public ZkConfig getZkConfig() {
|
||||||
return zkConfig;
|
return zkConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ import org.whispersystems.textsecuregcm.controllers.FeatureFlagsController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.KeepAliveController;
|
import org.whispersystems.textsecuregcm.controllers.KeepAliveController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.KeysController;
|
import org.whispersystems.textsecuregcm.controllers.KeysController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.MessageController;
|
import org.whispersystems.textsecuregcm.controllers.MessageController;
|
||||||
|
import org.whispersystems.textsecuregcm.controllers.PaymentsController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.ProfileController;
|
import org.whispersystems.textsecuregcm.controllers.ProfileController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.ProvisioningController;
|
import org.whispersystems.textsecuregcm.controllers.ProvisioningController;
|
||||||
import org.whispersystems.textsecuregcm.controllers.RemoteConfigController;
|
import org.whispersystems.textsecuregcm.controllers.RemoteConfigController;
|
||||||
|
@ -317,6 +318,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||||
|
|
||||||
ExternalServiceCredentialGenerator storageCredentialsGenerator = new ExternalServiceCredentialGenerator(config.getSecureStorageServiceConfiguration().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 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);
|
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushSchedulerClient, apnSender, accountsManager);
|
||||||
TwilioSmsSender twilioSmsSender = new TwilioSmsSender(config.getTwilioConfiguration());
|
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 VoiceVerificationController(config.getVoiceVerificationConfiguration().getUrl(), config.getVoiceVerificationConfiguration().getLocales()));
|
||||||
environment.jersey().register(new SecureStorageController(storageCredentialsGenerator));
|
environment.jersey().register(new SecureStorageController(storageCredentialsGenerator));
|
||||||
environment.jersey().register(new SecureBackupController(backupCredentialsGenerator));
|
environment.jersey().register(new SecureBackupController(backupCredentialsGenerator));
|
||||||
|
environment.jersey().register(new PaymentsController(paymentsCredentialsGenerator));
|
||||||
environment.jersey().register(attachmentControllerV1);
|
environment.jersey().register(attachmentControllerV1);
|
||||||
environment.jersey().register(attachmentControllerV2);
|
environment.jersey().register(attachmentControllerV2);
|
||||||
environment.jersey().register(attachmentControllerV3);
|
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