Skip to content

Commit c40920d

Browse files
authored
Merge pull request #40 from Authress/optimize-jwks
Optimize jwks
2 parents a9f4ec2 + 714285a commit c40920d

20 files changed

+24
-59
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ This is the changelog for [Authress SDK](readme.md).
33

44
## 3.1 ##
55
* [Breaking] Throw validation error on setting a property that doesn't exist in any of the Authress DTO Models.
6+
* Optimize JWKs fetching using the keyId
67

78
## 3.0 ##
89
* [Breaking] Added type checking everywhere - This means most models have breaking changes.

authress/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from authress.authress_client import AuthressClient
1010
from authress.http_client import HttpClient
1111
from authress.rest import ApiException
12+
from authress.utils.service_client_token_provider import ServiceClientTokenProvider
1213

1314
# import apis into sdk package
1415
from authress.api.access_records_api import AccessRecordsApi

authress/api/access_records_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
from authress.models.access_request_response import AccessRequestResponse
3838
from authress.models.claim_request import ClaimRequest
3939

40-
from authress.http_client import HttpClient
4140
from authress.api_response import ApiResponse
4241
from authress.exceptions import ( # noqa: F401
4342
ApiTypeError,
@@ -53,8 +52,6 @@ class AccessRecordsApi(object):
5352
"""
5453

5554
def __init__(self, api_client=None):
56-
if api_client is None:
57-
api_client = HttpClient.get_default()
5855
self.api_client = api_client
5956

6057
@validate_arguments

authress/api/accounts_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
from authress.models.identity_collection import IdentityCollection
3838
from authress.models.identity_request import IdentityRequest
3939

40-
from authress.http_client import HttpClient
4140
from authress.api_response import ApiResponse
4241
from authress.exceptions import ( # noqa: F401
4342
ApiTypeError,
@@ -53,8 +52,6 @@ class AccountsApi(object):
5352
"""
5453

5554
def __init__(self, api_client=None):
56-
if api_client is None:
57-
api_client = HttpClient.get_default()
5855
self.api_client = api_client
5956

6057
@validate_arguments

authress/api/applications_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
from authress.models.application_delegation import ApplicationDelegation
3232

33-
from authress.http_client import HttpClient
3433
from authress.api_response import ApiResponse
3534
from authress.exceptions import ( # noqa: F401
3635
ApiTypeError,
@@ -46,8 +45,6 @@ class ApplicationsApi(object):
4645
"""
4746

4847
def __init__(self, api_client=None):
49-
if api_client is None:
50-
api_client = HttpClient.get_default()
5148
self.api_client = api_client
5249

5350
@validate_arguments

authress/api/connections_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
from authress.models.connection_collection import ConnectionCollection
3333
from authress.models.user_connection_credentials import UserConnectionCredentials
3434

35-
from authress.http_client import HttpClient
3635
from authress.api_response import ApiResponse
3736
from authress.exceptions import ( # noqa: F401
3837
ApiTypeError,
@@ -48,8 +47,6 @@ class ConnectionsApi(object):
4847
"""
4948

5049
def __init__(self, api_client=None):
51-
if api_client is None:
52-
api_client = HttpClient.get_default()
5350
self.api_client = api_client
5451

5552
@validate_arguments

authress/api/extensions_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
from authress.models.o_auth_token_request import OAuthTokenRequest
3737
from authress.models.o_auth_token_response import OAuthTokenResponse
3838

39-
from authress.http_client import HttpClient
4039
from authress.api_response import ApiResponse
4140
from authress.exceptions import ( # noqa: F401
4241
ApiTypeError,
@@ -52,8 +51,6 @@ class ExtensionsApi(object):
5251
"""
5352

5453
def __init__(self, api_client=None):
55-
if api_client is None:
56-
api_client = HttpClient.get_default()
5754
self.api_client = api_client
5855

5956
@validate_arguments

authress/api/groups_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
from authress.models.group import Group
3434
from authress.models.group_collection import GroupCollection
3535

36-
from authress.http_client import HttpClient
3736
from authress.api_response import ApiResponse
3837
from authress.exceptions import ( # noqa: F401
3938
ApiTypeError,
@@ -49,8 +48,6 @@ class GroupsApi(object):
4948
"""
5049

5150
def __init__(self, api_client=None):
52-
if api_client is None:
53-
api_client = HttpClient.get_default()
5451
self.api_client = api_client
5552

5653
@validate_arguments

authress/api/invites_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
from authress.models.account import Account
3232
from authress.models.invite import Invite
3333

34-
from authress.http_client import HttpClient
3534
from authress.api_response import ApiResponse
3635
from authress.exceptions import ( # noqa: F401
3736
ApiTypeError,
@@ -47,8 +46,6 @@ class InvitesApi(object):
4746
"""
4847

4948
def __init__(self, api_client=None):
50-
if api_client is None:
51-
api_client = HttpClient.get_default()
5249
self.api_client = api_client
5350

5451
@validate_arguments

authress/api/resource_permissions_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
from authress.models.permissioned_resource_collection import PermissionedResourceCollection
3535
from authress.models.resource_users_collection import ResourceUsersCollection
3636

37-
from authress.http_client import HttpClient
3837
from authress.api_response import ApiResponse
3938
from authress.exceptions import ( # noqa: F401
4039
ApiTypeError,
@@ -50,8 +49,6 @@ class ResourcePermissionsApi(object):
5049
"""
5150

5251
def __init__(self, api_client=None):
53-
if api_client is None:
54-
api_client = HttpClient.get_default()
5552
self.api_client = api_client
5653

5754
@validate_arguments

authress/api/roles_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
from authress.models.role import Role
2929
from authress.models.role_collection import RoleCollection
3030

31-
from authress.http_client import HttpClient
3231
from authress.api_response import ApiResponse
3332
from authress.exceptions import ( # noqa: F401
3433
ApiTypeError,
@@ -44,8 +43,6 @@ class RolesApi(object):
4443
"""
4544

4645
def __init__(self, api_client=None) -> None:
47-
if api_client is None:
48-
api_client = HttpClient.get_default()
4946
self.api_client = api_client
5047

5148
@validate_arguments

authress/api/service_clients_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
from authress.models.client_access_key import ClientAccessKey
3535
from authress.models.client_collection import ClientCollection
3636

37-
from authress.http_client import HttpClient
3837
from authress.api_response import ApiResponse
3938
from authress.exceptions import ( # noqa: F401
4039
ApiTypeError,
@@ -50,8 +49,6 @@ class ServiceClientsApi(object):
5049
"""
5150

5251
def __init__(self, api_client=None):
53-
if api_client is None:
54-
api_client = HttpClient.get_default()
5552
self.api_client = api_client
5653

5754
@validate_arguments

authress/api/tenants_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
from authress.models.tenant_collection import TenantCollection
2828
from authress.models.tenant_user import TenantUser
2929

30-
from authress.http_client import HttpClient
3130
from authress.api_response import ApiResponse
3231
from authress.exceptions import ( # noqa: F401
3332
ApiTypeError,
@@ -43,8 +42,6 @@ class TenantsApi:
4342
"""
4443

4544
def __init__(self, api_client=None) -> None:
46-
if api_client is None:
47-
api_client = HttpClient.get_default()
4845
self.api_client = api_client
4946

5047
@validate_arguments

authress/api/token_verifier.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
from authress.utils import service_client_token_provider, PackageVersionProvider
1212

1313
class TokenVerifier(object):
14-
def __init__(self):
14+
def __init__(self, http_client=None):
15+
self.http_client = http_client
16+
if http_client is None:
17+
self.http_client = rest.RESTClientObject()
18+
1519
self.keyMap = dict()
1620
self.package_version_provider = PackageVersionProvider()
1721

@@ -72,14 +76,12 @@ def get_public_key(self, jwkKeyListUrl, kid):
7276
self.keyMap[hashKey] = self.get_key_uncached(jwkKeyListUrl, kid)
7377
return self.keyMap[hashKey]
7478

75-
def get_key_uncached(self, jwkKeyListUrl, kid):
76-
rest_client = rest.RESTClientObject()
77-
79+
def get_key_uncached(self, jwkKeyListUrl, kid):
7880
version = self.package_version_provider.get_version()
7981
headers = {
8082
'User-Agent': f'Authress SDK; Python; {version};'
8183
}
82-
result = rest_client.get_request(jwkKeyListUrl, headers=headers)
84+
result = self.http_client.request_with_retries('GET', jwkKeyListUrl, headers=headers)
8385

8486
for index, key in enumerate(json.loads(result.data)['keys']):
8587
if key['kid'] == kid:

authress/api/user_permissions_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
from authress.models.user_resources_collection import UserResourcesCollection
3535
from authress.models.user_role_collection import UserRoleCollection
3636

37-
from authress.http_client import HttpClient
3837
from authress.api_response import ApiResponse
3938
from authress.exceptions import ( # noqa: F401
4039
ApiTypeError,
@@ -50,8 +49,6 @@ class UserPermissionsApi(object):
5049
"""
5150

5251
def __init__(self, api_client=None):
53-
if api_client is None:
54-
api_client = HttpClient.get_default()
5552
self.api_client = api_client
5653

5754
@validate_arguments

authress/api/users_api.py

-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
from authress.models.user_identity import UserIdentity
3535
from authress.models.user_identity_collection import UserIdentityCollection
3636

37-
from authress.http_client import HttpClient
3837
from authress.api_response import ApiResponse
3938
from authress.exceptions import ( # noqa: F401
4039
ApiTypeError,
@@ -50,8 +49,6 @@ class UsersApi(object):
5049
"""
5150

5251
def __init__(self, api_client=None):
53-
if api_client is None:
54-
api_client = HttpClient.get_default()
5552
self.api_client = api_client
5653

5754
@validate_arguments

authress/authress_client.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
from authress.api import token_verifier
2424

2525
class AuthressClient(object):
26-
def __init__(self, authress_api_url=None, service_client_access_key=None):
26+
def __init__(self, authress_api_url=None, service_client_access_key=None, user_agent=None):
2727
self._host = authress_api_url if authress_api_url.startswith('http') else f"https://{authress_api_url}"
2828
self._host = re.sub(r'/+$', '', self._host)
29-
self._token_verifier = token_verifier.TokenVerifier()
30-
self._http_client = HttpClient(host=self._host, access_key=service_client_access_key)
29+
30+
self._http_client = HttpClient(host=self._host, access_key=service_client_access_key, user_agent=user_agent)
31+
self._token_verifier = token_verifier.TokenVerifier(http_client=self._http_client)
3132

3233
def set_token(self, token: str):
3334
self._http_client.set_token(token)

authress/http_client.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class HttpClient(object):
4848
}
4949
_pool = None
5050

51-
def __init__(self, host=None, access_key=None):
51+
def __init__(self, host=None, access_key=None, user_agent=None):
5252
self.host = host if host is not None and host.startswith('http') else f"https://{host}"
5353
self.access_key = access_key
5454
self.pool_threads = 1
@@ -60,7 +60,7 @@ def __init__(self, host=None, access_key=None):
6060
self.service_client_token_provider = service_client_token_provider.ServiceClientTokenProvider(self.access_key, self.host)
6161

6262
version = PackageVersionProvider().get_version()
63-
self.default_headers['User-Agent'] = f'Authress SDK; Python; {version};'
63+
self.default_headers['User-Agent'] = f'Authress SDK; Python; {version}; {user_agent or ""}'
6464

6565
def set_token(self, token):
6666
self.default_headers['Authorization'] = f'Bearer {token.replace("Bearer", "").strip()}'

test/test_service_client_token_provider.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from authress.models import *
77
from authress.utils import ServiceClientTokenProvider, JwtManager
88
from authress import AuthressClient
9-
from authress.http_client import HttpClient
109

1110
import unittest
1211
from unittest.mock import patch
@@ -27,10 +26,10 @@ def test_get_token(self):
2726

2827
access_key = 'eyJrZXlJZCI6ImNjYjFjZGJmLTM0NzYtNGNiNy05Njc1LTVlMzNmYjI5NTNjMyIsInByaXZhdGVLZXkiOiItLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cbk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRRFFidWFBd0V6VkJHZnZcbjBEL2JKSjRHa2JoV2oyRy9lYTF3UUZNeWxiK0ZzTDM1dGJvVHNIUGdvbUtGMDNNQkphWmRBVHhwcnhYa2xvYWNcblFhYkE4eXcyQ2lFbitHNjlMcUFnUVlLSmZzL1psWEo4MVJ0TkR0TkZRUTdPS0xpSGJrU1I1cFU3R0lKNENQZTZcbkxHM3UzUkVUbFFndmlhV2M2bzVOUkRMWTBIbzhya2w0Yk8rZjMycXg2SGV6dzBsUnZOK1I4L24vZUxLbCtGVlpcbk1yYzFkcmh5NDdtVU80ZnJKWW1LSzg2ZGZacVk4RVh2aGpjaFZzdHhSTXdtMlRDbUtWT2xsQWUrandmNTR5Q2NcbnUzcTNsRUxzcnhXTlRsVC9mRHBQQSt6MDh2MFdDa2ozdWo5SEh3REE1VjhZaUtJOEFheWRLSG9nYnA5eHp1amdcbnZwQmVacnRuQWdNQkFBRUNnZ0VBZnRpL0Z1UHcza0tNTG5vQ0lvK3FURDBxZmlOTVRZYnpjamp6YVBtUlVQODZcbjNsa21JUTFsdC9PYkdlNlJNc1dDOVY3bk1Ub0lqTkMrb3lHaEpoUFhlQnU2Q2VVN0g0N2NqRVRSK0hOZ2N2NXNcbmFtUVc5VkpzYU4wcThYUCt1UXoyVmdTS0ZTalpYY3UzVjJucWpVK2tNTktsNUtoVVRhYkJhMnh4dFZsS3l0bjlcbld6QnIzZExLVXBwYzdoZXFaa2diSHE2amZXd3h2Vk56cmhkNUZ1Tm5EeWI2R3QrUXhzYi83dmdhdnRsNmtXM0hcbnU5ZUtGcjJhdER4VHhaTDArRVIxWjVyV21MNzdUK3owQitYVkZJZ05ia2FlSURBZjEzRjBPSzE3YjJ4NmlSSjVcbnJCRTdCc0ZhMGVuOXBjSWN2UUxhbGFMREVOL1d2YWd4dnowSWZ4M1R3UUtCZ1FEbjVMSGhFczBzeWxYVUdrVlFcbmhFU1ZacGh5QzdFRHBZYm44UW5DNkI3ZDFtWkR1d1JuSkMyZXVxT1lNMFlVcWlGT3Q5RW9UMllNQy9jT2pUVTFcbndnMm9GQ0hqWUI4cGptNHVkb3B3MHRHcGRyb1piQVNkOHkzR1RuNitMK25tVGVzNjYxTGN6ekhSekhrTnh5OUJcbkNVNTRzWXhnK1M5bnhSTjdEVERxeTE2M1dRS0JnUURtR2Q1Snl4VnNyS3ZVSmFVbDM5ekZRcTh3cnpTZ0xZVVBcbjF0a1dHYWhIanFvRjYvSnM2YUZnZlYraXl5THk1dm03WEN0dUw2RGtEQW93NnVpS1NiRlhicnVCYW5GSDBnWktcbkRaVmVQcU9mbTVIYWJWalB1VmdPdW5HWHBOMnZ4QTdwNkg0SkMxOVkvUkg0MkY5bHE4aUtkejZXWHJYMjNPRHFcbjQrcHZtdzF3dndLQmdRQ0YyajlHNExobjR6OFptRFJzWG56TUZCVm90eER0UHUyWkVrd0ZJa0UyNFp2VCtxNTJcbjdxNGFramIrRXBLZ09QZlMzVTJ3eSt2bWhqMk1PN3Y4Rk5BWE5jKzkxRzBJYXJ0MHZGMzY4K1dyd09sNDVSM2hcbklrNUl5bVJrV1huVXd5TkZ0akgxWE8rdjN5djg1UDJFdDkrQTBWTnJZa3FYeG0wUk9UTUVSSEdldVFLQmdEZmdcbnNrMkRSc21rU1BuMHhsMGpOdTZrV2Z6ZG4wOENudHlRMVJqNzFCVEVmVitBdzlkVkNQNXdrOGZwd3F2d0VWZEJcbmM3NkhURy8weUlqR2t2LzZFMW5qSngrdlpLRUhUTVd3OU1QMVBERG5TNDBhbnNXYkFkcFp4bm9IN0ZuaHA2bC9cbjd4TnRNcE5lcVgyZnRkTHYyM3hjcHROSFhyTDdRcGRvRDZkWXBQUHJBb0dCQU5CN2QyME5kY1EzaTBmWGJ6dGhcbk1RUFIwK3NEVkViMUZjSUdXbDdPeXNvYy9UZ2prT3NhVDRTL2hXODg1RGR5ZnZHbjdpRmpyMDBPQVVyVjE5NlRcbmFwdDJNS0EvWVdWeG9Ud2kwZCs0UHZ5Mnk3SXBnMk9tcEE0bVliYnBXQ0NPS3dtczlEQ0E4MVVGeEJiMHdUbTdcbjlXVStVbGZMWDAvcGNkSFNEZkExbXVjZVxuLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLVxuIiwiYXVkaWVuY2UiOiIyMmJiYzUwMi0zYjdhLTRjNTQtOGE2ZS1jMDRhM2NhNGRmNWYuYWNjb3VudHMuYXV0aHJlc3MuaW8iLCJjbGllbnRJZCI6IjIzYjRiY2Q1LWMwYzEtNDYwMi05NGU1LThkYTgyNzNkMGRiMCJ9'
2928

30-
http_client = HttpClient("", access_key)
31-
token1 = http_client._get_client_token()
29+
service_client_token_provider = ServiceClientTokenProvider(access_key, "")
30+
token1 = service_client_token_provider.get_client_token()
3231
time.sleep(2)
33-
token2 = http_client._get_client_token()
32+
token2 = service_client_token_provider.get_client_token()
3433
assert token1 == token2
3534
pass
3635

@@ -42,10 +41,10 @@ def test_get_token_for_eddsa(self):
4241

4342
access_key = 'CLIENT.KEY.ACCOUNT.MC4CAQAwBQYDK2VwBCIEIIM7npIckfT431rYzEeF+hCqvHogpOllmVSgINwqQv+g'
4443

45-
http_client = HttpClient("", access_key)
46-
token1 = http_client._get_client_token()
44+
service_client_token_provider = ServiceClientTokenProvider(access_key, "")
45+
token1 = service_client_token_provider.get_client_token()
4746
time.sleep(2)
48-
token2 = http_client._get_client_token()
47+
token2 = service_client_token_provider.get_client_token()
4948
assert token1 == token2
5049
pass
5150

@@ -55,8 +54,8 @@ def test_get_token_without_access_key(self):
5554
Ignores access keys that are None
5655
"""
5756

58-
http_client = HttpClient("")
59-
token1 = http_client._get_client_token()
57+
service_client_token_provider = ServiceClientTokenProvider("")
58+
token1 = service_client_token_provider.get_client_token()
6059
assert token1 == None
6160
pass
6261

test/test_token_verifier.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_get_token_for_eddsa(self):
2929
token_verifier_instance.get_key_uncached = mock_get_key_uncached
3030
identity = token_verifier_instance.verify_token(authressCustomDomain=f"https://{customDomain}", token=access_key)
3131

32-
mock_get_key_uncached.assert_called_once_with(f"https://{customDomain}/v1/clients/CLIENT/.well-known/openid-configuration/jwks", "KEY")
32+
mock_get_key_uncached.assert_called_once_with(f"https://{customDomain}/v1/clients/CLIENT/.well-known/openid-configuration/jwks?kid=KEY", "KEY")
3333
assert identity['iss'] == f'https://{customDomain}/v1/clients/CLIENT'
3434
assert identity['sub'] == "CLIENT"
3535

0 commit comments

Comments
 (0)