-
Notifications
You must be signed in to change notification settings - Fork 5
feat(platform): support external token providers and simplify caching #513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
c2f0b1b
e9cf3aa
f74f48d
7e3fac5
f2296b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,89 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| """Authenticated API wrapper and configuration. | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| This module defines the thin API subclass and configuration that lift | ||||||||||||||||||||||||||||||||||||||||||||||
| ``token_provider`` to a first-class attribute. Kept separate from ``_client`` | ||||||||||||||||||||||||||||||||||||||||||||||
| so that resource modules can import these types directly without circular | ||||||||||||||||||||||||||||||||||||||||||||||
| dependencies. | ||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| from collections.abc import Callable | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| from aignx.codegen.api.public_api import PublicApi | ||||||||||||||||||||||||||||||||||||||||||||||
| from aignx.codegen.api_client import ApiClient | ||||||||||||||||||||||||||||||||||||||||||||||
| from aignx.codegen.configuration import AuthSettings, Configuration | ||||||||||||||||||||||||||||||||||||||||||||||
| from loguru import logger | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| class _OAuth2TokenProviderConfiguration(Configuration): | ||||||||||||||||||||||||||||||||||||||||||||||
| """Overwrites the original Configuration to call a function to obtain a bearer token. | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| The base class does not support callbacks. This is necessary for integrations where | ||||||||||||||||||||||||||||||||||||||||||||||
| access tokens may expire or need to be refreshed or rotated automatically. | ||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| def __init__( | ||||||||||||||||||||||||||||||||||||||||||||||
| self, host: str, ssl_ca_cert: str | None = None, token_provider: Callable[[], str] | None = None | ||||||||||||||||||||||||||||||||||||||||||||||
| ) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||
| super().__init__(host=host, ssl_ca_cert=ssl_ca_cert) | ||||||||||||||||||||||||||||||||||||||||||||||
| self.token_provider = token_provider | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| def auth_settings(self) -> AuthSettings: | ||||||||||||||||||||||||||||||||||||||||||||||
| token = self.token_provider() if self.token_provider else None | ||||||||||||||||||||||||||||||||||||||||||||||
| if not token: | ||||||||||||||||||||||||||||||||||||||||||||||
| if self.token_provider is not None: | ||||||||||||||||||||||||||||||||||||||||||||||
| logger.warning( | ||||||||||||||||||||||||||||||||||||||||||||||
| "token_provider returned an empty or None token; " | ||||||||||||||||||||||||||||||||||||||||||||||
| "request will proceed without an Authorization header" | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||
| return {} | ||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||
| "OAuth2AuthorizationCodeBearer": { | ||||||||||||||||||||||||||||||||||||||||||||||
| "type": "oauth2", | ||||||||||||||||||||||||||||||||||||||||||||||
| "in": "header", | ||||||||||||||||||||||||||||||||||||||||||||||
| "key": "Authorization", | ||||||||||||||||||||||||||||||||||||||||||||||
| "value": f"Bearer {token}", | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+39
to
+44
|
||||||||||||||||||||||||||||||||||||||||||||||
| return { | |
| "OAuth2AuthorizationCodeBearer": { | |
| "type": "oauth2", | |
| "in": "header", | |
| "key": "Authorization", | |
| "value": f"Bearer {token}", | |
| # Normalize token to avoid double 'Bearer ' prefixes if the provider | |
| # already returns a value starting with 'Bearer '. | |
| token_str = str(token).strip() | |
| bearer_value: str | |
| if token_str.lower().startswith("bearer "): | |
| bearer_value = token_str | |
| else: | |
| bearer_value = f"Bearer {token_str}" | |
| return { | |
| "OAuth2AuthorizationCodeBearer": { | |
| "type": "oauth2", | |
| "in": "header", | |
| "key": "Authorization", | |
| "value": bearer_value, |
Uh oh!
There was an error while loading. Please reload this page.