Skip to content

Commit 448f3ab

Browse files
committed
Removed keyword arg for advertising token version from encrypt(). Added an encrypt() and decrypt() function to the client which passthrough to the functions in encryption.py. Added an identity_scope parameter to the client's constructor. Refactored tests & examples which create a client to use the client.encrypt() and client.decrypt() passthroughs and to provide the appropriate identity_scope to the client's constructor.
1 parent f643a1a commit 448f3ab

File tree

8 files changed

+62
-45
lines changed

8 files changed

+62
-45
lines changed

examples/sample_auto_refresh.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
import time
44

5-
from uid2_client import EncryptionKeysAutoRefresher
5+
from uid2_client import EncryptionKeysAutoRefresher, IdentityScope
66
from uid2_client import Uid2Client
77
from uid2_client import decrypt
88

@@ -20,7 +20,7 @@ def _usage():
2020
secret_key = sys.argv[3]
2121
ad_token = sys.argv[4]
2222

23-
client = Uid2Client(base_url, auth_key, secret_key)
23+
client = Uid2Client(base_url, auth_key, secret_key, IdentityScope.UID2)
2424
with EncryptionKeysAutoRefresher(client, dt.timedelta(seconds=4), dt.timedelta(seconds=7)) as refresher:
2525
for i in range(0, 20):
2626
refresh_result = refresher.current_result()

examples/sample_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ def _usage():
2222
secret_key = sys.argv[3]
2323
ad_token = sys.argv[4]
2424

25-
client = Uid2Client(base_url, auth_key, secret_key)
25+
client = Uid2Client(base_url, auth_key, secret_key, IdentityScope.UID2)
2626
keys = client.refresh_keys()
27-
decrypt_result = decrypt(ad_token, keys)
27+
decrypt_result = client.decrypt(ad_token, keys)
2828

2929
print('UID2 =', decrypt_result.uid2)
3030
print('Established =', decrypt_result.established)
@@ -34,5 +34,5 @@ def _usage():
3434
# Not required for DSPs, but for those using UID2 sharing functionality this shows how to encrypt a raw UID2 into
3535
# a new advertising token.
3636
# IdentityScope could be UID2 or EUID
37-
new_ad_token = encrypt(decrypt_result.uid2, IdentityScope.UID2, keys)
37+
new_ad_token = client.encrypt(decrypt_result.uid2, keys)
3838
print('New Ad Token =', new_ad_token)

examples/sample_encryption.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def _usage():
2121
ad_token = sys.argv[4]
2222
str_data = sys.argv[5]
2323

24-
client = Uid2Client(base_url, auth_key, secret_key)
24+
client = Uid2Client(base_url, auth_key, secret_key, IdentityScope.UID2)
2525
keys = client.refresh_keys()
2626

2727
data = bytes(str_data, 'utf-8')

tests/sharing_test.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929

3030
class TestSharing(unittest.TestCase):
3131
def setup_sharing_and_encrypt(self, id_scope=IdentityScope.UID2):
32-
client = Uid2Client("endpoint", "key", _client_secret)
32+
client = Uid2Client("endpoint", "key", _client_secret, id_scope)
3333
json = self._key_set_to_json_for_sharing([_master_key, _site_key])
3434
keys = client.refresh_json(json)
3535

36-
ad_token = encrypt(_example_uid, id_scope, keys)
36+
ad_token = client.encrypt(_example_uid, keys)
3737

3838
return ad_token, keys
3939

@@ -75,12 +75,12 @@ def test_can_encrypt_and_decrypt_for_sharing(self):
7575

7676
def test_can_decrypt_another_clients_encrypted_token(self):
7777
ad_token, keys = self.setup_sharing_and_encrypt()
78-
receiving_client = Uid2Client("endpoint2", "authkey2", _client_secret)
78+
receiving_client = Uid2Client("endpoint2", "authkey2", _client_secret, IdentityScope.UID2)
7979
keys_json = self._key_set_to_json_for_sharing_with_header('"default_keyset_id": 12345,', 4874, [_master_key, _site_key])
8080

8181
receiving_keys = receiving_client.refresh_json(keys_json)
8282

