Skip to content

nanosdk.auth

Ready-made httpx.Auth implementations. Pass one as auth= to any client.

from nanosdk.auth import Bearer

api = Api("https://api.example.com", auth=Bearer(token))

They work with both Client and AsyncClient: httpx drives the same flow either way. Any other httpx.Auth (or a (user, password) tuple for basic auth) works as auth= too.

Classes:

Name Description
Bearer

Send Authorization: Bearer <token> with every request.

ApiKey

Send a static API key as a header or a query parameter.

OAuth2ClientCredentials

OAuth 2 client-credentials grant (RFC 6749 §4.4), for machine-to-machine APIs.

Bearer

Bearer(token: str | Callable[[], str])

Bases: Auth

Send Authorization: Bearer <token> with every request.

Example
Bearer("s3cr3t")
Bearer(lambda: vault.read("api-token"))  # read fresh for every request

Parameters:

Name Type Description Default
token str | Callable[[], str]

The token, or a function returning it that's called for each request (for rotating credentials).

required

Methods:

Name Description
auth_flow

Add the header (called by httpx for each request).

auth_flow

auth_flow(request: Request) -> Generator[Request, Response]

Add the header (called by httpx for each request).

ApiKey

ApiKey(
    name: str,
    value: str,
    *,
    location: Literal["header", "query"] = "header"
)

Bases: Auth

Send a static API key as a header or a query parameter.

Example
ApiKey("X-Api-Key", key)                    # X-Api-Key: <key>
ApiKey("api_key", key, location="query")    # ?api_key=<key>

Prefer a header when the API allows it: httpx logs request URLs (including the query string) at INFO on the httpx logger, so a query-string key can end up in your logs. nanosdk's own logs never include it.

Parameters:

Name Type Description Default
name str

The header or query-parameter name.

required
value str

The key.

required
location Literal['header', 'query']

Send it as a "header" or a "query" parameter.

'header'

Methods:

Name Description
auth_flow

Add the key (called by httpx for each request).

auth_flow

auth_flow(request: Request) -> Generator[Request, Response]

Add the key (called by httpx for each request).

OAuth2ClientCredentials

OAuth2ClientCredentials(
    token_url: str | URL,
    client_id: str,
    client_secret: str,
    *,
    scope: str | None = None,
    extra: Mapping[str, str] | None = None,
    credentials_in: Literal["header", "body"] = "header",
    leeway: float = 30.0,
    clock: Callable[[], float] = monotonic
)

Bases: Auth

OAuth 2 client-credentials grant (RFC 6749 §4.4), for machine-to-machine APIs.

Fetches a token on first use and caches it until leeway seconds before it expires. If the API answers 401 anyway (a revoked token, say), it fetches a new token and retries the request once. A failed token request raises APIStatusError.

Example
auth = OAuth2ClientCredentials(
    "https://auth.example.com/oauth/token", client_id, client_secret, scope="read"
)
api = Api("https://api.example.com", auth=auth)

One instance can be shared by several clients; concurrent requests that find the token expired may each fetch a new one.

Parameters:

Name Type Description Default
token_url str | URL

Absolute URL of the token endpoint. Token requests don't go through the client's base_url.

required
client_id str

The client ID.

required
client_secret str

The client secret.

required
scope str | None

Space-separated scopes to request.

None
extra Mapping[str, str] | None

Extra form fields for the token request (for example audience).

None
credentials_in Literal['header', 'body']

Send the credentials as HTTP basic auth ("header", the RFC's recommendation) or as form fields ("body").

'header'
leeway float

Refresh this many seconds before the token's expires_in runs out.

30.0
clock Callable[[], float]

Monotonic clock in seconds; replace it in tests.

monotonic

Raises:

Type Description
ValueError

If token_url isn't absolute.

Methods:

Name Description
auth_flow

Fetch or reuse a token, send the request, and refresh once on a 401.

auth_flow

auth_flow(request: Request) -> Generator[Request, Response]

Fetch or reuse a token, send the request, and refresh once on a 401.

Raises:

Type Description
APIStatusError

If the token endpoint rejects the credentials or answers without an access_token.