Authorization for the HTTP client
English | Русский
The library adds an IAM access token to outgoing HTTP requests. It obtains the token using a key identifier and secret key, then caches and refreshes it automatically. Calling code does not need to manage token lifetime or retries.
Use it when a service requires Authorization: Bearer <token> and IAM issues the token. Works both directly with httpx and with the HTTP client.
Installation
Requires Python 3.13 or later.
pip install cloudru-qa-http-client-auth
Import the library as the http_client_auth module.
Skills for AI agents
The package includes the http-client-auth-usage skill
with examples and usage rules for AI agents. Install the library
in your project environment, then run this from its root (requires uv):
uvx library-skills install --skill http-client-auth-usage --yes
For Claude Code, add --claude. The instructions are shipped with the library version.
Quick start
Synchronous client
import httpx
from http_client import HttpClient, options
from http_client_auth import IAM_Auth, IAM_HttpClient
iam_client = IAM_HttpClient("https://iam.example.com")
auth = IAM_Auth("your_key_id", "your_key_secret", iam_client)
# Directly with httpx
response = httpx.get("https://api.example.com/data", auth=auth)
# With http-client
client = HttpClient("https://api.example.com", options.with_auth(auth))
response = client.get("/data")
Asynchronous client
import httpx
from http_client import AsyncHttpClient, options
from http_client_auth import IAM_AsyncAuth, IAM_AsyncHttpClient
iam_client = IAM_AsyncHttpClient("https://iam.example.com")
auth = IAM_AsyncAuth("your_key_id", "your_key_secret", iam_client)
# Directly with httpx
async with httpx.AsyncClient(auth=auth) as client:
response = await client.get("https://api.example.com/data")
# With http-client
client = AsyncHttpClient("https://api.example.com", options.with_auth(auth))
response = await client.get("/data")
OpenID authorization
Use a different IAM client; everything else stays the same:
from http_client_auth import IAM_Auth, IAM_OpenID_HttpClient
iam_client = IAM_OpenID_HttpClient("https://iam.example.com")
auth = IAM_Auth("your_key_id", "your_key_secret", iam_client)
Closing clients
The IAM client owns its connection pool and must be closed by the caller; IAM_Auth does not own it:
with IAM_HttpClient("https://iam.example.com") as iam_client:
auth = IAM_Auth("your_key_id", "your_key_secret", iam_client)
with HttpClient("https://api.example.com", options.with_auth(auth)) as client:
response = client.get("/data")
For a long-lived client, call close(); for an asynchronous client, use await aclose().
Custom token store
By default, tokens are stored in process memory. To reuse them across processes, implement AuthStore:
import json
from datetime import datetime
from http_client_auth import AuthStore, IAM_Auth, IAM_HttpClient, Token
class RedisAuthStore(AuthStore):
def __init__(self, redis_client):
self._redis = redis_client
def get(self, key: str) -> Token | None:
raw = self._redis.get(f"token_for:{key}")
if raw is None:
return None
data = json.loads(raw)
return Token(data["access_token"], datetime.fromisoformat(data["expires_at"]))
def set(self, key: str, token: Token) -> None:
self._redis.set(
f"token_for:{key}",
json.dumps(
{
"access_token": token.access_token,
"expires_at": token.expires_at.isoformat(),
}
),
)
iam_client = IAM_HttpClient("https://iam.example.com")
auth = IAM_Auth("your_key_id", "your_key_secret", iam_client, store=RedisAuthStore(redis_client))
IAM_AsyncAuth accepts AsyncAuthStore, the same interface with asynchronous get and set:
from http_client_auth import AsyncAuthStore, Token
class RedisAsyncAuthStore(AsyncAuthStore):
def __init__(self, redis_client):
self._redis = redis_client
async def get(self, key: str) -> Token | None: ...
async def set(self, key: str, token: Token) -> None: ...
Logging
If you add logging to the IAM client, pass IAM_SANITIZE_KEYS. Otherwise the OpenID request's secret key and the response JWT appear in full in logs: http-client's default masking list does not cover them.
import logging
from http_client import options
from http_client_auth import IAM_SANITIZE_KEYS, IAM_OpenID_HttpClient
iam_client = IAM_OpenID_HttpClient(
"https://iam.example.com",
options.with_logger(logging.getLogger("iam"), sanitize_keys=IAM_SANITIZE_KEYS),
)
Components
Authorization:
| Class | Purpose |
|---|---|
IAM_Auth |
authorization for synchronous requests; implements httpx.Auth |
IAM_AsyncAuth |
the same for asynchronous requests |
IAM clients are passed to the authorization object as the first argument after the keys:
| Class | Purpose |
|---|---|
IAM_HttpClient |
public IAM API |
IAM_AsyncHttpClient |
public IAM API, asynchronous |
IAM_OpenID_HttpClient |
API OpenID |
IAM_OpenID_AsyncHttpClient |
OpenID API, asynchronous |
Token stores:
| Class | Purpose |
|---|---|
AuthStore |
synchronous store interface |
AsyncAuthStore |
asynchronous store interface |
InMemoryAuthStore |
in-memory store, default for IAM_Auth |
InMemoryAsyncAuthStore |
in-memory store, default for IAM_AsyncAuth |
Token |
access token and its expiry time |
Other:
| Name | Purpose |
|---|---|
AuthData |
IAM response: access token, lifetime, id_token |
IAM_SANITIZE_KEYS |
IAM secret keys for options.with_logger(sanitize_keys=...) |
Exceptions:
| Class | Raised when |
|---|---|
IAM_Error |
base class for all authorization errors |
IAM_AuthError |
IAM service returned an unsuccessful status code |
IAM_InvalidJsonResponseError |
IAM response could not be parsed |
Development
The library is developed in the qa-libraries monorepo
alongside the other cloudru-qa-* libraries. You need uv, GNU Make,
and checkmake.
Run commands from the repository root:
make sync # install dependencies for all libraries from uv.lock
make test-http-client-auth # tests for this library
make typecheck-http-client-auth # mypy for this library
make check # formatting, ruff, mypy, and tests for the entire workspace
Tests run on Python 3.13 and 3.14. Create a separate environment for another version:
make sync test-http-client-auth PYTHON_VERSION=3.14.
Publish a release with the git tag http-client-auth/v<version>. The tag version must match
the version in packages/http-client-auth/pyproject.toml.
Metadata
Release files for cloudru-qa-http-client-auth 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cloudru_qa_http_client_auth-1.0.0.tar.gz | 22.9 kB | With provenance | Details for cloudru_qa_http_client_auth-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cloudru_qa_http_client_auth-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for cloudru_qa_http_client_auth-1.0.0-py3-none-any.whl |
Total release size: 43.6 kB
Release files / cloudru_qa_http_client_auth-1.0.0.tar.gz
| Download URL | cloudru_qa_http_client_auth-1.0.0.tar.gz |
|---|---|
| Size | 22.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
29ccc713d7b2a8833e3e3bc91e0eaefcba992e1458033ab636c56621f0aa0b87
|
|
BLAKE2b-256 checksum How to use checksums |
df201362d513dcd190325f442e793b3579a2eacf88c01c91afdc712b77d102fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logRelease files / cloudru_qa_http_client_auth-1.0.0-py3-none-any.whl
| Download URL | cloudru_qa_http_client_auth-1.0.0-py3-none-any.whl |
|---|---|
| Size | 20.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9f1f688ea08b12292efb4d97f8779ccf75b414008e642323ccdb70508e3b6853
|
|
BLAKE2b-256 checksum How to use checksums |
629f0f6c674319e7e619a8cbaf8d7a52482a9d13b4a2a279a4a1bdf8c29e0688
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logSecurity for cloudru-qa-http-client-auth 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for cloudru_qa_http_client_auth-1.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.