1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OCI の Personal Access Token は 60 分超を指定しても 60 分で切れる

1
Posted at

1. はじめに

OCI Database Tools MCP Server を Claude Desktop / Claude Code に接続して使っていたところ、「さっきまで動いていたのに、急に切れて再接続できなくなる」 事象に遭遇しました。

クライアント側のログを見ると、こんなエラーが出ています。

Connection error: Error: Incompatible auth server:
  does not support dynamic client registration

原因を確認したところ、Bearer Token として渡している Personal Access Token (PAT) が失効していた ことでした。

ここで気になったのが、OCI コンソールの PAT 生成画面で 「失効までの分数 = 180」 と指定していたのに、ものの 1 時間で切れていることです。
画面上の入力欄には「1 から 527040 までの値にする必要があります」と注釈もあり、180 分どころか 年単位(527040 分 ≒ 1 年)まで指定できる はずなのに。

pat_generate_180_2.png

本記事では、

  • PAT の実体(JWT)をデコードして本当の有効期限を確認し、
  • UI 指定値と実発行値の関係を 10 分指定 / 180 分指定 の 2 通りで実測し、
  • Identity Domain (IDCS) の UI / API を一通り探して 延長設定の有無 を確定させる

ことを通じて、「OCI PAT の有効期限は最大 60 分にサイレントでキャップされる」 という挙動の原因を整理します。

今回の検証ゴール

# 検証項目
1 PAT の実体(JWT)の exp - iat が、UI 指定値どおりかをデコードして確認する
2 UI 値より小さい指定(10 分)と大きい指定(180 分)で発行された PAT を比較し、キャップが上方向だけに効くのか、それとも UI 値が常に無視されるのかを判定する
3 Identity Domain UI / API を辿って、ユーザー側で有効期限を延長できる設定箇所があるかを実証する

検証環境

項目 内容
OCI リージョン ap-tokyo-1
Identity Domain Default(IDCS 形式)
対象 MCP サーバ OCI Database Tools MCP Server(マネージド)

2. JWT をデコードして確認

2.1. PAT の実体は JWT

OCI コンソールでダウンロードした PAT ファイルを開くと、1 行の長大な文字列が入っています。これは xxxxx.yyyyy.zzzzz という 3 つの Base64URL 文字列をピリオドで結合した JWT (JSON Web Token) です。

# decode_jwt.ps1 (src/ に同梱)
param([Parameter(Mandatory=$true)][string]$Path)

$token   = (Get-Content $Path -Raw).Trim()
$payload = $token.Split('.')[1]
while ($payload.Length % 4) { $payload += '=' }
$bytes = [Convert]::FromBase64String($payload.Replace('-','+').Replace('_','/'))
$obj   = [Text.Encoding]::UTF8.GetString($bytes) | ConvertFrom-Json

$iat  = (Get-Date '1970-01-01').AddSeconds($obj.iat).ToLocalTime()
$exp  = (Get-Date '1970-01-01').AddSeconds($obj.exp).ToLocalTime()
$diff = $obj.exp - $obj.iat

"iat:       $iat"
"exp:       $exp"
"exp - iat: $diff 秒 (= $($diff/60) 分)"
"aud:       $($obj.aud)"
"client_id: $($obj.client_id)"
"tok_type:  $($obj.tok_type)"

180 分指定で発行した PAT をデコードした結果:

iat:       2026-05-23 19:54:54
exp:       2026-05-23 20:54:54
exp - iat: 3600 秒 (= 60 分)
aud:       urn:opc:dbtools:mcpserver:ocid1.databasetoolsmcpserver.oc1.ap-tokyo-1.amaaaaaa...
client_id: te
tok_type:  AT

UI で 180 分を指定したのに、exp - iatきっかり 3600 秒(= 60 分)
60 分を境にスパッと切られているのが分かります。

2.2. 主要 claim の読み解き

claim 値の例 意味
iat 2026-05-23 19:54:54 Issued At(発行時刻、Unix 秒)
exp 2026-05-23 20:54:54 Expiration(有効期限、Unix 秒)
aud urn:opc:dbtools:mcpserver:ocid1... Audience(このトークンが向けて発行された対象リソース)
tok_type AT Access Token(refresh token ではない)
client_id te 発行元クライアント。teToken Exchange(OCI 内部の組み込みクライアント)
sidle 480 Session Idle Timeout(IDCS UI セッションのアイドル分数。トークン寿命とは別)

