Managed AgentsのvaultでOAuthリフレッシュ失敗の診断手順
Managed Agentsのvaultでmcp_oauth認証情報のリフレッシュが失敗したとき、webhookとmcp_oauth_validateでどこまで原因を切り分けられるかを、statusの3値ごとの対応とあわせて示します。
Managed Agentsのvaultに登録したmcp_oauthクレデンシャルは、アクセストークンが期限切れになると自動で再取得されます。このリフレッシュが失敗するとvault_credential.refresh_failedイベントが発行されますが、届くのは「失敗した」という通知だけです。原因の切り分けにはmcp_oauth_validateエンドポイントを呼び、返ってくるstatusの3値(valid / invalid / unknown)で対応を分けます。
リフレッシュ失敗から復旧までの流れ
- 1
webhookで失敗を知る
vault_credential.refresh_failedを購読しておくと、失敗の時点で通知が届きます。 - 2
イベントのIDからクレデンシャルを取得する
webhookが運ぶのは
typeとidだけなので、詳細はGETで取りに行きます。 - 3
mcp_oauth_validateでstatusを見る
valid/invalid/unknownのどれかが返ります。 - 4
statusに応じて動く
invalidなら再認可かクレデンシャルの作り直し、unknownなら待って再試行します。
refresh_failedのwebhookで何が分かるか
vaultに登録したクレデンシャルは、セッション実行中もvaultのライフサイクル全体でも定期的に再解決されます。この仕組みのおかげで、クレデンシャルのローテーション・アーカイブ・削除がセッションを再起動せずに反映されます。mcp_oauthクレデンシャルの場合、再解決のタイミングでアクセストークンの有効期限も確認され、切れていればリフレッシュが試みられます。
失敗の通知を受け取るには、vaultとcredentialのwebhookを購読します。登録先はClaude Consoleの「Manage > Webhooks」で、エンドポイントはポート443のHTTPSで公開ホスト名を持つ必要があります。作成時にwhsec_で始まる署名シークレットが一度だけ表示されます。配信にはwebhook-id / webhook-timestamp / webhook-signatureのヘッダーが付き、SDKのunwrap()で署名検証とパースを一度に行えます。
購読できるイベントはvault.archived / vault.deleted / vault_credential.archived / vault_credential.deleted / vault_credential.refresh_failedなどです。refresh_failedの発行条件は、リフレッシュトークンが無効、またはOAuthサーバーから回復不能なエラーが返った場合とされています。
失敗したクレデンシャルの状態は、イベントのidでGETして確かめます。リフレッシュトークンの失効なのか、OAuthサーバーの回復不能なエラーなのかは、次の診断エンドポイントで判別します。
なお、クレデンシャルは登録時には検証されず、セッションの実行時に初めて使われます。無効な認証情報は認証エラーや下流のエラーとしてセッション中に出力されますが、セッション自体は止まりません。
mcp_oauth_validateで失敗原因を切り分ける
POST /v1/vaults/{vault_id}/credentials/{credential_id}/mcp_oauth_validateを呼ぶと、そのクレデンシャルが実際に使えるかどうかをAnthropic側が検証します。SDKではclient.beta.vaults.credentials.mcp_oauth_validate(...)に対応します。
curl --fail-with-body -sS -X POST \
"https://api.anthropic.com/v1/vaults/$vault_id/credentials/$credential_id/mcp_oauth_validate?beta=true" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01"レスポンスはvault_credential_validation型のオブジェクトです。mcp_probeにはMCPサーバーとのハンドシェイクで失敗した段階、refreshにはリフレッシュを試みた結果が入ります。
{
"type": "vault_credential_validation",
"credential_id": "vcrd_01ABC...",
"vault_id": "vlt_01XYZ...",
"validated_at": "2026-04-29T17:12:00Z",
"has_refresh_token": false,
"status": "invalid",
"mcp_probe": {
"method": "initialize",
"http_response": {
"status_code": 401,
"content_type": "application/json",
"body": "{\"error\":\"invalid_token\"}",
"body_truncated": false
}
},
"refresh": {
"status": "no_refresh_token",
"http_response": null
}
}この例ではhas_refresh_tokenがfalseで、refresh.statusもno_refresh_tokenです。リフレッシュトークンを登録していないクレデンシャルが、MCPサーバーへのinitialize呼び出しで401を返されている状態です。アクセストークンが失効していて、更新の手段もないことになります。
statusの3値ごとに取るべき対応
トップレベルのstatusが、次に何をするかを決めます。
statusの3値と対応
valid
トークンは正常に動いています。何もしなくて構いません。
invalid
認可自体が失効しているか、OAuthサーバーが4xxでリフレッシュを拒否しています。エンドユーザーに再認可を促します。
unknown
5xx・429・ネットワーク障害などの一時的なエラーです。少し待ってから再試行します。
invalidとunknownを混同すると対応を誤ります。invalidは連携そのものが切れているサインなので、再試行しても直りません。再認可で得た新しいアクセストークンとリフレッシュトークンで、クレデンシャルを更新します。unknownは相手側の不調なので、バックオフを挟んだ再試行が向いています。
再認可でクレデンシャルを更新するときは、access_token / expires_at / refresh.refresh_tokenを新しい値に差し替えます。稼働中のセッションがあっても再起動は不要で、次の再解決のタイミングで新しいトークンに切り替わります。
再認可しても直らないとき: 作り直しが必要なケース
再認可で値を差し替えても失敗が続くなら、更新では変えられない項目が原因かもしれません。構造的なフィールドは作成後にロックされ(下の対比のとおりです)、変更するには、既存のクレデンシャルをアーカイブして新規に作り直します。
特にtoken_endpointは、Anthropicがリフレッシュ要求をすべてそのURLへ送る設計です。リフレッシュトークンを発行したOAuthフローのトークンエンドポイントと食い違っていれば、更新を重ねても直りません。OAuthプロバイダー側でエンドポイントのURLが変わった場合や、クライアントIDを入れ替えた場合が該当します。
更新で直る項目と、作り直しが必要な項目
更新で直る
access_token、expires_at、refresh.refresh_token、refresh.scopeといった値です。refresh.token_endpoint_authのclient_secret、display_name、環境変数クレデンシャルのinjection_locationも更新できます。
作り直しが必要
mcp_server_url、token_endpoint、client_id(環境変数クレデンシャルならsecret_name)です。
作り直しのときは、アーカイブで古いクレデンシャルのキーが解放されます。同じvault内では、有効なクレデンシャルのmcp_server_urlが重複すると409が返ります。そのため、先にアーカイブしてから同じMCPサーバー向けの新しいクレデンシャルを作る順番になります。1つのvaultに置けるクレデンシャルは最大20個です。
refreshブロックの設定ミスを疑う
クレデンシャル作成時に渡すrefreshブロックには、token_endpoint / client_id / scope / refresh_tokenに加えて、リフレッシュ呼び出し自体をどう認証するかを決めるtoken_endpoint_auth.typeがあります。
token_endpoint_auth.type | 意味 |
|---|---|
none | 意味パブリッククライアント。クライアントシークレットを送らない |
client_secret_basic | 意味クライアントシークレットをHTTP Basic認証で送る |
client_secret_post | 意味クライアントシークレットをPOSTボディに含めて送る |
OAuthプロバイダーが要求する認証方式と、登録したtoken_endpoint_auth.typeが食い違うと、リフレッシュ呼び出しがOAuthサーバーに拒否されることがあります。手がかりはrefresh.http_responseです。OAuthサーバーが返したエラーの中身を見て、invalid_clientが含まれていないかを確認します。
invalid_clientはOAuth 2.0(RFC 6749)でクライアント認証の失敗を表すエラーコードです。これが返っているなら、リフレッシュトークンが失効したのではなく、クライアント認証の指定が合っていない可能性があります。その場合は、invalidステータスから連想しがちな再認可ではなく、認証方式の設定を見直します。client_secretの誤りなら、更新リクエストでrefresh.token_endpoint_authを差し替えます。noneとの切り替えなど更新パラメーターで表せない変更や、ロックされた項目が原因なら、クレデンシャルを作り直します。
認証方式に問題がなく、トークンだけを差し替えるなら、更新リクエストで済みます。
curl --fail-with-body -sS \
"https://api.anthropic.com/v1/vaults/$vault_id/credentials/$credential_id" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "content-type: application/json" \
-d '{
"auth": {
"type": "mcp_oauth",
"access_token": "xoxp-new-...",
"expires_at": "2099-12-31T23:59:59Z",
"refresh": {"refresh_token": "xoxe-1-new-..."}
}
}'アーカイブ済みのvault・credentialが原因になっていないか
リフレッシュ失敗の原因として見落としやすいのが、クレデンシャルやそれを含むvaultがすでにアーカイブ済みというケースです。vaultをアーカイブすると、配下のすべてのクレデンシャルもカスケードでアーカイブされ、シークレットはパージされます。アーカイブ以降に作られる新規セッションはそのvaultを参照できずに失敗し、すでに動いているセッションは継続します。
このときvault.archivedに加えて、配下の各クレデンシャルについてもvault_credential.archivedが1件ずつ発行されます。webhookの受信ログにvault_credential.archivedがまとめて届いたなら、個々のクレデンシャルではなく親のvaultのアーカイブを疑う手がかりになります。
クレデンシャル単体のアーカイブでもシークレットはパージされます。mcp_server_urlやsecret_nameといったキーは表示上残り、置き換え用の新しいクレデンシャルに再利用できる状態になります。シークレットが残っていない以上、再認可を促すのではなく、新しいクレデンシャルで置き換える対応になります。
削除はハード削除で、レコード自体が残りません。監査のために経緯を追いたいなら、削除ではなくアーカイブを選びます。
確認作業でつまずきやすいのが一覧APIの既定の挙動です。vaultやクレデンシャルの一覧は新しい順のページネーションで返りますが、アーカイブ済みのレコードは既定で除外されます。調査中の一覧にまさに問題のクレデンシャルが出てこず、「そんなクレデンシャルは存在しない」と誤認することがあります。include_archived=trueを付けて取得し直せば、アーカイブ済みも含めて確認できます。
よくある質問
static_bearerクレデンシャルでもこの診断は使えますか
static_bearerは固定のベアラートークンを使う方式で、リフレッシュの流れがないため、この診断の対象はmcp_oauthクレデンシャルです。トークンが無効になったときは、新しい値でクレデンシャルを更新します。
まとめ
webhookが知らせるのは失敗の事実とIDだけなので、mcp_oauth_validateのstatusを見てから動きます。invalidでも、invalid_clientが返っているなら再認可ではなくtoken_endpoint_authの設定や、ロックされたフィールドの食い違いを先に疑います。認証情報の管理全体をどう設計するかはAgent SDKのManaged Agentsの設計思想、MCPサーバーごとの許可範囲の考え方はMCPセキュリティガイド、SDK側からMCP接続を組む手順はAgent SDK MCP接続ガイドで扱っています。