mcpField
R
restricted-access

restricted-access

github.com/val-townセキュリティ1041 回インストール5 週間前に更新
リポジトリ

restricted-access について

Val Town の val にある HTTP エンドポイントのアクセス制限を設定するスキルです。コードの公開範囲とは別に、組織への許可、機械向けバイパストークン、閲覧者の識別を説明します。

主な機能

  1. 01コードとエンドポイントの公開範囲を区別
  2. 02エンドポイントのアクセス設定
  3. 03組織アクセスの許可と取り消し
  4. 04自動化用バイパストークンの管理
  5. 05サーバー側で閲覧者を識別

活用シーン

  1. 01内部ツールを組織限定にする
  2. 02バイパストークンで Webhook を許可
  3. 03制限付きエンドポイントのリダイレクトを調査
  4. 04ログイン済みの人間の閲覧者を識別

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/val-town/plugins --skill restricted-access

インストール後、Claude Code で/restricted-accessを入力して読み込まれたか確認します。

詳細

制限付きアプリアクセス

valには、独立した2つのアクセス設定があります。一方を変更しても、もう一方は変わりません。

  • コード(privacy:public/unlisted/private)— val.town上のソースを誰が読めるかを設定します。
  • アプリへのアクセス(httpPrivacy:public/restricted)— valのHTTPエンドポイントを誰が呼び出せるかを設定します。

コードが非公開でもエンドポイントが広く公開されているvalや、コードは公開されていてもエンドポイントが制限されているvalを作成できます。update_valのprivacyフィールドで変更できるのは前者だけです。アプリへのアクセスはset_http_privacyで変更します。

制限付きアプリアクセスは、この機能が有効になっている組織で利用できます。そのような組織で作成されたvalは、デフォルトでrestrictedになる場合があります。新しいvalのURLが公開されていると思い込まず、必ずget_val_detail、list_vals、create_val、またはremix_valのレスポンスからhttpPrivacyを確認してください。

このツールは適切ですか?

「アプリへのログインを必須にする」という意味に聞こえるものが2つあります。

  • 制限付きアプリアクセス(このスキル)は、コードが実行される前にプラットフォームのエッジでエンドポイントへのアクセスを制限します。アクセス権のないユーザーからのリクエストは、valに到達しません。認証コードを書く必要はありません。アクセス権は個人ではなく、組織全体に付与されます。
  • std/oauth(oauthスキルを参照)は、valの内部で動作します。ハンドラーをラップすると、Val Townのアカウントを持つユーザーなら誰でもログインできます。セッションを管理し、ユーザーごとの機能を構築できます。

チームだけが利用する内部ツールには、制限付きアクセスを選択してください。Val Townのユーザーなら誰でもサインインでき、アプリ独自のログインユーザーの概念が必要な場合は、std/oauthを選択してください。

誤って両方を重ねて使わないようにしてください。すでに制限されているvalにoauthMiddlewareを追加すると、訪問者はアクセスゲートとコード内の両方で認証する必要があります。制限付きvalで閲覧者の身元を確認する必要がある場合は、OAuthを追加せず、以下のIDヘッダーを使用してください。

アクセスできるユーザー

アクセス権は個人ではなく、組織に付与されます。valに組織へのアクセス許可があり、閲覧者がその組織のメンバーである場合に、閲覧者はアクセスできます。どちらか一方を削除すると、次のリクエストからアクセスが取り消されます。セッションの有効期間中にキャッシュされることはありません。

アクセス許可の付与方法は次のとおりです。

  • 直接付与 — add_allowed_userで組織へのアクセスを許可し、list_allowed_usersで現在の許可を確認し、remove_allowed_userで許可を取り消します。
  • ドメインルール — 特定のドメインのメールアドレスを持つ全員にアクセスを許可できます。これらは直接付与とともにlist_allowed_usersに表示されます。
  • 招待 — 許可された組織の外部にいる人をメールで招待できます。招待を承諾するとアクセスできるようになります。
  • バイパストークン — マシン用のプロジェクトスコープのシークレットです。以下を参照してください。

それ以外の人に表示される内容

