Skip to content

Commit 12de071

Browse files
committed
Store is CSTG token in response
1 parent e4434af commit 12de071

File tree

3 files changed

+20
-14
lines changed

3 files changed

+20
-14
lines changed

examples/sample_bidstream_client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ def _usage():
3131
print('Identity Scope =', decrypt_result.identity_scope)
3232
print('Identity Type =', decrypt_result.identity_type)
3333
print('Advertising Token Version =', decrypt_result.advertising_token_version)
34+
print('Is Client Side Generated =', decrypt_result.is_client_side_generated)
3435
print('Site Key Site ID =', decrypt_result.site_key_site_id)

tests/test_bidstream_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def assert_success(self, decryption_response, token_version, scope):
1919
self.assertEqual(decryption_response.identity_type, None)
2020
self.assertEqual(decryption_response.uid, example_uid)
2121
self.assertEqual(decryption_response.identity_scope, scope)
22+
self.assertEqual(decryption_response.is_client_side_generated, False)
2223
self.assertEqual((now - decryption_response.established).total_seconds(), 0)
2324

2425
def decrypt_and_assert_success(self, token, token_version, scope):
@@ -37,7 +38,6 @@ def test_smoke_test(self, mock_refresh_bidstream_keys): # SmokeTest
3738
self._client.refresh()
3839
self.decrypt_and_assert_success(token, expected_version, expected_scope)
3940

40-
4141
def test_phone_uids(self, mock_refresh_bidstream_keys): # PhoneTest
4242
for expected_scope, expected_version in test_cases_all_scopes_v3_v4_versions:
4343
with self.subTest(expected_scope=expected_scope, expected_version=expected_version):

uid2_client/encryption.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,13 @@ def _decrypt_token_v2(token_bytes, keys, domain_name, client_type, now):
158158
expires = dt.datetime.fromtimestamp(expires_ms / 1000.0, tz=timezone.utc)
159159
if expires < now:
160160
return DecryptedToken(DecryptionStatus.TOKEN_EXPIRED, None, None, None, None,
161-
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, expires)
161+
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, False, expires)
162162

163163
site_key_id = int.from_bytes(master_payload[8:12], 'big')
164164
site_key = keys.get(site_key_id)
165165
if site_key is None:
166-
return DecryptedToken(DecryptionStatus.NOT_AUTHORIZED_FOR_KEY, None, None, None, site_key.site_id,
167-
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, expires)
166+
return DecryptedToken(DecryptionStatus.NOT_AUTHORIZED_FOR_KEY, None, None, None, None,
167+
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, False, expires)
168168

169169
identity_iv = master_payload[12:28]
170170
identity = _decrypt(master_payload[28:], identity_iv, site_key)
@@ -180,10 +180,10 @@ def _decrypt_token_v2(token_bytes, keys, domain_name, client_type, now):
180180

181181
if not _token_has_valid_lifetime(keys, client_type, established, expires, now):
182182
return DecryptedToken(DecryptionStatus.INVALID_TOKEN_LIFETIME, id_str, established, site_id, site_key.site_id,
183-
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, expires)
183+
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, False, expires)
184184

185185
return DecryptedToken(DecryptionStatus.SUCCESS, id_str, established, site_id, site_key.site_id,
186-
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, expires)
186+
keys.get_identity_scope(), None, AdvertisingTokenVersion.ADVERTISING_TOKEN_V2, False, expires)
187187

188188

189189
def _get_identity_type_from_token(token_bytes):
@@ -210,7 +210,7 @@ def _decrypt_token_v3(token_bytes, keys, domain_name, client_type, now, token_ve
210210
expires = dt.datetime.fromtimestamp(expires_ms / 1000.0, tz=timezone.utc)
211211
if expires < now:
212212
return DecryptedToken(DecryptionStatus.TOKEN_EXPIRED, None, None, None, None,
213-
keys.get_identity_scope(), identity_type, token_version, expires)
213+
keys.get_identity_scope(), identity_type, token_version, None, expires)
214214

