マキモノ
Web開発無料✅ 公式検証済みv1.0.0 / 更新

認証付き社内Webアプリの一部だけを社外へ匿名公開する(前段ゲートウェイがある構成の落とし穴)

トンネル公開している社内アプリに認証不要の画面を1つだけ足す手順。前段ゲートウェイが /api/* を一律認証していると本体だけ直しても外部は401になり、しかもlocalhost検証では200で通ってしまう。素通し条件の書き方、公開APIの返却フィールド設計、公開URLに対する自動検証5項目まで。

出品者: kim@orgiast.jp📖 読込 約2,227トークン (約3円)💰 コスパ 18
トークン節約メーター87%節約
ゼロからAIに作らせた場合4.5万トークン
このMDを読ませた場合6,000トークン

3.9万トークンの節約 (API料金換算で約59円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。

この巻物について

認証付き社内Webアプリの一部だけを社外へ匿名公開する(前段ゲートウェイがある構成の落とし穴)」は、Web開発カテゴリのAI指示書(MDファイル)です。トンネル公開している社内アプリに認証不要の画面を1つだけ足す手順。前段ゲートウェイが /api/* を一律認証していると本体だけ直しても外部は401になり、しかもlocalhost検証では200で通ってしまう。素通し条件の書き方、公開APIの返却フィールド設計、公開URLに対する自動検証5項目まで。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.9万トークン(API料金換算で約59円)・87%のトークンを節約できます。

カテゴリ
Web開発
対応AI
claude-code、cursor、codex-cli
ライセンス
商用利用可 (再販不可)
価格
無料
ゼロから開発時
約4.5万トークン
この巻物使用時
約6,000トークン
節約量
約3.9万トークン (約59円)
更新日
2026-09-17

使い方 (AIに渡す3つの方法)

いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。

⬇ .md をダウンロード
claude "https://makimono-md.vercel.app/api/v1/files/web-3/raw を読み込んで、この指示書どおりに実装して"
claude-codecursorcodex-cliライセンス: 商用利用可 (再販不可)

中身

認証付き社内Webアプリの一部だけを社外へ匿名公開する(前段ゲートウェイがある構成の落とし穴)

社内向けに作った認証必須の Web アプリの中に、社外の人へ渡したい画面が1つだけ出てくることがある(空き日程の案内、受付フォーム、ステータス確認など)。 このとき「本体アプリに認証不要のルートを1本足す」だけでは外部から動かない構成がある。前段にゲートウェイ(リバースプロキシ役のアプリ)が挟まっている場合で、しかもローカル検証では成功してしまうため気づきにくい。

対象読者: 自宅/社内PCのアプリをトンネル(Tailscale Funnel、Cloudflare Tunnel、ngrok 等)で公開している人。


1. まず構成を実測する。README を信じない

公開URLが本体アプリに直結しているとは限らない。必ずトンネルの転送先を実測してから設計する。

# Tailscale Funnel の場合
tailscale serve status
https://<公開ホスト> (Funnel on)
|-- / proxy http://localhost:3939      # ← 本体が 3940 でも、ここが 3939 のことがある

この例では 3939 に別のゲートウェイアプリがいて、そこから本体(3940)へ中継している。 リポジトリの README に「トンネルは本体ポートに向く」と書かれていても、運用の途中でゲートウェイが挟まって README だけ古いままというのはよくある。実測値を正とする。

ゲートウェイの典型的な作り(Next.js の例):

  • 非 API パスは rewrite で本体へ素通し
  • API パスだけは自前のハンドラを通し、そこで認証してから本体へ中継する(本体のトークンをサーバ側で付け直す)
// gateway/next.config.js
async rewrites() {
  return [
    { source: '/app', destination: 'http://localhost:3940/app' },
    // api 以外は本体へ直接。api は下のハンドラに落とす
    { source: '/app/:path((?!api(?:/|$)).*)', destination: 'http://localhost:3940/app/:path*' },
  ];
}

2. 落とし穴: 本体だけ直しても外部からは 401

本体アプリに認証不要のルート /app/api/public/... を新設しても、ゲートウェイの中継ハンドラが /app/api/*無条件に認証していると、外部URLでは 401 になる。

なぜ気づきにくいか

叩き先結果
http://localhost:<本体ポート>/app/api/public/...200(ゲートウェイを経由しないため)
https://<公開ホスト>/app/api/public/...401(ゲートウェイで止まる)

公開ページ自体は rewrite で素通しなので 200 で開ける。だから「ページは表示される、でも中身が出ない」という壊れ方をする。 ローカル検証だけで「本番OK」と判断すると確実に見落とす。AI コーディングエージェントに任せた場合も、localhost の 200 を根拠に完了報告してくることがある。


3. 直し方: ゲートウェイ側に「公開パスの素通し」を1箇所だけ書く

素通しはパス接頭辞 + 読み取りメソッドの2条件で絞る。パスだけで開けると、同じ接頭辞下の書き込みまで公開される。

// gateway/app/<本体basePath>/api/[...path]/route.ts
async function proxyRequest(req: NextRequest, context: { params: { path: string[] } }) {
  // /<basePath>/api/public/* は社外向けの公開エンドポイント。
  // ゲートウェイの認証は通さず読み取りだけ素通しする。書き込みは従来どおり認証必須。
  const isPublicRead = context.params.path[0] === 'public'
    && (req.method === 'GET' || req.method === 'HEAD');

  if (!isPublicRead) {
    const auth = checkAuth(req);
    if (!auth.ok) return NextResponse.json({ error: auth.message }, { status: auth.status });
  }

  // 以降は従来どおり本体へ中継(本体用トークンをサーバ側で付け直す)
}

修正後はゲートウェイを再ビルドして再起動すること(ポートは変えない、本体プロセスは止めない)。ここを忘れると直したのに 401 のままになる。


4. 公開APIが返してよいものを先に決める

「認証を外す」と「情報を出す」は別の判断。公開エンドポイントはホワイトリストで組み立てる(内部の型をそのまま返さない)。

  • 返す: 求められた答えそのものだけ(例: 日付と時間帯)
  • 返さない: 予定や案件のタイトル、顧客名・個人名、場所、会議URL、件数、内部ID、キャッシュの更新時刻やファイルパス、エラーの内部事情
  • 「該当なし」の理由も返さない。理由を返すと外から内部状態を推測できる。該当しない行はレスポンスから落とす
  • エラー本文は利用者向けの固定文言にし、サーバのエラー文字列を画面に出さない
  • 簡易レート制限を入れる(プロセス内 Map で IP ごと60秒 N 件など。完全でなくてよい)
return Response.json({
  items: publicItems,        // 必要最小限のフィールドだけ詰め替えたもの
  text: formatForHumans(),   // そのままコピーして相手に貼れる整形済みテキスト
  generatedAt: nowIso(),
  freshness: isStale ? 'stale' : 'ok',
});

社外の人がそのまま相手に貼れる text を一緒に返すと、受け取った側の手間が減る。


5. 検証は必ず公開URLに対して行う

localhost の 200 を本番の証拠にしない。 最低限これだけは公開URLに対して自動で確かめる。

const BASE = 'https://<公開ホスト>';
const FORBIDDEN = ['summary', 'location', 'customerName', 'eventsCount']; // 出てはいけないキー

// 1. 公開API: Cookie も Authorization も付けずに 200、かつ機微キーが出ない
// 2. 既存の認証API: 認証なしで 401(公開化が波及していない)
// 3. 公開APIへの POST: 401 か 405(書き込みを素通ししていない)
// 4. 公開ページ: 200 で、想定の見出し文字列を含む
// 5. 既存トップ: 200(他の画面を壊していない)

fetch(url, { redirect: 'manual' }) で叩き、レスポンス本文に "<禁止キー>" が含まれないことを機械的に判定する。目視確認にしない。 2 と 3 を省くと、「公開したつもりが全体を開けてしまった」事故に気づけない。


6. チェックリスト

  • トンネルの転送先を実測した(README ではなく serve status 等の出力で)
  • 前段ゲートウェイの有無を確認した
  • ゲートウェイ側に公開パスの素通しを書いた(接頭辞 + GET/HEAD のみ)
  • ゲートウェイを再ビルド・再起動した
  • 公開APIの返却フィールドをホワイトリストで組んだ
  • 「該当なし」の理由を返していない
  • レート制限を入れた
  • 公開URLに対して 5 節の 1〜5 を全部 PASS させた
  • 公開URLを知っていれば誰でも見られることを、依頼者に明示して合意した
  • README に「トンネル→ゲートウェイ→本体」の実際の経路とポートを書いた

補足: そもそも公開してよいか

URL を知っていれば誰でも開ける=リンクが外部に転送されれば第三者も見られる、ということ。 「社外の人に渡したい」と「インターネットに公開してよい」は別なので、依頼者に何が出るかを具体的に示して合意を取ってから公開する。 合言葉を1つ挟むだけでも、無差別のアクセスは実用上ほぼ止まる(強度は求めない、誤爆防止の意味)。

よくある質問

「認証付き社内Webアプリの一部だけを社外へ匿名公開する(前段ゲートウェイがある構成の落とし穴)」とは何ですか?

トンネル公開している社内アプリに認証不要の画面を1つだけ足す手順。前段ゲートウェイが /api/* を一律認証していると本体だけ直しても外部は401になり、しかもlocalhost検証では200で通ってしまう。素通し条件の書き方、公開APIの返却フィールド設計、公開URLに対する自動検証5項目まで。

どれくらいトークン(費用)を節約できますか?

ゼロから開発すると約4.5万トークンかかりますが、この巻物を使えば約6,000トークンで済みます。差し引き約3.9万トークン(API料金換算で約59円)・87%の節約です。

どうやって使いますか?

無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。

どのAIツールに対応していますか?

claude-code、cursor、codex-cli に対応しています。

商用利用できますか?

ライセンスは「商用利用可 (再販不可)」です。

🤝 自分でAIを動かすのは、まだ不安…という方へ

この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。

AI代行堂を見る →

関連する巻物

この巻物、誰かのトークンも救えます

𝕏 で節約レシートをシェア