MCP Fusion/Security and governance/認証

認証

VinkiusについてAIに質問

コネクタ向けの 3 つの認証パッケージ。JWKS による JWT 検証、タイミングセーフな API キー、エージェントが操作できるツールにした OAuth 2.0 デバイス認可フローを提供します。

他者のアカウントに対して動作するコネクタは、誰が要求しているかを把握する必要があります。MCP Fusion には 3 つの認証パッケージがあり、それぞれミドルウェアと任意の認証ツールを備えています。そのため、エージェントをブロックし、追加確認を求め、認証後に再開させても、ハンドラーはその違いを意識せずに済みます。

ID はどこから来るか

認証は ctx から ID を読み取り、ctx はリクエストごとに contextFactory が作成します。標準的な配線は次のとおりです。

typescript
registry.attachToServer(server, {
  contextFactory: async (extra) => ({
    token: extra.session?.authToken ?? '',
    headers: extra.headers ?? {},
  }),
});

以下はすべてこのコンテキストを読み取ります。

JWT

bash
npm install @mcpfusion/jwt
typescript
import { requireJwt } from '@mcpfusion/jwt';

f.query('billing.list_invoices')
  .use(requireJwt({
    jwksUri: 'https://auth.example.com/.well-known/jwks.json',
    issuer: 'https://auth.example.com/',
    audience: 'my-connector',
    requiredClaims: ['sub', 'tenant_id'],
    onVerified: (ctx, payload) => {
      ctx.tenantId = payload.tenant_id;   // derived identity for the handler
    },
  }))
  .handle(async (input, ctx) => listInvoices(ctx.tenantId));

JwtVerifiersecret (HS256)、publicKey (PEM)、jwksUri (リモートキーセット、検証器ごとにキャッシュ) を受け付けます。jose をインストールすると RS256、ES256、JWKS がすべて動作します。ない場合は、ネイティブ HS256 パスが timingSafeEqual で検証し、他のアルゴリズムを拒否します。issueraudienceclockTolerance (60 秒)、requiredClaims はすべてのトークンで検証されます。verifyDetailed(){ valid, payload, reason } を返します。理由を null ではなく取得したい場合です。

トークン抽出の既定の順序は ctx.token、次に ctx.jwt、最後に ctx.headers.authorization です (Bearer プレフィックスは除去されます)。失敗すると、自己修復型 toolError が返され、コードは JWT_INVALID、復旧用のアクションは auth です。

JWT パッケージはトークンを検証しますが、更新は行いません。ソースにはリフレッシュトークンのサポートがないため、プロバイダーへの長期アクセスが必要なコネクタでは、以下の OAuth フローまたはクレデンシャルボールトを使用してください。

任意の createJwtAuthTool() は、クライアント自身がトークンを保持している場合に、エージェントから呼び出せるアクションとして verifystatus を公開します。

API キー

bash
npm install @mcpfusion/api-key
typescript
import { requireApiKey } from '@mcpfusion/api-key';

f.mutation('billing.refund')
  .use(requireApiKey({
    keys: [process.env.SERVICE_KEY!],
    onValidated: (ctx) => { ctx.service = 'billing-service'; },
  }))
  .handle(...);

キーは平文でも、構築時に SHA-256 で内部ハッシュ化したものでも、事前にハッシュ化したものでも構いません。また、非同期の validator 関数で検証することもできます。検査の順序は、空でないこと、minLength (既定値 16)、任意の prefix、その後にバリデーターまたはハッシュセットです。抽出の順序は ctx.apiKeyctx.headers['x-api-key']ctx.headers.authorization です (ApiKey Bearer のプレフィックスは除去されます)。

比較は意図として定時間です。マネージャーは最初に異なるバイトで短絡しない方法でハッシュを比較します。キーの長さを秘密情報として扱わないでください。

エージェント向け OAuth デバイスフロー

エージェントがまだ持っていないアカウントをコネクタが必要とする場合、チャットから操作できるフローでなければなりません。サーバーがコードと URL を渡し、人間がブラウザーで承認し、エージェントがもう一度尋ねます。これは RFC 8628 であり、パッケージはこれをツールに変換します。

bash
npm install @mcpfusion/oauth
typescript
import { createAuthTool, requireAuth } from '@mcpfusion/oauth';

const auth = createAuthTool({
  clientId: process.env.OAUTH_CLIENT_ID!,
  authorizationEndpoint: 'https://auth.example.com/device/code',
  tokenEndpoint: 'https://auth.example.com/device/token',
  onAuthenticated: (token) => { /* cache or forward the token */ },
});

f.query('analytics.report')
  .use(requireAuth())          // blocks with AUTH_REQUIRED until a token exists
  .handle(...);

このツールは 4 つのアクションを公開します。

ActionBehavior
loginデバイスコードを要求し、検証 URL とコードを返します
completeコードを一度交換します。authorization_pending は「まだです。もう一度尋ねてください」という意味です
statusトークンの有無と、必要に応じて所有ユーザーを報告します
logoutトークンを消去します

ポーリングループは RFC 8628 に従います。最初のポーリングは即時に行われ、authorization_pending では継続し、slow_down では 5 秒追加され、その他のエラーではプロバイダー自身の説明とともに終了し、期限に達すると "Device authorization expired. Start a new flow." が発生します。検証器が scope を自動送信することはなく、自動更新もありません。トークンストアはホームディレクトリのファイル (.mcpfusion/token.json、モード 0600、Windows では icacls フォールバック付き) です。単一ユーザー向けのローカル既定値として扱い、ホスト型コネクタでは独自の永続化を用意してください。

requireAuth() はトークンの存在を確認しますが、有効性は確認しません。上流のトークンを暗号学的に検証する必要がある場合は requireJwt と組み合わせてください。

本番環境での注意

  • サーバー間呼び出しではユーザートークンよりプラットフォームのクレデンシャルを優先してください。defineCredentials で宣言し、requireCredential で読み取ります。Credentials を参照してください。
  • Vinkius Cloud では接続トークンで呼び出し、コンソールの Connection Tokens でクライアントごとのアクセスを取り消してください。
  • 認証ミドルウェアはチェーンの他の部分と組み合わせられます。未認証の呼び出しが検証に到達しないよう最外層に置いてください。Middleware and context に例があります。

次のステップ