83-
result = decrypt(ad_token, receiving_keys)
83+
result = receiving_client.decrypt(ad_token, receiving_keys)
8484
self.assertEqual(_example_uid, result.uid2)
8585

8686
def test_sharing_token_is_v4(self):
@@ -121,51 +121,51 @@ def test_multiple_keys_per_keyset(self):
121121
_master_secret, keyset_id=1)
122122
site_key2 = EncryptionKey(_site_key_id, _site_id, _now - dt.timedelta(days=-2), _now - dt.timedelta(days=-1), _now - dt.timedelta(hours=-1),
123123
_site_secret, keyset_id=99999)
124-
client = Uid2Client("endpoint", "authkey", _client_secret)
124+
client = Uid2Client("endpoint", "authkey", _client_secret, IdentityScope.UID2)
125125
json_body = self._key_set_to_json_for_sharing([_master_key, master_key2, _site_key, site_key2])
126126
keys = client.refresh_json(json_body)
127127

128-
ad_token = encrypt(_example_uid, IdentityScope.UID2, keys)
128+
ad_token = client.encrypt(_example_uid, keys)
129129

130-
result = decrypt(ad_token, keys)
130+
result = client.decrypt(ad_token, keys)
131131

132132
self.assertEqual(_example_uid, result.uid2)
133133

134134
def test_cannot_encrypt_if_no_key_from_default_keyset(self):
135-
client = Uid2Client("endpoint", "authkey", _client_secret)
135+
client = Uid2Client("endpoint", "authkey", _client_secret, IdentityScope.UID2)
136136
json_body = self._key_set_to_json_for_sharing([_master_key])
137137
keys = client.refresh_json(json_body)
138138

139139
self.assertRaises(EncryptionError, encrypt, _example_uid, IdentityScope.UID2, keys)
140140

141141
def test_cannot_encrypt_if_theres_no_default_keyset_header(self):
142-
client = Uid2Client("endpoint", "authkey", _client_secret)
142+
client = Uid2Client("endpoint", "authkey", _client_secret, IdentityScope.UID2)
143143
json_body = self._key_set_to_json_for_sharing_with_header("", _site_id, [_master_key, _site_key])
144144
keys = client.refresh_json(json_body)
145145
self.assertRaises(EncryptionError, encrypt, _example_uid, IdentityScope.UID2, keys)
146146

147147

148148
def test_expiry_in_token_matches_expiry_in_reponse(self):
149-
client = Uid2Client("endpoint", "authkey", _client_secret)
149+
client = Uid2Client("endpoint", "authkey", _client_secret, IdentityScope.UID2)
150150
json_body = self._key_set_to_json_for_sharing_with_header('"default_keyset_id": 99999, "token_expiry_seconds": 2,', 99999, [_master_key, _site_key])
151151
keys = client.refresh_json(json_body)
152152

153153
now = dt.datetime.now(tz=timezone.utc)
154-
ad_token = encrypt(_example_uid, IdentityScope.UID2, keys)
154+
ad_token = client.encrypt(_example_uid, keys)
155155

156-
result = decrypt(ad_token, keys, now=now + dt.timedelta(seconds=1))
156+
result = client.decrypt(ad_token, keys, now=now + dt.timedelta(seconds=1))
157157
self.assertEqual(_example_uid, result.uid2)
158158

159159
self.assertRaises(EncryptionError, decrypt, ad_token, keys, now=now + dt.timedelta(seconds=3))
160160

161161
def test_encrypt_key_inactive(self):
162-
client = Uid2Client("endpoint", "authkey", _client_secret)
162+
client = Uid2Client("endpoint", "authkey", _client_secret, IdentityScope.UID2)
163163
key = EncryptionKey(245, _site_id, _now, _now + dt.timedelta(days=1), _now +dt.timedelta(days=2), _site_secret, keyset_id=99999)
164164
keys = client.refresh_json(self._key_set_to_json_for_sharing([_master_key, key]))
165165
self.assertRaises(EncryptionError, encrypt, _example_uid, IdentityScope.UID2, keys)
166166

