ApiClient creates a new httpx.AsyncClient per JWKS / OIDC fetch with no timeout and no single-flight, causing "Unknown auth error" storms under load
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- python
調査の方向性
src/auth0_api_python/utils.py から始め、ApiClient._fetch_jwks と _fetch_oidc_metadata を utils.fetch_jwks、utils.fetch_oidc_metadata、InMemoryCache.get を通じて追跡します。verify_request がこれらのキャッシュミスの経路に到達する仕組みと、httpx.AsyncClient がどのように使われているかを確認します。JWKS と OIDC の再取得で、クライアント、タイムアウト、同時リクエストに関して報告されている失敗動作を回避しつつ、認証成功時のセマンティクスを変更しなければ完了です。
索引モデルが issue の本文から書いたものです。
説明
Checklist
- I have looked into the Readme and Examples, and have not found a suitable solution or answer.
- I have looked into the API documentation and have not found a suitable solution or answer.
- I have searched the issues and have not found a suitable solution or answer.
- I have searched the Auth0 Community forums and have not found a suitable solution or answer.
- I agree to the terms within the Auth0 Code of Conduct.
Description
ApiClient._fetch_jwks and _fetch_oidc_metadata (via
utils.fetch_jwks / utils.fetch_oidc_metadata) construct a brand-new
httpx.AsyncClient() on every cache miss with no explicit timeout
configured, and there is no single-flight protection around the
refetch path. Combined, these turn routine cache expiry into a
self-inflicted outage under any non-trivial concurrency.
Reproduction
- Stand up a FastAPI service that calls
ApiClient.verify_request
on every authenticated route. - Drive ≥ ~30 RPS of authenticated requests against it (we hit it
on a 4 vCPU ECS Fargate task during a k6 load test). - Wait for the in-memory JWKS cache to expire — by default Auth0
returnsCache-Control: max-age=600, so this happens every ~10
minutes under steady load. - Observe a sudden burst of
httpx.ConnectTimeoutchained out of
ApiClient._fetch_jwks, surfacing to callers as opaque "Unknown
auth error" 5xx responses on every authenticated route until the
herd subsides. Sentry trace shows
auth0_api_python.errors.UnknownAuth0Exception←
httpx.ConnectTimeout.
Additional context
In src/auth0_api_python/utils.py
async def fetch_jwks(jwks_uri, custom_fetch=None):
...
async with httpx.AsyncClient() as client: # 1
resp = await client.get(jwks_uri) # 2
...
- No connection pooling across calls. A fresh client is created
and torn down per fetch. Every cache miss = a fresh TCP + TLS
handshake tohttps://<tenant>.auth0.com/. Under load this
exhausts ephemeral source-port budget on the host and slows
everything else on the box. - No explicit timeout.
httpx.AsyncClient()with notimeout=
uses httpx's default 5-second connect/read/write/pool budget. On a
stressed event loop or a slow Auth0 region that 5s budget is
routinely blown, raisinghttpx.ConnectTimeout/
httpx.ReadTimeout. Those bubble up into_fetch_jwksand the
caller seesConnectTimeoutchained toUnknownAuth0Exception—
not a 401, not a 503, just an opaque "unknown auth error". - No single-flight on refetch. When the in-memory cache expires
(InMemoryCache.getreturnsNone), every concurrent request
that reaches_fetch_jwkssimultaneously fires its own outbound
JWKS fetch. N requests in flight at the moment of expiry = N
concurrent JWKS calls to Auth0. Auth0 throttles some of them, the
others time out per (1) and (2), and any request that lost the
race fails auth.
The same three problems apply verbatim to fetch_oidc_metadata and
_fetch_oidc_metadata.
auth0-api-python version
1.0.0b8
Python version
3.11
- 主要言語
- Python
- スター
- 4
- フォーク
- 9
- PR マージ指標
- 30日以内にマージされた PR はありません
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
auth0/auth0-api-python のほかの issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
auth0/auth0-api-python#92 · コメント 2 件 · リアクション 1 件 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
auth0/auth0-api-python#113 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 52/100
auth0/auth0-api-python#59 ·
auth0/auth0-api-python の issue をすべて見る
似ている issue
-
documentation help wanted
難易度 2/5 1〜3時間 初心者へのやさしさ 90/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 90/100
simonw/sqlite-utils#872 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100