@@ -26,11 +26,15 @@ def encode_keys(keys):
2626 return key_json
2727
2828
29- def key_bidstream_response_json (keys , identity_scope = IdentityScope .UID2 ):
29+ def key_bidstream_response_with_lifetime_json (keys , identity_scope , max_bidstream_lifetime_seconds ):
30+ if identity_scope is None :
31+ identity_scope = IdentityScope .UID2
32+ if max_bidstream_lifetime_seconds is None :
33+ max_bidstream_lifetime_seconds = dt .timedelta (days = 3 ).total_seconds ()
3034 encoded_keys = encode_keys (keys )
3135 json_obj = {
3236 "body" : {
33- "max_bidstream_lifetime_seconds" : dt . timedelta ( days = 3 ). total_seconds () ,
37+ "max_bidstream_lifetime_seconds" : max_bidstream_lifetime_seconds ,
3438 "identity_scope" : identity_scope .name ,
3539 "allow_clock_skew_seconds" : 1800 , # 30 mins
3640 "keys" : encoded_keys ,
@@ -52,14 +56,22 @@ def key_bidstream_response_json(keys, identity_scope=IdentityScope.UID2):
5256 return json .dumps (json_obj )
5357
5458
59+ def key_bidstream_response_json (keys , identity_scope = IdentityScope .UID2 , max_bidstream_lifetime_seconds = None ):
60+ return key_bidstream_response_with_lifetime_json (keys , identity_scope , max_bidstream_lifetime_seconds )
61+
62+
5563def key_bidstream_response_json_default_keys (identity_scope = IdentityScope .UID2 ):
56- return key_bidstream_response_json ([master_key , site_key ], identity_scope )
64+ return key_bidstream_response_with_lifetime_json ([master_key , site_key ], identity_scope , None )
5765
5866
5967class TestBidStreamClient (unittest .TestCase ):
6068 _CONST_BASE_URL = 'base_url'
6169 _CONST_API_KEY = 'api_key'
6270
71+ def refresh (self , refresh_json ):
72+ refresh_response = self ._client ._refresh_json (refresh_json )
73+ self .assertTrue (refresh_response .success )
74+
6375 def assert_success (self , decryption_response , token_version , scope ):
6476 self .assertTrue (decryption_response .success )
6577 self .assertEqual (decryption_response .uid , example_uid )
@@ -88,21 +100,20 @@ def _decrypt_and_assert_success(self, token, token_version, scope):
88100 def setUp (self ):
89101 self ._client = BidstreamClient (self ._CONST_BASE_URL , self ._CONST_API_KEY , client_secret )
90102
91- def test_smoke_test (self ): # SmokeTest
103+ def test_smoke_test_for_bidstream (self ): # SmokeTestForBidstream
92104 for expected_scope , expected_version in test_cases_all_scopes_all_versions :
93105 with self .subTest (expected_scope = expected_scope , expected_version = expected_version ):
94- token = generate_uid_token (expected_scope , expected_version )
95- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys (
96- expected_scope ))
97- self .assertTrue (refresh_response .success )
106+ token = generate_uid_token (expected_scope , expected_version ,
107+ identity_established_at = now - dt .timedelta (days = 120 ),
108+ generated_at = YESTERDAY ,
109+ expires_at = IN_2_DAYS )
110+ self .refresh (key_bidstream_response_json_default_keys (expected_scope ))
98111 self ._decrypt_and_assert_success (token , expected_version , expected_scope )
99112
100113 def test_phone_uids (self ): # PhoneTest
101114 for expected_scope , expected_version in test_cases_all_scopes_v3_v4_versions :
102115 with self .subTest (expected_scope = expected_scope , expected_version = expected_version ):
103- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys (
104- expected_scope ))
105- self .assertTrue (refresh_response .success )
116+ self .refresh (key_bidstream_response_json_default_keys (expected_scope ))
106117 token = generate_uid_token (expected_scope , expected_version , phone_uid )
107118 self .assertEqual (IdentityType .Phone , get_identity_type (token ))
108119 result = self ._client .decrypt_token_into_raw_uid (token , None )
@@ -112,25 +123,40 @@ def test_phone_uids(self): # PhoneTest
112123 self .assertEqual (result .identity_scope , expected_scope )
113124 self .assertEqual (result .advertising_token_version , expected_version )
114125
115- def test_token_lifetime_too_long_for_bidstream (self ): # TokenLifetimeTooLongForBidstream
116- expires_in_sec = IN_3_DAYS + dt .timedelta (minutes = 1 )
126+ def test_token_lifetime_too_long_for_bidstream_but_remaining_lifetime_allowed (self ): # TokenLifetimeTooLongForBidstreamButRemainingLifetimeAllowed
127+ generated = YESTERDAY
128+ expires_in_sec = generated + dt .timedelta (days = 3 ) + dt .timedelta (minutes = 1 )
129+ max_bidstream_lifetime_seconds = dt .timedelta (days = 3 ).total_seconds ()
117130 for expected_scope , expected_version in test_cases_all_scopes_all_versions :
118131 with self .subTest (expected_scope = expected_scope , expected_version = expected_version ):
119- token = generate_uid_token (expected_scope , expected_version , expires_at = expires_in_sec )
120- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys (
121- expected_scope ))
122- self .assertTrue (refresh_response .success )
132+ token = generate_uid_token (expected_scope , expected_version , generated_at = generated ,
133+ expires_at = expires_in_sec )
134+ self .refresh (key_bidstream_response_json ([master_key , site_key ], expected_scope ,
135+ max_bidstream_lifetime_seconds ))
136+ result = self ._client .decrypt_token_into_raw_uid (token , None )
137+ if expected_version == AdvertisingTokenVersion .ADVERTISING_TOKEN_V2 :
138+ self .assert_success (result , expected_version , expected_scope )
139+ else :
140+ self .assert_fails (result , expected_version , expected_scope )
141+
142+ def test_token_remaining_lifetime_too_long_for_bidstream (self ): # TokenRemainingLifetimeTooLongForBidstream
143+ generated = now
144+ expires_in_sec = generated + dt .timedelta (days = 3 ) + dt .timedelta (minutes = 1 )
145+ for expected_scope , expected_version in test_cases_all_scopes_v3_v4_versions :
146+ with self .subTest (expected_scope = expected_scope , expected_version = expected_version ):
147+ token = generate_uid_token (expected_scope , expected_version , generated_at = generated ,
148+ expires_at = expires_in_sec )
149+ self .refresh (key_bidstream_response_json_default_keys (expected_scope ))
123150 result = self ._client .decrypt_token_into_raw_uid (token , None )
124151 self .assert_fails (result , expected_version , expected_scope )
125152
126153 def test_token_generated_in_the_future_to_simulate_clock_skew (self ): # TokenGeneratedInTheFutureToSimulateClockSkew
154+ # Note V2 does not have a "token generated" field, therefore v2 tokens can't have a future "token generated" date and are excluded from this test.
127155 created_at_future = dt .datetime .now (tz = timezone .utc ) + dt .timedelta (minutes = 31 ) #max allowed clock skew is 30m
128- for expected_scope , expected_version in test_cases_all_scopes_all_versions :
156+ for expected_scope , expected_version in test_cases_all_scopes_v3_v4_versions :
129157 with self .subTest (expected_scope = expected_scope , expected_version = expected_version ):
130- token = generate_uid_token (expected_scope , expected_version , created_at = created_at_future )
131- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys (
132- expected_scope ))
133- self .assertTrue (refresh_response .success )
158+ token = generate_uid_token (expected_scope , expected_version , generated_at = created_at_future )
159+ self .refresh (key_bidstream_response_json_default_keys (expected_scope ))
134160 result = self ._client .decrypt_token_into_raw_uid (token , None )
135161 self .assert_fails (result , expected_version , expected_scope )
136162 self .assertEqual (result .status , DecryptionStatus .INVALID_TOKEN_LIFETIME )
@@ -140,17 +166,14 @@ def test_token_generated_in_the_future_within_allowed_clock_skew(self): # Token
140166 for expected_scope , expected_version in test_cases_all_scopes_all_versions :
141167 with self .subTest (expected_scope = expected_scope , expected_version = expected_version ):
142168 token = generate_uid_token (expected_scope , expected_version , expires_at = created_at_future )
143- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys (
144- expected_scope ))
145- self .assertTrue (refresh_response .success )
169+ self .refresh (key_bidstream_response_json_default_keys (expected_scope ))
146170 self ._decrypt_and_assert_success (token , expected_version , expected_scope )
147171
148172 def test_legacy_response_from_old_operator (self ):
149173 test_cases = [AdvertisingTokenVersion .ADVERTISING_TOKEN_V2 ,
150174 AdvertisingTokenVersion .ADVERTISING_TOKEN_V3 ,
151175 AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 ]
152- refresh_response = self ._client ._refresh_json (key_set_to_json_for_sharing ([master_key , site_key ]))
153- self .assertTrue (refresh_response .success )
176+ self .refresh (key_set_to_json_for_sharing ([master_key , site_key ]))
154177 for token_version in test_cases :
155178 with self .subTest (token_version = token_version ):
156179 token = generate_uid_token (IdentityScope .UID2 , token_version )
@@ -164,7 +187,7 @@ def test_token_generated_in_the_future_legacy_client(self): # TokenGeneratedInT
164187 with self .subTest (expected_scope = expected_scope , expected_version = expected_version ):
165188 legacy_client .refresh_json (key_bidstream_response_json_default_keys (
166189 expected_scope ))
167- token = generate_uid_token (expected_scope , expected_version , created_at = created_at_future )
190+ token = generate_uid_token (expected_scope , expected_version , generated_at = created_at_future )
168191 result = legacy_client .decrypt (token )
169192 self .assert_success (result , expected_version , expected_scope )
170193
@@ -190,9 +213,7 @@ def test_identity_scope_and_types(self): # IdentityScopeAndType_TestCases
190213 for uid , identity_scope , identity_type in test_cases :
191214 with self .subTest (identity_scope = identity_scope , identity_type = identity_type ):
192215 token = generate_uid_token (identity_scope , AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 )
193- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys (
194- identity_scope ))
195- self .assertTrue (refresh_response .success )
216+ self .refresh (key_bidstream_response_json_default_keys (identity_scope ))
196217 self ._decrypt_and_assert_success (token , AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 , identity_scope )
197218
198219 def test_empty_keys (self ): # EmptyKeyContainer
@@ -207,9 +228,7 @@ def test_master_key_expired(self): #ExpiredKeyContainer
207228 site_key_expired = EncryptionKey (site_key_id , site_id , created = now , activates = now - dt .timedelta (hours = 2 ),
208229 expires = now - dt .timedelta (hours = 1 ), secret = site_secret , keyset_id = 99999 )
209230
210- refresh_response = self ._client ._refresh_json (key_bidstream_response_json (
211- [master_key_expired , site_key_expired ]))
212- self .assertTrue (refresh_response .success )
231+ self .refresh (key_bidstream_response_json ([master_key_expired , site_key_expired ]))
213232
214233 result = self ._client .decrypt_token_into_raw_uid (example_uid , None )
215234 self .assertFalse (result .success )
@@ -219,18 +238,15 @@ def test_not_authorized_for_master_key(self): #NotAuthorizedForMasterKey
219238
220239 another_master_key = EncryptionKey (master_key_id + site_key_id + 1 , - 1 , created = now , activates = now , expires = now + dt .timedelta (hours = 1 ), secret = master_secret )
221240 another_site_key = EncryptionKey (master_key_id + site_key_id + 2 , site_id , created = now , activates = now , expires = now + dt .timedelta (hours = 1 ), secret = site_secret )
222- refresh_response = self ._client ._refresh_json (key_bidstream_response_json (
223- [another_master_key , another_site_key ]))
224- self .assertTrue (refresh_response .success )
241+ self .refresh (key_bidstream_response_json ([another_master_key , another_site_key ]))
225242 token = generate_uid_token (IdentityScope .UID2 , AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 )
226243
227244 result = self ._client .decrypt_token_into_raw_uid (token , None )
228245 self .assertFalse (result .success )
229246 self .assertEqual (result .status , DecryptionStatus .NOT_AUTHORIZED_FOR_MASTER_KEY )
230247
231248 def test_invalid_payload (self ): #InvalidPayload
232- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys ())
233- self .assertTrue (refresh_response .success )
249+ self .refresh (key_bidstream_response_json_default_keys ())
234250 token = generate_uid_token (IdentityScope .UID2 , AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 )
235251 payload = Uid2Base64UrlCoder .decode (token )
236252 bad_token = base64 .urlsafe_b64encode (payload [:0 ])
@@ -240,13 +256,12 @@ def test_invalid_payload(self): #InvalidPayload
240256 self .assertEqual (result .status , DecryptionStatus .INVALID_PAYLOAD )
241257
242258 def test_token_expiry_custom_decryption_time (self ): #TokenExpiryAndCustomNow
243- refresh_response = self ._client ._refresh_json (key_bidstream_response_json_default_keys ())
244- self .assertTrue (refresh_response .success )
259+ self .refresh (key_bidstream_response_json_default_keys ())
245260
246261 expires_at = now - dt .timedelta (days = 60 )
247262 created_at = expires_at - dt .timedelta (minutes = 1 )
248263 token = generate_uid_token (IdentityScope .UID2 , AdvertisingTokenVersion .ADVERTISING_TOKEN_V4 ,
249- created_at = created_at , expires_at = expires_at )
264+ generated_at = created_at , expires_at = expires_at )
250265 result = self ._client ._decrypt_token_into_raw_uid (token , None , expires_at + dt .timedelta (seconds = 1 ))
251266 self .assertFalse (result .success )
252267 self .assertEqual (result .status , DecryptionStatus .EXPIRED_TOKEN )
0 commit comments