Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Validate VonageClient applicationId #533

Merged
merged 3 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ need a Vonage account. You'll need to have [created a Vonage account](https://da
- [Number Management](https://developer.vonage.com/en/numbers/overview)
- [Proactive Connect](https://developer.vonage.com/en/proactive-connect/overview)
- [Redact](https://developer.vonage.com/en/redact/overview)
- [SIM Swap](https://developer.vonage.com/en/sim-swap/overview)
- [SMS](https://developer.vonage.com/en/messaging/sms/overview)
- [Subaccounts](https://developer.vonage.com/en/account/subaccounts/overview)
- [Verify](https://developer.vonage.com/en/verify/overview)
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/vonage/client/AbstractMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ protected RequestBuilder applyAuth(RequestBuilder request) throws VonageClientEx
if (am instanceof HeaderAuthMethod) {
request.setHeader("Authorization", ((HeaderAuthMethod) am).getHeaderValue());
}
else if (am instanceof QueryParamsAuthMethod) {
if (am instanceof QueryParamsAuthMethod) {
RequestQueryParams qp = am instanceof ApiKeyQueryParamsAuthMethod ? null : normalRequestParams(request);
((QueryParamsAuthMethod) am).getAuthParams(qp).forEach(request::addParameter);
}
Expand Down Expand Up @@ -146,7 +146,7 @@ public String getApplicationIdOrApiKey() throws VonageUnexpectedException {
if (am instanceof JWTAuthMethod) {
return ((JWTAuthMethod) am).getApplicationId();
}
else if (am instanceof ApiKeyAuthMethod) {
if (am instanceof ApiKeyAuthMethod) {
return ((ApiKeyAuthMethod) am).getApiKey();
}
throw new IllegalStateException(am.getClass().getSimpleName() + " does not have API key.");
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/com/vonage/client/VonageClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ public static class Builder {
private AuthCollection authCollection;
private HttpConfig httpConfig = HttpConfig.defaultConfig();
private HttpClient httpClient;
private String applicationId, apiKey, apiSecret, signatureSecret;
private String apiKey, apiSecret, signatureSecret;
private UUID applicationId;
private byte[] privateKeyContents;
private HashUtil.HashType hashType = HashUtil.HashType.MD5;

Expand Down Expand Up @@ -298,7 +299,8 @@ public Builder httpClient(HttpClient httpClient) {
* @since 7.11.0
*/
public Builder applicationId(UUID applicationId) {
return applicationId(applicationId.toString());
this.applicationId = applicationId;
return this;
}

/**
Expand All @@ -309,8 +311,7 @@ public Builder applicationId(UUID applicationId) {
* @return This builder.
*/
public Builder applicationId(String applicationId) {
this.applicationId = applicationId;
return this;
return applicationId(UUID.fromString(applicationId));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/vonage/client/auth/AuthCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public AuthCollection(SortedSet<AuthMethod> authMethods) {
authList = authMethods;
}

public AuthCollection(String applicationId, byte[] privateKeyContents, String key, String secret, HashUtil.HashType hashType, String signature) {
public AuthCollection(UUID applicationId, byte[] privateKeyContents, String key, String secret, HashUtil.HashType hashType, String signature) {

this();

Expand Down Expand Up @@ -71,7 +71,7 @@ public AuthCollection(String applicationId, byte[] privateKeyContents, String ke
authList.add(new SignatureAuthMethod(key, signature, hashType));
}
if (applicationId != null) {
authList.add(new JWTAuthMethod(applicationId, privateKeyContents));
authList.add(new JWTAuthMethod(applicationId.toString(), privateKeyContents));
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/vonage/client/auth/hashutils/HashUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ public class HashUtil {
* @return representation of the input string with given hash type
* @throws NoSuchAlgorithmException if the algorithm is not available.
* @throws InvalidKeyException Only applicable to HMAC encoding types, when a bad key is provided.
*
* @deprecated This will be removed in the next major release.
*/
@Deprecated
public static String calculate(String input, HashType hashType) throws NoSuchAlgorithmException, InvalidKeyException {
return HASH_TYPES.get(hashType).calculate(input);
}
Expand All @@ -60,7 +63,10 @@ public static String calculate(String input, HashType hashType) throws NoSuchAlg
* @throws NoSuchAlgorithmException if the algorithm is not available.
* @throws InvalidKeyException Only applicable to HMAC encoding types, when a bad key is provided.
* @throws UnsupportedEncodingException if the specified encoding is unavailable.
*
* @deprecated This will be removed in the next major release.
*/
@Deprecated
public static String calculate(String input, String encoding, HashType hashType) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
return HASH_TYPES.get(hashType).calculate(input, encoding);
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/com/vonage/client/AbstractClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected AbstractClientTest() {
new ApiKeyHeaderAuthMethod(TestUtils.API_KEY, TestUtils.API_SECRET),
new ApiKeyQueryParamsAuthMethod(TestUtils.API_KEY, TestUtils.API_SECRET),
new SignatureAuthMethod(TestUtils.API_KEY, TestUtils.SIGNATURE_SECRET, HashUtil.HashType.HMAC_SHA256),
new JWTAuthMethod(TestUtils.APPLICATION_ID, new byte[0])
new JWTAuthMethod(TestUtils.APPLICATION_ID_STR, new byte[0])
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/java/com/vonage/client/AbstractMethodTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public void testApplyAuth() throws Exception {
assertEquals(2, request.getParameters().size());

var jwtAuthCollection = new AuthCollection(new JWTAuthMethod(
APPLICATION_ID, new TestUtils().loadKey("test/keys/application_key")
APPLICATION_ID_STR, new TestUtils().loadKey("test/keys/application_key")
));
when(mockWrapper.getAuthCollection()).thenReturn(jwtAuthCollection);
request = method.makeRequest();
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/com/vonage/client/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@
import java.util.*;

public class TestUtils {
public static final UUID APPLICATION_ID = UUID.randomUUID();
public static final String
APPLICATION_ID = UUID.randomUUID().toString(),
APPLICATION_ID_STR = APPLICATION_ID.toString(),
API_KEY = "a1b2c3d4",
API_SECRET = "1234567890abcdef",
SIGNATURE_SECRET = "kTCRawcijyNTfQ1sNqVrz3ZDyRQRZXoL8IhaYTrMxKg153UcHT",
Expand Down
30 changes: 22 additions & 8 deletions src/test/java/com/vonage/client/VonageClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,20 @@
import io.jsonwebtoken.Jwts;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;

public class VonageClientTest extends AbstractClientTest<VonageClient> {
private final TestUtils testUtils = new TestUtils();
private final Path privateKeyPath;

public VonageClientTest() throws Exception {
privateKeyPath = Paths.get(getClass().getResource("test/keys/application_key").toURI());
}


@Test
public void testConstructVonageClient() throws Exception {
Expand Down Expand Up @@ -77,7 +84,7 @@ public void testGenerateJwt() throws Exception {
byte[] privateKeyBytes = testUtils.loadKey("test/keys/application_key");
VonageClient client = VonageClient.builder()
.privateKeyContents(privateKeyBytes)
.applicationId(APPLICATION_ID).build();
.applicationId(APPLICATION_ID_STR).build();

String constructedToken = client.generateJwt();

Expand All @@ -88,7 +95,7 @@ public void testGenerateJwt() throws Exception {

Claims claims = Jwts.parser().verifyWith(key).build().parseSignedClaims(constructedToken).getPayload();

assertEquals(APPLICATION_ID, claims.get("application_id"));
assertEquals(APPLICATION_ID_STR, claims.get("application_id"));
}

@Test
Expand All @@ -115,7 +122,7 @@ public void testSoloSignatureSecret() {
@Test
public void testSoloApplicationId() {
assertThrows(VonageClientCreationException.class, () ->
VonageClient.builder().applicationId(APPLICATION_ID).build()
VonageClient.builder().applicationId(APPLICATION_ID_STR).build()
);
}

Expand Down Expand Up @@ -160,7 +167,7 @@ public void testApplicationIdWithCertContentsAsBytes() throws Exception {
byte[] keyBytes = testUtils.loadKey("test/keys/application_key");

VonageClient vonageClient = VonageClient.builder()
.applicationId(APPLICATION_ID)
.applicationId(APPLICATION_ID_STR)
.privateKeyContents(keyBytes)
.build();

Expand All @@ -173,16 +180,16 @@ public void testApplicationIdWithCertContentsAsString() throws Exception {
TestUtils testUtils = new TestUtils();
String key = new String(testUtils.loadKey("test/keys/application_key"));

VonageClient vonageClient = VonageClient.builder().applicationId(APPLICATION_ID).privateKeyContents(key).build();
VonageClient vonageClient = VonageClient.builder().applicationId(APPLICATION_ID_STR).privateKeyContents(key).build();
AuthCollection authCollection = vonageClient.getHttpWrapper().getAuthCollection();
assertTrue(authCollection.hasAuthMethod(JWTAuthMethod.class));
}

@Test
public void testApplicationIdWithCertPath() throws Exception {
VonageClient vonageClient = VonageClient.builder()
.applicationId(APPLICATION_ID)
.privateKeyPath(Paths.get(getClass().getResource("test/keys/application_key").toURI()))
.applicationId(APPLICATION_ID_STR)
.privateKeyPath(privateKeyPath)
.build();
AuthCollection authCollection = vonageClient.getHttpWrapper().getAuthCollection();
assertTrue(authCollection.hasAuthMethod(JWTAuthMethod.class));
Expand All @@ -192,12 +199,19 @@ public void testApplicationIdWithCertPath() throws Exception {
public void testApplicationIdWithCertPathAsString() throws Exception {
VonageClient vonageClient = VonageClient.builder()
.applicationId(APPLICATION_ID)
.privateKeyPath(Paths.get(getClass().getResource("test/keys/application_key").toURI()).toString())
.privateKeyPath(privateKeyPath)
.build();
AuthCollection authCollection = vonageClient.getHttpWrapper().getAuthCollection();
assertTrue(authCollection.hasAuthMethod(JWTAuthMethod.class));
}

@Test
public void testInvalidApplicationId() throws Exception {
assertThrows(IllegalArgumentException.class, () -> VonageClient.builder()
.privateKeyPath(privateKeyPath).applicationId(API_KEY).build()
);
}

@Test
public void testDefaultHttpConfig() {
HttpConfig config = HttpConfig.defaultConfig();
Expand Down
14 changes: 7 additions & 7 deletions src/test/java/com/vonage/client/auth/AuthCollectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@
package com.vonage.client.auth;

import com.vonage.client.TestUtils;
import static com.vonage.client.TestUtils.*;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;

public class AuthCollectionTest {
private static final Set<Class<? extends AuthMethod>>
JWT_AUTH_CLASS_SET = Collections.singleton(JWTAuthMethod.class),
TOKEN_AUTH_CLASS_SET = Collections.singleton(ApiKeyHeaderAuthMethod.class);

final byte[] privateKeyContents = new TestUtils().loadKey("test/keys/application_key");
final String applicationId = TestUtils.APPLICATION_ID,
apiKey = TestUtils.API_KEY, apiSecret = TestUtils.API_SECRET;

final JWTAuthMethod jwtAuth = new JWTAuthMethod(applicationId, privateKeyContents);
final JWTAuthMethod jwtAuth = new JWTAuthMethod(APPLICATION_ID_STR, privateKeyContents);

public AuthCollectionTest() throws Exception {
}
Expand Down Expand Up @@ -65,7 +65,7 @@ public void testNoAcceptableAuthMethod() throws Exception {

@Test
public void testAuthMethodPrecedence() throws Exception {
ApiKeyHeaderAuthMethod tAuth = new ApiKeyHeaderAuthMethod(apiKey, apiSecret);
ApiKeyHeaderAuthMethod tAuth = new ApiKeyHeaderAuthMethod(API_KEY, API_SECRET);
AuthCollection auths = new AuthCollection();
auths.add(tAuth);
auths.add(jwtAuth);
Expand All @@ -76,7 +76,7 @@ public void testAuthMethodPrecedence() throws Exception {

@Test
public void testIncompatibleAuths() throws Exception {
ApiKeyHeaderAuthMethod tAuth = new ApiKeyHeaderAuthMethod(apiKey, apiSecret);
ApiKeyHeaderAuthMethod tAuth = new ApiKeyHeaderAuthMethod(API_KEY, API_SECRET);
AuthCollection auths = new AuthCollection();
auths.add(tAuth);

Expand All @@ -90,7 +90,7 @@ public void testIncompatibleAuths() throws Exception {

@Test
public void testLongConstructorJwtAndApiSecret() throws Exception {
var ac = new AuthCollection(applicationId, privateKeyContents, apiKey, apiSecret, null, null);
var ac = new AuthCollection(APPLICATION_ID, privateKeyContents, API_KEY, API_SECRET, null, null);

assertTrue(ac.hasAuthMethod(JWTAuthMethod.class));
assertTrue(ac.hasAuthMethod(ApiKeyQueryParamsAuthMethod.class));
Expand All @@ -114,7 +114,7 @@ public void testLongConstructorJwtAndApiSecret() throws Exception {
public void testAddReplacesExistingAuthMethod() throws Exception {
class CustomJwt extends JWTAuthMethod {
public CustomJwt() {
super(applicationId, privateKeyContents);
super(APPLICATION_ID_STR, privateKeyContents);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ public void testCreateConversation() throws Exception {
public void testCreateConversationEndpoint() throws Exception {
new ConversationsEndpointTestSpec<Conversation, Conversation>() {
final Callback callback = Callback.builder().url("http://example.com/callback")
.eventMask("Test value").applicationId(TestUtils.APPLICATION_ID)
.eventMask("Test value").applicationId(TestUtils.APPLICATION_ID_STR)
.nccoUrl("http://example.com/ncco").method(HttpMethod.POST).build();

@Override
Expand Down
Loading