Skip to main content

tfrs-auth (Python)

PyPI License: MIT

TFRS AccessToken 客户端工具包:把「PAT / client_credentials → 短 RS256 JWT 换发 (RFC 8693)+ 缓存/刷新」与「Claims/scope 契约 + 纯验签」抽成可复用包,避免每个 MCP 工具 / SDK 重复实现 token 获取与生命周期管理。

下游集成只涉及两个角色:主叫方(换发并携带 token)与被叫方(验签收到的 token)。

SoT = TFRSManager Contract Registry。本包 contract.py 为镜像,变更先改 Manager。 强制执行层(验签中间件/Socket.IO/ESO/默认拒绝 CI)不在本包,留 TFRobotServer。

安装

已发布至 PyPI:https://pypi.org/project/tfrs-auth/(MIT 许可证)。

# 从 PyPI(推荐)
uv add tfrs-auth                  # 核心:契约 + 纯验签(仅依赖 pyjwt[crypto])
uv add "tfrs-auth[httpx]"         # 含客户端 token source / JWKS live 拉取
# 或:pip install "tfrs-auth[httpx]"

# 或从 git + tag(未发布版本)
uv add "tfrs-auth[httpx] @ git+https://cnb.cool/turingfocus/foundation/tfrs-foundation-py@<tag>#subdirectory=packages/tfrs-auth"
  • 核心(契约 + verify.from_jwks 纯验签):只需 pyjwt[crypto],无 httpx 也可 import。
  • 可选 extra httpx:换发 token(token source)或 JwtVerifier.from_url live 拉取 JWKS 时才需要。

用法

主叫方 —— 换发并携带 token(client_credentials,S5 A2A 主叫端)

from tfrs_auth import AsyncCachingTokenSource, ClientCredentials

cred = ClientCredentials.for_robot(
    client_id=machine_client_id,          # 机器人自身 Account.ID
    client_secret=machine_client_secret,  # tfp_ 明文(machineClientSecret)
    callee_robot_id=callee_id,            # → aud=robot:<calleeId>
    scope=["a2a:invoke"],                 # 省略则不带 scope
)
async with AsyncCachingTokenSource(
    cred, token_url="https://<user-host>/api/v1/oauth/token"
) as source:
    token = await source.token()          # 缓存 + 临期自动刷新 + single-flight + 429/503 退避
    headers = {"Authorization": f"{token.token_type} {token.access_token}"}
  • source 长期持有、复用(它本身就是缓存);不要每个请求新建一个。.token() 幂等: 缓存未临期直接返回,临期了自动换发,并发只放一个换发在途、其余等待后命中缓存。
  • 同步场景用 CachingTokenSource(线程锁做 single-flight,API 与 async 版对称)。
  • 想复用既有 httpx client:传 http_client=...;token source 只关闭自己创建的 client。

被叫方 —— 验签收到的 token(资源服务器侧)

from tfrs_auth import JwtVerifier

# 线上:从 JWKS URL 构造(拉取 + 按 kid 缓存带 TTL + 未知-kid 限速刷新)
verifier = JwtVerifier.from_url(
    "https://<user-host>/.well-known/jwks.json",
    issuer="https://<user-host>",         # 强烈建议传
    audience=f"robot:{my_robot_id}",      # 强烈建议传:受众隔离
)
claims = verifier.verify(access_token)    # 成功返回 Claims;失败抛 TokenVerificationError
assert claims.has_scope("a2a:invoke")

离线/测试零网络:JwtVerifier.from_jwks(jwks_dict, issuer=..., audience=...)verifier 同样长期复用(内含 JWKS 缓存);单次想覆盖受众用 verifier.verify(tok, audience="robot:123")

⚠️ 资源服务器务必传 issueraudience:二者仅在提供时才校验。不传 audience 会放行签给任意机器人的 token,丧失 aud=robot:<id> 受众隔离(issuer 之于颁发者 隔离同理)。from_url 的未知-kid 刷新已内置限速(min_refresh_interval,默认 10s), 避免被构造的随机-kid token 放大成对 JWKS 端点的 DoS。

错误处理(带类型,绝不字符串匹配)

from tfrs_auth import (
    TokenExchangeError,      # 换发失败基类;.retryable 标识 429/503
    TokenVerificationError,  # 验签失败(过期 / 签名错 / aud·iss 不符)
    TransportError,          # JWKS / 换发的网络层失败
    TemporarilyUnavailableError, InvalidClientError, InvalidScopeError,  # 细分子类
)

# 主叫方:退避已内置,兜住自动重试后仍失败的情况
try:
    token = await source.token()
except TokenExchangeError as e:
    ...  # e.retryable 区分 429/503 等瞬时失败

# 被叫方:网络失败与验签失败应同时兜住
try:
    claims = verifier.verify(access_token)
except (TokenVerificationError, TransportError):
    ...  # → 401

速查表

你要做的事 用什么
主叫端换发 token(async / sync) AsyncCachingTokenSource / CachingTokenSource + ClientCredentials.for_robot(...)
取 token await source.token()Token(.access_token, .token_type, .expires_at, .is_expired())
被叫端验签(线上) JwtVerifier.from_url(jwks_url, issuer=, audience=)
被叫端验签(离线/测试) JwtVerifier.from_jwks(jwks, issuer=, audience=)
拿契约常量/工具 from tfrs_auth import ACTIVE_SCOPES, robot_audience, scopes_to_str, Scope

模块

模块 内容
contract Scope(8 active + 2 reserved) · Claims · GrantType/SubjectTokenType URN · OAuthErrorCode · JWKS/kid 形状
errors 异常树(InvalidClientError(401) / InvalidTargetError / TemporarilyUnavailableError(503) …)+ from_oauth_error
client Token · TokenSource/AsyncTokenSource · CachingTokenSource / AsyncCachingTokenSource(single-flight + 退避)
credentials ClientCredentials · PatCredential(✅)· UserJwtCredential(✅)
verify JwtVerifier(RS256 + JWKS)
transport BearerAuth / AsyncBearerAuth(httpx auth,✅)

边界与状态

  • 已实现contract / errors / client(sync+async caching) / credentials.ClientCredentials / credentials.PatCredential / credentials.UserJwtCredential / verify / transport.BearerAuth(+ AsyncBearerAuth)。
  • 无骨架:三层 + transport 全部已实现。transport 为 opt-in(from tfrs_auth.transport import,需 tfrs-auth[httpx];不进包根 __all__,保 httpx-optional)。

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tfrs_auth-0.2.0.tar.gz (30.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tfrs_auth-0.2.0-py3-none-any.whl (27.6 kB view details)

Uploaded Python 3

File details

Details for the file tfrs_auth-0.2.0.tar.gz.

File metadata

  • Download URL: tfrs_auth-0.2.0.tar.gz
  • Upload date:
  • Size: 30.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tfrs_auth-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c9870920141728b174588539cee995f4748c06cad984ca8c6e44acf71323c5f2
MD5 7ba8806adbdc0644598d389cd21288c9
BLAKE2b-256 8bc0b6d22bf60a196fbe2918a4d44f9ca984524160025e3b468ef6133974e88d

See more details on using hashes here.

File details

Details for the file tfrs_auth-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: tfrs_auth-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 27.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for tfrs_auth-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 896903477cfa31f66ff37d3255b5ac42bd3163d5b3778278e8459b7234a94fc2
MD5 38585b0ef71060c279be680c88e90a91
BLAKE2b-256 45af1b725ccf5d8887fc0554ed47c064fbf797881d05bf5f99195e0125758552

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page