Skip to content

Commit 9347011

Browse files
committed
Updated raw UID2 version generation logic
1 parent 78dc5fc commit 9347011

13 files changed

Lines changed: 335 additions & 305 deletions

src/main/java/com/uid2/operator/model/IdentityEnvironment.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ public enum IdentityEnvironment {
77

88
public final int value;
99

10-
IdentityEnvironment(int value) { this.value = value; }
10+
IdentityEnvironment(int value) {
11+
this.value = value;
12+
}
1113

1214
public static IdentityEnvironment fromValue(int value) {
1315
return switch (value) {
@@ -17,4 +19,13 @@ public static IdentityEnvironment fromValue(int value) {
1719
default -> throw new ClientInputValidationException("Invalid valid for IdentityEnvironment: " + value);
1820
};
1921
}
22+
23+
public static IdentityEnvironment fromString(String value) {
24+
return switch (value.toLowerCase()) {
25+
case "test" -> Test;
26+
case "integ" -> Integ;
27+
case "prod" -> Prod;
28+
default -> throw new ClientInputValidationException("Invalid valid for IdentityEnvironment: " + value);
29+
};
30+
}
2031
}

src/main/java/com/uid2/operator/model/UserIdentity.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,22 @@
22

33
import java.time.Instant;
44
import java.util.Arrays;
5-
import java.util.Objects;
65

76
public class UserIdentity {
87
public final IdentityScope identityScope;
98
public final IdentityType identityType;
9+
public final IdentityEnvironment identityEnvironment;
1010
public final byte[] id;
1111
public final int privacyBits;
1212
public final Instant establishedAt;
1313
public final Instant refreshedAt;
1414

15-
public UserIdentity(IdentityScope identityScope, IdentityType identityType, byte[] id, int privacyBits,
15+
public UserIdentity(IdentityScope identityScope, IdentityType identityType, IdentityEnvironment identityEnvironment,
16+
byte[] id, int privacyBits,
1617
Instant establishedAt, Instant refreshedAt) {
1718
this.identityScope = identityScope;
1819
this.identityType = identityType;
20+
this.identityEnvironment = identityEnvironment;
1921
this.id = id;
2022
this.privacyBits = privacyBits;
2123
this.establishedAt = establishedAt;
@@ -25,6 +27,7 @@ public UserIdentity(IdentityScope identityScope, IdentityType identityType, byte
2527
public boolean matches(UserIdentity that) {
2628
return this.identityScope.equals(that.identityScope) &&
2729
this.identityType.equals(that.identityType) &&
30+
this.identityEnvironment.equals(that.identityEnvironment) &&
2831
Arrays.equals(this.id, that.id);
2932
}
3033
}

src/main/java/com/uid2/operator/service/EncryptedTokenEncoder.java

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717

1818
public class EncryptedTokenEncoder implements ITokenEncoder {
1919
private final KeyManager keyManager;
20+
private final IdentityEnvironment identityEnvironment;
2021

21-
public EncryptedTokenEncoder(KeyManager keyManager) {
22+
public EncryptedTokenEncoder(KeyManager keyManager, IdentityEnvironment identityEnvironment) {
2223
this.keyManager = keyManager;
24+
this.identityEnvironment = identityEnvironment;
2325
}
2426

2527
public byte[] encode(AdvertisingToken t, Instant asOf) {
@@ -124,7 +126,7 @@ private RefreshToken decodeRefreshTokenV2(Buffer b) {
124126
TokenVersion.V2, createdAt, validTill,
125127
new OperatorIdentity(0, OperatorType.Service, 0, 0),
126128
new PublisherIdentity(siteId, 0, 0),
127-
new UserIdentity(IdentityScope.UID2, IdentityType.Email, identity, privacyBits, Instant.ofEpochMilli(establishedMillis), null));
129+
new UserIdentity(IdentityScope.UID2, IdentityType.Email, this.identityEnvironment, identity, privacyBits, Instant.ofEpochMilli(establishedMillis), null));
128130
}
129131

130132
private RefreshToken decodeRefreshTokenV3(Buffer b, byte[] bytes) {
@@ -157,7 +159,7 @@ private RefreshToken decodeRefreshTokenV3(Buffer b, byte[] bytes) {
157159

158160
return new RefreshToken(
159161
TokenVersion.V3, createdAt, expiresAt, operatorIdentity, publisherIdentity,
160-
new UserIdentity(identityScope, identityType, id, privacyBits, establishedAt, null));
162+
new UserIdentity(identityScope, identityType, this.identityEnvironment, id, privacyBits, establishedAt, null));
161163
}
162164

163165
@Override
@@ -225,13 +227,12 @@ public AdvertisingToken decodeAdvertisingTokenV2(Buffer b) {
225227
Instant.ofEpochMilli(expiresMillis),
226228
new OperatorIdentity(0, OperatorType.Service, 0, masterKeyId),
227229
new PublisherIdentity(siteId, siteKeyId, 0),
228-
new UserIdentity(IdentityScope.UID2, IdentityType.Email, advertisingId, privacyBits, Instant.ofEpochMilli(establishedMillis), null)
230+
new UserIdentity(IdentityScope.UID2, IdentityType.Email, this.identityEnvironment, advertisingId, privacyBits, Instant.ofEpochMilli(establishedMillis), null)
229231
);
230232

231233
} catch (Exception e) {
232234
throw new RuntimeException("Couldn't decode advertisingTokenV2", e);
233235
}
234-
235236
}
236237

237238
public AdvertisingToken decodeAdvertisingTokenV3orV4(Buffer b, byte[] bytes, TokenVersion tokenVersion) {
@@ -253,8 +254,7 @@ public AdvertisingToken decodeAdvertisingTokenV3orV4(Buffer b, byte[] bytes, Tok
253254
final IdentityScope identityScope = id.length == 32 ? IdentityScope.UID2 : decodeIdentityScopeV3(id[0]);
254255
final IdentityType identityType = id.length == 32 ? IdentityType.Email : decodeIdentityTypeV3(id[0]);
255256

256-
if (id.length > 32)
257-
{
257+
if (id.length > 32) {
258258
if (identityScope != decodeIdentityScopeV3(b.getByte(0))) {
259259
throw new ClientInputValidationException("Failed decoding advertisingTokenV3: Identity scope mismatch");
260260
}
@@ -265,7 +265,7 @@ public AdvertisingToken decodeAdvertisingTokenV3orV4(Buffer b, byte[] bytes, Tok
265265

266266
return new AdvertisingToken(
267267
tokenVersion, createdAt, expiresAt, operatorIdentity, publisherIdentity,
268-
new UserIdentity(identityScope, identityType, id, privacyBits, establishedAt, refreshedAt)
268+
new UserIdentity(identityScope, identityType, this.identityEnvironment, id, privacyBits, establishedAt, refreshedAt)
269269
);
270270
}
271271

@@ -338,7 +338,6 @@ public static String bytesToBase64Token(byte[] advertisingTokenBytes, TokenVersi
338338

339339
@Override
340340
public IdentityTokens encode(AdvertisingToken advertisingToken, RefreshToken refreshToken, Instant refreshFrom, Instant asOf) {
341-
342341
final byte[] advertisingTokenBytes = encode(advertisingToken, asOf);
343342
final String base64AdvertisingToken = bytesToBase64Token(advertisingTokenBytes, advertisingToken.version);
344343

@@ -367,16 +366,16 @@ private byte[] encryptIdentityV2(PublisherIdentity publisherIdentity, UserIdenti
367366
}
368367
}
369368

370-
static private byte encodeIdentityTypeV3(UserIdentity userIdentity) {
369+
private static byte encodeIdentityTypeV3(UserIdentity userIdentity) {
371370
return (byte) (TokenUtils.encodeIdentityScope(userIdentity.identityScope) | (userIdentity.identityType.value << 2) | 3);
372371
// "| 3" is used so that the 2nd char matches the version when V3 or higher. Eg "3" for V3 and "4" for V4
373372
}
374373

375-
static private IdentityScope decodeIdentityScopeV3(byte value) {
374+
private static IdentityScope decodeIdentityScopeV3(byte value) {
376375
return IdentityScope.fromValue((value & 0x10) >> 4);
377376
}
378377

379-
static private IdentityType decodeIdentityTypeV3(byte value) {
378+
private static IdentityType decodeIdentityTypeV3(byte value) {
380379
return IdentityType.fromValue((value & 0xf) >> 2);
381380
}
382381

@@ -392,7 +391,7 @@ static PublisherIdentity decodePublisherIdentityV3(Buffer b, int offset) {
392391

393392
static void encodeOperatorIdentityV3(Buffer b, OperatorIdentity operatorIdentity) {
394393
b.appendInt(operatorIdentity.siteId);
395-
b.appendByte((byte)operatorIdentity.operatorType.value);
394+
b.appendByte((byte) operatorIdentity.operatorType.value);
396395
b.appendInt(operatorIdentity.operatorVersion);
397396
b.appendInt(operatorIdentity.operatorKeyId);
398397
}

src/main/java/com/uid2/operator/service/IUIDOperatorService.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.util.List;
1111

1212
public interface IUIDOperatorService {
13-
1413
IdentityTokens generateIdentity(IdentityRequest request, Duration refreshIdentityAfter, Duration refreshExpiresAfter, Duration identityExpiresAfter);
1514

1615
RefreshResponse refreshIdentity(RefreshToken token, Duration refreshIdentityAfter, Duration refreshExpiresAfter, Duration identityExpiresAfter);
@@ -25,6 +24,4 @@ public interface IUIDOperatorService {
2524
void invalidateTokensAsync(UserIdentity userIdentity, Instant asOf, String uidTraceId, Handler<AsyncResult<Instant>> handler);
2625

2726
boolean advertisingTokenMatches(String advertisingToken, UserIdentity userIdentity, Instant asOf);
28-
29-
Instant getLatestOptoutEntry(UserIdentity userIdentity, Instant asOf);
3027
}

src/main/java/com/uid2/operator/service/InputUtil.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package com.uid2.operator.service;
22

3+
import com.uid2.operator.model.IdentityEnvironment;
34
import com.uid2.operator.model.IdentityScope;
45
import com.uid2.operator.model.IdentityType;
56
import com.uid2.operator.model.UserIdentity;
67

78
import java.time.Instant;
89

9-
public class InputUtil {
10+
public final class InputUtil {
11+
private static final String GMAILDOMAIN = "gmail.com";
12+
private static final int MIN_PHONENUMBER_DIGITS = 10;
13+
private static final int MAX_PHONENUMBER_DIGITS = 15;
1014

11-
private static String GMAILDOMAIN = "gmail.com";
12-
13-
private static int MIN_PHONENUMBER_DIGITS = 10;
14-
private static int MAX_PHONENUMBER_DIGITS = 15;
15+
private InputUtil() {
16+
}
1517

1618
public static InputVal normalizeEmailHash(String input) {
1719
final int inputLength = input.length();
@@ -65,8 +67,7 @@ public static boolean isPhoneNumberNormalized(String phoneNumber) {
6567

6668
// count the digits, return false if non-digit character is found
6769
int totalDigits = 0;
68-
for (int i = 1; i < phoneNumber.length(); ++i)
69-
{
70+
for (int i = 1; i < phoneNumber.length(); ++i) {
7071
if (!InputUtil.isAsciiDigit(phoneNumber.charAt(i)))
7172
return false;
7273
++totalDigits;
@@ -80,7 +81,7 @@ public static boolean isPhoneNumberNormalized(String phoneNumber) {
8081

8182
public static InputVal normalizeEmail(String email) {
8283
final String normalize = normalizeEmailString(email);
83-
if (normalize != null && normalize.length() > 0) {
84+
if (normalize != null && !normalize.isEmpty()) {
8485
return InputVal.validEmail(email, normalize);
8586
}
8687
return InputVal.invalidEmail(email);
@@ -143,15 +144,15 @@ public static String normalizeEmailString(String email) {
143144
wsBuffer.append(c);
144145
break;
145146
}
146-
if (wsBuffer.length() > 0) {
147-
sb.append(wsBuffer.toString());
147+
if (!wsBuffer.isEmpty()) {
148+
sb.append(wsBuffer);
148149
wsBuffer = new StringBuilder();
149150
}
150151
sb.append(c);
151152
}
152153
}
153154
}
154-
if (sb.length() == 0) {
155+
if (sb.isEmpty()) {
155156
return null;
156157
}
157158
final String domainPart = sb.toString();
@@ -162,7 +163,7 @@ public static String normalizeEmailString(String email) {
162163
} else {
163164
addressPartToUse = preSb;
164165
}
165-
if (addressPartToUse.length() == 0) {
166+
if (addressPartToUse.isEmpty()) {
166167
return null;
167168
}
168169

@@ -174,7 +175,7 @@ public enum IdentityInputType {
174175
Hash
175176
}
176177

177-
private static enum EmailParsingState {
178+
private enum EmailParsingState {
178179
Starting,
179180
Pre,
180181
SubDomain,
@@ -255,16 +256,19 @@ public IdentityType getIdentityType() {
255256
return identityType;
256257
}
257258

258-
public IdentityInputType getInputType() { return inputType; }
259+
public IdentityInputType getInputType() {
260+
return inputType;
261+
}
259262

260263
public boolean isValid() {
261264
return valid;
262265
}
263266

264-
public UserIdentity toUserIdentity(IdentityScope identityScope, int privacyBits, Instant establishedAt) {
267+
public UserIdentity toUserIdentity(IdentityScope identityScope, IdentityEnvironment identityEnvironment, int privacyBits, Instant establishedAt) {
265268
return new UserIdentity(
266269
identityScope,
267270
this.identityType,
271+
identityEnvironment,
268272
getIdentityInput(),
269273
privacyBits,
270274
establishedAt,

src/main/java/com/uid2/operator/service/TokenUtils.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
import com.uid2.operator.model.IdentityVersion;
77
import com.uid2.shared.model.SaltEntry;
88

9-
public class TokenUtils {
9+
public final class TokenUtils {
10+
private TokenUtils() {
11+
}
12+
1013
public static byte[] getIdentityHash(String identityString) {
1114
return EncodingUtils.getSha256Bytes(identityString);
1215
}
@@ -42,7 +45,7 @@ public static byte[] getAdvertisingIdV2FromIdentityHash(String identityString, S
4245
public static byte[] getAdvertisingIdV3(IdentityScope scope, IdentityType type, byte[] firstLevelHash, String rotatingSalt) {
4346
final byte[] sha = EncodingUtils.getSha256Bytes(EncodingUtils.toBase64String(firstLevelHash), rotatingSalt);
4447
final byte[] id = new byte[33];
45-
id[0] = (byte)(encodeIdentityScope(scope) | encodeIdentityType(type));
48+
id[0] = (byte) (encodeIdentityScope(scope) | encodeIdentityType(type));
4649
System.arraycopy(sha, 0, id, 1, 32);
4750
return id;
4851
}
@@ -55,9 +58,9 @@ public static byte[] getAdvertisingIdV3FromIdentityHash(IdentityScope scope, Ide
5558
return getAdvertisingIdV3(scope, type, getFirstLevelHashFromIdentityHash(identityString, firstLevelSalt), rotatingSalt);
5659
}
5760

58-
public static byte[] getAdvertisingIdV4(IdentityScope scope, IdentityType type, IdentityEnvironment environment, byte[] firstLevelHash, SaltEntry.KeyMaterial encryptingKey, String rotatingSalt) throws Exception {
61+
public static byte[] getAdvertisingIdV4(IdentityScope scope, IdentityType type, IdentityEnvironment environment, byte[] firstLevelHash, SaltEntry.KeyMaterial encryptingKey) throws Exception {
5962
byte metadata = (byte) (encodeIdentityVersion(IdentityVersion.V4) | encodeIdentityScope(scope) | encodeIdentityType(type) | encodeIdentityEnvironment(environment));
60-
return V4TokenUtils.buildAdvertisingIdV4(metadata, firstLevelHash, encryptingKey.id(), encryptingKey.key(), rotatingSalt);
63+
return V4TokenUtils.buildAdvertisingIdV4(metadata, firstLevelHash, encryptingKey.id(), encryptingKey.key(), encryptingKey.salt());
6164
}
6265

6366
public static byte encodeIdentityScope(IdentityScope identityScope) { return (byte) (identityScope.value << 4); }

0 commit comments

Comments
 (0)