Skip to content

Commit c4dd161

Browse files
committed
SDK-340: Update README with anchor info, added origin_server_certs as anchor property
1 parent dd62230 commit c4dd161

File tree

8 files changed

+68
-35
lines changed

8 files changed

+68
-35
lines changed

README.md

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,40 @@ Here is an example of how this works:
118118
```python
119119
client = Client(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)
120120
activity_details = client.get_activity_details(token)
121-
user_profile = activity_details.user_profile
122-
123-
user_id = user_profile.get('user_id')
124-
selfie = user_profile.get('selfie')
125-
given_names = user_profile.get('given_names')
126-
family_name = user_profile.get('family_name')
127-
full_name = user_profile.get('full_name')
128-
phone_number = user_profile.get('phone_number')
129-
date_of_birth = user_profile.get('date_of_birth')
130-
is_age_verified = user_profile.get('is_age_verified')
131-
postal_address = user_profile.get('postal_address')
132-
gender = user_profile.get('gender')
133-
nationality = user_profile.get('nationality')
134-
135-
base64_selfie_uri = activity_details.get('base64_selfie_uri')
121+
122+
profile = activity_details.profile
123+
124+
selfie = profile.get('selfie').value
125+
given_names = profile.get('given_names').value
126+
family_name = profile.get('family_name').value
127+
full_name = profile.get('full_name').value
128+
phone_number = profile.get('phone_number').value
129+
date_of_birth = profile.get('date_of_birth').value
130+
is_age_verified = profile.get('is_age_verified').value
131+
postal_address = profile.get('postal_address').value
132+
gender = profile.get('gender').value
133+
nationality = profile.get('nationality').value
134+
135+
remember_me_id = activity_details.user_id
136+
base64_selfie_uri = activity_details.base64_selfie_uri
137+
```
138+
139+
You can retrieve the anchors, sources and verifiers for each attribute as follows:
140+
```python
141+
given_names_attribute = profile.get('given_names')
142+
143+
given_names_anchors = given_names_attribute.anchors
144+
given_names_sources = given_names_attribute.sources
145+
given_names_verifiers = given_names_attribute.verifiers
146+
```
147+
148+
You can also retrieve further properties from these respective anchors in the following way:
149+
```python
150+
source_anchor = given_names_sources[0]
151+
value = source_anchor.value
152+
sub_type = source_anchor.sub_type
153+
timestamp = source_anchor.signed_timestamp
154+
origin_server_certs = source_anchor.origin_server_certs
136155
```
137156

138157
## AML Integration
@@ -252,7 +271,7 @@ For information on testing with multiple Python versions, see [VERSION-SUPPORT.m
252271

253272
* Activity Details
254273
* [X] User ID `user_id`
255-
* [X] Profile `user_profile`
274+
* [X] Profile `profile`
256275
* [X] Photo `selfie`
257276
* [X] Given Names `given_names`
258277
* [X] Family Name `family_name`

yoti_python_sdk/activity_details.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __init__(self, receipt, decrypted_profile=None):
2626
self.profile[field.name] = attribute.attribute(field.name, value, anchors)
2727
self.user_profile[field.name] = value # will be deprecated in v3.0.0
2828

29-
if field.name == 'selfie':
29+
if field.name == config.ATTRIBUTE_SELFIE:
3030
self.try_parse_selfie_field(field)
3131

3232
if field.name.startswith(config.ATTRIBUTE_AGE_OVER) or field.name.startswith(
@@ -54,12 +54,12 @@ def try_parse_age_verified_field(self, field, anchors):
5454
field.content_type
5555
)
5656
if is_age_verified == 'true':
57-
self.user_profile['is_age_verified'] = True
58-
self.profile['is_age_verified'] = attribute.attribute(is_age_verified, True, anchors)
57+
self.user_profile[config.ATTRIBUTE_IS_AGE_VERIFIED] = True
58+
self.profile[config.ATTRIBUTE_IS_AGE_VERIFIED] = attribute.attribute(is_age_verified, True, anchors)
5959
return
6060
if is_age_verified == 'false':
61-
self.user_profile['is_age_verified'] = False
62-
self.profile['is_age_verified'] = attribute.attribute(is_age_verified, False, anchors)
61+
self.user_profile[config.ATTRIBUTE_IS_AGE_VERIFIED] = False
62+
self.profile[config.ATTRIBUTE_IS_AGE_VERIFIED] = attribute.attribute(is_age_verified, False, anchors)
6363
return
6464

6565
raise TypeError("age_verified_field unable to be parsed")

yoti_python_sdk/anchor.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313

1414

1515
class Anchor:
16-
def __init__(self, anchor_type="Unknown", sub_type="", value="", signed_timestamp=None):
16+
def __init__(self, anchor_type="Unknown", sub_type="", value="", signed_timestamp=None, origin_server_certs=None):
1717
self.__anchor_type = anchor_type
1818
self.__sub_type = sub_type
1919
self.__value = value
2020
self.__signed_timestamp = signed_timestamp
21+
self.__origin_server_certs = origin_server_certs
2122

2223
def __iter__(self):
2324
return self
@@ -40,10 +41,11 @@ def parse_anchors(anchors):
4041
origin_server_certs_list = list(anc.origin_server_certs)
4142
origin_server_certs_item = origin_server_certs_list[0]
4243

43-
cert = crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, origin_server_certs_item).to_cryptography()
44+
crypto_cert = crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1,
45+
origin_server_certs_item).to_cryptography()
4446

