From 7c572a72c7256ebf8cbe5829d4c20d8504e0cf91 Mon Sep 17 00:00:00 2001 From: Cody Constine Date: Mon, 13 May 2024 14:45:37 -0600 Subject: [PATCH 1/3] Adding the ability to diable CSTG key --- .../TokenResponseStatsCollector.java | 3 +- .../operator/vertx/UIDOperatorVerticle.java | 6 +++ .../operator/UIDOperatorVerticleTest.java | 50 ++++++++++++++++++- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java b/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java index 09af68a94..4e4880f6f 100644 --- a/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java +++ b/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java @@ -38,7 +38,8 @@ public enum ResponseStatus { PayloadHasNoBody, /* End of CSTG-related Status */ Unknown, - NoActiveKey + NoActiveKey, + UNAUTHORIZED } public static void record(ISiteStore siteStore, Integer siteId, Endpoint endpoint, TokenVersion advertisingTokenVersion, ResponseStatus responseStatus) { diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index 8f2e20012..ee02f8709 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -337,6 +337,12 @@ private void handleClientSideTokenGenerateImpl(RoutingContext rc) throws NoSuchA return; } + if(clientSideKeypair.isDisabled()) { + SendClientErrorResponseAndRecordStats(ResponseStatus.Unauthorized, 401, rc, "Unauthorized", + null, TokenResponseStatsCollector.Endpoint.ClientSideTokenGenerateV2, TokenResponseStatsCollector.ResponseStatus.UNAUTHORIZED, siteProvider); + return; + } + if (!hasValidOriginOrAppName(rc, request, clientSideKeypair)) { return; } diff --git a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java index 1a57827d8..ccddb3cc7 100644 --- a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java +++ b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java @@ -42,7 +42,6 @@ import io.vertx.ext.web.client.WebClient; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; -import org.apache.commons.collections4.CollectionUtils; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -3094,6 +3093,55 @@ void cstgLogsInvalidAppName(String appName, Vertx vertx, VertxTestContext testCo }); } + @Test + void catalogsDisabledAsUnauthorized(Vertx vertx, VertxTestContext testContext) throws NoSuchAlgorithmException, InvalidKeyException { + ListAppender logWatcher = new ListAppender<>(); + logWatcher.start(); + ((Logger) LoggerFactory.getLogger(UIDOperatorVerticle.class)).addAppender(logWatcher); + this.uidOperatorVerticle.setLastInvalidOriginProcessTime(Instant.now().minusSeconds(3600)); + + setupCstgBackend(); + String subscriptionID = "PpRrE5YY84"; + ClientSideKeypair keypairDisabled = new ClientSideKeypair(subscriptionID, clientSideTokenGeneratePublicKey, clientSideTokenGeneratePrivateKey, clientSideTokenGenerateSiteId, "", Instant.now(), true, ""); + when(clientSideKeypairProvider.getSnapshot()).thenReturn(clientSideKeypairSnapshot); + when(clientSideKeypairSnapshot.getKeypair(subscriptionID)).thenReturn(keypairDisabled); + + final KeyFactory kf = KeyFactory.getInstance("EC"); + final PublicKey serverPublicKey = ClientSideTokenGenerateTestUtil.stringToPublicKey(clientSideTokenGeneratePublicKey, kf); + final PrivateKey clientPrivateKey = ClientSideTokenGenerateTestUtil.stringToPrivateKey(clientSideTokenGeneratePrivateKey, kf); + final SecretKey secretKey = ClientSideTokenGenerateTestUtil.deriveKey(serverPublicKey, clientPrivateKey); + + final byte[] iv = Random.getBytes(12); + final long timestamp = Instant.now().toEpochMilli(); + final JsonArray aad = JsonArray.of(timestamp); + String rawId = "random@unifiedid.com"; + + JsonObject identityPayload = new JsonObject(); + identityPayload.put("email_hash", getSha256(rawId)); + byte[] payloadBytes = ClientSideTokenGenerateTestUtil.encrypt(identityPayload.toString().getBytes(), secretKey.getEncoded(), iv, aad.toBuffer().getBytes()); + final String payload = EncodingUtils.toBase64String(payloadBytes); + + JsonObject requestJson = new JsonObject(); + requestJson.put("payload", payload); + requestJson.put("iv", EncodingUtils.toBase64String(iv)); + requestJson.put("public_key", serverPublicKey.toString()); + requestJson.put("timestamp", timestamp); + requestJson.put("subscription_id", subscriptionID); + + Tuple.Tuple2 data = createClientSideTokenGenerateRequest(IdentityType.Email, "random@unifiedid.com", Instant.now().toEpochMilli(), false, null); + sendCstg(vertx, + "v2/token/client-generate", + null, + requestJson, + secretKey, + 401, + testContext, + respJson -> { + assertEquals("Unauthorized", respJson.getString("message")); + testContext.completeNow(); + }); + } + @ParameterizedTest @CsvSource({ "true,http://gototest.com", From 5bca3446be13fe78bd06f31b78d491ee3c63806e Mon Sep 17 00:00:00 2001 From: Cody Constine Date: Tue, 14 May 2024 16:10:46 -0600 Subject: [PATCH 2/3] Fixed broken test --- src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java index ccddb3cc7..b3a549cf5 100644 --- a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java +++ b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java @@ -3108,7 +3108,7 @@ void catalogsDisabledAsUnauthorized(Vertx vertx, VertxTestContext testContext) t final KeyFactory kf = KeyFactory.getInstance("EC"); final PublicKey serverPublicKey = ClientSideTokenGenerateTestUtil.stringToPublicKey(clientSideTokenGeneratePublicKey, kf); - final PrivateKey clientPrivateKey = ClientSideTokenGenerateTestUtil.stringToPrivateKey(clientSideTokenGeneratePrivateKey, kf); + final PrivateKey clientPrivateKey = ClientSideTokenGenerateTestUtil.stringToPrivateKey("MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDsqxZicsGytVqN2HZqNDHtV422Lxio8m1vlflq4Jb47Q==", kf); final SecretKey secretKey = ClientSideTokenGenerateTestUtil.deriveKey(serverPublicKey, clientPrivateKey); final byte[] iv = Random.getBytes(12); From 1ead5cdd3073a0542de796a3fa3aed80b7c7c3dc Mon Sep 17 00:00:00 2001 From: Cody Constine Date: Mon, 20 May 2024 09:53:05 -0600 Subject: [PATCH 3/3] Addressing PR comments, fixing up the test --- .../TokenResponseStatsCollector.java | 2 +- .../operator/vertx/UIDOperatorVerticle.java | 2 +- .../uid2/operator/UIDOperatorVerticleTest.java | 18 +++++++----------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java b/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java index 4e4880f6f..bd6f10edf 100644 --- a/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java +++ b/src/main/java/com/uid2/operator/monitoring/TokenResponseStatsCollector.java @@ -39,7 +39,7 @@ public enum ResponseStatus { /* End of CSTG-related Status */ Unknown, NoActiveKey, - UNAUTHORIZED + Unauthorized } public static void record(ISiteStore siteStore, Integer siteId, Endpoint endpoint, TokenVersion advertisingTokenVersion, ResponseStatus responseStatus) { diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index ee02f8709..59c46bae6 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -339,7 +339,7 @@ private void handleClientSideTokenGenerateImpl(RoutingContext rc) throws NoSuchA if(clientSideKeypair.isDisabled()) { SendClientErrorResponseAndRecordStats(ResponseStatus.Unauthorized, 401, rc, "Unauthorized", - null, TokenResponseStatsCollector.Endpoint.ClientSideTokenGenerateV2, TokenResponseStatsCollector.ResponseStatus.UNAUTHORIZED, siteProvider); + clientSideKeypair.getSiteId(), TokenResponseStatsCollector.Endpoint.ClientSideTokenGenerateV2, TokenResponseStatsCollector.ResponseStatus.Unauthorized, siteProvider); return; } diff --git a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java index b3a549cf5..33d8339fb 100644 --- a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java +++ b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java @@ -3094,7 +3094,7 @@ void cstgLogsInvalidAppName(String appName, Vertx vertx, VertxTestContext testCo } @Test - void catalogsDisabledAsUnauthorized(Vertx vertx, VertxTestContext testContext) throws NoSuchAlgorithmException, InvalidKeyException { + void cstgDisabledAsUnauthorized(Vertx vertx, VertxTestContext testContext) throws NoSuchAlgorithmException, InvalidKeyException { ListAppender logWatcher = new ListAppender<>(); logWatcher.start(); ((Logger) LoggerFactory.getLogger(UIDOperatorVerticle.class)).addAppender(logWatcher); @@ -3110,20 +3110,12 @@ void catalogsDisabledAsUnauthorized(Vertx vertx, VertxTestContext testContext) t final PublicKey serverPublicKey = ClientSideTokenGenerateTestUtil.stringToPublicKey(clientSideTokenGeneratePublicKey, kf); final PrivateKey clientPrivateKey = ClientSideTokenGenerateTestUtil.stringToPrivateKey("MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDsqxZicsGytVqN2HZqNDHtV422Lxio8m1vlflq4Jb47Q==", kf); final SecretKey secretKey = ClientSideTokenGenerateTestUtil.deriveKey(serverPublicKey, clientPrivateKey); - - final byte[] iv = Random.getBytes(12); final long timestamp = Instant.now().toEpochMilli(); - final JsonArray aad = JsonArray.of(timestamp); - String rawId = "random@unifiedid.com"; - JsonObject identityPayload = new JsonObject(); - identityPayload.put("email_hash", getSha256(rawId)); - byte[] payloadBytes = ClientSideTokenGenerateTestUtil.encrypt(identityPayload.toString().getBytes(), secretKey.getEncoded(), iv, aad.toBuffer().getBytes()); - final String payload = EncodingUtils.toBase64String(payloadBytes); JsonObject requestJson = new JsonObject(); - requestJson.put("payload", payload); - requestJson.put("iv", EncodingUtils.toBase64String(iv)); + requestJson.put("payload", ""); + requestJson.put("iv", ""); requestJson.put("public_key", serverPublicKey.toString()); requestJson.put("timestamp", timestamp); requestJson.put("subscription_id", subscriptionID); @@ -3138,6 +3130,10 @@ void catalogsDisabledAsUnauthorized(Vertx vertx, VertxTestContext testContext) t testContext, respJson -> { assertEquals("Unauthorized", respJson.getString("message")); + assertTokenStatusMetrics( + clientSideTokenGenerateSiteId, + TokenResponseStatsCollector.Endpoint.ClientSideTokenGenerateV2, + TokenResponseStatsCollector.ResponseStatus.Unauthorized); testContext.completeNow(); }); }