AI Connect/Core concepts/認証とスコープ

認証とスコープ

VinkiusについてAIに質問

アプリケーションの資格情報はサーバー側に置き、externalId は信頼できる識別情報から導出し、コネクターの資格情報は値を読み戻さずに書き込みます。

SDK は App ID と Application Key を使ってバックエンドを認証します。ただし、エンドユーザーは認証しません。アプリケーション側で、呼び出し元の検証、要求された操作の認可、そしてユーザースコープを持つすべてのリクエストで使われる externalId の導出を行う必要があります。

アプリケーションキーをサーバー境界の内側に置く

typescript
import { Vinkius } from '@vinkius/connect';

export const vinkius = new Vinkius({
  appId: process.env.VINKIUS_APP_ID!,
  apiKey: process.env.VINKIUS_APP_KEY!,
});

概念としては、リクエストは Application Key をベアラー認証として、App ID をアプリケーションヘッダーとして送信します。このクライアントをブラウザーコードで初期化したり、どちらかの値をクライアントに返したりしないでください。

SDK には、ホスト型 OAuth やコネクター設定 UI の API はありません。コネクターが資格情報を必要とする場合、アプリケーションが独自の認証済みサーバーフローでそれらを収集し、credentials.set() で送信します。

認証済みの状態から externalId を導出する

typescript
interface Session {
  userId: string;
}

async function listActions(session: Session) {
  return vinkius.user(session.userId).capabilities();
}

ユーザー識別子には、安定した、できれば推測できない独自の値を使用してください。SDK は次の値を拒否します:

  • 空であるか、255 文字を超えている。
  • 空白、/、バックスラッシュを含んでいる。
  • vk_app_user_ で始まっている。これはあなたの ID ではなく内部識別子を表します。

user(externalId) はハンドルを返すだけで、リクエストは行いません。ensure(metadata) は省略可能です:

typescript
await vinkius.user(session.userId).ensure({ plan: 'team' });

API はこの呼び出しをべき等なアップサートとして扱います。メタデータに秘密情報を含めないでください。資格情報の保管場所ではありません。

クライアントが選択したユーザースコープを拒否する

リクエストボディがユーザーを選択するため、このエンドポイントは脆弱です:

typescript
// Do not use this pattern without an authorization check.
const { externalId } = await request.json();
const capabilities = await vinkius.user(externalId).capabilities();

ハンドルを構築する前にスコープを結び付けてください:

typescript
async function handleCapabilities(request: Request) {
  const session = await requireSession(request); // application code
  const capabilities = await vinkius.user(session.userId).capabilities();

  return Response.json(
    capabilities.map(({ name, description, inputSchema }) => ({
      name,
      description,
      inputSchema,
    })),
  );
}

認可の境界はセッション参照です。App ID とキーが認証するのはアプリケーションであって、特定のブラウザーユーザーではありません。

値を収集する前に資格情報のスキーマを読む

credentials.schema() はカタログからコネクターのメタデータを読み取ります。既存のユーザー接続は必要ありません:

typescript
const github = vinkius.user(session.userId).connector('github');
const schema = await github.credentials.schema();

スキーマを参考に、サーバーのフォームがどのフィールドを受け付けるべきかを決めてください。すべてのコネクターがトークンや同じキー名を使うと想定しないでください。

接続を作成してから資格情報を書き込む

typescript
await github.connect();
const state = await github.credentials.set({
  GITHUB_TOKEN: submittedToken,
});

console.log(state.configured.GITHUB_TOKEN);

credentials.status()credentials.set() は接続を必要とし、なければ ConnectorNotConnectedError をスローします。レスポンスにはスキーマと設定済みキーのマップが含まれ、保存された資格情報の値は含まれません:

typescript
const state = await github.credentials.status();
// state.configured: Record<string, boolean>

送信した値は、アプリケーション側のコードでは秘密情報として扱ってください。トランスポートのオブザーバビリティ向けマスキングは既知のフィールド名の固定リストを対象としますが、他の場所でログに出力する可能性のあるすべてのカスタム名を特定できるわけではありません。

アプリケーション環境を分離する

開発、ステージング、本番トラフィックそれぞれに異なる App ID とキーを使用してください。これにより、アプリケーション認証の境界でユーザー、接続状態、資格情報のローテーションが分離されます。

次のステップ