Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public class UIDOperatorService implements IUIDOperatorService {

private final OperatorIdentity operatorIdentity;
private final TokenVersion refreshTokenVersion;
private final boolean identityV3Enabled;
// if we use Raw UID v3 format for the raw UID2/EUIDs generated in this operator
private final boolean rawUidV3Enabled;

private final Handler<Boolean> saltRetrievalResponseHandler;

Expand Down Expand Up @@ -90,7 +91,7 @@ public UIDOperatorService(JsonObject config, IOptOutStore optOutStore, ISaltProv
}

this.refreshTokenVersion = TokenVersion.V3;
this.identityV3Enabled = config.getBoolean("identity_v3", false);
this.rawUidV3Enabled = config.getBoolean("identity_v3", false);
}

@Override
Expand Down Expand Up @@ -230,7 +231,7 @@ private MappedIdentity getAdvertisingId(UserIdentity firstLevelHashIdentity, Ins
final SaltEntry rotatingSalt = getSaltProviderSnapshot(asOf).getRotatingSalt(firstLevelHashIdentity.id);

return new MappedIdentity(
this.identityV3Enabled
this.rawUidV3Enabled
? TokenUtils.getAdvertisingIdV3(firstLevelHashIdentity.identityScope, firstLevelHashIdentity.identityType, firstLevelHashIdentity.id, rotatingSalt.getSalt())
: TokenUtils.getAdvertisingIdV2(firstLevelHashIdentity.id, rotatingSalt.getSalt()),
rotatingSalt.getHashedId());
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/com/uid2/operator/EUIDOperatorVerticleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public EUIDOperatorVerticleTest() throws IOException {
@Override
protected IdentityScope getIdentityScope() { return IdentityScope.EUID; }
@Override
protected boolean useRawUidV3() { return true; }
@Override
protected void addAdditionalTokenGenerateParams(JsonObject payload) {
if (payload != null && !payload.containsKey("tcf_consent_string")) {
payload.put("tcf_consent_string", "CPehNtWPehNtWABAMBFRACBoALAAAEJAAIYgAKwAQAKgArABAAqAAA");
Expand Down
23 changes: 16 additions & 7 deletions src/test/java/com/uid2/operator/TokenEncodingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.vertx.core.json.JsonObject;
import org.junit.Assert;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.EnumSource;

import java.time.Instant;
Expand Down Expand Up @@ -86,15 +87,23 @@ public void testRefreshTokenEncoding(TokenVersion tokenVersion) {
}

@ParameterizedTest
@EnumSource(TokenVersion.class)
public void testAdvertisingTokenEncodings(TokenVersion tokenVersion) {
@CsvSource({"false, V4", //same as current UID2 prod (as at 2024-12-10)
"true, V4", //same as current EUID prod (as at 2024-12-10)
//the following combinations aren't used in any UID2/EUID environments but just testing them regardless
"false, V3",
"true, V3",
"false, V2",
"true, V2",
}
)
public void testAdvertisingTokenEncodings(boolean useRawUIDv3, TokenVersion adTokenVersion) {
final EncryptedTokenEncoder encoder = new EncryptedTokenEncoder(this.keyManager);
final Instant now = EncodingUtils.NowUTCMillis();

final byte[] rawUid = UIDOperatorVerticleTest.getRawUid(IdentityType.Email, "[email protected]", IdentityScope.UID2, tokenVersion != TokenVersion.V2);
final byte[] rawUid = UIDOperatorVerticleTest.getRawUid(IdentityType.Email, "[email protected]", IdentityScope.UID2, useRawUIDv3);

final AdvertisingToken token = new AdvertisingToken(
tokenVersion,
adTokenVersion,
now,
now.plusSeconds(60),
new OperatorIdentity(101, OperatorType.Service, 102, 103),
Expand All @@ -103,9 +112,9 @@ public void testAdvertisingTokenEncodings(TokenVersion tokenVersion) {
);

final byte[] encodedBytes = encoder.encode(token, now);
final AdvertisingToken decoded = encoder.decodeAdvertisingToken(EncryptedTokenEncoder.bytesToBase64Token(encodedBytes, tokenVersion));
final AdvertisingToken decoded = encoder.decodeAdvertisingToken(EncryptedTokenEncoder.bytesToBase64Token(encodedBytes, adTokenVersion));

assertEquals(tokenVersion, decoded.version);
assertEquals(adTokenVersion, decoded.version);
assertEquals(token.createdAt, decoded.createdAt);
assertEquals(token.expiresAt, decoded.expiresAt);
assertTrue(token.userIdentity.matches(decoded.userIdentity));
Expand All @@ -114,7 +123,7 @@ public void testAdvertisingTokenEncodings(TokenVersion tokenVersion) {
assertEquals(token.publisherIdentity.siteId, decoded.publisherIdentity.siteId);

Buffer b = Buffer.buffer(encodedBytes);
int keyId = b.getInt(tokenVersion == TokenVersion.V2 ? 1 : 2); //TODO - extract master key from token should be a helper function
int keyId = b.getInt(adTokenVersion == TokenVersion.V2 ? 1 : 2); //TODO - extract master key from token should be a helper function
assertEquals(Data.MasterKeySiteId, keyManager.getSiteIdFromKeyId(keyId));
}
}
24 changes: 12 additions & 12 deletions src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import com.uid2.operator.util.Tuple;
import com.uid2.operator.vertx.OperatorShutdownHandler;
import com.uid2.operator.vertx.UIDOperatorVerticle;
import com.uid2.operator.vertx.ClientInputValidationException;
import com.uid2.shared.Utils;
import com.uid2.shared.auth.ClientKey;
import com.uid2.shared.auth.Keyset;
Expand All @@ -27,9 +26,7 @@
import com.uid2.shared.secret.KeyHasher;
import com.uid2.shared.store.*;
import com.uid2.shared.store.reader.RotatingKeysetProvider;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.search.MeterNotFoundException;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
Expand Down Expand Up @@ -158,7 +155,7 @@ private void setupConfig(JsonObject config) {
config.put(Const.Config.SharingTokenExpiryProp, 60 * 60 * 24 * 30);

config.put("identity_scope", getIdentityScope().toString());
config.put("identity_v3", useIdentityV3());
config.put("identity_v3", useRawUidV3());
config.put("client_side_token_generate", true);
config.put("key_sharing_endpoint_provide_app_names", true);
config.put("client_side_token_generate_log_invalid_http_origins", true);
Expand Down Expand Up @@ -622,23 +619,23 @@ private void assertTokenStatusMetrics(Integer siteId, TokenResponseStatsCollecto
}

private byte[] getAdvertisingIdFromIdentity(IdentityType identityType, String identityString, String firstLevelSalt, String rotatingSalt) {
return getRawUid(identityType, identityString, firstLevelSalt, rotatingSalt, getIdentityScope(), useIdentityV3());
return getRawUid(identityType, identityString, firstLevelSalt, rotatingSalt, getIdentityScope(), useRawUidV3());
}

private static byte[] getRawUid(IdentityType identityType, String identityString, String firstLevelSalt, String rotatingSalt, IdentityScope identityScope, boolean useIdentityV3) {
return !useIdentityV3
private static byte[] getRawUid(IdentityType identityType, String identityString, String firstLevelSalt, String rotatingSalt, IdentityScope identityScope, boolean useRawUidV3) {
return !useRawUidV3
? TokenUtils.getAdvertisingIdV2FromIdentity(identityString, firstLevelSalt, rotatingSalt)
: TokenUtils.getAdvertisingIdV3FromIdentity(identityScope, identityType, identityString, firstLevelSalt, rotatingSalt);
}

public static byte[] getRawUid(IdentityType identityType, String identityString, IdentityScope identityScope, boolean useIdentityV3) {
return !useIdentityV3
public static byte[] getRawUid(IdentityType identityType, String identityString, IdentityScope identityScope, boolean useRawUidV3) {
return !useRawUidV3
? TokenUtils.getAdvertisingIdV2FromIdentity(identityString, firstLevelSalt, rotatingSalt123.getSalt())
: TokenUtils.getAdvertisingIdV3FromIdentity(identityScope, identityType, identityString, firstLevelSalt, rotatingSalt123.getSalt());
}

private byte[] getAdvertisingIdFromIdentityHash(IdentityType identityType, String identityString, String firstLevelSalt, String rotatingSalt) {
return !useIdentityV3()
return !useRawUidV3()
? TokenUtils.getAdvertisingIdV2FromIdentityHash(identityString, firstLevelSalt, rotatingSalt)
: TokenUtils.getAdvertisingIdV3FromIdentityHash(getIdentityScope(), identityType, identityString, firstLevelSalt, rotatingSalt);
}
Expand All @@ -665,7 +662,7 @@ private JsonObject setupIdentityMapServiceLinkTest() {

protected TokenVersion getTokenVersion() {return TokenVersion.V4;}

final boolean useIdentityV3() { return getTokenVersion() != TokenVersion.V2; }
protected boolean useRawUidV3() { return false; }
protected IdentityScope getIdentityScope() { return IdentityScope.UID2; }
protected void addAdditionalTokenGenerateParams(JsonObject payload) {}

Expand Down Expand Up @@ -816,7 +813,10 @@ private AdvertisingToken validateAndGetToken(EncryptedTokenEncoder encoder, Json
final String advertisingTokenString = body.getString("advertising_token");
validateAdvertisingToken(advertisingTokenString, getTokenVersion(), getIdentityScope(), identityType);
AdvertisingToken advertisingToken = encoder.decodeAdvertisingToken(advertisingTokenString);
if (getTokenVersion() == TokenVersion.V4) {

// without useIdentityV3() the assert will be trigger as there's no IdentityType in v4 token generated with
// a raw UID v2 as old raw UID format doesn't store the identity type (and scope)
if (useRawUidV3() && getTokenVersion() == TokenVersion.V4) {
assertEquals(identityType, advertisingToken.userIdentity.identityType);
}
return advertisingToken;
Expand Down
Loading