167167
def test_encrypt_key_expired(self):
168-
client = Uid2Client("endpoint", "authkey", _client_secret)
168+
client = Uid2Client("endpoint", "authkey", _client_secret, IdentityScope.UID2)
169169
key = EncryptionKey(245, _site_id, _now, _now, _now - dt.timedelta(days=1), _site_secret, keyset_id=99999)
170170
keys = client.refresh_json(self._key_set_to_json_for_sharing([_master_key, key]))
171171
self.assertRaises(EncryptionError, encrypt, _example_uid, IdentityScope.UID2, keys)

tests/test_encryption.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,20 +340,6 @@ def test_decrypt_token_v2_custom_now(self):
340340
result = decrypt(token, keys, now=expiry - dt.timedelta(seconds=1))
341341
self.assertEqual(_example_id, result.uid2)
342342

343-
344-
def test_smoke_token_v3(self):
345-
uid2 = _example_id
346-
identity_scope = IdentityScope.UID2
347-
now = dt.datetime.now(tz=timezone.utc)
348-
349-
keys = EncryptionKeysCollection([_master_key, _site_key, _keyset_key], default_keyset_id=20,
350-
master_keyset_id=9999, caller_site_id=20)
351-
352-
result = encrypt(uid2, identity_scope, keys, now=now, ad_token_version=AdvertisingTokenVersion.ADVERTISING_TOKEN_V3)
353-
final = decrypt(result, keys, now=now)
354-
355-
self.assertEqual(uid2, final.uid2)
356-
357343
def test_smoke_token_v4(self):
358344
uid2 = _example_id
359345
identity_scope = IdentityScope.UID2

tests/test_key_parse.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import unittest
2-
from uid2_client import Uid2Client
2+
from uid2_client import Uid2Client, IdentityScope
33
import datetime as dt
44
import base64
55

@@ -36,7 +36,7 @@ def test_key_parse(self):
3636
"}, " + \
3737
"\"status\": \"success\" }"
3838

39-
client = Uid2Client("ep", "ak", "ioG3wKxAokmp+rERx6A4kM/13qhyolUXIu14WN16Spo=")
39+
client = Uid2Client("ep", "ak", "ioG3wKxAokmp+rERx6A4kM/13qhyolUXIu14WN16Spo=", IdentityScope.UID2)
4040

4141
now = dt.datetime.now(tz=dt.timezone.utc)
4242

@@ -65,7 +65,7 @@ def test_key_parse(self):
6565
self.assertEqual("DD67xF8OFmbJ1/lMPQ6fGRDbJOT4kXErrYWcKdFfCUE=", base64.b64encode(key.secret).decode("ascii"))
6666

6767
def test_parse_key_error(self):
68-
client = Uid2Client("ep", "ak", "ioG3wKxAokmp+rERx6A4kM/13qhyolUXIu14WN16Spo=")
68+
client = Uid2Client("ep", "ak", "ioG3wKxAokmp+rERx6A4kM/13qhyolUXIu14WN16Spo=", IdentityScope.UID2)
6969
self.assertRaises(BaseException, client.refresh_json, "{\"status\": \"error\"}")
7070
self.assertRaises(BaseException, client.refresh_json, "{\"body\": \"error\"}")
7171
self.assertRaises(BaseException, client.refresh_json, "{\"body\": [1, 2, 3]}")

uid2_client/client.py

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
import urllib.request as request
1414
import pkg_resources
1515

16-
from .keys import EncryptionKey, EncryptionKeysCollection
16+
from uid2_client import encryption
1717
from .encryption import _decrypt_gcm, _encrypt_gcm
18+
from .keys import EncryptionKey, EncryptionKeysCollection
19+
from .identity_scope import IdentityScope
1820

1921

