6.4 KiB
6.4 KiB
MCPletA2A Passkey 認証
真正の WebAuthn/FIDO2 Passkey 認証。外部 amiPro FIDO2 サーバーと連携。
アーキテクチャ
Host (Node.js)
│
├── PasskeyServer ──→ ブラウザページ起動(自己完結型フロー)
│ │
│ ├── userId 入力
│ ├── FIDO2 サーバーにユーザー確認
│ ├── 未登録 → 自動で Passkey 登録(Touch ID 等)
│ ├── 認証(Touch ID 等)
│ └── 結果を Host に HTTP callback
│
├── PasskeyPlatformService ──→ AmiProFIDO2Client ──→ FIDO2 Server
│ (統一管理: 登録/認証/セッション) (https://fido2.epk.amipro.me)
│
└── PasskeyAPIServer (REST proxy, port 8443)
/api/passkey/attestation/options
/api/passkey/attestation/result
/api/passkey/assertion/options
/api/passkey/assertion/result
ファイル構成
platform_impl/src/passkey/
├── amipro-fido2-client.ts # amiPro FIDO2 サーバー REST クライアント
├── platform-service.ts # 統一 Passkey 管理サービス
├── passkey-server.ts # ブラウザ WebAuthn 式典サーバー(自己完結型ページ)
├── api-server.ts # REST API プロキシ
├── index.ts # エクスポート
├── storage.ts # IPasskeyStorage インターフェース (ローカル用、予備)
├── challenge-manager.ts # チャレンジ管理 (ローカル用、予備)
├── fido2-backend.ts # FIDO2 検証 (ローカル用、予備)
├── client.ts # ブラウザ側 WebAuthn クライアント
└── mcplet-helper.ts # MCPlet ツール統合ヘルパー
設定
# reference_impl/config/reference.yaml
passkey:
mode: https # localhost | https
rpId: a2a-demo.mcplet.ai # WebAuthn Relying Party ID
fido2ServerUrl: https://fido2.epk.amipro.me # 外部 FIDO2 サーバー
apiPort: 8443 # REST API ポート
ユーザーフロー
新規ユーザー(未登録)
ブラウザページ起動
↓
1. userId 入力(または自動入力)
↓
2. FIDO2 サーバーに問い合わせ → "ユーザーが存在しません"
↓
3. 自動で登録モードに切替 → Touch ID 等で Passkey 登録
↓
4. 登録成功 → 自動で認証に進む
↓
5. Touch ID 等で認証
↓
6. session + username を Host に返却
既存ユーザー(登録済み)
ブラウザページ起動
↓
1. userId 入力(または自動入力)
↓
2. FIDO2 サーバーに問い合わせ → OK(allowCredentials 返却)
↓
3. Touch ID 等で認証
↓
4. session + username を Host に返却
amiPro FIDO2 Server API
| エンドポイント | 説明 |
|---|---|
POST /attestation/options |
登録オプション取得(challenge + publicKey params) |
POST /attestation/result |
登録結果送信(attestationObject 検証) |
POST /assertion/options |
認証オプション取得(challenge + allowCredentials) |
POST /assertion/result |
認証結果送信(signature 検証) |
POST /usr/validsession |
セッション検証 |
POST /usr/delsession |
ログアウト |
エンコーディング: Base64URL(dfido2-lib.js 互換)
開発環境セットアップ
1. /etc/hosts
127.0.0.1 a2a-demo.mcplet.ai
2. 自己署名証明書の生成
cd platform_impl
mkdir -p certs
openssl req -x509 -newkey rsa:2048 \
-keyout certs/key.pem -out certs/cert.pem \
-days 365 -nodes -subj "/CN=a2a-demo.mcplet.ai" \
-addext "subjectAltName=DNS:a2a-demo.mcplet.ai,IP:127.0.0.1"
3. 証明書の信頼(macOS)
# Admin 権限あり
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain certs/cert.pem
# Admin 権限なし(Edge で有効、Chrome は完全再起動が必要)
security add-trusted-cert -r trustRoot \
-k ~/Library/Keychains/login.keychain-db certs/cert.pem
4. テスト
cd platform_impl
# API 接続テストのみ
npx tsx test-passkey.ts
# 統一フロー(自動登録+認証)
npx tsx test-passkey.ts test a2a-test-user
# 新規ユーザー(userId 手入力)
npx tsx test-passkey.ts new
重要な注意事項
WebAuthn rpId とドメインの一致
WebAuthn は rpId がブラウザページのドメインと一致することを要求する。
http://127.0.0.1 のページでは rpId a2a-demo.mcplet.ai は使用不可。
必ず /etc/hosts + HTTPS(または Chrome flag)で一致させること。
Passkey のブラウザ間共有
macOS の Touch ID / iCloud キーチェーンで作成された Passkey はブラウザ間で共有される。
ただし Chrome の --user-data-dir=tmp で起動すると隔離プロファイルとなり、
プラットフォーム Passkey にアクセスできない。常にデフォルトブラウザを使用すること。
本番環境 vs 開発環境
| 項目 | 開発環境 | 本番環境 |
|---|---|---|
| 証明書 | 自己署名 + キーチェーン信頼 | 正規 SSL 証明書 |
| rpId | a2a-demo.mcplet.ai (hosts) | 実ドメイン (DNS) |
| FIDO2 server | fido2.epk.amipro.me | 同 or 専用サーバー |
PASSKEY_DEV_HTTP |
設定可(Chrome flag 必要) | 不使用 |
Platform 統合
base-agent.ts での Passkey 呼び出し
// action 型ツールで auth.required === 'passkey' の場合、自動で仪式を開始
if (tool.meta.mcpletType === 'action' && tool.meta.auth?.required === 'passkey') {
const assertion = await this.performPasskeyCeremony(tool);
if (!assertion) {
return this.errorResult(toolName, 'Passkey authentication failed', 'AUTH_FAILED');
}
callParams = { ...args, _mcplet_auth: assertion };
}
MCPletHost 初期化
if (config.passkey) {
this.passkeyPlatformService = new PasskeyPlatformService(rpId, fido2ServerUrl);
this.passkeyAPIServer = new PasskeyAPIServer(platformService, rpId, origin);
this.passkeyAPIServer.start(config.passkey.apiPort || 8443);
this.passkeyServer = new PasskeyServer(rpId, fido2ServerUrl);
}