Skip to content
Open
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
14 changes: 11 additions & 3 deletions src/main/java/com/uid2/operator/service/V2RequestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public boolean isValid() {

private static final byte VERSION = 1;

// Appended to request-envelope parse errors to help callers who send an unencrypted body (e.g. a raw
// curl request with base64-encoded JSON) understand that the body must be an encrypted request envelope.
static final String ENCRYPTION_HINT = " The request body must be an encrypted request envelope, not plain or"
+ " base64-encoded JSON. If you are calling this endpoint directly (for example with curl), base64-encoding"
+ " the JSON is not enough. See"
+ " https://unifiedid.com/docs/getting-started/gs-encryption-decryption#encryption-and-decryption-code-examples"
+ " for payload encryption and response decryption code examples.";

public static final int V2_REFRESH_PAYLOAD_LENGTH = 388;
public static final long V2_REQUEST_TIMESTAMP_DRIFT_THRESHOLD_IN_MINUTES = 1;

Expand Down Expand Up @@ -119,18 +127,18 @@ private static V2Request parseRequestCommon(byte[] bodyBytes, ClientKey ck, IClo
}

if (bodyBytes.length < MIN_PAYLOAD_LENGTH) {
return new V2Request("Invalid body: Body too short. Check encryption method.");
return new V2Request("Invalid body: Body too short. Check encryption method." + ENCRYPTION_HINT);
}

if (bodyBytes[0] != VERSION) {
return new V2Request("Invalid body: Version mismatch.");
return new V2Request("Invalid body: Version mismatch." + ENCRYPTION_HINT);
}

byte[] decryptedBody;
try {
decryptedBody = AesGcm.decrypt(bodyBytes, 1, ck.getSecretBytes());
} catch (Exception ex) {
return new V2Request("Invalid body: Check encryption key (ClientSecret)");
return new V2Request("Invalid body: Check encryption key (ClientSecret)" + ENCRYPTION_HINT);
}

// Request envelop format:
Expand Down
19 changes: 18 additions & 1 deletion src/test/java/com/uid2/operator/V2RequestUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,24 @@ public void testParseRequestWithTooShortBody() {

V2RequestUtil.V2Request res = V2RequestUtil.parseRequestAsString("dGVzdA==", null, clock);

assertEquals("Invalid body: Body too short. Check encryption method.", res.errorMessage);
assertThat(res.errorMessage).startsWith("Invalid body: Body too short. Check encryption method.");
assertThat(res.errorMessage).contains("gs-encryption-decryption");
}

@Test
public void testParseRequestWithVersionMismatch() {
when(clock.now()).thenReturn(MOCK_NOW);

// Base64 of plain (unencrypted) JSON long enough to pass the length check but whose first byte
// is not the expected envelope version byte - this is what a raw curl-with-base64 request produces.
String plainJsonBase64 = java.util.Base64.getEncoder().encodeToString(
"{\"email_hash\":\"tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=\",\"version\":2}"
.getBytes(java.nio.charset.StandardCharsets.UTF_8));

V2RequestUtil.V2Request res = V2RequestUtil.parseRequestAsString(plainJsonBase64, null, clock);

assertThat(res.errorMessage).startsWith("Invalid body: Version mismatch.");
assertThat(res.errorMessage).contains("gs-encryption-decryption");
}

@Test
Expand Down