Skip to content

Commit 6ee9102

Browse files
authored
jon-1207-consistent-token-prefixes (#28)
1 parent 0220ef4 commit 6ee9102

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

src/main/java/com/uid2/client/Uid2TokenGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ private static String generateUID2TokenWithDebugInfo(String uid, Key masterKey,
108108
char firstChar = uid.charAt(0);
109109
IdentityType identityType = (firstChar == 'F' || firstChar == 'B') ? IdentityType.Phone : IdentityType.Email; //see UID2-79+Token+and+ID+format+v3
110110

111-
rootWriter.put((byte)((params.identityScope << 4) | (identityType.value << 2)));
111+
rootWriter.put((byte)((params.identityScope << 4) | (identityType.value << 2) | 3));
112112
rootWriter.put((byte)adTokenVersion.value());
113113
rootWriter.putInt((int)masterKey.getId());
114114
rootWriter.put(encryptedMasterPayload);

src/test/java/com/uid2/client/EncryptionTestsV4.java

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public void crossPlatformConsistencyCheck_Decrypt() throws Exception {
9090
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
9191
client.refreshJson(keySetToJson(masterKey, siteKey));
9292
//verify that the dynamically created ad token can be decrypted
93-
String runtimeAdvertisingToken = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, masterKey, SITE_ID, siteKey, params);
93+
String runtimeAdvertisingToken = generateUid2TokenV4(EXAMPLE_UID, masterKey, SITE_ID, siteKey, params);
9494
//best effort check as the token might simply just not require padding
9595
assertEquals(-1, runtimeAdvertisingToken.indexOf('='));
9696

@@ -104,27 +104,51 @@ public void crossPlatformConsistencyCheck_Decrypt() throws Exception {
104104
assertEquals(EXAMPLE_UID, res.getUid());
105105
}
106106

107+
private static void validateAdvertisingToken(String advertisingTokenString, IdentityScope identityScope, IdentityType identityType) {
108+
String firstChar = advertisingTokenString.substring(0, 1);
109+
if (identityScope == IdentityScope.UID2) {
110+
assertEquals(identityType == IdentityType.Email ? "A" : "B", firstChar);
111+
} else {
112+
assertEquals(identityType == IdentityType.Email ? "E" : "F", firstChar);
113+
}
114+
115+
String secondChar = advertisingTokenString.substring(1, 2);
116+
assertEquals("4", secondChar);
117+
118+
//No URL-unfriendly characters allowed:
119+
assertEquals(-1, advertisingTokenString.indexOf('='));
120+
assertEquals(-1, advertisingTokenString.indexOf('+'));
121+
assertEquals(-1, advertisingTokenString.indexOf('/'));
122+
}
123+
124+
private static String generateUid2TokenV4(String uid, Key masterKey, long siteId, Key siteKey, Uid2TokenGenerator.Params params) {
125+
String advertisingToken = Uid2TokenGenerator.generateUid2TokenV4(uid, masterKey, siteId, siteKey, params);
126+
validateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email);
127+
return advertisingToken;
128+
}
129+
130+
107131
@Test
108132
public void smokeTest() throws Exception {
109133
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
110134
client.refreshJson(keySetToJson(MASTER_KEY, SITE_KEY));
111-
String advertisingToken = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
135+
String advertisingToken = generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
112136
DecryptionResponse res = client.decrypt(advertisingToken);
113137
assertEquals(EXAMPLE_UID, res.getUid());
114138
}
115139

116140
@Test
117141
public void emptyKeyContainer() throws Exception {
118142
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
119-
String advertisingToken = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
143+
String advertisingToken = generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
120144
DecryptionResponse res = client.decrypt(advertisingToken);
121145
assertEquals(DecryptionStatus.NOT_INITIALIZED, res.getStatus());
122146
}
123147

124148
@Test
125149
public void expiredKeyContainer() throws Exception {
126150
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
127-
String advertisingToken = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
151+
String advertisingToken = generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
128152

129153
Key masterKeyExpired = new Key(MASTER_KEY_ID, -1, NOW, NOW.minus(2, ChronoUnit.HOURS), NOW.minus(1, ChronoUnit.HOURS), getMasterSecret());
130154
Key siteKeyExpired = new Key(SITE_KEY_ID, SITE_ID, NOW, NOW.minus(2, ChronoUnit.HOURS), NOW.minus(1, ChronoUnit.HOURS), getSiteSecret());
@@ -137,7 +161,7 @@ public void expiredKeyContainer() throws Exception {
137161
@Test
138162
public void notAuthorizedForMasterKey() throws Exception {
139163
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
140-
String advertisingToken = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
164+
String advertisingToken = generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
141165

142166
Key anotherMasterKey = new Key(MASTER_KEY_ID + SITE_KEY_ID + 1, -1, NOW, NOW, NOW.plus(1, ChronoUnit.HOURS), getMasterSecret());
143167
Key anotherSiteKey = new Key(MASTER_KEY_ID + SITE_KEY_ID + 2, SITE_ID, NOW, NOW, NOW.plus(1, ChronoUnit.HOURS), getSiteSecret());
@@ -150,7 +174,7 @@ public void notAuthorizedForMasterKey() throws Exception {
150174
@Test
151175
public void invalidPayload() throws Exception {
152176
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
153-
String payload = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
177+
String payload = generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, Uid2TokenGenerator.defaultParams());
154178
byte[] payloadInBytes = Uid2Base64UrlCoder.decode(payload);
155179
String advertisingToken = Uid2Base64UrlCoder.encode(Arrays.copyOfRange(payloadInBytes, 0, payloadInBytes.length - 1));
156180
client.refreshJson(keySetToJson(MASTER_KEY, SITE_KEY));
@@ -165,7 +189,7 @@ public void tokenExpiryAndCustomNow() throws Exception {
165189

166190
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
167191
client.refreshJson(keySetToJson(MASTER_KEY, SITE_KEY));
168-
String advertisingToken = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, params);
192+
String advertisingToken = generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, SITE_KEY, params);
169193

170194
DecryptionResponse res = client.decrypt(advertisingToken, expiry.plus(1, ChronoUnit.SECONDS));
171195
assertEquals(DecryptionStatus.EXPIRED_TOKEN, res.getStatus());
@@ -180,7 +204,7 @@ public void encryptDataTokenDecryptKeyExpired() throws Exception {
180204
UID2Client client = new UID2Client("ep", "ak", CLIENT_SECRET, IdentityScope.UID2);
181205
final Key key = new Key(SITE_KEY_ID, SITE_ID2, NOW, NOW, NOW.minus(1, ChronoUnit.DAYS), getTestSecret(9));
182206
client.refreshJson(keySetToJson(MASTER_KEY, key));
183-
final String advertisingToken = Uid2TokenGenerator.generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, key, Uid2TokenGenerator.defaultParams());
207+
final String advertisingToken = generateUid2TokenV4(EXAMPLE_UID, MASTER_KEY, SITE_ID, key, Uid2TokenGenerator.defaultParams());
184208
EncryptionDataResponse encrypted = client.encryptData(EncryptionDataRequest.forData(data).withAdvertisingToken(advertisingToken));
185209
assertEquals(EncryptionStatus.NOT_AUTHORIZED_FOR_KEY, encrypted.getStatus());
186210
}

src/test/java/com/uid2/client/PublisherTests.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ public void integrationBadRequests() {
9393
IdentityTokens currentIdentity = IdentityTokens.fromJsonString(PublisherTests.expectedDecryptedJsonForTokenGenerateResponse);
9494
Uid2Exception exception = assertThrows(Uid2Exception.class, //expired token
9595
() -> publisherUid2Client.refreshToken(currentIdentity));
96-
assertTrue(exception.getMessage().contains("expired"));
96+
//We no longer assert on what the exception contains - since an expired key is later deleted, and deleted keys give a different error
97+
//Previous code: assertTrue(exception.getMessage().contains("expired"));
9798

9899

99100
assertThrows(NullPointerException.class, () -> publisherUid2Client.generateToken(TokenGenerateInput.fromEmail(null)));
@@ -111,9 +112,12 @@ public void integrationBadRequests() {
111112

112113
assertThrows(IllegalArgumentException.class, () -> new PublisherUid2Client(UID2_BASE_URL, UID2_API_KEY, "bad secret key"));
113114

114-
PublisherUid2Client invalidSecretKey = new PublisherUid2Client(UID2_BASE_URL, UID2_API_KEY, "incorrectSecretKey");
115-
Uid2Exception invalidSecretKeyException = assertThrows(Uid2Exception.class, () -> invalidSecretKey.generateToken(TokenGenerateInput.fromEmail("[email protected]")));
116-
assertTrue(invalidSecretKeyException.getMessage().contains("400"));
115+
PublisherUid2Client invalidSecretKey = new PublisherUid2Client(UID2_BASE_URL, UID2_API_KEY, "invalidSecretKey");
116+
assertThrows(RuntimeException.class, () -> invalidSecretKey.generateToken(TokenGenerateInput.fromEmail("[email protected]")));
117+
118+
PublisherUid2Client incorrectSecretKey = new PublisherUid2Client(UID2_BASE_URL, UID2_API_KEY, PublisherTests.UID2_SECRET_KEY); //PublisherTests.UID2_SECRET_KEY is an incorrect key because it's not a client secret for UID2_API_KEY (UID2_SECRET_KEY is the correct secret)
119+
Uid2Exception incorrectSecretKeyException = assertThrows(Uid2Exception.class, () -> incorrectSecretKey.generateToken(TokenGenerateInput.fromEmail("[email protected]")));
120+
assertTrue(incorrectSecretKeyException.getMessage().contains("400"));
117121
}
118122

119123
@Test //this test requires these env vars to be configured: EUID_BASE_URL, EUID_API_KEY, EUID_SECRET_KEY
@@ -159,7 +163,7 @@ private static byte[] hexStringToByteArray(String s) {
159163
return data;
160164
}
161165

162-
private final static String UID2_SECRET_KEY = "ioG3wKxAokmp+rERx6A4kM/13qhyolUXIu14WN16Spo=";
166+
public final static String UID2_SECRET_KEY = "ioG3wKxAokmp+rERx6A4kM/13qhyolUXIu14WN16Spo=";
163167
private final PublisherUid2Helper publisherUid2Helper = new PublisherUid2Helper(UID2_SECRET_KEY);
164168
private final byte[] nonce = hexStringToByteArray("312fe5aa08b2a049");
165169

0 commit comments

Comments
 (0)