From 9c8ae0c6f84fed399f31e359400041dd11768918 Mon Sep 17 00:00:00 2001 From: Caroline6312 Date: Mon, 29 Apr 2024 13:20:47 -0700 Subject: [PATCH 1/6] Change input from domain name to domain or app names for UID2Client and BidstreamClient decrypt methods --- src/UID2.Client/BidstreamClient.cs | 8 ++-- src/UID2.Client/DecryptionStatus.cs | 2 +- src/UID2.Client/IUID2Client.cs | 8 ++-- src/UID2.Client/KeyContainer.cs | 6 +-- src/UID2.Client/Site.cs | 2 +- src/UID2.Client/TokenHelper.cs | 4 +- src/UID2.Client/UID2Client.cs | 12 +++--- src/UID2.Client/UID2Encryption.cs | 34 ++++++++-------- test/UID2.Client.Test/BidstreamClientTests.cs | 39 +++++++++++++++++-- test/UID2.Client.Test/EncryptionTestsV2.cs | 28 ++++++++++--- test/UID2.Client.Test/EncryptionTestsV3.cs | 28 ++++++++++--- test/UID2.Client.Test/EncryptionTestsV4.cs | 29 +++++++++++--- test/UID2.Client.Test/KeyParserTests.cs | 20 +++++----- test/UID2.Client.Test/TestData.cs | 4 +- 14 files changed, 155 insertions(+), 69 deletions(-) diff --git a/src/UID2.Client/BidstreamClient.cs b/src/UID2.Client/BidstreamClient.cs index 1018a82..6c44378 100644 --- a/src/UID2.Client/BidstreamClient.cs +++ b/src/UID2.Client/BidstreamClient.cs @@ -12,14 +12,14 @@ public BidstreamClient(string endpoint, string authKey, string secretKey) _tokenHelper = new TokenHelper(endpoint, authKey, secretKey); } - public DecryptionResponse DecryptTokenIntoRawUid(string token, string domainNameFromBidRequest) + public DecryptionResponse DecryptTokenIntoRawUid(string token, string domainOrAppNameFromBidRequest) { - return DecryptTokenIntoRawUid(token, domainNameFromBidRequest, DateTime.UtcNow); + return DecryptTokenIntoRawUid(token, domainOrAppNameFromBidRequest, DateTime.UtcNow); } - internal DecryptionResponse DecryptTokenIntoRawUid(string token, string domainNameFromBidRequest, DateTime utcNow) + internal DecryptionResponse DecryptTokenIntoRawUid(string token, string domainOrAppNameFromBidRequest, DateTime utcNow) { - return _tokenHelper.Decrypt(token, utcNow, domainNameFromBidRequest, ClientType.Bidstream); + return _tokenHelper.Decrypt(token, utcNow, domainOrAppNameFromBidRequest, ClientType.Bidstream); } diff --git a/src/UID2.Client/DecryptionStatus.cs b/src/UID2.Client/DecryptionStatus.cs index 00e4ec3..089050b 100644 --- a/src/UID2.Client/DecryptionStatus.cs +++ b/src/UID2.Client/DecryptionStatus.cs @@ -16,7 +16,7 @@ public enum DecryptionStatus /// DSPs are still expected to check their records for user opt out, even when this status is not returned /// UserOptedOut, - DomainNameCheckFailed, + DomainOrAppNameCheckFailed, InvalidTokenLifetime } } diff --git a/src/UID2.Client/IUID2Client.cs b/src/UID2.Client/IUID2Client.cs index 722f060..abf26f0 100644 --- a/src/UID2.Client/IUID2Client.cs +++ b/src/UID2.Client/IUID2Client.cs @@ -40,17 +40,17 @@ public interface IUID2Client DecryptionResponse Decrypt(string token, DateTime utcNow); DecryptionResponse Decrypt(string token); /// - /// Decrypt advertising token to extract UID2 details and does a domain name check with the provided domainNameFromBidRequest param + /// Decrypt advertising token to extract UID2 details and does a domain or app name check with the provided domainOrAppNameFromBidRequest param /// for tokens from Client Side Token Generation /// /// The UID2 Token - /// The domain name from bid request which should match the domain name of the publisher (registered with UID2 admin) + /// The domain or app name from bid request which should match the domain or app name of the publisher (registered with UID2 admin) /// generating this token previously using Client Side Token Generation /// /// Response showing if decryption is successful and the resulting UID if successful. - /// Or it could return error codes/string indicating what went wrong (such as DecryptionStatus.DomainNameCheckFailed) + /// Or it could return error codes/string indicating what went wrong (such as DecryptionStatus.DomainOrAppNameCheckFailed) /// - DecryptionResponse Decrypt(string token, string domainNameFromBidRequest); + DecryptionResponse Decrypt(string token, string domainOrAppNameFromBidRequest); EncryptionDataResponse Encrypt(string rawUid); [Obsolete("Please use Encrypt(string rawUid) instead.")] diff --git a/src/UID2.Client/KeyContainer.cs b/src/UID2.Client/KeyContainer.cs index 69865ce..5271eca 100644 --- a/src/UID2.Client/KeyContainer.cs +++ b/src/UID2.Client/KeyContainer.cs @@ -114,14 +114,14 @@ public bool TryGetMasterKey(DateTime now, out Key key) return TryGetKeysetActiveKey(_masterKeysetId, now, out key); } - public bool IsDomainNameAllowedForSite(int siteId, string domainName) + public bool IsDomainOrAppNameAllowedForSite(int siteId, string domainOrAppName) { - if (domainName == null) + if (domainOrAppName == null) { return false; } - return this._siteIdToSite.TryGetValue(siteId, out var site) && site.AllowDomainName(domainName); + return this._siteIdToSite.TryGetValue(siteId, out var site) && site.AllowDomainName(domainOrAppName); } private bool TryGetKeysetActiveKey(int keysetId, DateTime now, out Key key) diff --git a/src/UID2.Client/Site.cs b/src/UID2.Client/Site.cs index 7caca0b..36e1ac1 100644 --- a/src/UID2.Client/Site.cs +++ b/src/UID2.Client/Site.cs @@ -10,7 +10,7 @@ internal class Site public Site(int id, IEnumerable domainNames) { Id = id; - _domainNames = new HashSet(domainNames, StringComparer.OrdinalIgnoreCase); + _domainNames = new HashSet(domainNames); } public int Id { get; } diff --git a/src/UID2.Client/TokenHelper.cs b/src/UID2.Client/TokenHelper.cs index ee90620..9977c09 100644 --- a/src/UID2.Client/TokenHelper.cs +++ b/src/UID2.Client/TokenHelper.cs @@ -15,7 +15,7 @@ internal TokenHelper(string endpoint, string authKey, string secretKey) _uid2ClientHelper = new Uid2ClientHelper(endpoint, authKey, secretKey); } - internal DecryptionResponse Decrypt(string token, DateTime now, string domainNameFromBidRequest, ClientType clientType) + internal DecryptionResponse Decrypt(string token, DateTime now, string domainOrAppNameFromBidRequest, ClientType clientType) { var container = Volatile.Read(ref _container); if (container == null) @@ -30,7 +30,7 @@ internal DecryptionResponse Decrypt(string token, DateTime now, string domainNam try { - return UID2Encryption.Decrypt(token, container, now, domainNameFromBidRequest, container.IdentityScope, clientType); + return UID2Encryption.Decrypt(token, container, now, domainOrAppNameFromBidRequest, container.IdentityScope, clientType); } catch (Exception) { diff --git a/src/UID2.Client/UID2Client.cs b/src/UID2.Client/UID2Client.cs index 2e064f7..f09fc98 100644 --- a/src/UID2.Client/UID2Client.cs +++ b/src/UID2.Client/UID2Client.cs @@ -34,20 +34,20 @@ public UID2Client(string endpoint, string authKey, string secretKey, IdentitySco public DecryptionResponse Decrypt(string token) { - return Decrypt(token, DateTime.UtcNow, null, ClientType.LegacyWithoutDomainCheck); + return Decrypt(token, DateTime.UtcNow, null, ClientType.LegacyWithoutDomainOrAppNameCheck); } public DecryptionResponse Decrypt(string token, DateTime utcNow) { - return Decrypt(token, utcNow, null, ClientType.LegacyWithoutDomainCheck); + return Decrypt(token, utcNow, null, ClientType.LegacyWithoutDomainOrAppNameCheck); } - public DecryptionResponse Decrypt(string token, string domainNameFromBidRequest) + public DecryptionResponse Decrypt(string token, string domainOrAppNameFromBidRequest) { - return Decrypt(token, DateTime.UtcNow, domainNameFromBidRequest, ClientType.LegacyWithDomainCheck); + return Decrypt(token, DateTime.UtcNow, domainOrAppNameFromBidRequest, ClientType.LegacyWithDomainOrAppNameCheck); } - private DecryptionResponse Decrypt(string token, DateTime now, string domainNameFromBidRequest, ClientType clientType) + private DecryptionResponse Decrypt(string token, DateTime now, string domainOrAppNameFromBidRequest, ClientType clientType) { var container = Volatile.Read(ref _container); if (container == null) @@ -62,7 +62,7 @@ private DecryptionResponse Decrypt(string token, DateTime now, string domainName try { - return UID2Encryption.Decrypt(token, container, now, domainNameFromBidRequest, _identityScope, clientType); + return UID2Encryption.Decrypt(token, container, now, domainOrAppNameFromBidRequest, _identityScope, clientType); } catch (Exception) { diff --git a/src/UID2.Client/UID2Encryption.cs b/src/UID2.Client/UID2Encryption.cs index 03fa35d..673ffe9 100644 --- a/src/UID2.Client/UID2Encryption.cs +++ b/src/UID2.Client/UID2Encryption.cs @@ -13,8 +13,8 @@ internal enum ClientType { Sharing, Bidstream, - LegacyWithoutDomainCheck, - LegacyWithDomainCheck + LegacyWithoutDomainOrAppNameCheck, + LegacyWithDomainOrAppNameCheck } internal static class UID2Encryption @@ -26,7 +26,7 @@ internal static class UID2Encryption private static char[] BASE64_URL_SPECIAL_CHARS = { '-', '_' }; - internal static DecryptionResponse Decrypt(string token, KeyContainer keys, DateTime now, string domainName, IdentityScope identityScope, ClientType clientType) + internal static DecryptionResponse Decrypt(string token, KeyContainer keys, DateTime now, string domainOrAppName, IdentityScope identityScope, ClientType clientType) { if (token.Length < 4) { @@ -39,24 +39,24 @@ internal static DecryptionResponse Decrypt(string token, KeyContainer keys, Date if (data[0] == 2) { - return DecryptV2(Convert.FromBase64String(token), keys, now, domainName, clientType); + return DecryptV2(Convert.FromBase64String(token), keys, now, domainOrAppName, clientType); } if (data[1] == (int)AdvertisingTokenVersion.V3) { - return DecryptV3(Convert.FromBase64String(token), keys, now, identityScope, 3, domainName, clientType); + return DecryptV3(Convert.FromBase64String(token), keys, now, identityScope, 3, domainOrAppName, clientType); } if (data[1] == (int)AdvertisingTokenVersion.V4) { //same as V3 but use Base64URL encoding - return DecryptV3(UID2Base64UrlCoder.Decode(token), keys, now, identityScope, 4, domainName, clientType); + return DecryptV3(UID2Base64UrlCoder.Decode(token), keys, now, identityScope, 4, domainOrAppName, clientType); } return DecryptionResponse.MakeError(DecryptionStatus.VersionNotSupported); } - private static DecryptionResponse DecryptV2(byte[] encryptedId, KeyContainer keys, DateTime now, string domainName, ClientType clientType) + private static DecryptionResponse DecryptV2(byte[] encryptedId, KeyContainer keys, DateTime now, string domainOrAppName, ClientType clientType) { if (encryptedId.Length != TOKEN_V2_LENGTH) { @@ -118,9 +118,9 @@ private static DecryptionResponse DecryptV2(byte[] encryptedId, KeyContainer key return new DecryptionResponse(DecryptionStatus.UserOptedOut, null, established, siteId, siteKey.SiteId, null, advertisingTokenVersion, privacyBits.IsClientSideGenerated, expiry); } - if (!IsDomainNameAllowedForSite(clientType, privacyBits, siteId, domainName, keys)) + if (!IsDomainOrAppNameAllowedForSite(clientType, privacyBits, siteId, domainOrAppName, keys)) { - return new DecryptionResponse(DecryptionStatus.DomainNameCheckFailed, null, established, siteId, siteKey.SiteId, null, advertisingTokenVersion, privacyBits.IsClientSideGenerated, expiry); + return new DecryptionResponse(DecryptionStatus.DomainOrAppNameCheckFailed, null, established, siteId, siteKey.SiteId, null, advertisingTokenVersion, privacyBits.IsClientSideGenerated, expiry); } if (!DoesTokenHaveValidLifetime(clientType, keys, now, expiry, now)) @@ -129,7 +129,7 @@ private static DecryptionResponse DecryptV2(byte[] encryptedId, KeyContainer key return new DecryptionResponse(DecryptionStatus.Success, idString, established, siteId, siteKey.SiteId, null, advertisingTokenVersion, privacyBits.IsClientSideGenerated, expiry); } - private static DecryptionResponse DecryptV3(byte[] encryptedId, KeyContainer keys, DateTime now, IdentityScope identityScope, int advertisingTokenVersion, string domainName, ClientType clientType) + private static DecryptionResponse DecryptV3(byte[] encryptedId, KeyContainer keys, DateTime now, IdentityScope identityScope, int advertisingTokenVersion, string domainOrAppName, ClientType clientType) { if (encryptedId.Length < TOKEN_V3_MIN_LENGTH) { @@ -203,9 +203,9 @@ private static DecryptionResponse DecryptV3(byte[] encryptedId, KeyContainer key return new DecryptionResponse(DecryptionStatus.UserOptedOut, null, established, siteId, siteKey.SiteId, identityType, advertisingTokenVersion, privacyBits.IsClientSideGenerated, expiry); } - if (!IsDomainNameAllowedForSite(clientType, privacyBits, siteId, domainName, keys)) + if (!IsDomainOrAppNameAllowedForSite(clientType, privacyBits, siteId, domainOrAppName, keys)) { - return new DecryptionResponse(DecryptionStatus.DomainNameCheckFailed, null, established, siteId, siteKey.SiteId, identityType, advertisingTokenVersion, privacyBits.IsClientSideGenerated, expiry); + return new DecryptionResponse(DecryptionStatus.DomainOrAppNameCheckFailed, null, established, siteId, siteKey.SiteId, identityType, advertisingTokenVersion, privacyBits.IsClientSideGenerated, expiry); } if (!DoesTokenHaveValidLifetime(clientType, keys, generated, expiry, now)) @@ -242,15 +242,15 @@ private static bool DoesTokenHaveValidLifetimeImpl(DateTime generatedOrNow, Date return (generatedOrNow - now).TotalSeconds <= allowClockSkewSeconds; //returns false if token generated too far in the future } - private static bool IsDomainNameAllowedForSite(ClientType clientType, PrivacyBits privacyBits, int siteId, string domainName, KeyContainer keys) + private static bool IsDomainOrAppNameAllowedForSite(ClientType clientType, PrivacyBits privacyBits, int siteId, string domainOrAppName, KeyContainer keys) { if (!privacyBits.IsClientSideGenerated) return true; - if (clientType != ClientType.Bidstream && clientType != ClientType.LegacyWithDomainCheck) + if (clientType != ClientType.Bidstream && clientType != ClientType.LegacyWithDomainOrAppNameCheck) return true; - return keys.IsDomainNameAllowedForSite(siteId, domainName); + return keys.IsDomainOrAppNameAllowedForSite(siteId, domainOrAppName); } internal static EncryptionDataResponse Encrypt(string rawUid, KeyContainer keys, IdentityScope identityScope, DateTime now) @@ -327,8 +327,8 @@ internal static EncryptionDataResponse EncryptData(EncryptionDataRequest request { try { - // if the enableDomainNameCheck param is enabled , the caller would have to provide siteId as part of the EncryptionDataRequest. - DecryptionResponse decryptedToken = Decrypt(request.AdvertisingToken, keys, now, domainName: null, identityScope, ClientType.LegacyWithoutDomainCheck); + // if the enableDomainOrAppNameCheck param is enabled , the caller would have to provide siteId as part of the EncryptionDataRequest. + DecryptionResponse decryptedToken = Decrypt(request.AdvertisingToken, keys, now, domainOrAppName: null, identityScope, ClientType.LegacyWithoutDomainOrAppNameCheck); if (!decryptedToken.Success) { return EncryptionDataResponse.MakeError(EncryptionStatus.TokenDecryptFailure); diff --git a/test/UID2.Client.Test/BidstreamClientTests.cs b/test/UID2.Client.Test/BidstreamClientTests.cs index 207547f..e4c8ed6 100644 --- a/test/UID2.Client.Test/BidstreamClientTests.cs +++ b/test/UID2.Client.Test/BidstreamClientTests.cs @@ -302,21 +302,49 @@ private void UserOptedOutTest(TokenVersion tokenVersion) } [Theory] - // These are the domains associated with site SITE_ID, as defined by KeySharingResponse(); + // These are the domain or app names associated with site SITE_ID, as defined by KeySharingResponse(); [InlineData("example.com", TokenVersion.V2)] [InlineData("example.org", TokenVersion.V2)] + [InlineData("com.123.Game.App.android", TokenVersion.V2)] [InlineData("example.com", TokenVersion.V3)] [InlineData("example.org", TokenVersion.V3)] + [InlineData("com.123.Game.App.android", TokenVersion.V3)] [InlineData("example.com", TokenVersion.V4)] [InlineData("example.org", TokenVersion.V4)] - private void TokenIsCstgDerivedTest(string domainName, TokenVersion tokenVersion) + [InlineData("com.123.Game.App.android", TokenVersion.V4)] + private void TokenIsCstgDerivedTest(string domainOrAppName, TokenVersion tokenVersion) { Refresh(KeySharingResponse(new[] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).WithVersion(tokenVersion).Build(); ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email, tokenVersion); - var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainName); + var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainOrAppName); + Assert.True(res.IsClientSideGenerated); + Assert.True(res.Success); + Assert.Equal(DecryptionStatus.Success, res.Status); + Assert.Equal(EXAMPLE_EMAIL_RAW_UID2_V2, res.Uid); + } + + [Theory] + // These are the domain or app names associated with site SITE_ID but vary in capitalization, as defined by KeySharingResponse(); + [InlineData("example.com", TokenVersion.V2)] + [InlineData("example.org", TokenVersion.V2)] + [InlineData("com.123.Game.App.android", TokenVersion.V2)] + [InlineData("example.com", TokenVersion.V3)] + [InlineData("example.org", TokenVersion.V3)] + [InlineData("com.123.Game.App.android", TokenVersion.V3)] + [InlineData("example.com", TokenVersion.V4)] + [InlineData("example.org", TokenVersion.V4)] + [InlineData("com.123.Game.App.android", TokenVersion.V4)] + private void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName, TokenVersion tokenVersion) + { + Refresh(KeySharingResponse(new[] { MASTER_KEY, SITE_KEY })); + + var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); + string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).WithVersion(tokenVersion).Build(); + ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email, tokenVersion); + var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); @@ -328,16 +356,19 @@ private void TokenIsCstgDerivedTest(string domainName, TokenVersion tokenVersion [InlineData("", TokenVersion.V2)] [InlineData("example.net", TokenVersion.V2)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.edu", TokenVersion.V2)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). + [InlineData("com.123.Game.App.ios", TokenVersion.V2)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("foo.com", TokenVersion.V2)] // Domain not associated with any site. [InlineData((string)null, TokenVersion.V3)] [InlineData("", TokenVersion.V3)] [InlineData("example.net", TokenVersion.V3)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.edu", TokenVersion.V3)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). + [InlineData("com.123.Game.App.ios", TokenVersion.V3)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("foo.com", TokenVersion.V3)] // Domain not associated with any site. [InlineData((string)null, TokenVersion.V4)] [InlineData("", TokenVersion.V4)] [InlineData("example.net", TokenVersion.V4)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.edu", TokenVersion.V4)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). + [InlineData("com.123.Game.App.ios", TokenVersion.V4)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("foo.com", TokenVersion.V4)] // Domain not associated with any site. private void TokenIsCstgDerivedDomainNameFailTest(string domainName, TokenVersion tokenVersion) { @@ -347,7 +378,7 @@ private void TokenIsCstgDerivedDomainNameFailTest(string domainName, TokenVersio var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); - Assert.Equal(DecryptionStatus.DomainNameCheckFailed, res.Status); + Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); Assert.Null(res.Uid); } diff --git a/test/UID2.Client.Test/EncryptionTestsV2.cs b/test/UID2.Client.Test/EncryptionTestsV2.cs index 57189b8..7944d31 100644 --- a/test/UID2.Client.Test/EncryptionTestsV2.cs +++ b/test/UID2.Client.Test/EncryptionTestsV2.cs @@ -39,27 +39,45 @@ public void UserOptedOutTest() } [Theory] - // These are the domains associated with site SITE_ID, as defined by KeySharingResponse(); + // These are the domain or app names associated with site SITE_ID, as defined by KeySharingResponse(); [InlineData("example.com")] [InlineData("example.org")] - public void TokenIsCstgDerivedTest(string domainName) + [InlineData("com.123.Game.App.android")] + public void TokenIsCstgDerivedTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); Assert.Equal(EXAMPLE_EMAIL_RAW_UID2_V2, res.Uid); } + + [Theory] + // These are the domain or app names associated with site SITE_ID but vary in capitalization, as defined by KeySharingResponse(); + [InlineData("example.Com")] + [InlineData("Example.org")] + [InlineData("com.123.game.App.android")] + public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName) + { + _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); + var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); + string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); + var res = _client.Decrypt(advertisingToken, domainOrAppName); + Assert.True(res.IsClientSideGenerated); + Assert.False(res.Success); + Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); + } [Theory] [InlineData((string)null)] [InlineData("")] - // Domains associated with site SITE_ID2, as defined by KeySharingResponse(). + // Domain or app names associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.net")] [InlineData("example.edu")] + [InlineData("com.123.Game.App.ios")] // Domain not associated with any site. [InlineData("foo.com")] public void TokenIsCstgDerivedDomainNameFailTest(string domainName) @@ -70,7 +88,7 @@ public void TokenIsCstgDerivedDomainNameFailTest(string domainName) var res = _client.Decrypt(advertisingToken, domainName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); - Assert.Equal(DecryptionStatus.DomainNameCheckFailed, res.Status); + Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); Assert.Null(res.Uid); } diff --git a/test/UID2.Client.Test/EncryptionTestsV3.cs b/test/UID2.Client.Test/EncryptionTestsV3.cs index 5b56094..2469891 100644 --- a/test/UID2.Client.Test/EncryptionTestsV3.cs +++ b/test/UID2.Client.Test/EncryptionTestsV3.cs @@ -59,27 +59,45 @@ public void UserOptedOutTest() } [Theory] - // These are the domains associated with site SITE_ID, as defined by KeySharingResponse(); + // These are the domain or app names associated with site SITE_ID, as defined by KeySharingResponse(); [InlineData("example.com")] [InlineData("example.org")] - public void TokenIsCstgDerivedTest(string domainName) + [InlineData("com.123.Game.App.android")] + public void TokenIsCstgDerivedTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); Assert.Equal(EXAMPLE_EMAIL_RAW_UID2_V2, res.Uid); } + + [Theory] + // These are the domain or app names associated with site SITE_ID but vary in capitalization, as defined by KeySharingResponse(); + [InlineData("example.Com")] + [InlineData("Example.org")] + [InlineData("com.123.game.App.android")] + public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName) + { + _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); + var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); + string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); + var res = _client.Decrypt(advertisingToken, domainOrAppName); + Assert.True(res.IsClientSideGenerated); + Assert.False(res.Success); + Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); + } [Theory] [InlineData((string)null)] [InlineData("")] - // Domains associated with site SITE_ID2, as defined by KeySharingResponse(). + // Domain or app names associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.net")] [InlineData("example.edu")] + [InlineData("com.123.Game.App.ios")] // Domain not associated with any site. [InlineData("foo.com")] public void TokenIsCstgDerivedDomainNameFailTest(string domainName) @@ -90,7 +108,7 @@ public void TokenIsCstgDerivedDomainNameFailTest(string domainName) var res = _client.Decrypt(advertisingToken, domainName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); - Assert.Equal(DecryptionStatus.DomainNameCheckFailed, res.Status); + Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); Assert.Null(res.Uid); } diff --git a/test/UID2.Client.Test/EncryptionTestsV4.cs b/test/UID2.Client.Test/EncryptionTestsV4.cs index 23289f8..55557ff 100644 --- a/test/UID2.Client.Test/EncryptionTestsV4.cs +++ b/test/UID2.Client.Test/EncryptionTestsV4.cs @@ -189,28 +189,47 @@ public void UserOptedOutTest() } [Theory] - // These are the domains associated with site SITE_ID, as defined by KeySharingResponse(); + // These are the domain or app names associated with site SITE_ID, as defined by KeySharingResponse(); [InlineData("example.com")] [InlineData("example.org")] - public void TokenIsCstgDerivedTest(string domainName) + [InlineData("com.123.Game.App.android")] + public void TokenIsCstgDerivedTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); Assert.Equal(EXAMPLE_EMAIL_RAW_UID2_V2, res.Uid); } + + [Theory] + // These are the domain or app names associated with site SITE_ID but vary in capitalization, as defined by KeySharingResponse(); + [InlineData("example.Com")] + [InlineData("Example.org")] + [InlineData("com.123.game.App.android")] + public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName) + { + _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); + var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); + string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); + ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email); + var res = _client.Decrypt(advertisingToken, domainOrAppName); + Assert.True(res.IsClientSideGenerated); + Assert.False(res.Success); + Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); + } [Theory] [InlineData((string)null)] [InlineData("")] - // Domains associated with site SITE_ID2, as defined by KeySharingResponse(). + // Domain or app names associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.net")] [InlineData("example.edu")] + [InlineData("com.123.Game.App.ios")] // Domain not associated with any site. [InlineData("foo.com")] public void TokenIsCstgDerivedDomainNameFailTest(string domainName) @@ -221,7 +240,7 @@ public void TokenIsCstgDerivedDomainNameFailTest(string domainName) var res = _client.Decrypt(advertisingToken, domainName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); - Assert.Equal(DecryptionStatus.DomainNameCheckFailed, res.Status); + Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); Assert.Null(res.Uid); } diff --git a/test/UID2.Client.Test/KeyParserTests.cs b/test/UID2.Client.Test/KeyParserTests.cs index 22760fd..efebc1c 100644 --- a/test/UID2.Client.Test/KeyParserTests.cs +++ b/test/UID2.Client.Test/KeyParserTests.cs @@ -156,7 +156,7 @@ public void ParseMissingSiteData() var keyContainer = KeyParser.Parse(json); - var isDomainNameForSite = keyContainer.IsDomainNameAllowedForSite(1, "example.com"); + var isDomainNameForSite = keyContainer.IsDomainOrAppNameAllowedForSite(1, "example.com"); Assert.False(isDomainNameForSite); @@ -184,9 +184,9 @@ public void ParseEmptySiteData() var keyContainer = KeyParser.Parse(json); - var isDomainNameForSite = keyContainer.IsDomainNameAllowedForSite(1, "example.com"); + var isDomainNameForSite = keyContainer.IsDomainOrAppNameAllowedForSite(1, "example.com"); Assert.False(isDomainNameForSite); - Assert.False(keyContainer.IsDomainNameAllowedForSite(1, null)); + Assert.False(keyContainer.IsDomainOrAppNameAllowedForSite(1, null)); Assert.True(keyContainer.TryGetKey(3, out var key)); } @@ -220,14 +220,14 @@ public void ParseSiteDataSharingEndpoint() var keyContainer = KeyParser.Parse(s); - Assert.True(keyContainer.IsDomainNameAllowedForSite(9, "example.com")); - Assert.False(keyContainer.IsDomainNameAllowedForSite(9, "example.org")); - Assert.False(keyContainer.IsDomainNameAllowedForSite(9, "example.net")); + Assert.True(keyContainer.IsDomainOrAppNameAllowedForSite(9, "example.com")); + Assert.False(keyContainer.IsDomainOrAppNameAllowedForSite(9, "example.org")); + Assert.False(keyContainer.IsDomainOrAppNameAllowedForSite(9, "example.net")); - Assert.False(keyContainer.IsDomainNameAllowedForSite(100, "example.com")); - Assert.True(keyContainer.IsDomainNameAllowedForSite(100, "example.org")); - Assert.True(keyContainer.IsDomainNameAllowedForSite(100, "example.net")); - Assert.False(keyContainer.IsDomainNameAllowedForSite(100, null)); + Assert.False(keyContainer.IsDomainOrAppNameAllowedForSite(100, "example.com")); + Assert.True(keyContainer.IsDomainOrAppNameAllowedForSite(100, "example.org")); + Assert.True(keyContainer.IsDomainOrAppNameAllowedForSite(100, "example.net")); + Assert.False(keyContainer.IsDomainOrAppNameAllowedForSite(100, null)); Assert.True(keyContainer.TryGetKey(3, out var key)); } diff --git a/test/UID2.Client.Test/TestData.cs b/test/UID2.Client.Test/TestData.cs index 981a547..ac4e2bb 100644 --- a/test/UID2.Client.Test/TestData.cs +++ b/test/UID2.Client.Test/TestData.cs @@ -79,12 +79,12 @@ internal static string KeySharingResponse(IEnumerable keys, int? callerSite new { id = SITE_ID, - domain_names = new[] { "example.com", "example.org" } + domain_names = new[] { "example.com", "example.org", "com.123.Game.App.android" } }, new { id = SITE_ID2, - domain_names = new[] { "example.net", "example.edu" } + domain_names = new[] { "example.net", "example.edu", "com.123.Game.App.ios" } } } } From f10d4ddbdd8d1bc26f8afc84314f6e383c7d0c89 Mon Sep 17 00:00:00 2001 From: Caroline6312 Date: Mon, 29 Apr 2024 16:38:54 -0700 Subject: [PATCH 2/6] change more test names --- test/UID2.Client.Test/EncryptionTestsV2.cs | 4 ++-- test/UID2.Client.Test/EncryptionTestsV3.cs | 4 ++-- test/UID2.Client.Test/EncryptionTestsV4.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/UID2.Client.Test/EncryptionTestsV2.cs b/test/UID2.Client.Test/EncryptionTestsV2.cs index 7944d31..9a2993b 100644 --- a/test/UID2.Client.Test/EncryptionTestsV2.cs +++ b/test/UID2.Client.Test/EncryptionTestsV2.cs @@ -80,12 +80,12 @@ public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNam [InlineData("com.123.Game.App.ios")] // Domain not associated with any site. [InlineData("foo.com")] - public void TokenIsCstgDerivedDomainNameFailTest(string domainName) + public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); diff --git a/test/UID2.Client.Test/EncryptionTestsV3.cs b/test/UID2.Client.Test/EncryptionTestsV3.cs index 2469891..23e8757 100644 --- a/test/UID2.Client.Test/EncryptionTestsV3.cs +++ b/test/UID2.Client.Test/EncryptionTestsV3.cs @@ -100,12 +100,12 @@ public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNam [InlineData("com.123.Game.App.ios")] // Domain not associated with any site. [InlineData("foo.com")] - public void TokenIsCstgDerivedDomainNameFailTest(string domainName) + public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); diff --git a/test/UID2.Client.Test/EncryptionTestsV4.cs b/test/UID2.Client.Test/EncryptionTestsV4.cs index 55557ff..275b0e3 100644 --- a/test/UID2.Client.Test/EncryptionTestsV4.cs +++ b/test/UID2.Client.Test/EncryptionTestsV4.cs @@ -232,12 +232,12 @@ public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNam [InlineData("com.123.Game.App.ios")] // Domain not associated with any site. [InlineData("foo.com")] - public void TokenIsCstgDerivedDomainNameFailTest(string domainName) + public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); From 46eac0c40e1b8248d4bd9363d0b94ecd3fa984f3 Mon Sep 17 00:00:00 2001 From: Caroline6312 Date: Mon, 29 Apr 2024 16:40:01 -0700 Subject: [PATCH 3/6] change more test names --- test/UID2.Client.Test/BidstreamClientTests.cs | 13 ++++++++----- test/UID2.Client.Test/EncryptionTestsV2.cs | 9 +++++---- test/UID2.Client.Test/EncryptionTestsV3.cs | 11 ++++++----- test/UID2.Client.Test/EncryptionTestsV4.cs | 9 +++++---- test/UID2.Client.Test/KeyParserTests.cs | 8 ++++---- 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/test/UID2.Client.Test/BidstreamClientTests.cs b/test/UID2.Client.Test/BidstreamClientTests.cs index e4c8ed6..880cf3e 100644 --- a/test/UID2.Client.Test/BidstreamClientTests.cs +++ b/test/UID2.Client.Test/BidstreamClientTests.cs @@ -370,12 +370,12 @@ private void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNa [InlineData("example.edu", TokenVersion.V4)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("com.123.Game.App.ios", TokenVersion.V4)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("foo.com", TokenVersion.V4)] // Domain not associated with any site. - private void TokenIsCstgDerivedDomainNameFailTest(string domainName, TokenVersion tokenVersion) + private void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName, TokenVersion tokenVersion) { Refresh(KeySharingResponse(new[] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).WithVersion(tokenVersion).Build(); - var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainName); + var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); Assert.False(res.Success); Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); @@ -383,26 +383,29 @@ private void TokenIsCstgDerivedDomainNameFailTest(string domainName, TokenVersio } [Theory] - // Any domain name is OK, because the token is not client-side generated. + // Any domain or app name is OK, because the token is not client-side generated. [InlineData((string)null, TokenVersion.V2)] [InlineData("", TokenVersion.V2)] [InlineData("example.com", TokenVersion.V2)] [InlineData("foo.com", TokenVersion.V2)] + [InlineData("com.uid2.devapp", TokenVersion.V2)] [InlineData((string)null, TokenVersion.V3)] [InlineData("", TokenVersion.V3)] [InlineData("example.com", TokenVersion.V3)] [InlineData("foo.com", TokenVersion.V3)] + [InlineData("com.uid2.devapp", TokenVersion.V3)] [InlineData((string)null, TokenVersion.V4)] [InlineData("", TokenVersion.V4)] [InlineData("example.com", TokenVersion.V4)] [InlineData("foo.com", TokenVersion.V4)] - private void TokenIsNotCstgDerivedDomainNameSuccessTest(string domainName, TokenVersion tokenVersion) + [InlineData("com.uid2.devapp", TokenVersion.V4)] + private void TokenIsNotCstgDerivedDomainNameSuccessTest(string domainOrAppName, TokenVersion tokenVersion) { Refresh(KeySharingResponse(new[] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(false).Build(); string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).WithVersion(tokenVersion).Build(); ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email, tokenVersion); - var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainName); + var res = _client.DecryptTokenIntoRawUid(advertisingToken, domainOrAppName); Assert.False(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); diff --git a/test/UID2.Client.Test/EncryptionTestsV2.cs b/test/UID2.Client.Test/EncryptionTestsV2.cs index 9a2993b..4b553c7 100644 --- a/test/UID2.Client.Test/EncryptionTestsV2.cs +++ b/test/UID2.Client.Test/EncryptionTestsV2.cs @@ -92,13 +92,13 @@ public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) Assert.Null(res.Uid); } - // if there is domain name associated with sites but we explicitly call + // if there is domain or app name associated with sites but we explicitly call // DecryptionResponse Decrypt(string token) or DecryptionResponse Decrypt(string token, DateTime utcNow) // and we do not want to do domain name check // the Decrypt function would still decrypt successfully // in case DSP does not want to enable domain name check [Fact] - public void TokenIsCstgDerivedNoDomainNameTest() + public void TokenIsCstgDerivedNoDomainOrAppNameTest() { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); @@ -116,12 +116,13 @@ public void TokenIsCstgDerivedNoDomainNameTest() [InlineData("")] [InlineData("example.com")] [InlineData("foo.com")] - public void TokenIsNotCstgDerivedDomainNameSuccessTest(string domainName) + [InlineData("com.uid2.devapp")] + public void TokenIsNotCstgDerivedDomainOrAppNameSuccessTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(false).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.False(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); diff --git a/test/UID2.Client.Test/EncryptionTestsV3.cs b/test/UID2.Client.Test/EncryptionTestsV3.cs index 23e8757..e024118 100644 --- a/test/UID2.Client.Test/EncryptionTestsV3.cs +++ b/test/UID2.Client.Test/EncryptionTestsV3.cs @@ -112,13 +112,13 @@ public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) Assert.Null(res.Uid); } - // if there is domain name associated with sites but we explicitly call + // if there is domain or app name associated with sites but we explicitly call // DecryptionResponse Decrypt(string token) or DecryptionResponse Decrypt(string token, DateTime utcNow) // and we do not want to do domain name check // the Decrypt function would still decrypt successfully // in case DSP does not want to enable domain name check [Fact] - public void TokenIsCstgDerivedNoDomainNameTest() + public void TokenIsCstgDerivedNoDomainOrAppNameTest() { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); @@ -131,17 +131,18 @@ public void TokenIsCstgDerivedNoDomainNameTest() } [Theory] - // Any domain name is OK, because the token is not client-side generated. + // Any domain or app name is OK, because the token is not client-side generated. [InlineData((string) null)] [InlineData("")] [InlineData("example.com")] [InlineData("foo.com")] - public void TokenIsNotCstgDerivedDomainNameSuccessTest(string domainName) + [InlineData("com.uid2.devapp")] + public void TokenIsNotCstgDerivedDomainOrAppNameSuccessTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(false).Build(); var advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.False(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); diff --git a/test/UID2.Client.Test/EncryptionTestsV4.cs b/test/UID2.Client.Test/EncryptionTestsV4.cs index 275b0e3..2e1c77e 100644 --- a/test/UID2.Client.Test/EncryptionTestsV4.cs +++ b/test/UID2.Client.Test/EncryptionTestsV4.cs @@ -244,13 +244,13 @@ public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) Assert.Null(res.Uid); } - // if there is domain name associated with sites but we explicitly call + // if there is domain or app name associated with sites but we explicitly call // DecryptionResponse Decrypt(string token) or DecryptionResponse Decrypt(string token, DateTime utcNow) // and we do not want to do domain name check // the Decrypt function would still decrypt successfully // in case DSP does not want to enable domain name check [Fact] - public void TokenIsCstgDerivedNoDomainNameTest() + public void TokenIsCstgDerivedNoDomainOrAppNameTest() { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); @@ -268,13 +268,14 @@ public void TokenIsCstgDerivedNoDomainNameTest() [InlineData("")] [InlineData("example.com")] [InlineData("foo.com")] - public void TokenIsNotCstgDerivedDomainNameSuccessTest(string domainName) + [InlineData("com.uid2.devapp")] + public void TokenIsNotCstgDerivedDomainNameSuccessTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(false).Build(); string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email); - var res = _client.Decrypt(advertisingToken, domainName); + var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.False(res.IsClientSideGenerated); Assert.True(res.Success); Assert.Equal(DecryptionStatus.Success, res.Status); diff --git a/test/UID2.Client.Test/KeyParserTests.cs b/test/UID2.Client.Test/KeyParserTests.cs index efebc1c..19a9143 100644 --- a/test/UID2.Client.Test/KeyParserTests.cs +++ b/test/UID2.Client.Test/KeyParserTests.cs @@ -156,9 +156,9 @@ public void ParseMissingSiteData() var keyContainer = KeyParser.Parse(json); - var isDomainNameForSite = keyContainer.IsDomainOrAppNameAllowedForSite(1, "example.com"); + var isDomainOrAppNameForSite = keyContainer.IsDomainOrAppNameAllowedForSite(1, "example.com"); - Assert.False(isDomainNameForSite); + Assert.False(isDomainOrAppNameForSite); Assert.True(keyContainer.TryGetKey(3, out var key)); } @@ -184,8 +184,8 @@ public void ParseEmptySiteData() var keyContainer = KeyParser.Parse(json); - var isDomainNameForSite = keyContainer.IsDomainOrAppNameAllowedForSite(1, "example.com"); - Assert.False(isDomainNameForSite); + var isDomainOrAppNameForSite = keyContainer.IsDomainOrAppNameAllowedForSite(1, "example.com"); + Assert.False(isDomainOrAppNameForSite); Assert.False(keyContainer.IsDomainOrAppNameAllowedForSite(1, null)); Assert.True(keyContainer.TryGetKey(3, out var key)); } From 63788fcdf19b03caf343b386b849d18b00afad03 Mon Sep 17 00:00:00 2001 From: Caroline6312 Date: Mon, 29 Apr 2024 17:40:35 -0700 Subject: [PATCH 4/6] Add more test case and update readmes --- README.md | 2 +- test/UID2.Client.Test/BidstreamClientTests.cs | 6 ++++++ test/UID2.Client.Test/EncryptionTestsV2.cs | 2 ++ test/UID2.Client.Test/EncryptionTestsV3.cs | 2 ++ test/UID2.Client.Test/EncryptionTestsV4.cs | 2 ++ test/UID2.Client.Test/TestData.cs | 4 ++-- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c5ddd77..ecf59e4 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ dotnet test To run the sample app: ``` -dotnet run --project src/SampleApp/SampleApp.csproj https://integ.uidapi.com \ +dotnet run --project src/SampleApp/SampleApp.csproj https://operator-integ.uidapi.com \ ``` diff --git a/test/UID2.Client.Test/BidstreamClientTests.cs b/test/UID2.Client.Test/BidstreamClientTests.cs index 880cf3e..5a6d53e 100644 --- a/test/UID2.Client.Test/BidstreamClientTests.cs +++ b/test/UID2.Client.Test/BidstreamClientTests.cs @@ -306,12 +306,15 @@ private void UserOptedOutTest(TokenVersion tokenVersion) [InlineData("example.com", TokenVersion.V2)] [InlineData("example.org", TokenVersion.V2)] [InlineData("com.123.Game.App.android", TokenVersion.V2)] + [InlineData("123456789", TokenVersion.V2)] [InlineData("example.com", TokenVersion.V3)] [InlineData("example.org", TokenVersion.V3)] [InlineData("com.123.Game.App.android", TokenVersion.V3)] + [InlineData("123456789", TokenVersion.V3)] [InlineData("example.com", TokenVersion.V4)] [InlineData("example.org", TokenVersion.V4)] [InlineData("com.123.Game.App.android", TokenVersion.V4)] + [InlineData("123456789", TokenVersion.V4)] private void TokenIsCstgDerivedTest(string domainOrAppName, TokenVersion tokenVersion) { Refresh(KeySharingResponse(new[] { MASTER_KEY, SITE_KEY })); @@ -357,18 +360,21 @@ private void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNa [InlineData("example.net", TokenVersion.V2)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.edu", TokenVersion.V2)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("com.123.Game.App.ios", TokenVersion.V2)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). + [InlineData("123456780", TokenVersion.V2)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("foo.com", TokenVersion.V2)] // Domain not associated with any site. [InlineData((string)null, TokenVersion.V3)] [InlineData("", TokenVersion.V3)] [InlineData("example.net", TokenVersion.V3)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.edu", TokenVersion.V3)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("com.123.Game.App.ios", TokenVersion.V3)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). + [InlineData("123456780", TokenVersion.V3)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("foo.com", TokenVersion.V3)] // Domain not associated with any site. [InlineData((string)null, TokenVersion.V4)] [InlineData("", TokenVersion.V4)] [InlineData("example.net", TokenVersion.V4)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("example.edu", TokenVersion.V4)] // Domain associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("com.123.Game.App.ios", TokenVersion.V4)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). + [InlineData("123456780", TokenVersion.V4)] // App associated with site SITE_ID2, as defined by KeySharingResponse(). [InlineData("foo.com", TokenVersion.V4)] // Domain not associated with any site. private void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName, TokenVersion tokenVersion) { diff --git a/test/UID2.Client.Test/EncryptionTestsV2.cs b/test/UID2.Client.Test/EncryptionTestsV2.cs index 4b553c7..54339e5 100644 --- a/test/UID2.Client.Test/EncryptionTestsV2.cs +++ b/test/UID2.Client.Test/EncryptionTestsV2.cs @@ -43,6 +43,7 @@ public void UserOptedOutTest() [InlineData("example.com")] [InlineData("example.org")] [InlineData("com.123.Game.App.android")] + [InlineData("123456789")] public void TokenIsCstgDerivedTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); @@ -78,6 +79,7 @@ public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNam [InlineData("example.net")] [InlineData("example.edu")] [InlineData("com.123.Game.App.ios")] + [InlineData("123456780")] // Domain not associated with any site. [InlineData("foo.com")] public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) diff --git a/test/UID2.Client.Test/EncryptionTestsV3.cs b/test/UID2.Client.Test/EncryptionTestsV3.cs index e024118..5275752 100644 --- a/test/UID2.Client.Test/EncryptionTestsV3.cs +++ b/test/UID2.Client.Test/EncryptionTestsV3.cs @@ -63,6 +63,7 @@ public void UserOptedOutTest() [InlineData("example.com")] [InlineData("example.org")] [InlineData("com.123.Game.App.android")] + [InlineData("123456789")] public void TokenIsCstgDerivedTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); @@ -98,6 +99,7 @@ public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNam [InlineData("example.net")] [InlineData("example.edu")] [InlineData("com.123.Game.App.ios")] + [InlineData("123456780")] // Domain not associated with any site. [InlineData("foo.com")] public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) diff --git a/test/UID2.Client.Test/EncryptionTestsV4.cs b/test/UID2.Client.Test/EncryptionTestsV4.cs index 2e1c77e..9231dcf 100644 --- a/test/UID2.Client.Test/EncryptionTestsV4.cs +++ b/test/UID2.Client.Test/EncryptionTestsV4.cs @@ -193,6 +193,7 @@ public void UserOptedOutTest() [InlineData("example.com")] [InlineData("example.org")] [InlineData("com.123.Game.App.android")] + [InlineData("123456789")] public void TokenIsCstgDerivedTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); @@ -230,6 +231,7 @@ public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNam [InlineData("example.net")] [InlineData("example.edu")] [InlineData("com.123.Game.App.ios")] + [InlineData("123456780")] // Domain not associated with any site. [InlineData("foo.com")] public void TokenIsCstgDerivedDomainOrAppNameFailTest(string domainOrAppName) diff --git a/test/UID2.Client.Test/TestData.cs b/test/UID2.Client.Test/TestData.cs index ac4e2bb..b078ba3 100644 --- a/test/UID2.Client.Test/TestData.cs +++ b/test/UID2.Client.Test/TestData.cs @@ -79,12 +79,12 @@ internal static string KeySharingResponse(IEnumerable keys, int? callerSite new { id = SITE_ID, - domain_names = new[] { "example.com", "example.org", "com.123.Game.App.android" } + domain_names = new[] { "example.com", "example.org", "com.123.Game.App.android", "123456789" } }, new { id = SITE_ID2, - domain_names = new[] { "example.net", "example.edu", "com.123.Game.App.ios" } + domain_names = new[] { "example.net", "example.edu", "com.123.Game.App.ios", "123456780" } } } } From 481d4a2d521e8a801201ee5e02cb856e67558d8e Mon Sep 17 00:00:00 2001 From: Caroline6312 Date: Mon, 29 Apr 2024 20:26:31 -0700 Subject: [PATCH 5/6] Reverse case sensitive change --- src/UID2.Client/Site.cs | 2 +- test/UID2.Client.Test/BidstreamClientTests.cs | 2 +- test/UID2.Client.Test/EncryptionTestsV2.cs | 7 ++++--- test/UID2.Client.Test/EncryptionTestsV3.cs | 7 ++++--- test/UID2.Client.Test/EncryptionTestsV4.cs | 7 ++++--- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/UID2.Client/Site.cs b/src/UID2.Client/Site.cs index 36e1ac1..7caca0b 100644 --- a/src/UID2.Client/Site.cs +++ b/src/UID2.Client/Site.cs @@ -10,7 +10,7 @@ internal class Site public Site(int id, IEnumerable domainNames) { Id = id; - _domainNames = new HashSet(domainNames); + _domainNames = new HashSet(domainNames, StringComparer.OrdinalIgnoreCase); } public int Id { get; } diff --git a/test/UID2.Client.Test/BidstreamClientTests.cs b/test/UID2.Client.Test/BidstreamClientTests.cs index 5a6d53e..853b1f4 100644 --- a/test/UID2.Client.Test/BidstreamClientTests.cs +++ b/test/UID2.Client.Test/BidstreamClientTests.cs @@ -340,7 +340,7 @@ private void TokenIsCstgDerivedTest(string domainOrAppName, TokenVersion tokenVe [InlineData("example.com", TokenVersion.V4)] [InlineData("example.org", TokenVersion.V4)] [InlineData("com.123.Game.App.android", TokenVersion.V4)] - private void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName, TokenVersion tokenVersion) + private void DomainOrAppNameCaseInSensitiveTest(string domainOrAppName, TokenVersion tokenVersion) { Refresh(KeySharingResponse(new[] { MASTER_KEY, SITE_KEY })); diff --git a/test/UID2.Client.Test/EncryptionTestsV2.cs b/test/UID2.Client.Test/EncryptionTestsV2.cs index 54339e5..79492bf 100644 --- a/test/UID2.Client.Test/EncryptionTestsV2.cs +++ b/test/UID2.Client.Test/EncryptionTestsV2.cs @@ -61,15 +61,16 @@ public void TokenIsCstgDerivedTest(string domainOrAppName) [InlineData("example.Com")] [InlineData("Example.org")] [InlineData("com.123.game.App.android")] - public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName) + public void DomainOrAppNameCaseInSensitiveTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); - Assert.False(res.Success); - Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); + Assert.True(res.Success); + Assert.Equal(DecryptionStatus.Success, res.Status); + Assert.Equal(EXAMPLE_EMAIL_RAW_UID2_V2, res.Uid); } [Theory] diff --git a/test/UID2.Client.Test/EncryptionTestsV3.cs b/test/UID2.Client.Test/EncryptionTestsV3.cs index 5275752..b8eddbe 100644 --- a/test/UID2.Client.Test/EncryptionTestsV3.cs +++ b/test/UID2.Client.Test/EncryptionTestsV3.cs @@ -81,15 +81,16 @@ public void TokenIsCstgDerivedTest(string domainOrAppName) [InlineData("example.Com")] [InlineData("Example.org")] [InlineData("com.123.game.App.android")] - public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName) + public void DomainOrAppNameCaseInSensitiveTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); string advertisingToken = _tokenBuilder.WithPrivacyBits(privacyBits).Build(); var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); - Assert.False(res.Success); - Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); + Assert.True(res.Success); + Assert.Equal(DecryptionStatus.Success, res.Status); + Assert.Equal(EXAMPLE_EMAIL_RAW_UID2_V2, res.Uid); } [Theory] diff --git a/test/UID2.Client.Test/EncryptionTestsV4.cs b/test/UID2.Client.Test/EncryptionTestsV4.cs index 9231dcf..34b1dd1 100644 --- a/test/UID2.Client.Test/EncryptionTestsV4.cs +++ b/test/UID2.Client.Test/EncryptionTestsV4.cs @@ -212,7 +212,7 @@ public void TokenIsCstgDerivedTest(string domainOrAppName) [InlineData("example.Com")] [InlineData("Example.org")] [InlineData("com.123.game.App.android")] - public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppName) + public void DomainOrAppNameCaseInSensitiveTest(string domainOrAppName) { _client.RefreshJson(KeySharingResponse(new [] { MASTER_KEY, SITE_KEY })); var privacyBits = PrivacyBitsBuilder.Builder().WithClientSideGenerated(true).Build(); @@ -220,8 +220,9 @@ public void DomainOrAppNameCaseSensitiveAndCheckFailedTest(string domainOrAppNam ValidateAdvertisingToken(advertisingToken, IdentityScope.UID2, IdentityType.Email); var res = _client.Decrypt(advertisingToken, domainOrAppName); Assert.True(res.IsClientSideGenerated); - Assert.False(res.Success); - Assert.Equal(DecryptionStatus.DomainOrAppNameCheckFailed, res.Status); + Assert.True(res.Success); + Assert.Equal(DecryptionStatus.Success, res.Status); + Assert.Equal(EXAMPLE_EMAIL_RAW_UID2_V2, res.Uid); } [Theory] From b0f972c9bbef128e59f64d85f8b29d7cdd5cedbd Mon Sep 17 00:00:00 2001 From: Caroline6312 Date: Wed, 1 May 2024 14:00:15 -0700 Subject: [PATCH 6/6] flipping the casing --- test/UID2.Client.Test/BidstreamClientTests.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/UID2.Client.Test/BidstreamClientTests.cs b/test/UID2.Client.Test/BidstreamClientTests.cs index 853b1f4..1d59bc4 100644 --- a/test/UID2.Client.Test/BidstreamClientTests.cs +++ b/test/UID2.Client.Test/BidstreamClientTests.cs @@ -331,15 +331,15 @@ private void TokenIsCstgDerivedTest(string domainOrAppName, TokenVersion tokenVe [Theory] // These are the domain or app names associated with site SITE_ID but vary in capitalization, as defined by KeySharingResponse(); - [InlineData("example.com", TokenVersion.V2)] - [InlineData("example.org", TokenVersion.V2)] - [InlineData("com.123.Game.App.android", TokenVersion.V2)] - [InlineData("example.com", TokenVersion.V3)] - [InlineData("example.org", TokenVersion.V3)] - [InlineData("com.123.Game.App.android", TokenVersion.V3)] - [InlineData("example.com", TokenVersion.V4)] - [InlineData("example.org", TokenVersion.V4)] - [InlineData("com.123.Game.App.android", TokenVersion.V4)] + [InlineData("Example.com", TokenVersion.V2)] + [InlineData("Example.Org", TokenVersion.V2)] + [InlineData("com.123.Game.app.android", TokenVersion.V2)] + [InlineData("Example.com", TokenVersion.V3)] + [InlineData("Example.Org", TokenVersion.V3)] + [InlineData("com.123.Game.app.android", TokenVersion.V3)] + [InlineData("Example.com", TokenVersion.V4)] + [InlineData("Example.Org", TokenVersion.V4)] + [InlineData("com.123.Game.app.android", TokenVersion.V4)] private void DomainOrAppNameCaseInSensitiveTest(string domainOrAppName, TokenVersion tokenVersion) { Refresh(KeySharingResponse(new[] { MASTER_KEY, SITE_KEY }));