rp_python_sdk 0.6.0__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/PKG-INFO +4 -1
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/README.md +3 -0
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/pyproject.toml +1 -1
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/endpoints/get_participants.py +6 -4
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/endpoints/pushed_authorisation_request.py +5 -2
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/endpoints/retrieve_tokens.py +20 -12
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/model.py +12 -4
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/sdk_config.py +4 -2
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/__init__.py +0 -0
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/endpoints/user_info.py +0 -0
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/endpoints/util/fapi.py +0 -0
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/filters/participant_filters.py +0 -0
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/relying_party_client_sdk.py +0 -0
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/relying_party_client_sdk_exception.py +0 -0
- {rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/setup_logger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rp_python_sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Python SDK for Relying Parties to enable simple integration with the Digital Identity ecosystem
|
|
5
5
|
License: Proprietary
|
|
6
6
|
Author: Erik Pragt
|
|
@@ -423,6 +423,9 @@ poetry publish
|
|
|
423
423
|
|
|
424
424
|
## Release Notes
|
|
425
425
|
|
|
426
|
+
### 0.7.0 (June 14, 2024)
|
|
427
|
+
- Changed purpose field to allow 3 to 300 characters (up from 50)
|
|
428
|
+
|
|
426
429
|
### 0.6.0 (May 17, 2024)
|
|
427
430
|
- Removed logging configuration (see [PR #11](https://github.com/connectid-tools/rp-python-sdk/pull/11))
|
|
428
431
|
|
|
@@ -407,6 +407,9 @@ poetry publish
|
|
|
407
407
|
|
|
408
408
|
## Release Notes
|
|
409
409
|
|
|
410
|
+
### 0.7.0 (June 14, 2024)
|
|
411
|
+
- Changed purpose field to allow 3 to 300 characters (up from 50)
|
|
412
|
+
|
|
410
413
|
### 0.6.0 (May 17, 2024)
|
|
411
414
|
- Removed logging configuration (see [PR #11](https://github.com/connectid-tools/rp-python-sdk/pull/11))
|
|
412
415
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "rp_python_sdk"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Python SDK for Relying Parties to enable simple integration with the Digital Identity ecosystem"
|
|
5
5
|
authors = ["Erik Pragt <erik.pragt@connectid.com.au>"]
|
|
6
6
|
license = "Proprietary"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import time
|
|
2
1
|
from datetime import date
|
|
3
2
|
|
|
4
3
|
import requests
|
|
4
|
+
|
|
5
5
|
from rp_python_sdk.filters.participant_filters import remove_out_of_date_certifications, \
|
|
6
6
|
remove_unofficial_certifications, filter_for_fallback_identity_service_providers, \
|
|
7
7
|
remove_participants_without_auth_servers, remove_fallback_identity_service_provider, \
|
|
@@ -14,7 +14,6 @@ from rp_python_sdk.setup_logger import logger
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def get_participants(config: SdkConfig) -> list[Participant]:
|
|
17
|
-
|
|
18
17
|
participants = _retrieve_full_participants_list(config)
|
|
19
18
|
|
|
20
19
|
filtered_participants = remove_fallback_identity_service_provider(participants)
|
|
@@ -30,18 +29,21 @@ def get_participants(config: SdkConfig) -> list[Participant]:
|
|
|
30
29
|
if len(config.custom_config.required_claims) != 0:
|
|
31
30
|
logger.debug(f"Identity provider list filtered for participants that support the "
|
|
32
31
|
f"following claims: {config.custom_config.required_claims}")
|
|
33
|
-
filtered_participants = filter_auth_servers_for_supported_claims(filtered_participants,
|
|
32
|
+
filtered_participants = filter_auth_servers_for_supported_claims(filtered_participants,
|
|
33
|
+
config.custom_config.required_claims)
|
|
34
34
|
|
|
35
35
|
if len(config.custom_config.required_participant_certifications) != 0:
|
|
36
36
|
logger.debug(f"Identity provider list filtered for participants that support the "
|
|
37
37
|
f"following certifications: {config.custom_config.required_participant_certifications}")
|
|
38
|
-
filtered_participants = filter_for_required_certifications(filtered_participants,
|
|
38
|
+
filtered_participants = filter_for_required_certifications(filtered_participants,
|
|
39
|
+
config.custom_config.required_participant_certifications)
|
|
39
40
|
|
|
40
41
|
filtered_participants = remove_inactive_auth_servers(filtered_participants)
|
|
41
42
|
filtered_participants = remove_participants_without_auth_servers(filtered_participants)
|
|
42
43
|
|
|
43
44
|
return filtered_participants
|
|
44
45
|
|
|
46
|
+
|
|
45
47
|
def retrieve_fallback_provider_participants(config: SdkConfig) -> list[Participant]:
|
|
46
48
|
participants = _retrieve_full_participants_list(config)
|
|
47
49
|
|
{rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/endpoints/pushed_authorisation_request.py
RENAMED
|
@@ -119,6 +119,9 @@ def send_pushed_authorisation_request(config: SdkConfig,
|
|
|
119
119
|
|
|
120
120
|
log_x_fapi_interaction_id_matches(authorisation_server, "send_pushed_authorisation_request", x_fapi_interaction_id, response)
|
|
121
121
|
|
|
122
|
+
if not response.ok:
|
|
123
|
+
raise RelyingPartyClientSdkException(f"Response code for PAR to {authorisation_server_id} not successful, was: {response.status_code} x-fapi-interaction-id: {x_fapi_interaction_id}")
|
|
124
|
+
|
|
122
125
|
request_uri = response.json()['request_uri']
|
|
123
126
|
logger.debug(f"PAR was sent, request_uri='{request_uri}'")
|
|
124
127
|
|
|
@@ -127,8 +130,8 @@ def send_pushed_authorisation_request(config: SdkConfig,
|
|
|
127
130
|
|
|
128
131
|
|
|
129
132
|
def _check_valid_purpose(purpose) -> None:
|
|
130
|
-
if len(purpose) < 3 or len(purpose) >
|
|
131
|
-
raise RelyingPartyClientSdkException("Purpose must be between 3 and
|
|
133
|
+
if len(purpose) < 3 or len(purpose) > 300:
|
|
134
|
+
raise RelyingPartyClientSdkException("Purpose must be between 3 and 300 characters")
|
|
132
135
|
|
|
133
136
|
illegal_chars = ["<", ">", "(", ")", "{", "}", "'", "\\"]
|
|
134
137
|
|
|
@@ -25,17 +25,20 @@ def retrieve_tokens(config: SdkConfig, authorisation_server_id: str, callback_bo
|
|
|
25
25
|
|
|
26
26
|
if issuer_metadata.issuer != callback_body.iss:
|
|
27
27
|
raise RelyingPartyClientSdkException(
|
|
28
|
-
f"Issuer returned from authorization endpoint ({callback_body.iss} does not match issuer defined
|
|
28
|
+
f"Issuer returned from authorization endpoint ({callback_body.iss} does not match issuer defined "
|
|
29
|
+
f"in authorization server well-known ({issuer_metadata.issuer})")
|
|
29
30
|
|
|
30
31
|
x_fapi_interaction_id = create_x_fapi_interaction_id()
|
|
31
32
|
logger.info(
|
|
32
|
-
f"Retrieving token response from authorisation server: {authorisation_server_id} -
|
|
33
|
+
f"Retrieving token response from authorisation server: {authorisation_server_id} - "
|
|
34
|
+
f"{authorisation_server.customer_friendly_name}, x-fapi-interaction-id: {x_fapi_interaction_id}")
|
|
33
35
|
|
|
34
36
|
token_endpoint = issuer_metadata.get_preferred_token_endpoint()
|
|
35
37
|
|
|
36
38
|
if callback_body.state != original_state:
|
|
37
39
|
raise RelyingPartyClientSdkException(
|
|
38
|
-
f"Callback response state value does not match state, callback state: {callback_body.state},
|
|
40
|
+
f"Callback response state value does not match state, callback state: {callback_body.state}, "
|
|
41
|
+
f"state {original_state}, x-fapi-interaction-id: {x_fapi_interaction_id}")
|
|
39
42
|
|
|
40
43
|
if callback_body.iss != issuer_metadata.issuer:
|
|
41
44
|
raise RelyingPartyClientSdkException(
|
|
@@ -86,6 +89,11 @@ def retrieve_tokens(config: SdkConfig, authorisation_server_id: str, callback_bo
|
|
|
86
89
|
|
|
87
90
|
log_x_fapi_interaction_id_matches(authorisation_server, "retrieve_tokens", x_fapi_interaction_id, response)
|
|
88
91
|
|
|
92
|
+
if not response.ok:
|
|
93
|
+
raise RelyingPartyClientSdkException(
|
|
94
|
+
f"Response code for token endpoint to {token_endpoint} not successful, was: {response.status_code}, "
|
|
95
|
+
f"x-fapi-interaction-id: {x_fapi_interaction_id}, response body: " + response.text)
|
|
96
|
+
|
|
89
97
|
token_input = TokenInput.from_json(response.text)
|
|
90
98
|
|
|
91
99
|
jwks_response_body = _get_jwks_json(issuer_metadata, x_fapi_interaction_id)
|
|
@@ -99,7 +107,8 @@ def retrieve_tokens(config: SdkConfig, authorisation_server_id: str, callback_bo
|
|
|
99
107
|
call_user_info(config, authorisation_server_id, token_set.token_input.access_token)
|
|
100
108
|
|
|
101
109
|
logger.info(
|
|
102
|
-
f"Token response successfully retrieved from authorisation server {authorisation_server_id},
|
|
110
|
+
f"Token response successfully retrieved from authorisation server {authorisation_server_id}, "
|
|
111
|
+
f"x-fapi-interaction-id: {x_fapi_interaction_id}, txn: {token_set.claims['txn']}")
|
|
103
112
|
|
|
104
113
|
return token_set
|
|
105
114
|
|
|
@@ -167,7 +176,8 @@ def _validate_payload(json_payload: dict[str, Any], nonce: str, callback_body: C
|
|
|
167
176
|
# Check the iss claim is valid
|
|
168
177
|
if json_payload['iss'] != callback_body.iss:
|
|
169
178
|
raise RelyingPartyClientSdkException(
|
|
170
|
-
f'iss claim in token response "{json_payload["iss"]}" does not match
|
|
179
|
+
f'iss claim in token response "{json_payload["iss"]}" does not match '
|
|
180
|
+
f'the expected value of "{callback_body.iss}"')
|
|
171
181
|
|
|
172
182
|
# Extract aud claim from either list or string
|
|
173
183
|
if isinstance(json_payload['aud'], list):
|
|
@@ -207,7 +217,8 @@ def _validate_header(json_header, jwks, allowed_algs, id_token: str) -> None:
|
|
|
207
217
|
|
|
208
218
|
if jwk is None:
|
|
209
219
|
raise RelyingPartyClientSdkException(
|
|
210
|
-
f"kid provided does not match any key in the jwks for specified algorithm in
|
|
220
|
+
f"kid provided does not match any key in the jwks for specified algorithm in "
|
|
221
|
+
f"token header: {json_header['alg']}")
|
|
211
222
|
|
|
212
223
|
found_alg = any(alg.lower() == json_header['alg'].lower() for alg in allowed_algs)
|
|
213
224
|
if not found_alg:
|
|
@@ -243,12 +254,9 @@ def _get_jwks_json(issuer_metadata: IssuerMetadata, x_fapi_interaction_id: str)
|
|
|
243
254
|
response = requests.get(issuer_metadata.jwks_uri, headers=headers)
|
|
244
255
|
response.raise_for_status()
|
|
245
256
|
|
|
246
|
-
if not
|
|
257
|
+
if not response.ok:
|
|
247
258
|
raise RelyingPartyClientSdkException(
|
|
248
|
-
f"Response code for JWKS to {issuer_metadata.jwks_uri} not successful, was: {response.status_code},
|
|
259
|
+
f"Response code for JWKS to {issuer_metadata.jwks_uri} not successful, was: {response.status_code}, "
|
|
260
|
+
f"x-fapi-interaction-id: {x_fapi_interaction_id}, response body: {response.text}")
|
|
249
261
|
|
|
250
262
|
return response.json()
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
def _is_success(response: requests.Response):
|
|
254
|
-
return 200 <= response.status_code < 300
|
|
@@ -125,13 +125,21 @@ class IssuerMetadata(JSONWizard):
|
|
|
125
125
|
mtls_endpoint_aliases: MtlsEndpointAliases
|
|
126
126
|
|
|
127
127
|
def get_preferred_token_endpoint(self) -> str:
|
|
128
|
-
return self.mtls_endpoint_aliases.token_endpoint
|
|
128
|
+
return self.mtls_endpoint_aliases.token_endpoint \
|
|
129
|
+
if self.mtls_endpoint_aliases.token_endpoint \
|
|
130
|
+
else self.token_endpoint
|
|
129
131
|
|
|
130
132
|
def get_preferred_pushed_authorization_request_endpoint(self) -> str:
|
|
131
|
-
return self.mtls_endpoint_aliases.pushed_authorization_request_endpoint
|
|
133
|
+
return self.mtls_endpoint_aliases.pushed_authorization_request_endpoint \
|
|
134
|
+
if self.mtls_endpoint_aliases.pushed_authorization_request_endpoint \
|
|
135
|
+
else self.pushed_authorization_request_endpoint
|
|
132
136
|
|
|
133
137
|
def get_preferred_authorization_endpoint(self) -> str:
|
|
134
|
-
return self.mtls_endpoint_aliases.authorization_endpoint
|
|
138
|
+
return self.mtls_endpoint_aliases.authorization_endpoint \
|
|
139
|
+
if self.mtls_endpoint_aliases.authorization_endpoint \
|
|
140
|
+
else self.authorization_endpoint
|
|
135
141
|
|
|
136
142
|
def get_preferred_userinfo_endpoint(self) -> str:
|
|
137
|
-
return self.mtls_endpoint_aliases.userinfo_endpoint
|
|
143
|
+
return self.mtls_endpoint_aliases.userinfo_endpoint \
|
|
144
|
+
if self.mtls_endpoint_aliases.userinfo_endpoint\
|
|
145
|
+
else self.userinfo_endpoint
|
|
@@ -30,10 +30,12 @@ class CustomConfig:
|
|
|
30
30
|
else:
|
|
31
31
|
if self.required_claims:
|
|
32
32
|
logger.info(
|
|
33
|
-
f"Identity provider list will be filtered for participants
|
|
33
|
+
f"Identity provider list will be filtered for participants "
|
|
34
|
+
f"that support the following claims: {self.required_claims}")
|
|
34
35
|
if self.required_participant_certifications:
|
|
35
36
|
logger.info(
|
|
36
|
-
f"Identity provider list will be filtered for participants
|
|
37
|
+
f"Identity provider list will be filtered for participants "
|
|
38
|
+
f"that support the following certifications: {self.required_participant_certifications}")
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
@dataclass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rp_python_sdk-0.6.0 → rp_python_sdk-0.7.0}/rp_python_sdk/relying_party_client_sdk_exception.py
RENAMED
|
File without changes
|
|
File without changes
|