-
Notifications
You must be signed in to change notification settings - Fork 3
Add BidStreamClient and SharingClient #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -116,25 +114,7 @@ def decrypt(self, token): | |||
EncryptionError: if token version is not supported, the token has expired, | |||
or no required decryption keys present in the keys collection | |||
""" | |||
return encryption.decrypt(token, self._keys) | |||
|
|||
def _parse_keys_json(self, resp_body): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to refresh_keys_util.py
@@ -79,15 +80,12 @@ def refresh_keys(self): | |||
Returns: | |||
EncryptionKeysCollection containing the keys | |||
""" | |||
req, nonce = make_v2_request(self._secret_key, dt.datetime.now(tz=timezone.utc)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to refresh_keys_util.py
uid2_client/client.py
Outdated
@@ -36,7 +38,7 @@ class Uid2Client: | |||
Connect to the UID2 service and obtain the latest encryption keys: | |||
>>> from uid2_client import * | |||
>>> client = Uid2Client('https://prod.uidapi.com', 'my-authorization-key', 'my-secret-key') | |||
>>> keys = client.refresh_keys() | |||
>>> keys = client.refresh_sharing_keys() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should remain unchanged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, I missed this
uid2_client/sharing_client.py
Outdated
self._auth_key = auth_key | ||
self._secret_key = base64.b64decode(secret_key) | ||
|
||
def encrypt_raw_uid_into_sharing_token(self, uid2, keyset_id=None, now=dt.datetime.now(tz=dt.timezone.utc)): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we don't want to have a now
parameter on these public methods. In the .NET SDK the DateTime
param is on the internal method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch. I missed that the C# method is internal. Changed the method signature
uid2_client/sharing_client.py
Outdated
self._auth_key = auth_key | ||
self._secret_key = base64.b64decode(secret_key) | ||
|
||
def encrypt_raw_uid_into_sharing_token(self, uid2, keyset_id=None, now=dt.datetime.now(tz=dt.timezone.utc)): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default argument values are evaluated at the point of function definition, so now
doesn't behave the way we want it to. This is a per-existing issue but we should fix it, at least in new code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very interesting. I didn't know this and assumed they are evaluated when the function is invoked. Thanks!
@@ -1,7 +1,4 @@ | |||
"""Internal module for holding the Uid2Client class. | |||
|
|||
Do not use this module directly, import through uid2_client module instead, e.g. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this comment removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UID2Client class is being deprecated and participants can use this directly. The publisher guide mentions this
uid2_client/refresh_keys_util.py
Outdated
base64.b64decode(key['secret']), | ||
keyset_id) | ||
keys.append(key) | ||
if resp_body["identity_scope"] == "EUID": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this inside the keys loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's right, it doesn't need to be in the for loop. My indentation is incorrect
uid2_client/refresh_keys_util.py
Outdated
keyset_id = None | ||
if "keyset_id" in key: | ||
keyset_id = key["keyset_id"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do
keyset_id = key.get("keyset_id")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, that's more elegant
pyproject.toml
Outdated
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" | |||
|
|||
[project] | |||
name = "uid2_client" | |||
version = "2.2.8" | |||
version = "2.3.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, when do we need to change the version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cYKatherine @thomasm-ttd is this handled by the github action now, so we shouldn't change version manually like this?
if resp_body["identity_scope"] == "EUID": | ||
identity_scope = IdentityScope.EUID | ||
for key in resp_body["keys"]: | ||
keyset_id = key.get("keyset_id") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"keyset_id" is removed from key objects. Should we also remove it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NVM, this function is also used in the deprecated client class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its being removed from /key/bidstream
response but it will continue to exist in /key/sharing
response
keyset_id = key.get("keyset_id") | ||
key = EncryptionKey(key['id'], | ||
key.get('site_id', -1), | ||
_make_dt(key['created']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you like to replace all method to get(), like key.get("created")?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for response fields which are necessary for the key to work, it makes sense to alert the user in case of a missing value. So key['created']
will throw an exception if the field is absent.
Using key.get("created")
it will silently fail. I am assuming that alerting the user by throwing an exception is the right way to go
tests/test_sharing_client.py
Outdated
self.assertEqual(result.identity_scope, expected_scope) | ||
self.assertEqual(result.advertising_token_version, expected_version) | ||
|
||
def test_phone_uids(self, mock_refresh_sharing_keys): # PhoneTest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the PhoneTest equivalent? Let's use the same order between SDKs to make it easier
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually did reorganize the test cases between the SDKs :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate? We need to keep them in the same order to make it easier for future maintainers. If you want to propose a better order, let's discuss but you'll need to change them in all SDKs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just meant that I sync'd the tests in python SDK with the C# one. They were not in the same order in Python SDK.
examples/sample_bidstream_client.py
Outdated
print('UID =', decrypt_result.uid) | ||
print('Established =', decrypt_result.established) | ||
print('Site ID =', decrypt_result.site_id) | ||
print('Identity Scope =', decrypt_result.identity_scope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
identity_scope
belongs at the BidstreamClient level rather than the token level. It's probably not needed there either since it's the consumer who chooses whether to connect to EUID vs UID2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. will remove this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems you've still left some identity_scope
s at the token level, could you please check?
uid2_client/bid_stream_client.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be named bidstream_client.py
?
uid2_client/bid_stream_client.py
Outdated
|
||
|
||
class BidstreamClient: | ||
"""Client for interacting with UID2 BidStream services |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/BidStream/Bidstream/
uid2_client/bid_stream_client.py
Outdated
|
||
Methods: | ||
refresh_keys: Refresh encryption keys from UID2 servers | ||
decrypt_ad_token_into_raw_uid: decrypt an advertising token |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decrypt_token_into_raw_uid
uid2_client/bid_stream_client.py
Outdated
""" | ||
|
||
def __init__(self, base_url, auth_key, secret_key): | ||
"""Create a new BidStreamClient client. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BidstreamClient
uid2_client/encryption.py
Outdated
@@ -32,8 +38,9 @@ class _PayloadType(Enum): | |||
base64_url_special_chars = {"-", "_"} | |||
|
|||
|
|||
# DEPRECATED, DO NOT CALL DIRECTLY. PLEASE USE Uid2Client's client.decrypt() | |||
def decrypt(token, keys, now=dt.datetime.now(tz=timezone.utc)): | |||
# DEPRECATED, DO NOT CALL DIRECTLY. For DSPs PLEASE USE BidStreamClient's decrypt_ad_token_into_raw_uid() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bidstream
/ decrypt_token_into_raw_uid
uid2_client/bid_stream_client.py
Outdated
|
||
This will synchronously connect to the corresponding UID2 service and fetch the latest | ||
set of encryption keys which can then be used to decrypt advertising tokens using | ||
the decrypt_token function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decrypt_token_into_raw_uid
uid2_client/client_type.py
Outdated
|
||
|
||
class ClientType(Enum): | ||
Sharing = 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we make these UPPER_CASE
to match DecryptionStatus
enum values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I copied it from C# SDk and forgot to change
@property | ||
def encrypted_data(self): | ||
return self._encrypted_data | ||
#uid = encrypted_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we delete this line
examples/sample_sharing.py
Outdated
@@ -24,14 +27,14 @@ def _usage(): | |||
# client = EuidClientFactory.create(base_url, auth_key, secret_key) | |||
# for UID2 use: | |||
client = Uid2ClientFactory.create(base_url, auth_key, secret_key) | |||
client.refresh_keys() | |||
client.refresh() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this still called refresh_keys
?
established (datetime): UTC date/time for when the token was first generated | ||
site_id (int): site ID which the token is originating from | ||
site_key_site_id (int): site ID of the site key which the token is encrypted with | ||
""" | ||
|
||
def __init__(self, uid2, established, site_id, site_key_site_id): | ||
self.uid2 = uid2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes this release a breaking change, so we need to bump the major version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out. I was trying not to break any existing functionality, for now I added a property alias uid2
for existing clients to work. At the same time the overall changes in the PR look big enough to me to warrant a major version upgrade.
89738e5
to
588e980
Compare
Introduce two new clients
BidStreamClient
andSharingClient
and deprecate the existingUid2PublisherClient
.domain_name
for decrypting ad tokens, but allow None for now. The actual domain_name checks will follow in a future PRencrypt
/decrypt
/refresh
interface to return a*response
object always that contains the value or exception reason. Keeps it consistent with C# SDK