特に重要なのが audこの MCP サーバの OCID にロックされている ため、万が一漏洩しても他のリソースには使えませんが、逆に サーバを作り直すと再発行が必要 という制約もあります。

2.3. GitHub PAT との違い

「PAT」というと GitHub の ghp_xxxxxxxxxx... のような不透明な長命トークンを思い浮かべますが、OCI の PAT は仕組みがかなり異なります

GitHub PAT OCI PAT
形式 不透明文字列 JWT(RS256 署名付き)
検証方式 サーバ側 DB 照合 署名検証だけで完結(ステートレス)
寿命 ユーザー指定(無期限可) IDCS ポリシー支配(典型 60 分)
失効 手動で revoke exp で自動失効

GitHub のイメージで「PAT は長く使えるもの」と思い込んでいると、OCI で 短命の JWT で切り分けに時間がかかった・・というお話です。


3. UI 値と実発行値を実測

UI 入力欄が 1〜527,040 分を受け付けるのに、実発行が 60 分で頭打ちになるなら、「下方向(短い指定)」も同じく無視されるのか? が次の疑問です。

仮説 内容 10 分指定の予測
(a) 上限キャップ説 UI 値は要求値、IDCS 側の最大値(3600 秒)で頭打ち 600 秒(指定通り)
(b) 完全無視説 UI 値は完全に無視、常に 3600 秒で発行 3600 秒(指定無視)

判定するため、もう一度 PAT を 「失効までの分数 = 10」 で発行し直してデコードします。

pat_generate_10.png

iat:       2026-05-23 20:36:31
exp:       2026-05-23 20:46:31
exp - iat: 600 秒 (= 10 分)

10 分指定はそのまま 10 分で発行され、180 分指定だけが 60 分に切り詰められています。つまり、 60分でキャップされるような動きであることがわかります。

OCI PAT の有効期限は、UI 入力値に対して以下の 非対称な挙動 をします。

UI 指定値 実発行 exp - iat 挙動
10 分 600 秒(= 10 分) 指定どおり
180 分 3600 秒(= 60 分) ⚠️ 60 分にキャップ
527040 分(=最大) 3600 秒(= 60 分) ⚠️ 60 分にキャップ

UI 入力欄の注釈「1 から 527,040 までの値にする必要があります」は 嘘ではないものの、
60 分を超える値を入れても 警告もエラーも一切出さずに 60 分にされる ため、
画面だけ見て運用設計するとハマります。

3.1. なぜ 60 分なのか — 公式 Docs の根拠

これは IDCS の標準仕様で、根拠は公式 Docs の 「トークン有効期限表」 にあります。
「OAuthアクセス・トークンの有効期間」のセクションに、既定値 3600 秒 と、ATの有効期限が OAuthConfig / リソース・アプリケーション / カスタム の組み合わせで決まる旨が明記されています。

「リソース・アプリケーションの有効期限時間もユーザー・セッションの有効期限時間も構成されておらず、カスタム有効期限時間も指定されていない場合、ATの有効期限はデフォルトの OAuthアクセス・トークンの有効期間である 3600 秒 になります。」
トークン有効期限表 - OCI Documentation

同 Docs によれば、Access Token の最終有効期限は次の 3 階層の最小値 で決まります。

# 階層 設定場所
OAuthConfig Access Token Expiry(グローバル既定) テナント単位 / 既定 3600 秒
Resource App Expiry(リソース個別) Identity Domain の Resource Server 型アプリ
Custom Expiry(リクエスト時) OAuth scope に urn:opc:resource:expiry=<seconds> を付与
最終 exp - iat = min( ① OAuthConfig, ② Resource App, ③ Custom Expiry )

これに今回の実測を当てはめると、

UI 指定 ③ Custom Expiry ① OAuthConfig 最小値 実発行 一致
180 分 = 10800 秒 10800 3600 3600 3600 ✅
10 分 = 600 秒 600 3600 600 600 ✅

実測と公式の説明が完全に整合します。
OCI Database Tools MCP の PAT 生成画面の値は ③ の Custom Expiry として渡され、① の既定値 3600 秒で頭打ちされていた、というのが正体です。

