poelis-sdk 0.1.2__py3-none-any.whl → 0.1.3__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.

Potentially problematic release.


This version of poelis-sdk might be problematic. Click here for more details.

poelis_sdk/_transport.py CHANGED
@@ -6,6 +6,7 @@ import random
6
6
  import httpx
7
7
 
8
8
  from .exceptions import ClientError, HTTPError, NotFoundError, RateLimitError, ServerError, UnauthorizedError
9
+ from .auth0 import Auth0TokenManager
9
10
 
10
11
  """HTTP transport abstraction for the Poelis SDK.
11
12
 
@@ -28,8 +29,8 @@ class Transport:
28
29
 
29
30
  Args:
30
31
  base_url: Base API URL.
31
- token: Bearer token for Authorization header.
32
- org_id: Optional organization id for tenant scoping.
32
+ api_key: API key for Auth0 authentication.
33
+ org_id: Organization id for tenant scoping.
33
34
  timeout_seconds: Request timeout in seconds.
34
35
  """
35
36
 
@@ -37,13 +38,18 @@ class Transport:
37
38
  self._api_key = api_key
38
39
  self._org_id = org_id
39
40
  self._timeout = timeout_seconds
41
+
42
+ # Initialize Auth0 token manager
43
+ self._auth0_manager = Auth0TokenManager(api_key, org_id, base_url)
40
44
 
41
45
  def _headers(self, extra: Optional[Mapping[str, str]] = None) -> Dict[str, str]:
42
46
  headers: Dict[str, str] = {
43
47
  "Accept": "application/json",
44
48
  "Content-Type": "application/json",
45
49
  }
46
- headers["Authorization"] = f"ApiKey {self._api_key}"
50
+ # Get fresh JWT token from Auth0
51
+ token = self._auth0_manager.get_token()
52
+ headers["Authorization"] = f"Bearer {token}"
47
53
  headers["X-Poelis-Org"] = self._org_id
48
54
  if extra:
49
55
  headers.update(dict(extra))
