Skip to content

Commit 4a73b41

Browse files
sreejithKExaltureSreejith
andauthored
[MSUE-129] - Updates in the lib (#88)
* msue129 * Added missing file * Review comment addressed * Review comment -p2 Co-authored-by: Sreejith <A-8697@LE1770.local>
1 parent c29903a commit 4a73b41

File tree

7 files changed

+156
-8
lines changed

7 files changed

+156
-8
lines changed

build.gradle

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ repositories {
1212
}
1313

1414
compileJava {
15-
sourceCompatibility = 1.7
16-
targetCompatibility = 1.7
15+
sourceCompatibility = 1.8
16+
targetCompatibility = 1.8
1717
}
1818

1919
compileTestJava {
@@ -23,11 +23,12 @@ compileTestJava {
2323
dependencies {
2424
testCompile group: 'junit', name: 'junit', version: '4.11'
2525
testCompile group: 'org.skyscreamer', name: 'jsonassert', version: '1.3.0'
26-
testCompile group: 'com.squareup.okhttp3', name: 'mockwebserver', version: '3.4.2'
26+
testCompile group: 'com.squareup.okhttp3', name: 'mockwebserver', version: '4.10.0'
2727
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
28-
compile 'com.google.code.gson:gson:2.7'
29-
compile 'com.squareup.okhttp3:okhttp:3.4.2'
30-
compile 'com.squareup.okio:okio:1.9.0'
28+
compile 'com.google.code.gson:gson:2.10'
29+
compile 'com.squareup.okhttp3:okhttp:4.10.0'
30+
compile 'com.squareup.okio:okio:3.2.0'
31+
compile 'commons-codec:commons-codec:1.15'
3132
}
3233

3334
task wrapper(type: Wrapper) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.siftscience;
2+
3+
public class Constants {
4+
5+
public static final String API_VERSION = "v205";
6+
public static final String LIB_VERSION = "3.7.0";
7+
public static final String USER_AGENT_HEADER = String.format("SiftScience/%s sift-java/%s", API_VERSION, LIB_VERSION);
8+
}

src/main/java/com/siftscience/SiftMerchantRequest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import java.io.IOException;
1313

14+
import static com.siftscience.Constants.USER_AGENT_HEADER;
15+
1416
public abstract class SiftMerchantRequest<T extends SiftMerchantResponse> {
1517
private final String accountId;
1618
FieldSet fieldSet;
@@ -43,7 +45,7 @@ protected void modifyRequestBuilder(Request.Builder builder) {
4345
public T send() throws IOException {
4446
fieldSet.validate();
4547

46-
Request.Builder okRequestBuilder = new Request.Builder().url(this.url());
48+
Request.Builder okRequestBuilder = new Request.Builder().addHeader("User-Agent", USER_AGENT_HEADER).url(this.url());
4749
modifyRequestBuilder(okRequestBuilder);
4850
Request request = okRequestBuilder.build();
4951
T response = buildResponse(okClient.newCall(request).execute(), fieldSet);

src/main/java/com/siftscience/SiftRequest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import java.io.IOException;
77

8+
import static com.siftscience.Constants.USER_AGENT_HEADER;
9+
810
/**
911
* SiftRequest is the base class for all Sift API requests. It implements the `send` method which
1012
* should be used by all subtypes as it provides standard error handling logic.
@@ -41,7 +43,7 @@ public T send() throws IOException {
4143
fieldSet.validate();
4244

4345
// Ok now that the fieldSet is valid, construct and send the request.
44-
Request.Builder okRequestBuilder = new Request.Builder().url(this.url());
46+
Request.Builder okRequestBuilder = new Request.Builder().addHeader("User-Agent", USER_AGENT_HEADER).url(this.url());
4547
modifyRequestBuilder(okRequestBuilder);
4648
Request request = okRequestBuilder.build();
4749
T response = buildResponse(okClient.newCall(request).execute(), fieldSet);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.siftscience.utils;
2+
3+
import org.apache.commons.codec.digest.HmacAlgorithms;
4+
import org.apache.commons.codec.digest.HmacUtils;
5+
6+
public class WebhookValidator {
7+
private static final String SHA1 = "sha1=";
8+
private static final String SHA256 = "sha256=";
9+
10+
/**
11+
*
12+
* @param siftScienceSignature value of the 'X-Sift-Science-Signature' signature in the http header of the webhook request.
13+
* @param requestBody body of the webhook request
14+
* @param secretKey sift webhook secret key
15+
* @return true, if the webhook request received is coming from Sift
16+
*/
17+
18+
public static boolean isValidWebhook(String siftScienceSignature, String requestBody, String secretKey) {
19+
String verificationSignature_Sha1 = SHA1 + new HmacUtils(HmacAlgorithms.HMAC_SHA_1, secretKey.getBytes()).hmacHex(requestBody);
20+
String verificationSignature_Sha256 = SHA256 + new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secretKey.getBytes()).hmacHex(requestBody);
21+
22+
return siftScienceSignature.equals(verificationSignature_Sha1) || siftScienceSignature.equals(verificationSignature_Sha256);
23+
}
24+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.siftscience;
2+
3+
import com.siftscience.model.ApplyDecisionFieldSet;
4+
import okhttp3.OkHttpClient;
5+
import okhttp3.mockwebserver.MockResponse;
6+
import okhttp3.mockwebserver.MockWebServer;
7+
import okhttp3.mockwebserver.RecordedRequest;
8+
import org.junit.Assert;
9+
import org.junit.Test;
10+
import static java.net.HttpURLConnection.HTTP_OK;
11+
12+
public class SiftRequestTest {
13+
14+
@Test
15+
public void testUserAgentHeader() throws Exception {
16+
MockWebServer server = new MockWebServer();
17+
MockResponse response = new MockResponse();
18+
response.setResponseCode(HTTP_OK);
19+
20+
server.enqueue(response);
21+
server.start();
22+
String userId = "a_user_id";
23+
24+
// Create a new client and link it to the mock server.
25+
SiftClient client = new SiftClient("YOUR_API_KEY", "YOUR_ACCOUNT_ID",
26+
new OkHttpClient.Builder()
27+
.addInterceptor(OkHttpUtils.urlRewritingInterceptor(server))
28+
.build());
29+
30+
// Build and execute the request against the mock server.
31+
ApplyDecisionRequest request = client.buildRequest(
32+
new ApplyDecisionFieldSet()
33+
.setUserId(userId)
34+
.setTime(System.currentTimeMillis()));
35+
36+
request.send();
37+
38+
// Verify the request.
39+
RecordedRequest recordedRequest = server.takeRequest();
40+
Assert.assertEquals("SiftScience/v205 sift-java/3.7.0", recordedRequest.getHeader("User-Agent"));
41+
}
42+
43+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.siftscience.utils;
2+
3+
import org.apache.commons.codec.digest.HmacAlgorithms;
4+
import org.apache.commons.codec.digest.HmacUtils;
5+
import org.junit.Assert;
6+
import org.junit.Test;
7+
8+
import static com.siftscience.utils.WebhookValidator.isValidWebhook;
9+
10+
public class WebhookValidatorTest {
11+
12+
@Test
13+
public void testWebhookValidation_sha1() {
14+
15+
final String secretKey = "1d708fe409f22591";
16+
final String requestBody = "{\n" +
17+
" \"entity\": {\n" +
18+
" \"type\": \"user\",\n" +
19+
" \"id\": \"USER123\"\n" +
20+
" },\n" +
21+
" \"decision\": {\n" +
22+
" \"id\": \"block_user_payment_abuse\"\n" +
23+
" },\n" +
24+
" \"time\": 1461963439151\n" +
25+
"}";
26+
final String signature = "sha1=" + new HmacUtils(HmacAlgorithms.HMAC_SHA_1, secretKey).hmacHex(requestBody);
27+
28+
Assert.assertTrue(isValidWebhook(signature, requestBody, secretKey));
29+
}
30+
31+
@Test
32+
public void testWebhookValidation_sha256() {
33+
34+
final String secretKey = "1d708fe409f22591";
35+
final String requestBody = "{\n" +
36+
" \"entity\": {\n" +
37+
" \"type\": \"user\",\n" +
38+
" \"id\": \"USER123\"\n" +
39+
" },\n" +
40+
" \"decision\": {\n" +
41+
" \"id\": \"block_user_payment_abuse\"\n" +
42+
" },\n" +
43+
" \"time\": 1461963439151\n" +
44+
"}";
45+
final String signature = "sha256=" + new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secretKey.getBytes()).hmacHex(requestBody);
46+
47+
Assert.assertTrue(isValidWebhook(signature, requestBody, secretKey));
48+
}
49+
50+
@Test
51+
public void testWebhookValidationForInvalidSecretKey() {
52+
53+
final String secretKey = "1d708fe409f22591";
54+
final String requestBody = "{\n" +
55+
" \"entity\": {\n" +
56+
" \"type\": \"user\",\n" +
57+
" \"id\": \"USER123\"\n" +
58+
" },\n" +
59+
" \"decision\": {\n" +
60+
" \"id\": \"block_user_payment_abuse\"\n" +
61+
" },\n" +
62+
" \"time\": 1461963439151\n" +
63+
"}";
64+
final String signature = "sha1=" + new HmacUtils(HmacAlgorithms.HMAC_SHA_1, secretKey.getBytes()).hmacHex(requestBody);
65+
66+
Assert.assertFalse(isValidWebhook(signature, requestBody, "invalid key"));
67+
}
68+
}

0 commit comments

Comments
 (0)