3.2. 延長する設定箇所はあるのか

3 階層の最小値で決まるなら、① OAuthConfig か ② Resource App を伸ばせば 180 分も通る はず ― ということで、Identity Domain の中を一通り探しました。

# 探索 結果
1 コンソール → ドメイン → Default → 設定(セッション設定) セッション期間 = 480 分 のみ。Access Token Expiry の項目は存在しない
2 同 → 統合アプリケーション(GUI) 自分が登録した claude-desktop-client(Confidential Client)のみ
3 OCI CLI apps list --filter 'name co "dbtools" or "DatabaseTool" or "MCP"' []
4 OCI CLI apps list --filter 'name eq "<resource_app_id>"' []

ドメイン設定の「セッション設定」には セッション期間アイドル・タイムアウト の2 つしかなく、Access Token Expiry の欄は見当たりません。
これらの 480 分はあくまで コンソール UI セッションの寿命(JWT の sidle: 480 claim に対応)であって、発行された Access Token の寿命とは別物です。

idcs_session_settings.png

統合アプリケーション一覧にも、自分で OAuth 用に登録した claude-desktop-client 1 件だけが見えます。

idcs_integrated_apps.png

ちなみに claude-desktop-client を開くと 「トークン発行ポリシー」 という、いかにも寿命をいじれそうなセクションがありますが、中身は 「認可されたリソース: 明示的」というアクセス可否のホワイトリスト設定で、TTL の項目ではありません。
そもそも、このアプリは今回の PAT 発行経路上にいません。JWT の client_idte
(Token Exchange = OCI 内部の組み込みクライアント)であって claude-desktop-client の Client ID 8894d... ではないため、ここを編集しても今回の PAT 発行フローには構造的に作用しない という関係のようです。

image.png

トークン有効期限表 によれば本来 Access Token Expiry は アプリ単位(= Resource Server 型アプリの設定)で変更できるようなのですが、OCI Database Tools MCP の Resource App はテナント内のどこからも見えない(GUI 非表示・API でも 0 件)ため、ユーザー側からは編集できない ことが確定しました。

OCI Database Tools MCP Server 自体のドキュメントにも、サラッとですが 1 時間で切れる旨が明記されています。

「Bearerトークンは約1時間有効です。」
MCPサーバーのトラブルシューティング - Autonomous Database(「ストリーム可能な HTTP エラー – 401」セクション)


4. まとめ

# 検証項目 結論
1 PAT の exp - iat が UI 指定値どおりか 60 分以下なら指定どおり、60 分超は 60 分にキャップ(仮説 a 確定)
2 「上方向だけキャップ」か「常に無視」か 上方向だけサイレントキャップ。下方向(短く指定)は素通し
3 ユーザー側で延長できる設定箇所はあるか 存在しない。Resource App が OCI マネージド側に隠蔽されているため GUI/API どちらからも見えない

公式 Docs の 「3 階層の最小値ルール」 に当てはめると、OCI Database Tools MCP の PAT は 常に IDCS のグローバル既定 3600 秒 で頭打ちされ、これを伸ばす設定面がユーザー側に露出していない、というのが本記事の発見でした。

実運用上は 60 分前提でフローを組む しかありません。
具体的には次のような選択肢が候補になります(後ろ 2 つは未検証の提案ベース)。

  • 手動再発行(実証済み): 1 時間ごとに OCI コンソールから取り直して MCP 設定ファイルの Authorization: Bearer ... を更新する最小コストの運用。検証や試用フェーズではこれで十分
  • 自動再発行ラッパーが候補(未検証): OAuth client_credentials grant で PAT 相当のトークンを再取得するスクリプトを mcp-remote 起動前に噛ませて、毎回置換する構成
  • urn:opc:resource:expiry の scope 指定も候補(未検証): トークン有効期限表 には明示要求の手段として記載があるが、UI 経由の PAT 発行フローからは指定できないので、自動化スクリプト側で OAuth 直接呼び出しに切り替えた場合の候補

本記事の範囲では、「PAT は最大 60 分」を前提として運用設計に組み込んでおくと、失効でハマる時間を減らせます ―― ここまでが今回の結論です。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?