2022
def _make_dt(timestamp):
@@ -33,12 +35,12 @@ class Uid2Client:
3335
Examples:
3436
Connect to the UID2 service and obtain the latest encryption keys:
3537
>>> from uid2_client import *
36-
>>> client = Uid2Client('https://prod.uidapi.com', 'my-authorization-key', 'my-secret-key')
38+
>>> client = Uid2Client('https://prod.uidapi.com', 'my-authorization-key', 'my-secret-key', IdentityScope.UID2)
3739
>>> keys = client.refresh_keys()
3840
>>> uid2 = decrypt('some-ad-token', keys).uid2
3941
"""
4042

41-
def __init__(self, base_url, auth_key, secret_key):
43+
def __init__(self, base_url, auth_key, secret_key, identity_scope):
4244
"""Create a new Uid2Client client.
4345
4446
Args:
@@ -52,6 +54,7 @@ def __init__(self, base_url, auth_key, secret_key):
5254
self._base_url = base_url
5355
self._auth_key = auth_key
5456
self._secret_key = base64.b64decode(secret_key)
57+
self._identity_scope = identity_scope
5558

5659
def refresh_keys(self):
5760
"""Get the latest encryption keys for advertising tokens.
@@ -72,6 +75,37 @@ def refresh_json(self, json_str):
7275
body = json.loads(json_str)
7376
return self._parse_keys_json(body['body'])
7477

78+
def encrypt(self, uid2, keys, keyset_id=None):
79+
""" Encrypt an UID2 into a sharing token
80+
81+
Args:
82+
uid2: the UID2 or EUID to be encrypted
83+
keys (EncryptionKeysCollection): collection of keys to choose from for encryption
84+
keyset_id (int) : An optional keyset id to use for the encryption. Will use default keyset if left blank
85+
86+
Keyword Args:
87+
now (Datetime): the datettime to use for now. Defaults to utc now
88+
89+
Returns (str): Sharing Token
90+
"""
91+
return encryption.encrypt(uid2, self._identity_scope, keys, keyset_id)
92+
93+
def decrypt(self, token, keys, now=dt.datetime.now(tz=timezone.utc)):
94+
"""Decrypt advertising token to extract UID2 details.
95+
96+
Args:
97+
token (str): advertising token to decrypt
98+
keys (EncryptionKeysCollection): collection of keys to decrypt the token
99+
now (datetime): date/time to use as "now" when doing token expiration check
100+
101+
Returns:
102+
DecryptedToken: details extracted from the advertising token
103+
104+
Raises:
105+
EncryptionError: if token version is not supported, the token has expired,
106+
or no required decryption keys present in the keys collection
107+
"""
108+
return encryption.decrypt(token, keys, now)
75109

76110
def _parse_keys_json(self, resp_body):
77111
keys = []

uid2_client/encryption.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ def encrypt(uid2, identity_scope, keys, keyset_id=None, **kwargs):
202202
203203
Keyword Args:
204204
now (Datetime): the datettime to use for now. Defaults to utc now
205-
ad_token_version (AdvertisingTokenVersion): Defaults to v4
206205
207206
Returns (str): Sharing Token
208207
@@ -211,9 +210,7 @@ def encrypt(uid2, identity_scope, keys, keyset_id=None, **kwargs):
211210
if now is None:
212211
now = dt.datetime.now(tz=timezone.utc)
213212

214-
ad_token_version = kwargs.get("ad_token_version")
215-
if ad_token_version is None:
216-
ad_token_version = AdvertisingTokenVersion.ADVERTISING_TOKEN_V4
213+
ad_token_version = AdvertisingTokenVersion.ADVERTISING_TOKEN_V4
217214

218215
key = keys.get_default_keyset_key(now) if keyset_id is None else keys.get_by_keyset_key(keyset_id, now)
219216
master_key = keys.get_by_keyset_key(keys.get_master_keyset_id(), now)
@@ -249,7 +246,7 @@ def encrypt_data(data, identity_scope, **kwargs):
249246
key from; the key will be selected using site_id
250247
site_id (int): ID of the site for which the encryption key is to be used;
251248
the key will be looked up from the keys collection;
252-
if this is specified, you can't specificy advertising_token
249+
if this is specified, you can't specify advertising_token
253250
advertising_token (str): token to decrypt in order to obtain the site_id
254251
now (datetime): date/time to use as "now" for checking whether advertising_token
255252
or site encryption key have expired (default: UTC now) as well as

0 commit comments

Comments
 (0)