kinde-python-sdk 1.2.7__py3-none-any.whl → 1.2.8__py3-none-any.whl
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.
- {kinde_python_sdk-1.2.7.dist-info → kinde_python_sdk-1.2.8.dist-info}/METADATA +1 -1
- {kinde_python_sdk-1.2.7.dist-info → kinde_python_sdk-1.2.8.dist-info}/RECORD +7 -7
- {kinde_python_sdk-1.2.7.dist-info → kinde_python_sdk-1.2.8.dist-info}/WHEEL +1 -1
- kinde_sdk/kinde_api_client.py +159 -0
- kinde_sdk/test/test_kinde_api_client.py +86 -0
- {kinde_python_sdk-1.2.7.dist-info → kinde_python_sdk-1.2.8.dist-info}/LICENSE +0 -0
- {kinde_python_sdk-1.2.7.dist-info → kinde_python_sdk-1.2.8.dist-info}/top_level.txt +0 -0
|
@@ -2,7 +2,7 @@ kinde_sdk/__init__.py,sha256=cBbmyFIDIH3kIYStgbhPnRJgsfe1EGa9_kLnimT4m7k,726
|
|
|
2
2
|
kinde_sdk/api_client.py,sha256=ofpdNwrQxXPFlv5KRisoPOXDta9K_Eg_IbD2hwLjAE8,58495
|
|
3
3
|
kinde_sdk/configuration.py,sha256=oqZGvKEf4kNNURbI1pip2ZVVcDyRTSmmnjXWziH4s80,15765
|
|
4
4
|
kinde_sdk/exceptions.py,sha256=1rFuvc5vj6ZjnT_m1yd_vCyFROfV_4ytcmFrj3rg1jw,4736
|
|
5
|
-
kinde_sdk/kinde_api_client.py,sha256=
|
|
5
|
+
kinde_sdk/kinde_api_client.py,sha256=G5jZLahs3GqFFza5c-JnrXkBiwXFIaBWMUN5v6rH1gc,19160
|
|
6
6
|
kinde_sdk/rest.py,sha256=HKfSGwlWNMRgB8wrT0u__2K-ZNFSSmAyBBFLH-dCilM,10552
|
|
7
7
|
kinde_sdk/schemas.py,sha256=PC7NB7JscfXesOxq2TyddRb_3N2gqSZGUjsCKP3_7RU,97655
|
|
8
8
|
kinde_sdk/apis/__init__.py,sha256=RTosXhMn41tMsKPUjIy-VK-_efOWzhkKiuGggJ3A6E0,214
|
|
@@ -509,7 +509,7 @@ kinde_sdk/paths/oauth2_v2_user_profile/__init__.py,sha256=O-78h6bM2O__SxkzxirG-q
|
|
|
509
509
|
kinde_sdk/paths/oauth2_v2_user_profile/get.py,sha256=XDLPbzx2q_CkZ4Da5LJXGZBAySPxRrAoIYyilwedplA,8381
|
|
510
510
|
kinde_sdk/paths/oauth2_v2_user_profile/get.pyi,sha256=aFY0cUUoAko2Gai-WIj4awMxCrHSjCMepztWdxwpdIA,8205
|
|
511
511
|
kinde_sdk/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
512
|
-
kinde_sdk/test/test_kinde_api_client.py,sha256=
|
|
512
|
+
kinde_sdk/test/test_kinde_api_client.py,sha256=Tp-akbRcKcMMoCWWiSrXIwafC-aM-HdM-OhOFWjRuto,12764
|
|
513
513
|
kinde_sdk/test/test_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
514
514
|
kinde_sdk/test/test_models/test_add_organization_users_response.py,sha256=OxtCMFQ7WirbzdeBL0VXXcIBkrv_RXdr2jrbuhivzxU,1017
|
|
515
515
|
kinde_sdk/test/test_models/test_api.py,sha256=5w0EcvDwo1tWfZ00TVNnyV79tW7z22H0DNfq6Rbswg8,517
|
|
@@ -582,8 +582,8 @@ kinde_sdk/test/test_models/test_user_profile_v2.py,sha256=QltYLnrMdUUM_rw6Fg5Nyw
|
|
|
582
582
|
kinde_sdk/test/test_models/test_users.py,sha256=IGWziLNMAJbamUqoQxvcQKKd5G1D5Gp1sns9fdhxLt4,526
|
|
583
583
|
kinde_sdk/test/test_models/test_users_response.py,sha256=ZHgkFH98bHU1JLIGh7R7MU4XfEqPY3QnkRiHZ2eLqmg,858
|
|
584
584
|
kinde_sdk/test/test_models/test_webhook.py,sha256=9iZ6FjNBEA-rPbO1Deq0qonOkVp-ANoxFt0__O8COqg,533
|
|
585
|
-
kinde_python_sdk-1.2.
|
|
586
|
-
kinde_python_sdk-1.2.
|
|
587
|
-
kinde_python_sdk-1.2.
|
|
588
|
-
kinde_python_sdk-1.2.
|
|
589
|
-
kinde_python_sdk-1.2.
|
|
585
|
+
kinde_python_sdk-1.2.8.dist-info/LICENSE,sha256=iT6AIO6NJn_mo0kDD5mpz2zp9GpzH6YdhqOmkCBg-kQ,1385
|
|
586
|
+
kinde_python_sdk-1.2.8.dist-info/METADATA,sha256=btNLaoqmgB2q-4M_mgeBriTd8v91h-37vt31BJiKde0,1961
|
|
587
|
+
kinde_python_sdk-1.2.8.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
588
|
+
kinde_python_sdk-1.2.8.dist-info/top_level.txt,sha256=Tx4AaXvRSme43PIec8zPL_lCo02AWIRBG8JADU0GedQ,10
|
|
589
|
+
kinde_python_sdk-1.2.8.dist-info/RECORD,,
|
kinde_sdk/kinde_api_client.py
CHANGED
|
@@ -133,6 +133,12 @@ class KindeApiClient(ApiClient):
|
|
|
133
133
|
self._refresh_token()
|
|
134
134
|
return True
|
|
135
135
|
return False
|
|
136
|
+
|
|
137
|
+
def is_authenticated_token(self, token_value: dict) -> dict:
|
|
138
|
+
if token_value:
|
|
139
|
+
if token_value.is_expired():
|
|
140
|
+
return self._refresh_token_value(token_value)
|
|
141
|
+
return None
|
|
136
142
|
|
|
137
143
|
def create_org(self) -> str:
|
|
138
144
|
return f"{self.registration_url}&is_create_org=true"
|
|
@@ -145,23 +151,50 @@ class KindeApiClient(ApiClient):
|
|
|
145
151
|
self._decode_token_if_needed(token_name)
|
|
146
152
|
value = self.__decoded_tokens[token_name].get(key)
|
|
147
153
|
return {"name": key, "value": value}
|
|
154
|
+
|
|
155
|
+
def get_claim_token(self, token_value: dict, key: str, token_name: str = "access_token") -> Any:
|
|
156
|
+
if token_name not in self.TOKEN_NAMES:
|
|
157
|
+
raise KindeTokenException(
|
|
158
|
+
f"Please use only tokens from the list: {self.TOKEN_NAMES}"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
decoded_tokens = self._decode_token_if_needed_value(token_name,token_value)
|
|
162
|
+
value = decoded_tokens[token_name].get(key)
|
|
163
|
+
return {"name": key, "value": value}
|
|
148
164
|
|
|
149
165
|
def get_permission(self, permission: str) -> Dict[str, Any]:
|
|
150
166
|
return {
|
|
151
167
|
"org_code": self.get_claim("org_code")["value"],
|
|
152
168
|
"is_granted": permission in self.get_claim("permissions")["value"],
|
|
153
169
|
}
|
|
170
|
+
|
|
171
|
+
def get_permission_token(self, token_value: dict, permission: str) -> Dict[str, Any]:
|
|
172
|
+
return {
|
|
173
|
+
"org_code": self.get_claim_token(token_value, "org_code")["value"],
|
|
174
|
+
"is_granted": permission in self.get_claim_token(token_value, "permissions")["value"],
|
|
175
|
+
}
|
|
154
176
|
|
|
155
177
|
def get_permissions(self) -> Dict[str, Any]:
|
|
156
178
|
return {
|
|
157
179
|
"org_code": self.get_claim("org_code")["value"],
|
|
158
180
|
"permissions": self.get_claim("permissions")["value"],
|
|
159
181
|
}
|
|
182
|
+
|
|
183
|
+
def get_permissions_token(self, token_value: dict) -> Dict[str, Any]:
|
|
184
|
+
return {
|
|
185
|
+
"org_code": self.get_claim_token(token_value, "org_code")["value"],
|
|
186
|
+
"permissions": self.get_claim_token(token_value, "permissions")["value"],
|
|
187
|
+
}
|
|
160
188
|
|
|
161
189
|
def get_organization(self) -> Dict[str, str]:
|
|
162
190
|
return {
|
|
163
191
|
"org_code": self.get_claim("org_code")["value"],
|
|
164
192
|
}
|
|
193
|
+
|
|
194
|
+
def get_organization_token(self, token_value: dict) -> Dict[str, str]:
|
|
195
|
+
return {
|
|
196
|
+
"org_code": self.get_claim_token(token_value, "org_code")["value"],
|
|
197
|
+
}
|
|
165
198
|
|
|
166
199
|
def get_user_details(self) -> Dict[str, str]:
|
|
167
200
|
return {
|
|
@@ -171,11 +204,25 @@ class KindeApiClient(ApiClient):
|
|
|
171
204
|
"email": self.get_claim("email", "id_token")["value"],
|
|
172
205
|
"picture": self.get_claim("picture", "id_token")["value"],
|
|
173
206
|
}
|
|
207
|
+
|
|
208
|
+
def get_user_details_token(self,token_value: dict) -> Dict[str, str]:
|
|
209
|
+
return {
|
|
210
|
+
"id": self.get_claim_token(token_value, "sub","id_token")["value"],
|
|
211
|
+
"given_name": self.get_claim_token(token_value, "given_name", "id_token")["value"],
|
|
212
|
+
"family_name": self.get_claim_token(token_value, "family_name", "id_token")["value"],
|
|
213
|
+
"email": self.get_claim_token(token_value, "email", "id_token")["value"],
|
|
214
|
+
"picture": self.get_claim_token(token_value, "picture", "id_token")["value"],
|
|
215
|
+
}
|
|
174
216
|
|
|
175
217
|
def get_user_organizations(self) -> Dict[str, List[str]]:
|
|
176
218
|
return {
|
|
177
219
|
"org_codes": self.get_claim("org_codes", "id_token")["value"],
|
|
178
220
|
}
|
|
221
|
+
|
|
222
|
+
def get_user_organizations_token(self, token_value: dict) -> Dict[str, List[str]]:
|
|
223
|
+
return {
|
|
224
|
+
"org_codes": self.get_claim_token(token_value, "org_codes", "id_token")["value"],
|
|
225
|
+
}
|
|
179
226
|
|
|
180
227
|
def get_flag(
|
|
181
228
|
self, code: str, default_value: Any = None, flag_type: str = ""
|
|
@@ -205,15 +252,53 @@ class KindeApiClient(ApiClient):
|
|
|
205
252
|
result_flag["type"] = FlagType[flag_type].value
|
|
206
253
|
|
|
207
254
|
return result_flag
|
|
255
|
+
|
|
256
|
+
def get_flag_token(
|
|
257
|
+
self, token_value: dict, code: str, default_value: Any = None, flag_type: str = ""
|
|
258
|
+
) -> Any:
|
|
259
|
+
flags = self.get_claim_token(token_value, "feature_flags")["value"] or {}
|
|
260
|
+
flag = {}
|
|
261
|
+
|
|
262
|
+
if code not in list(flags.keys()):
|
|
263
|
+
if default_value is None:
|
|
264
|
+
raise KindeRetrieveException(
|
|
265
|
+
f"Flag {code} was not found, and no default value has been provided"
|
|
266
|
+
)
|
|
267
|
+
else:
|
|
268
|
+
flag = flags[code]
|
|
269
|
+
if flag_type and flag.get("t") and flag_type != flag.get("t"):
|
|
270
|
+
raise KindeRetrieveException(
|
|
271
|
+
f"Flag {code} is of type {FlagType[flag.get('t')].value} - requested type {FlagType[flag_type].value}"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
result_flag = {
|
|
275
|
+
"code": code,
|
|
276
|
+
"value": flag.get("v") if flag else default_value,
|
|
277
|
+
"is_default": not bool(flag),
|
|
278
|
+
}
|
|
279
|
+
flag_type = flag["t"] if flag else flag_type
|
|
280
|
+
if flag_type:
|
|
281
|
+
result_flag["type"] = FlagType[flag_type].value
|
|
282
|
+
|
|
283
|
+
return result_flag
|
|
208
284
|
|
|
209
285
|
def get_boolean_flag(self, code: str, default_value: Any = None) -> bool:
|
|
210
286
|
return self.get_flag(code, default_value, "b")["value"]
|
|
287
|
+
|
|
288
|
+
def get_boolean_flag_token(self, token_value: dict, code: str, default_value: Any = None) -> bool:
|
|
289
|
+
return self.get_flag_token(token_value, code, default_value, "b")["value"]
|
|
211
290
|
|
|
212
291
|
def get_string_flag(self, code: str, default_value: Any = None) -> str:
|
|
213
292
|
return self.get_flag(code, default_value, "s")["value"]
|
|
293
|
+
|
|
294
|
+
def get_string_flag_token(self, token_value: dict, code: str, default_value: Any = None) -> str:
|
|
295
|
+
return self.get_flag_token(token_value, code, default_value, "s")["value"]
|
|
214
296
|
|
|
215
297
|
def get_integer_flag(self, code: str, default_value: Any = None) -> int:
|
|
216
298
|
return self.get_flag(code, default_value, "i")["value"]
|
|
299
|
+
|
|
300
|
+
def get_integer_flag_token(self, token_value: dict, code: str, default_value: Any = None) -> int:
|
|
301
|
+
return self.get_flag_token(token_value, code, default_value, "i")["value"]
|
|
217
302
|
|
|
218
303
|
def call_api(self, *args, **kwargs) -> Any:
|
|
219
304
|
self._get_or_refresh_access_token()
|
|
@@ -248,6 +333,34 @@ class KindeApiClient(ApiClient):
|
|
|
248
333
|
self.__decoded_tokens[token_name] = jwt.decode(**decode_token_params)
|
|
249
334
|
else:
|
|
250
335
|
raise KindeTokenException(f"Token {token_name} doesn't exist.")
|
|
336
|
+
|
|
337
|
+
def _decode_token_if_needed_value(self, token_name: str, token_value: dict) -> dict:
|
|
338
|
+
if token_name not in token_value:
|
|
339
|
+
if not token_value:
|
|
340
|
+
raise KindeTokenException(
|
|
341
|
+
"Access token doesn't exist.\n"
|
|
342
|
+
"When grant_type is CLIENT_CREDENTIALS use fetch_token().\n"
|
|
343
|
+
'For other grant_type use "get_login_url()" or "get_register_url()".'
|
|
344
|
+
)
|
|
345
|
+
token = token_value.get(token_name)
|
|
346
|
+
|
|
347
|
+
signing_key = self.jwks_client.get_signing_key_from_jwt(token)
|
|
348
|
+
|
|
349
|
+
if token:
|
|
350
|
+
decode_token_params = {
|
|
351
|
+
"jwt":token,
|
|
352
|
+
"key": signing_key.key,
|
|
353
|
+
"algorithms":["RS256"],
|
|
354
|
+
"options":{
|
|
355
|
+
"verify_signature": True,
|
|
356
|
+
"verify_exp": True,
|
|
357
|
+
"verify_aud": False
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return jwt.decode(**decode_token_params)
|
|
361
|
+
else:
|
|
362
|
+
raise KindeTokenException(f"Token {token_name} doesn't exist.")
|
|
363
|
+
return token_value
|
|
251
364
|
|
|
252
365
|
def fetch_token(self, authorization_response: Optional[str] = None) -> None:
|
|
253
366
|
if self.grant_type == GrantType.CLIENT_CREDENTIALS:
|
|
@@ -274,6 +387,31 @@ class KindeApiClient(ApiClient):
|
|
|
274
387
|
self.configuration.access_token = self.__access_token_obj.get("access_token")
|
|
275
388
|
self._clear_decoded_tokens()
|
|
276
389
|
|
|
390
|
+
def fetch_token_value(self, authorization_response: Optional[str] = None) -> dict:
|
|
391
|
+
if self.grant_type == GrantType.CLIENT_CREDENTIALS:
|
|
392
|
+
params = {"grant_type": "client_credentials"}
|
|
393
|
+
if self.audience:
|
|
394
|
+
params["audience"] = self.audience
|
|
395
|
+
else:
|
|
396
|
+
if authorization_response is None:
|
|
397
|
+
raise KindeConfigurationException(
|
|
398
|
+
'"authorization_response" parameter is required when grant_type is different than CLIENT_CREDENTIALS.'
|
|
399
|
+
)
|
|
400
|
+
params = {"authorization_response": authorization_response}
|
|
401
|
+
if self.grant_type == GrantType.AUTHORIZATION_CODE_WITH_PKCE:
|
|
402
|
+
params["code_verifier"] = self.code_verifier
|
|
403
|
+
|
|
404
|
+
access_token_obj = self.client.fetch_token(
|
|
405
|
+
self.token_endpoint,
|
|
406
|
+
headers={
|
|
407
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
408
|
+
"Kinde-SDK": "/".join(("Python", kinde_sdk_version)),
|
|
409
|
+
},
|
|
410
|
+
**params,
|
|
411
|
+
)
|
|
412
|
+
return access_token_obj
|
|
413
|
+
|
|
414
|
+
|
|
277
415
|
def _get_or_refresh_access_token(self) -> None:
|
|
278
416
|
if self.grant_type == GrantType.CLIENT_CREDENTIALS:
|
|
279
417
|
if not self.__access_token_obj or self.__access_token_obj.is_expired():
|
|
@@ -309,6 +447,27 @@ class KindeApiClient(ApiClient):
|
|
|
309
447
|
self._clear_decoded_tokens()
|
|
310
448
|
else:
|
|
311
449
|
raise KindeTokenException('"Access token" and "Refresh token" are invalid.')
|
|
450
|
+
|
|
451
|
+
def _refresh_token_value(self, token_value: dict) -> dict:
|
|
452
|
+
refresh_token = token_value.get("refresh_token")
|
|
453
|
+
|
|
454
|
+
if refresh_token:
|
|
455
|
+
token_value = self.client.refresh_token(
|
|
456
|
+
self.token_endpoint,
|
|
457
|
+
headers={
|
|
458
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
459
|
+
"Kinde-SDK": "/".join(("Python", kinde_sdk_version)),
|
|
460
|
+
},
|
|
461
|
+
refresh_token=refresh_token,
|
|
462
|
+
)
|
|
463
|
+
if not token_value:
|
|
464
|
+
raise KindeTokenException(
|
|
465
|
+
'"Access token" and "Refresh token" are invalid.'
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
return token_value
|
|
469
|
+
else:
|
|
470
|
+
raise KindeTokenException('"Access token" and "Refresh token" are invalid.')
|
|
312
471
|
|
|
313
472
|
def _add_additional_params(self, url: str, additional_params: Optional[Dict[str, str]] = None) -> str:
|
|
314
473
|
|
|
@@ -98,6 +98,12 @@ class TestKindeApiClient(unittest.TestCase):
|
|
|
98
98
|
client.fetch_token(authorization_response="https://example.com/callback?code=test_code")
|
|
99
99
|
self.mock_oauth2_session.return_value.fetch_token.assert_called_once()
|
|
100
100
|
|
|
101
|
+
def test_fetch_token_authorization_code_token(self):
|
|
102
|
+
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
103
|
+
self.mock_oauth2_session.return_value.fetch_token.return_value = {"access_token": "test_token"}
|
|
104
|
+
token_value = client.fetch_token_value(authorization_response="https://example.com/callback?code=test_code")
|
|
105
|
+
self.mock_oauth2_session.return_value.fetch_token.assert_called_once()
|
|
106
|
+
|
|
101
107
|
@patch('kinde_sdk.kinde_api_client.ApiClient.call_api')
|
|
102
108
|
def test_super_call_api_with_correct_args(self, mock_super_call_api):
|
|
103
109
|
client = self._create_kinde_client(GrantType.CLIENT_CREDENTIALS)
|
|
@@ -142,6 +148,86 @@ class TestKindeApiClient(unittest.TestCase):
|
|
|
142
148
|
mock_get_claim.assert_any_call("permissions")
|
|
143
149
|
self.assertEqual(mock_get_claim.call_count, 2)
|
|
144
150
|
|
|
151
|
+
def test_get_permissions_token(self):
|
|
152
|
+
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
153
|
+
|
|
154
|
+
result = client.get_permissions_token({"access_token":{"org_code":"org123","permissions": ["read", "write", "delete"]}})
|
|
155
|
+
|
|
156
|
+
expected_result = {
|
|
157
|
+
"org_code": "org123",
|
|
158
|
+
"permissions": ["read", "write", "delete"]
|
|
159
|
+
}
|
|
160
|
+
self.assertEqual(result, expected_result)
|
|
161
|
+
|
|
162
|
+
def test_get_permission_token(self):
|
|
163
|
+
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
164
|
+
|
|
165
|
+
result = client.get_permission_token({"access_token":{"org_code":"org123","permissions": ["read", "write", "delete"]}},"read")
|
|
166
|
+
|
|
167
|
+
expected_result = {
|
|
168
|
+
"org_code": "org123",
|
|
169
|
+
"is_granted": True
|
|
170
|
+
}
|
|
171
|
+
self.assertEqual(result, expected_result)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def test_get_claim_token(self):
|
|
175
|
+
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
176
|
+
|
|
177
|
+
result = client.get_claim_token({"access_token":{"org_code":"org123","permissions": ["read", "write", "delete"]}},"org_code")
|
|
178
|
+
|
|
179
|
+
expected_result = {
|
|
180
|
+
"name": "org_code",
|
|
181
|
+
"value": "org123"
|
|
182
|
+
}
|
|
183
|
+
self.assertEqual(result, expected_result)
|
|
184
|
+
|
|
185
|
+
def test_get_user_details_token(self):
|
|
186
|
+
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
187
|
+
|
|
188
|
+
result = client.get_user_details_token({
|
|
189
|
+
"access_token":{"org_code":"org123","permissions": ["read", "write", "delete"]}
|
|
190
|
+
,"id_token":{"sub":"123","given_name":"John","family_name":"Doe","email":"john@example.com","picture":"https://example.com/pic.jpg"}
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
expected_result = {
|
|
194
|
+
"id":"123","given_name":"John","family_name":"Doe","email":"john@example.com","picture":"https://example.com/pic.jpg"
|
|
195
|
+
}
|
|
196
|
+
self.assertEqual(result, expected_result)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def test_get_flag_token(self):
|
|
200
|
+
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
201
|
+
|
|
202
|
+
result = client.get_flag_token({
|
|
203
|
+
"access_token":{"org_code":"org123","permissions": ["read", "write", "delete"],"feature_flags":{"test_flag":{"v":True,"t":"b"}}}
|
|
204
|
+
,"id_token":{"sub":"123","given_name":"John","family_name":"Doe","email":"john@example.com","picture":"https://example.com/pic.jpg"}
|
|
205
|
+
},
|
|
206
|
+
"test_flag"
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
expected_result = {
|
|
210
|
+
"code":"test_flag",
|
|
211
|
+
"value":True,
|
|
212
|
+
"is_default":False,
|
|
213
|
+
"type":"boolean"
|
|
214
|
+
}
|
|
215
|
+
self.assertEqual(result, expected_result)
|
|
216
|
+
|
|
217
|
+
def test_get_boolean_flag_token(self):
|
|
218
|
+
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
219
|
+
|
|
220
|
+
result = client.get_boolean_flag_token({
|
|
221
|
+
"access_token":{"org_code":"org123","permissions": ["read", "write", "delete"],"feature_flags":{"test_flag":{"v":True,"t":"b"}}}
|
|
222
|
+
,"id_token":{"sub":"123","given_name":"John","family_name":"Doe","email":"john@example.com","picture":"https://example.com/pic.jpg"}
|
|
223
|
+
},
|
|
224
|
+
"test_flag"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
expected_result = True
|
|
228
|
+
self.assertEqual(result, expected_result)
|
|
229
|
+
|
|
230
|
+
|
|
145
231
|
def test_fetch_token_headers_with_authorization_code(self):
|
|
146
232
|
client = self._create_kinde_client(GrantType.AUTHORIZATION_CODE)
|
|
147
233
|
self.mock_oauth2_session.return_value.fetch_token.return_value = {"access_token": "test_token"}
|
|
File without changes
|
|
File without changes
|