netlify-access-control について
netlify-access-control は、サイト、プレビュー、ページへのアクセスを制限したいチーム向けに、Netlify の保護設定の選択を支援するスキルです。アプリのユーザー認証、サイト保護、チーム SSO を区別し、判断指針とダッシュボードの設定経路を示します。
主な機能
- 013 種類の認証レイヤーを区別
- 02アクセス要件に応じた保護方式の選択
- 03プライベートプロジェクトと共有パスワードの説明
- 04ダッシュボードの設定経路を提示
- 05プラン制限と注意点の案内
活用シーン
- 01チームメンバーだけにサイトを公開
- 02プレビューのデプロイだけを保護
- 03特定ページに複数のパスワードを設定
- 04SSO セッション期限切れによる 401 の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ netlify/ context-and-tools --skill netlify-access-controlインストール後、Claude Code で/netlify-access-controlを入力して読み込まれたか確認します。
同梱ファイルreferences/two-layer-pattern.md
詳細
Netlify アクセス制御 — 保護レイヤーを選ぶ
このスキルでは、適切な保護レイヤーへ案内します。それぞれの設定方法は説明しません。**これらの設定には、公開 API、CLI コマンド、MCP ツールがありません。**確認や変更のために api.netlify.com に curl したり、ローカルの認証トークンを読み取ったりしないでください。ユーザーにはダッシュボードへのパスとチェックリストを案内してください。失敗した場合は、試したことを報告して終了してください。
最初に:「認証」の意味を切り分ける — 無関係な 3 つのレイヤー
ユーザーはこれらを頻繁に混同します。何を指しているのかを確認してから、案内してください。
- Netlify Identity — 「アプリ内でこのユーザーが誰か」。
nf_jwtを発行します。→ netlify-identity スキルに案内してください。ここでは扱いません。 - パスワード保護/プロジェクトの公開範囲 — 「このリクエストでサイトを読み込めるかどうか」。ここで扱います。
- チーム/組織の SAML SSO — 「Netlify のダッシュボードにログインできるか」。ダッシュボードへのアクセスを制限し、チームログインによるサイト保護の基盤にもなります。
セッションは別々です。同じプロバイダー(例:Google)が無関係に 2 か所で使われることがあります。アプリユーザー向けの Identity OAuth と、チームメンバー向けの SAML IdP です。
**二重ログインの落とし穴:**パスワード保護/チームログインの境界セッションと Identity アプリセッションの間には、橋渡しがありません。共有 Cookie、ヘッダー転送、JWT 交換はできません。両者を連携させようとしないでください。組み合わせた多層構成とそのトレードオフについては、references/two-layer-pattern.md を参照してください。Netlify ログイン自体はアプリコードに届きます。プライベートプロジェクトまたはチームログイン保護では、関数とエッジ関数に、サインイン済みの Netlify ユーザーが context.user として渡されます。そのログインをすべてのアプリユーザーが通過できるなら、それがアプリの ID となるため、2 つ目のログインは不要です。
**内部アプリで、ログインを 1 回だけにしたい場合(二重ログインなし):**まず、誰が使うのかを確認してください。
- プロジェクトの Netlify ログインを通過できる → Private project(クレジットベースのプラン。Team Owner 以外も対象にする場合は Pro)または team login protection(Enterprise)を使い、関数で
context.userを利用してユーザーごとに処理します。 - 通過できない(例:Netlify シートを持たない従業員)→ Auth0 extension で企業 IdP とフェデレーションを行ってから、2 層構成にします。
選択ガイド(このスキルの役割)
- サイト全体をチームに限定し、メールで招待する → Private project(クレジットベース)または Team login protection(Password Protection)。
- 共有パスワードを知っている人なら誰でもアクセスできるようにする → Basic password protection(Pro)または Password の公開範囲(クレジットベースの Pro のみ)。クレジットベースの Free/Personal では利用できません。代わりにプロジェクトを Private にしてください。
- 本番環境は公開のまま、プレビューのみ保護する → Previews only/Non-production deploys only を対象にします。
- サイトを閲覧するために SSO を必須にする → Only SSO allowed (strict) を設定した Organization/Team SSO を有効にしてから、Password Protection で Team login protection を設定します。
- どのチームメンバーがリクエストを送ったかを特定する → プライベートプロジェクトまたはチームログイン保護を使い、関数/エッジ関数で
context.userを読み取ります(基本的なパスワード保護ではドキュメント化されていません)。 - 複数のパスワードで特定のページ/セクションを保護する → Basic authentication with custom HTTP headers(旧称:Selective password protection):https://docs.netlify.com/manage/security/secure-access-to-sites/basic-authentication-with-custom-http-headers/
- 独自のエンドユーザーを認証する → Netlify Identity/OAuth provider tokens/Role-based access control with JWT → netlify-identity に案内してください。
- 悪意のある/自動化されたトラフィックや AI クローラーをブロックする → Advanced Web Security(WAF/Firewall Traffic Rules/レート制限)または User Agent Blocker 拡張機能:https://docs.netlify.com/build/build-with-ai/block-ai-crawlers/
主な違い:Private と Password
- Private では、Netlify の認証情報によるログインが必須です。共有パスワードはありません。メールで招待します。チームメンバーのみがアクセスする場合におすすめです。
- Password は、誰でも使える共通の共有パスワードです(管理チームのメンバーも入力する必要があります)。SSO は利用できません。訪問者個人を識別することもできません。
- チームログイン保護 は Private と同じ仕組みです。訪問者は Netlify チームのメンバーとしてログインする必要があり、招待した レビュアー もアクセスできます(人数は無制限で、従来のプランではメンバー数に含まれません。クレジットベースのプランでは Pro 以上が必要です)。Git コントリビューターはログインできません。Developer にアップグレードするのではなく、レビュアーとして招待してください。
訪問者の識別:context.user
チームログイン保護 を有効にしている場合、またはプライベートプロジェクトでは、関数とエッジ関数で、ログイン済みの Netlify ユーザーを context.user として取得できます。フィールドを推測せず、https://docs.netlify.com/build/functions/api/#user および https://docs.netlify.com/build/edge-functions/api/#user を参照してください。
SSO セッションで発生する問題:1 時間ほどで 401 が返る
SSO で保護されたサイトで、ユーザーから「セッション中にログアウトされた」または 401 が返るという報告があった場合:SSO 認証トークンは 1 時間で期限切れになり、その後のリクエストは 401 を返します。SSO 保護を設定したサイトでは Netlify-Site-Protection-Expires-In ヘッダーが返されます。この値は、リクエストのトークンが期限切れになるまでの秒数です。期限切れになる前に更新してください。
// Client-side. Checks the Netlify SSO protection header and reloads before expiry.
const res = await fetch(window.location.href, { method: "HEAD" });
const secondsLeft = Number(res.headers.get("Netlify-Site-Protection-Expires-In"));
// Tokens last 1 hour (3600s). Reload a bit early to avoid a 401.
if (!Number.isNaN(secondsLeft) && secondsLeft < 60) {
window.location.reload();
}
UI のパス(唯一の方法 — API はありません)
クレジットベースのプラン(Free、Personal、Pro) — プロジェクト単位の「パスワード保護」は、プロジェクトの公開範囲 に置き換えられています。
- プロジェクト単位:Project configuration > General > Visitor access > Project visibility —
https://app.netlify.com/projects/{site_name}/configuration/general/#project-visibility。公開範囲を編集 → (チームのデフォルトがある場合は Customize)→ Public / Password(Pro のみ)/ Private → Preview access(Production and previews / Previews only)を設定 → Save。 - Free と Personal には Password オプションがありません。閲覧者を制限するには Private を使用します(チームオーナーのみ表示でき、他のユーザーの招待には Pro が必要です)。
- チームのデフォルト:Team settings > General > Visitor access > Default project visibility —
https://app.netlify.com/teams/{team_name}/settings/general#default-project-visibility。選択肢:新規プロジェクトを Private にする / すべてのプロジェクトを Private にする / 新規プロジェクトを Public にする。 - ここにはチーム単位のデフォルトの パスワード 設定はありません。プロジェクトごとにパスワードを設定してください。
Enterprise / Open Source / レガシー(クレジットベースではないプラン) — Password Protection UI を使用します。
- サイト単位:Project configuration > General > Visitor access > Password Protection —
https://app.netlify.com/projects/{site_name}/configuration/general#visitor-access。設定 → Basic または Team login → 適用範囲(All deploys / Non-production deploys only)→ Save。 - チームのデフォルト:Team settings > Access & security > Visitor access > Default Password Protection settings —
https://app.netlify.com/teams/{team_name}/settings/access#default-site-protection-settings。独自の設定がないすべてのサイトに適用されます。
レガシーからクレジットベースへの対応関係: 保護なし→Public · Basic protection→Password(Pro のみ)· Team protection→Private · All deploys→Production and previews · Non-production deploys only→Previews only。
制約事項と注意点
- サイト単位のパスワード保護は、チームのデフォルト設定より優先されます。
- これらの設定を変更できるユーザー: プロジェクトの公開範囲 —(一部の Enterprise プランでは)Organization Owner、Team Owner、およびそのプロジェクトへのアクセス権を持つ Developer。Internal Builder は本番環境に公開できないため、プロジェクトを公開状態にできません。 パスワード保護 — Developer はサイトごとに変更し、Team Owner はチームのデフォルト設定を行います。
- 高度な Web セキュリティは、パスワード/ログインのプロンプトより先に実行されます — ブロックされた IP は、プロンプトを見る前にエラーページに到達します。内部での順序:Firewall Traffic Rules → WAF → Rate limiting。
- サードパーティの Webhook(Slack、Stripe など)は、非公開プロジェクトにアクセスできません — Webhook を受信するには、プロジェクトを公開する必要があります。
- 公開するには、本番環境へのデプロイが少なくとも 1 回成功している必要があります。
- パスワード保護の対象を非本番環境へのデプロイのみにする機能は、Enterprise 専用です。
- プランによる制限: サイト全体の基本的なパスワード保護 → すべての Pro プラン。パスワード保護のすべてのオプション → Enterprise。クレジットベースの Free/Personal では、パスワード保護を利用できません。 プロジェクトの公開範囲(公開/非公開、デフォルトで非公開)→ クレジットベースの Free/Personal/Pro のみ。パスワード保護された公開範囲 → Pro のみ。Free/Personal では、非公開プロジェクトを表示できるのは Team Owner のみです(1 シート)。Pro ではメンバー数に制限がありません。
- チームのデフォルト設定は作成日により異なります: 2026 年 7 月 28 日以降に作成されたチームでは、新しいプロジェクトのデフォルトは非公開です。それ以前に作成されたチームのデフォルトは公開です。
- 名称変更: 「site-wide password protection」(パスワード保護オプションの旧名称)。「Selective password protection」→ カスタム HTTP ヘッダーを使用した基本認証。
参照先:https://docs.netlify.com/manage/security/secure-access-to-sites/overview/ · https://docs.netlify.com/manage/security/secure-access-to-sites/password-protection/ · https://docs.netlify.com/manage/security/secure-access-to-sites/project-visibility/
Netlify の独自ルール(アクセス制御)
これらはドキュメント上の事実ではなく、組織内の規約です。ctx-gen によりレンダリングされたスキルに統合され、生成されることはありません。スキルのメンテナーが管理します。
- これはルーティングと切り分けのためのスキルです。範囲を絞り、適切な保護レイヤーを選ぶことに専念してください。それぞれのレイヤーについて解説する役割ではありません。
- Password-Protection と Identity を組み合わせたパターンは、このスキルの
references/two-layer-pattern.mdに記載されています。 - Netlify の「Auth」には、ユーザーが常に混同する、互いに無関係な3つのレイヤーがあります。Netlify Identity(「アプリ内でこのユーザーが誰か」—
nf_jwtを発行します)、Password Protection/プロジェクトの公開範囲(「このリクエストでサイトを読み込めるか」)、Team/Org の SAML SSO(「Netlify ダッシュボードにログインできるか」)です。セッションは別々です。同じプロバイダー(Google)が、互いに無関係な2つの場所に使われることもあります。アプリユーザー向けの Identity OAuth と、チームメンバー向けの SAML IdP です。何かを推奨する前に、違いを明確にしてください。 - チームログインまたは非公開プロジェクトのセッションと、Identity のアプリセッションの間では、二重ログインが実際に発生します。Cookie の共有もヘッダーの転送も JWT の交換もありません。この2つを連携させるための試行に時間をかけないでください。トレードオフは
references/two-layer-pattern.mdに記載されています。Netlify のログイン自体はアプリコードにも到達します。非公開プロジェクト、またはチームログイン保護が有効な場合、関数とエッジ関数は、サインイン済みの Netlify ユーザーをcontext.userとして受け取ります。アプリを使う全員がそのログインを通過できるなら、それがアプリの ID となるため、2回目のログインは不要です。 - これらの設定には、公開 API も CLI コマンドも MCP ツールもありません。設定の確認や変更のために
api.netlify.comを curl したり、ローカルの認証トークンを読み取ったりしないでください。ダッシュボードの場所とチェックリストを案内し、失敗した場合は試した内容を伝えて、そこで止めてください。 - アプリユーザー向けの Identity の設定、認証コード、OAuth プロバイダーは netlify-identity スキルの対象です。そちらに案内してください。このスキルはレイヤーの選択のみを扱います。
- サインインを1回にしたい社内アプリの場合、まず誰が使うのかを確認してください。プロジェクトの Netlify ログインを通過できるなら、非公開プロジェクト(Credit ベースのプランでは、Team Owner 以外は Pro)またはチームログイン保護(Enterprise)を推奨し、関数で
context.userを使ってユーザーごとの動作を実装します。Netlify シートを持たない従業員など、通過できないユーザーがいる場合は、2層構成より先に、企業の IdP とフェデレーションする Auth0 extension を推奨します。 - 説明文のトリガーには、ユーザーが実際に報告する SSO セッションの症状、つまり「セッション中にログアウトした」、SSO で保護されたサイトでの 401、トークンの期限切れ/更新を含める必要があります。設定に関する表現だけでは不十分です。症状をトリガーに含めないと、
Netlify-Site-Protection-Expires-Inのガイダンスにたどり着けません。 - チームログイン保護では Git Contributors が除外されます。その場合の回答は必ず Reviewers としてください。Developer シートを案内してはいけません。Reviewers はチームログイン保護されたデプロイを開けます。従来のプランでは人数無制限でメンバー数にも含まれず、Credit ベースのプランでは Pro 以上が必要です。Git Contributor のアクセスに関する回答では、必ず Reviewer の方法を案内してください。Developer へのアップグレードを勧めるのは、製品がすでに無料で解決できる問題に対して、1人ずつ有料シートを販売することになります。このルールが防ごうとしている失敗は、除外だけを伝えて解決策を示さないことです。実際に起きています。許可されるロールを「X、Y、Z のみ」のような閉じたリストとして説明しないでください。後から Reviewer の方法を追加しても、閉じたリストは Reviewers が締め出されているように読めるため、エージェントがその説明を繰り返します。ロール名を挙げる必要はありません。通常、質問は Git Contributors についてのみです。
- 設定方法だけでなく、誰が変更できるかも伝えてください。プロジェクトの公開範囲を変更できるのは、Organization Owners(一部の Enterprise プランの場合)、Team Owners、およびそのプロジェクトへのアクセス権を持つ Developers です。Internal Builders は本番環境に公開できないため、プロジェクトを公開状態にできません。Password Protection を変更できるのは、サイトごとに Developer、チームのデフォルト設定では Team Owner です。権限のない人にチェックリストを渡しても、先に進めません。