Estado
Implementado e verificado localmente. A verificação de ida e voltacom um IdP real (busca de JWKS, assinatura/verificação de tokencontra uma instância XID ativa) ainda não foi realizada e deve serconcluída antes do uso em produção.
Status do registry: UNPUBLISHED. Instale este SDK somente a partir do checkout do código-fonte do repositório; não use um registry de pacotes externo.
A autenticação de requisições aceita somente Bearer por padrão. Um cookie JWT pertencente ao aplicativo só é lido quando seu nome exato é configurado. O cookie opaco do Core __Host-xid.rt.* nunca é pesquisado nem verificado localmente; troque-o encaminhando o header Cookie completo para o POST /v1/sessions/token da mesma origem exata, com redirects desativados, e aceite somente uma resposta que contenha apenas o campo token.
Instalar
pip install "xid @ git+https://github.com/StringKe/xid#subdirectory=sdk/python"Início rápido
Construa um XidClient na inicialização e reutilize-o. Ocliente faz cache do JWKS internamente.
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 (Bearer-only by default)
status = await client.authenticate_request(headers=dict(request.headers))
if not status.authenticated:
raise Unauthorized()
user_id = status.claims.sub
# Explicit same-origin Core session -> JWT exchange
token = await client.exchange_session_token(
incoming_request_url="https://app.example.com/account",
cookie_header=request.headers["cookie"],
)Verifica 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))Integração com FastAPI
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}Opções do XidClient
| Parâmetro | Padrão | Descrição |
|---|---|---|
issuer |
obrigatório | URL do emissor XID |
audience |
None |
Claim aud esperado; None ignora a validação |
jwks_ttl |
3600 |
TTL do cache em memória do JWKS em segundos |
http_timeout |
10.0 |
Timeout de busca do JWKS em segundos |
cookie_name |
disabled |
Nome do cookie JWT pertencente ao aplicativo; desativado salvo configuração explícita |
leeway |
0 |
Tolerância de desvio de relógio em segundos |
API principal
| Método | Descrição |
|---|---|
await client.verify_token(token) |
Verifica string JWT; lança TokenVerificationError em caso defalha. |
await client.authenticate_request(headers, cookies) |
Extrai e verifica o token de headers/cookies. RetornaAuthStatus; não lança exceções. |
client.verify_webhook(payload, headers, secret) |
Síncrono. Valida HMAC-SHA256 svix + janela de replay de 5 minutos.Lança WebhookVerificationError em caso de falha. |
await client.aclose() |
Libera os recursos do cliente HTTP subjacente. |
Notas da plataforma
- Prioridade assíncrona. Chamadores síncronos (Django/Flask) podemenvolver com
asyncio.run(). - Depende de
pyjwt[crypto] >=2.8ehttpx >=0.27. Python3.10+ obrigatório. - Implantações com múltiplos workers não compartilham cache JWKS entreprocessos. Um cache compartilhado (Redis) é uma melhoria planejada.