@@ -111,18 +111,20 @@ def _decrypt_token(token, keys, domain_name, client_type, now):
111111 return DecryptedToken .make_error (DecryptionStatus .VERSION_NOT_SUPPORTED )
112112
113113
114- def _token_has_valid_lifetime (keys , client_type , established , expires , now ):
114+ def _token_has_valid_lifetime (keys , client_type , generated_or_now , expires , now ):
115+ # generated_or_now allows "now" for token v2, since v2 does not contain a "token generated" field.
116+ # v2 therefore checks against remaining lifetime rather than total lifetime
115117 if client_type is ClientType .BIDSTREAM :
116118 max_life_time_seconds = keys .get_max_bidstream_lifetime_seconds ()
117119 elif client_type is ClientType .SHARING :
118120 max_life_time_seconds = keys .get_max_sharing_lifetime_seconds ()
119121 else :
120122 return True # Skip check for legacy clients
121123
122- if (expires - established ).total_seconds () > max_life_time_seconds :
124+ if (expires - generated_or_now ).total_seconds () > max_life_time_seconds :
123125 return False
124- elif established > now :
125- return (established - now ).total_seconds () <= keys .get_allow_clock_skew_seconds ()
126+ elif generated_or_now > now :
127+ return (generated_or_now - now ).total_seconds () <= keys .get_allow_clock_skew_seconds ()
126128 else :
127129 return True
128130
@@ -165,7 +167,7 @@ def _decrypt_token_v2(token_bytes, keys, domain_name, client_type, now):
165167 established_ms = int .from_bytes (identity [idx :idx + 8 ], 'big' )
166168 established = dt .datetime .fromtimestamp (established_ms / 1000.0 , tz = timezone .utc )
167169
168- if not _token_has_valid_lifetime (keys , client_type , established , expires , now ):
170+ if not _token_has_valid_lifetime (keys , client_type , now , expires , now ):
169171 return DecryptedToken (DecryptionStatus .INVALID_TOKEN_LIFETIME , id_str , established , site_id , site_key .site_id ,
170172 keys .get_identity_scope (), None , AdvertisingTokenVersion .ADVERTISING_TOKEN_V2 , False , expires )
171173
@@ -199,7 +201,7 @@ def _decrypt_token_v3(token_bytes, keys, domain_name, client_type, now, token_ve
199201 return DecryptedToken (DecryptionStatus .EXPIRED_TOKEN , None , None , None , None ,
200202 keys .get_identity_scope (), identity_type , token_version , None , expires )
201203
202- # created 8:16
204+ generated_ms = int . from_bytes ( master_payload [ 8 :16 ], 'big' ) # Token Generated
203205 # operator site id 16:20
204206 # operator type 20
205207 # operator version 21:25
@@ -219,6 +221,10 @@ def _decrypt_token_v3(token_bytes, keys, domain_name, client_type, now, token_ve
219221 # privacy bits 16:20
220222 privacy_bits = bitarray ()
221223 privacy_bits .frombytes (site_payload [16 :20 ])
224+ established_ms = int .from_bytes (site_payload [20 :28 ], 'big' )
225+ id_bytes = site_payload [36 :]
226+ id_str = base64 .b64encode (id_bytes ).decode ('ascii' )
227+
222228 is_client_side_generated = False
223229 if privacy_bits [1 ]:
224230 is_client_side_generated = True
@@ -227,17 +233,13 @@ def _decrypt_token_v3(token_bytes, keys, domain_name, client_type, now, token_ve
227233 return DecryptedToken (DecryptionStatus .DOMAIN_NAME_CHECK_FAILED , None , None , site_id , site_key .site_id ,
228234 keys .get_identity_scope (), identity_type , token_version , is_client_side_generated , expires )
229235
230- established_ms = int .from_bytes (site_payload [20 :28 ], 'big' )
231236 established = dt .datetime .fromtimestamp (established_ms / 1000.0 , tz = timezone .utc )
232- # refreshed_ms 28:36
237+ generated = dt . datetime . fromtimestamp ( generated_ms / 1000.0 , tz = timezone . utc )
233238
234- if not _token_has_valid_lifetime (keys , client_type , established , expires , now ):
239+ if not _token_has_valid_lifetime (keys , client_type , generated , expires , now ):
235240 return DecryptedToken (DecryptionStatus .INVALID_TOKEN_LIFETIME , None , established , site_id , site_key .site_id ,
236241 keys .get_identity_scope (), identity_type , token_version , is_client_side_generated , expires )
237242
238- id_bytes = site_payload [36 :]
239- id_str = base64 .b64encode (id_bytes ).decode ('ascii' )
240-
241243 return DecryptedToken (DecryptionStatus .SUCCESS , id_str , established , site_id , site_key .site_id ,
242244 keys .get_identity_scope (), identity_type , token_version , is_client_side_generated , expires )
243245
@@ -286,7 +288,7 @@ def encrypt(uid2, identity_scope, keys, keyset_id=None, **kwargs):
286288 if identity_scope is None :
287289 identity_scope = keys .get_identity_scope ()
288290 try :
289- params = Params (expiry = token_expiry , identity_scope = identity_scope , token_generated_at = now )
291+ params = Params (expiry = token_expiry , identity_scope = identity_scope , token_generated = now )
290292 return EncryptionDataResponse .make_success (UID2TokenGenerator .generate_uid2_token_v4 (uid2 , master_key , site_id , key , params ))
291293 except Exception :
292294 return EncryptionDataResponse .make_error (EncryptionStatus .ENCRYPTION_FAILURE )
0 commit comments