45-
for i in range(len(cert.extensions)):
46-
extensions = cert.extensions[i]
47+
for i in range(len(crypto_cert.extensions)):
48+
extensions = crypto_cert.extensions[i]
4749
if hasattr(extensions, 'oid'):
4850
oid = extensions.oid
4951
if hasattr(oid, 'dotted_string'):
@@ -61,7 +63,8 @@ def parse_anchors(anchors):
6163
anchor_type,
6264
anc.sub_type,
6365
Anchor.decode_asn1_value(extension_value.value),
64-
anc.signed_time_stamp))
66+
anc.signed_time_stamp,
67+
crypto_cert))
6568

6669
return parsed_anchors
6770

@@ -107,3 +110,7 @@ def signed_timestamp(self):
107110
return ""
108111

109112
return signed_timestamp_parsed
113+
114+
@property
115+
def origin_server_certs(self):
116+
return self.__origin_server_certs

yoti_python_sdk/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
ATTRIBUTE_AGE_OVER = "age_over:"
44
ATTRIBUTE_AGE_UNDER = "age_under:"
55
ATTRIBUTE_POSTAL_ADDRESS = "postal_address"
6+
ATTRIBUTE_SELFIE = "selfie"
67
ATTRIBUTE_STRUCTURED_POSTAL_ADDRESS = "structured_postal_address"
8+
ATTRIBUTE_IS_AGE_VERIFIED = "is_age_verified"
79
ANCHOR_SOURCE = "SOURCE"
810
ANCHOR_VERIFIER = "VERIFIER"
911
KEY_FORMATTED_ADDRESS = "formatted_address"

yoti_python_sdk/tests/anchor_parser.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import binascii
22
import io
3-
43
from os.path import abspath, dirname, join
54

65
from yoti_python_sdk import anchor

yoti_python_sdk/tests/test_activity_details.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868

6969
def create_selfie_field(activity_details):
7070
activity_details.field = lambda: None
71-
activity_details.field.name = "selfie"
71+
activity_details.field.name = config.ATTRIBUTE_SELFIE
7272
activity_details.field.value = "base64(ง •̀_•́)ง"
7373
activity_details.field.content_type = Protobuf.CT_STRING
7474

@@ -108,17 +108,17 @@ def test_try_parse_age_verified_field_age_over():
108108
create_age_verified_field(activity_details, True, "true".encode(), 18)
109109

110110
ActivityDetails.try_parse_age_verified_field(activity_details, activity_details.field, None)
111-
assert activity_details.user_profile['is_age_verified'] is True
112-
assert activity_details.profile['is_age_verified'].value is True
111+
assert activity_details.user_profile[config.ATTRIBUTE_IS_AGE_VERIFIED] is True
112+
assert activity_details.profile[config.ATTRIBUTE_IS_AGE_VERIFIED].value is True
113113

