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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rp_python_sdk
3
- Version: 0.6.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.6.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, config.custom_config.required_claims)
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, config.custom_config.required_participant_certifications)
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
 
@@ -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) > 50:
131
- raise RelyingPartyClientSdkException("Purpose must be between 3 and 50 characters")
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 in authorization server well-known ({issuer_metadata.issuer})")
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} - {authorisation_server.customer_friendly_name}, x-fapi-interaction-id: {x_fapi_interaction_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}, state {original_state}, x-fapi-interaction-id: {x_fapi_interaction_id}")
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}, x-fapi-interaction-id: {x_fapi_interaction_id}, txn: {token_set.claims['txn']}")
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 the expected value of "{callback_body.iss}"')
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 token header: {json_header['alg']}")
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 _is_success(response):
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}, x-fapi-interaction-id: {x_fapi_interaction_id}, response body: {response.text}")
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 if self.mtls_endpoint_aliases.token_endpoint else self.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 if self.mtls_endpoint_aliases.pushed_authorization_request_endpoint else self.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 if self.mtls_endpoint_aliases.authorization_endpoint else self.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 if self.mtls_endpoint_aliases.userinfo_endpoint else self.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 that support the following claims: {self.required_claims}")
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 that support the following certifications: {self.required_participant_certifications}")
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