poelis_sdk/auth0.py ADDED
@@ -0,0 +1,85 @@
1
+ """Auth0 Client Credentials flow for SDK authentication.
2
+
3
+ This module handles automatic JWT token acquisition using Auth0 Client Credentials
4
+ flow when users provide API keys. The API key serves as the client_id, and we
5
+ derive the client_secret and audience from the API key format.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import time
11
+ from typing import Optional
12
+
13
+ import httpx
14
+
15
+
16
+ class Auth0TokenManager:
17
+ """Manages Auth0 JWT tokens using Client Credentials flow.
18
+
19
+ Automatically acquires and refreshes tokens based on API keys.
20
+ """
21
+
22
+ def __init__(self, api_key: str, org_id: str, base_url: str) -> None:
23
+ """Initialize token manager.
24
+
25
+ Args:
26
+ api_key: API key from webapp (used as client_id)
27
+ org_id: Organization ID for audience
28
+ base_url: Base URL to derive Auth0 domain and audience
29
+ """
30
+ self.api_key = api_key
31
+ self.org_id = org_id
32
+ self.base_url = base_url
33
+
34
+ # Extract Auth0 domain from API key format
35
+ # Format: poelis_live_org_dev_<client_id>_<secret>
36
+ parts = api_key.split('_')
37
+ if len(parts) >= 4 and parts[0] == 'poelis' and parts[1] == 'live':
38
+ self.client_id = parts[3] # Extract client_id from API key
39
+ self.client_secret = '_'.join(parts[4:]) # Rest is secret
40
+ else:
41
+ raise ValueError("Invalid API key format. Expected: poelis_live_org_dev_<client_id>_<secret>")
42
+
43
+ # Derive Auth0 domain and audience
44
+ self.auth0_domain = "poelis-prod.eu.auth0.com"
45
+ self.audience = base_url
46
+
47
+ self._token: Optional[str] = None
48
+ self._expires_at: float = 0
49
+
50
+ def get_token(self) -> str:
51
+ """Get valid JWT token, refreshing if needed.
52
+
53
+ Returns:
54
+ str: JWT token for Authorization header
55
+ """
56
+ if self._token and time.time() < self._expires_at - 60: # Refresh 1min early
57
+ return self._token
58
+
59
+ return self._refresh_token()
60
+
61
+ def _refresh_token(self) -> str:
62
+ """Acquire new JWT token from Auth0.
63
+
64
+ Returns:
65
+ str: Fresh JWT token
66
+ """
67
+ token_url = f"https://{self.auth0_domain}/oauth/token"
68
+
69
+ data = {
70
+ "client_id": self.client_id,
71
+ "client_secret": self.client_secret,
72
+ "audience": self.audience,
73
+ "grant_type": "client_credentials"
74
+ }
75
+
76
+ with httpx.Client() as client:
77
+ response = client.post(token_url, data=data)
78
+ response.raise_for_status()
79
+
80
+ token_data = response.json()
81
+ self._token = token_data["access_token"]
82
+ expires_in = token_data.get("expires_in", 3600)
83
+ self._expires_at = time.time() + expires_in
84
+
85
+ return self._token
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: poelis-sdk
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Official Python SDK for Poelis
5
5
  Project-URL: Homepage, https://poelis.ai
6
6
  Project-URL: Source, https://github.com/PoelisTechnologies/poelis-python-sdk
@@ -1,5 +1,6 @@
1
1
  poelis_sdk/__init__.py,sha256=QzPuy0lsmF0JEOrcnHDWsUfR_WCO1XpegwrYpSGyUVI,738
2
- poelis_sdk/_transport.py,sha256=0yLpcMbZB7KUmBBG3epwbGi2NwOqt0dwMBYh-Y8o6Pc,5830
2
+ poelis_sdk/_transport.py,sha256=F5EX0EJFHJPAE638nKzlX5zLSU6FIMzMemqgh05_V6U,6061
3
+ poelis_sdk/auth0.py,sha256=mNa7QvNR9dWS39jpUE9GYfgkbBF-A7shvLqzQAeH28U,2879
3
4
  poelis_sdk/browser.py,sha256=zyMoNqFCvKZDV4ZSFVk2N1-HHiq80gzmkGN3uRo1CuM,12409
4
5
  poelis_sdk/client.py,sha256=Sr05go8eNpEXswWAhomQuSakE5Oai_kUsGDwHgPnnLY,3731
5
6
  poelis_sdk/exceptions.py,sha256=qX5kpAr8ozJUOW-CNhmspWVIE-bvUZT_PUnimYuBxNY,1101
@@ -11,7 +12,7 @@ poelis_sdk/workspaces.py,sha256=LNVt73nqdssNx42_YB_V5Qp35kEdFn9rNBYmEjpM7vk,1518
11
12
  poelis_sdk/.github/workflows/sdk-ci.yml,sha256=hWO-igHeTAsxEJGCueteEQnAEi00GWXJJPa8DWgqhHM,750
12
13
  poelis_sdk/.github/workflows/sdk-docs.yml,sha256=bS1uUxOKRMA6TWrmzzJHTokyP0Nt0aJwojcLAgLoEhs,1166
13
14
  poelis_sdk/.github/workflows/sdk-publish-testpypi.yml,sha256=FBZcfDrtUijs6rcC8WeIimi9SfgoB8Xm5pTNtcztT44,776
14
- poelis_sdk-0.1.2.dist-info/METADATA,sha256=jGVzZZFVynSO28j2FE02st7UekeGOZEGRxaJP08zu3U,3280
15
- poelis_sdk-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- poelis_sdk-0.1.2.dist-info/licenses/LICENSE,sha256=EEmE_r8wk_pdXB8CWp1LG6sBOl7--hNSS2kV94cI6co,1075
17
- poelis_sdk-0.1.2.dist-info/RECORD,,
15
+ poelis_sdk-0.1.3.dist-info/METADATA,sha256=Z69IrLD4-Bb8oC1cYZF0frbl8IT-uvthky8fY7NIEdI,3280
16
+ poelis_sdk-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
+ poelis_sdk-0.1.3.dist-info/licenses/LICENSE,sha256=EEmE_r8wk_pdXB8CWp1LG6sBOl7--hNSS2kV94cI6co,1075
18
+ poelis_sdk-0.1.3.dist-info/RECORD,,