114114

115115
def test_try_parse_age_verified_field_age_under():
116116
activity_details = ActivityDetails(successful_receipt())
117117
create_age_verified_field(activity_details, False, "false".encode(), 55)
118118

119119
ActivityDetails.try_parse_age_verified_field(activity_details, activity_details.field, None)
120-
assert activity_details.user_profile['is_age_verified'] is False
121-
assert activity_details.profile['is_age_verified'].value is False
120+
assert activity_details.user_profile[config.ATTRIBUTE_IS_AGE_VERIFIED] is False
121+
assert activity_details.profile[config.ATTRIBUTE_IS_AGE_VERIFIED].value is False
122122

123123

124124
def test_try_parse_age_verified_field_non_bool_value_throws_error():

yoti_python_sdk/tests/test_anchor.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
import datetime
3-
import yoti_python_sdk
43

4+
import yoti_python_sdk
55
from yoti_python_sdk import config
66
from yoti_python_sdk.tests import anchor_parser
77

@@ -13,6 +13,7 @@ def test_parse_anchors_driving_license():
1313
assert parsed_anchor.signed_timestamp == datetime.datetime(2018, 4, 11, 13, 13, 3, 923537)
1414
assert parsed_anchor.sub_type == ""
1515
assert parsed_anchor.value == "DRIVING_LICENCE"
16+
assert parsed_anchor.origin_server_certs.serial == int("46131813624213904216516051554755262812")
1617

1718

1819
def test_parse_anchors_passport():
@@ -22,6 +23,7 @@ def test_parse_anchors_passport():
2223
assert parsed_anchor.signed_timestamp == datetime.datetime(2018, 4, 12, 14, 14, 32, 835537)
2324
assert parsed_anchor.sub_type == "OCR"
2425
assert parsed_anchor.value == "PASSPORT"
26+
assert parsed_anchor.origin_server_certs.serial == int("277870515583559162487099305254898397834")
2527

2628

2729
def test_parse_yoti_admin():
@@ -31,6 +33,7 @@ def test_parse_yoti_admin():
3133
assert parsed_anchor.signed_timestamp == datetime.datetime(2018, 4, 11, 13, 13, 4, 95238)
3234
assert parsed_anchor.sub_type == ""
3335
assert parsed_anchor.value == "YOTI_ADMIN"
36+
assert parsed_anchor.origin_server_certs.serial == int("256616937783084706710155170893983549581")
3437

3538

3639
def test_anchor_returns_correct_default_values():
@@ -40,3 +43,4 @@ def test_anchor_returns_correct_default_values():
4043
assert anchor.signed_timestamp is None
4144
assert anchor.sub_type == ""
4245
assert anchor.value == ""
46+
assert anchor.origin_server_certs is None

yoti_python_sdk/tests/test_client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from cryptography.fernet import base64
99
from past.builtins import basestring
1010

11+
from yoti_python_sdk import config
12+
1113
try:
1214
from unittest import mock
1315
except ImportError:
@@ -141,10 +143,10 @@ def test_requesting_activity_details_with_correct_data(
141143
mock_get.assert_called_once_with(url=expected_activity_details_url, headers=expected_get_headers)
142144
assert isinstance(activity_details, ActivityDetails)
143145
assert activity_details.user_id == "ijH4kkqMKTG0FSNUgQIvd2Z3Nx1j8f5RjVQMyoKOvO/hkv43Ik+t6d6mGfP2tdrN"
144-
selfie_user_profile = activity_details.user_profile.get('selfie')
146+
selfie_user_profile = activity_details.user_profile.get(config.ATTRIBUTE_SELFIE)
145147
assert isinstance(selfie_user_profile, basestring)
146148

147-
selfie_profile = activity_details.profile.get('selfie').value
149+
selfie_profile = activity_details.profile.get(config.ATTRIBUTE_SELFIE).value
148150
assert isinstance(selfie_profile, basestring)
149151

150152
base64_selfie_uri = getattr(activity_details, 'base64_selfie_uri')

0 commit comments

Comments
 (0)