Skip to content

sdk/python

Async Python server SDK for networkless JWT verification, request authentication, and webhook signature validation.

Status

Implemented and verified locally. Real IdP round-trip verification (JWKS fetch, token sign/verify against a live XID instance) has not been performed yet and must be completed before production use.

Install

pip install xid

Quick start

Construct one XidClient at startup and reuse it. The client caches JWKS internally.

from xid import XidClient

client = XidClient(
    issuer="https://xid.dev",
    audience="https://api.yourapp.com",  # optional
)

# Verify a token
claims = await client.verify_token("eyJ...")
print(claims.sub, claims.email, claims.scope)

# Authenticate a request
status = await client.authenticate_request(
    headers=dict(request.headers),
    cookies=dict(request.cookies),
)
if not status.authenticated:
    raise Unauthorized()
user_id = status.claims.sub

Verify webhook

from xid import WebhookVerificationError

try:
    webhook = client.verify_webhook(
        payload=request.body,
        headers=dict(request.headers),
        secret="whsec_xxx",
    )
    import json
    event = json.loads(webhook.body)
except WebhookVerificationError as exc:
    raise BadRequest(str(exc))

FastAPI integration

from fastapi import FastAPI, Depends, HTTPException, Request
from xid import XidClient, TokenClaims

app = FastAPI()
xid = XidClient(issuer="https://xid.dev")

@app.on_event("shutdown")
async def shutdown():
    await xid.aclose()

async def require_auth(request: Request) -> TokenClaims:
    status = await xid.authenticate_request(dict(request.headers))
    if not status.authenticated:
        raise HTTPException(status_code=401)
    return status.claims

@app.get("/me")
async def me(claims: TokenClaims = Depends(require_auth)):
    return {"sub": claims.sub, "email": claims.email}

XidClient options

Parameter Default Description
issuer required XID issuer URL
audience None Expected aud claim; None skips validation
jwks_ttl 3600 JWKS in-memory cache TTL in seconds
http_timeout 10.0 JWKS fetch timeout in seconds
cookie_name __session Cookie key for session token extraction
leeway 0 Clock skew tolerance in seconds

Core API

Method Description
await client.verify_token(token) Verify JWT string; raises TokenVerificationError on failure.
await client.authenticate_request(headers, cookies) Extract and verify token from headers/cookies. Returns AuthStatus; does not raise.
client.verify_webhook(payload, headers, secret) Synchronous. Validates svix HMAC-SHA256 + 5-minute replay window. Raises WebhookVerificationError on failure.
await client.aclose() Release underlying HTTP client resources.

Platform notes

  • Async-first. Sync callers (Django/Flask) can wrap with asyncio.run().
  • Depends on pyjwt[crypto] >=2.8 and httpx >=0.27. Python 3.10+ required.
  • Multi-worker deployments share no JWKS cache across processes. A shared cache (Redis) is a planned improvement.
Navigation

Type to search...

Use arrow keys to navigateEnter to selectEscape to close