215215
# created 8:16
216216
# operator site id 16:20
@@ -221,8 +221,8 @@ def _decrypt_token_v3(token_bytes, keys, domain_name, client_type, now, token_ve
221221
site_key_id = int.from_bytes(master_payload[29:33], 'big')
222222
site_key = keys.get(site_key_id)
223223
if site_key is None:
224-
return DecryptedToken(DecryptionStatus.NOT_AUTHORIZED_FOR_KEY, None, None, None, site_key.site_id,
225-
keys.get_identity_scope(), identity_type, token_version, expires)
224+
return DecryptedToken(DecryptionStatus.NOT_AUTHORIZED_FOR_KEY, None, None, None, None,
225+
keys.get_identity_scope(), identity_type, token_version, None, expires)
226226

227227
site_payload = _decrypt_gcm(master_payload[33:], site_key.secret)
228228

@@ -232,24 +232,27 @@ def _decrypt_token_v3(token_bytes, keys, domain_name, client_type, now, token_ve
232232
# privacy bits 16:20
233233
privacy_bits = bitarray()
234234
privacy_bits.frombytes(site_payload[16:20])
235+
is_client_side_generated = False
236+
if privacy_bits[1]:
237+
is_client_side_generated = True
235238

236239
if not _is_domain_name_allowed_for_site(client_type, domain_name, privacy_bits):
237240
return DecryptedToken(DecryptionStatus.DOMAIN_NAME_CHECK_FAILED, None, None, site_id, site_key.site_id,
238-
keys.get_identity_scope(), identity_type, token_version, expires)
241+
keys.get_identity_scope(), identity_type, token_version, is_client_side_generated, expires)
239242

240243
established_ms = int.from_bytes(site_payload[20:28], 'big')
241244
established = dt.datetime.fromtimestamp(established_ms / 1000.0, tz=timezone.utc)
242245
# refreshed_ms 28:36
243246

244247
if not _token_has_valid_lifetime(keys, client_type, established, expires, now):
245248
return DecryptedToken(DecryptionStatus.INVALID_TOKEN_LIFETIME, None, established, site_id, site_key.site_id,
246-
keys.get_identity_scope(), identity_type, token_version, expires)
249+
keys.get_identity_scope(), identity_type, token_version, is_client_side_generated, expires)
247250

248251
id_bytes = site_payload[36:]
249252
id_str = base64.b64encode(id_bytes).decode('ascii')
250253

251254
return DecryptedToken(DecryptionStatus.SUCCESS, id_str, established, site_id, site_key.site_id,
252-
keys.get_identity_scope(), identity_type, token_version, expires)
255+
keys.get_identity_scope(), identity_type, token_version, is_client_side_generated, expires)
253256

254257

255258
def _encrypt_token(uid2, identity_scope, master_key, site_key, site_id, now, token_expiry, ad_token_version):
@@ -537,7 +540,8 @@ class DecryptedToken:
537540
site_key_site_id (int): site ID of the site key which the token is encrypted with
538541
"""
539542

540-
def __init__(self, status, uid, established, site_id, site_key_site_id, identity_scope, identity_type, advertising_token_version, expiry):
543+
def __init__(self, status, uid, established, site_id, site_key_site_id, identity_scope, identity_type,
544+
advertising_token_version, is_client_side_generated, expiry):
541545
self.status = status
542546
self.uid = uid
543547
self.established = established
@@ -546,6 +550,7 @@ def __init__(self, status, uid, established, site_id, site_key_site_id, identity
546550
self.identity_type = identity_type
547551
self.identity_scope = identity_scope
548552
self.advertising_token_version = advertising_token_version
553+
self.is_client_side_generated = is_client_side_generated
549554
self.expiry = expiry
550555

551556
@property
@@ -554,7 +559,7 @@ def success(self):
554559

555560
@staticmethod
556561
def make_error(decryption_status):
557-
return DecryptedToken(decryption_status, None, None, None, None, None, None, None, None)
562+
return DecryptedToken(decryption_status, None, None, None, None, None, None, None, None, None)
558563

559564

560565
class DecryptedData:

0 commit comments

Comments
 (0)