未認証のリクエストはvalに到達しません。プラットフォームは、Val Townのログインページまたは認証ページへの302リダイレクトを返します。これは、制限付きvalのデバッグ時に最もよくある混乱の原因です。

  • fetch_val_endpointは、追従しないリダイレクトを報告します。
  • curlには、応答ではなくval.townへの302が表示されます。
  • APIクライアントが、JSONを期待していたところでログインページのHTMLを受け取ります。
  • アクセス権のない訪問者がログイン済みの場合、組織へのアクセス権が必要であることを説明する403が表示されます。

これらは、いずれもvalのコードが壊れていることを意味しません。まずhttpPrivacyを確認してください。restrictedなら、アクセスゲートは正常に機能しています。set_http_privacyでvalを公開するか、呼び出し元の組織にアクセスを許可するか、バイパストークンを使用してください。

自動化とWebhook

マシンはログインリダイレクトを完了できません。そのため、Webhook(Stripe、GitHub、別のvalのcronジョブなど)を受け取る制限付きvalには、対象のvalだけにスコープされたシークレットであるバイパストークンが必要です。

create_bypass_tokenで作成します。シークレットは一度だけ表示され、再取得できません。list_bypass_tokensとrevoke_bypass_tokenでトークンを管理します。

次のいずれかの方法で指定します。

// Header (preferred — keeps the secret out of logs and referrers)
await fetch(url, { headers: { "X-Val-Town-Access": Deno.env.get("MY_BYPASS_TOKEN")! } });

// Query param (for services that only accept a URL, e.g. some webhook configs)
await fetch(`${url}?val_town_access=${Deno.env.get("MY_BYPASS_TOKEN")}`);

プラットフォームはハンドラーの実行前にヘッダーとクエリーパラメーターを取り除くため、コードからこれらを参照することはできません。バイパストークンを使ったリクエストには、閲覧者のIDが含まれません。これは匿名のマシンからの呼び出しです。

閲覧者の識別

ゲートを通ってアクセスした人間の閲覧者には、プラットフォームから有効期間の短い署名付きの X-Val-Town-User ヘッダーが転送されます。これは本人確認情報そのものではありません。val 独自の API トークンを使って閲覧者のプロフィールと交換してください。このトークンは Val Town によって valtown 環境変数として注入されます。

const IDENTITY_HEADER = "X-Val-Town-User";

/** Returns the viewer's public profile, or null when there isn't one. */
async function getViewer(req: Request) {
  const signed = req.headers.get(IDENTITY_HEADER);
  if (!signed) return null;

  const res = await fetch("https://api.val.town/v3/val/viewer", {
    headers: {
      Authorization: `Bearer ${Deno.env.get("valtown")}`,
      [IDENTITY_HEADER]: signed,
    },
  });
  if (!res.ok) return null;

  // { id, username, type, bio, profileImageUrl, url, links }
  return await res.json();
}

重要なルール:

  • 閲覧者は常に任意として扱ってください。 公開 val やバイパストークンを使ったリクエストには閲覧者がいません。! で存在を断定したり、null の結果にインデックスでアクセスしたりしないでください。
  • リクエストごとにサーバー側で解決してください。 認証情報の有効期間は短く、あなたの val に紐づいています。永続化したり、ブラウザーに渡したり、クライアント側のコードから照会したりしないでください。
  • 返されるのは公開プロフィール情報のみです — ハンドル、自己紹介、アバター、プロフィール URL です。メールアドレスや請求プランは含まれません。これらに依存する val を作成しないでください。

上記の転送方法(X-Val-Town-User と /v3/val/viewer の照会)は現時点での仕組みであり、変更される可能性があります。ただし、3 つのルールは変わりません。

アプリへのアクセスを管理する

タスクツール
現在の設定を確認するget_val_detail(httpPrivacy フィールド)
エンドポイントを公開または制限するset_http_privacy
アクセス権を持つユーザーを確認するlist_allowed_users
組織にアクセス権を付与/取り消すadd_allowed_user / remove_allowed_user
自動化シークレットを作成/一覧表示/取り消すcreate_bypass_token / list_bypass_tokens / revoke_bypass_token

制限付き val を iframe に埋め込めるのは val.town のみです。そのため、外部サイトに埋め込むと、ログインしているユーザーにかかわらずブラウザーによってブロックされます。

コメント