「社内ツールや会員限定のページを、手軽にGoogleログインで守りたい」——そんなときに最速なのが Cloudflare Access(Zero Trust)です。
Accessは、サイトの前段にCloudflareが立って認証を代行する仕組みです。Googleを認証元(IdP)に設定すれば、コードを書かずに「Googleでログインした許可ユーザーだけ」にアクセスを限定できます。
この記事は Cloudflareとは?初心者向けガイド の関連記事です。コード不要で会員制(限定公開)サイトを作る手順をハンズオンで解説します。「登録・課金まで含む本格的な会員サイト」を自作したい場合は、姉妹記事の Workers + Google OAuthで会員サイトを自作する もあわせてご覧ください。
[目次を開く]
Cloudflare Access(Zero Trust)とは?
Cloudflare Accessは、CloudflareのZero Trust製品の一つで、アプリやサイトの手前に認証ゲートを置くサービスです。訪問者はまずCloudflareのログイン画面を通り、認証に成功した人だけが背後のサイトに到達できます。
最大の利点は、アプリ側に認証コードを書かなくてよいことです。既存の静的サイトやアプリに、あとから認証を被せられます。
訪問者 → Cloudflare Access(Googleでログイン)→ 許可ユーザーのみ → あなたのサイト
↑
未認証・限外ユーザーはここでブロック こんな用途に向く
- 社内ツール・管理画面の保護
- 顧客・会員限定のクローズドなページ
- 公開前のステージング環境を関係者だけに公開
注意:Accessは「入れる/入れない」を判定するアクセス制御です。会員登録フロー、プロフィール管理、課金などを持つ「本格的な会員サイト」を作りたい場合は、Workersでの自作(姉妹記事)が適しています。
料金
Accessを含むZero Trustには無料プランがあり、少人数なら無料で始められます(目安として3050人規模までの無料枠が提供されてきました。最新の人数・条件は公式で確認してください)。社内ツールや小規模な会員ゲートなら、まず無料枠で十分なケースが多いです。
事前に準備するもの
- Cloudflareで管理しているドメイン(ネームサーバー変更済み。未だなら入門記事を参照)
- 保護したいサイト/アプリ(例:Cloudflare Pagesで公開したサイト)
- Googleアカウント(認証に使う。Google CloudでOAuthクライアントを作成します)
ハンズオン:Google認証でサイトを守る
1. Zero Trustを有効化する
Cloudflareダッシュボードから「Zero Trust」を開き、初回はチーム名(例 your-team.cloudflareaccess.com)を設定します。これがログイン画面のドメインになります。
2. Googleを認証元(IdP)として追加する
まず Google Cloud Console で OAuth 2.0 クライアントを作成し、クライアントID / シークレットを取得します。リダイレクトURIには、Accessのコールバックを指定します。
https://<チーム名>.cloudflareaccess.com/cdn-cgi/access/callback 次にZero Trustの「Settings → Authentication → Login methods」で Google を追加し、上記のクライアントID/シークレットを登録します。(Google Workspaceを使えば、社内ドメイン全体を対象にできます。)
3. 保護するアプリを追加する
「Access → Applications → Add an application → Self-hosted」を選び、保護したいドメインやパスを指定します(例 members.example.com や example.com/members)。
4. ポリシー(許可ルール)を作る
「誰を入れるか」をポリシーで定義します。代表的な条件は次のとおりです。
| 条件(Include) | 例 |
|---|---|
| Emails | 特定のメールアドレスを個別許可 |
| Emails ending in | @example.com ドメイン全員を許可 |
| Google Groups | 特定のGoogleグループのメンバーを許可 |
例えば「@example.com のメールを持つ人だけ許可」とすれば、社内メンバー限定のサイトが完成します。
5. 動作を確認する
保護したドメインにアクセスすると、Cloudflareのログイン画面が表示され、Googleログインを要求されます。許可ユーザーでログインすればサイトが表示され、限外ユーザーは拒否されます。
動作確認をコマンドで行う(ブラウザの Cookie に惑わされない)
ブラウザは以前のログイン状態(Cookie)を持っているので、「保護できているか」は Cookie を持たない curl で確かめるのが確実です。保護したホスト名を変数に入れて実行します。
HOST=members.example.com # 保護したホスト名に置き換える
curl -sI "https://$HOST/" | grep -iE '^(HTTP|location)' 期待する結果は次の2行です。ステータスが 302 で、location にチーム名ドメインの /cdn-cgi/access/login/ が出ていれば、Access が前段で止めています。
HTTP/2 302
location: https://<チーム名>.cloudflareaccess.com/cdn-cgi/access/login/... ここで 200 とサイト本体の HTML が返るなら、そのホスト名は保護されていません。次の表で切り分けます。
設定したのに入れてしまう/ログイン画面が出ない時の切り分け表
| 症状 | まず疑う原因 | 確認する場所 |
|---|---|---|
curl で 200 が返り、サイトが素通しになる | DNS レコードがプロキシ(オレンジ雲)になっていない。Access は Cloudflare を経由した通信にしか掛からない | DNS の該当レコードが「Proxied」になっているか |
別のホスト名では 302 になるのに、このホスト名だけ 200 | Application の対象ドメイン/パスと、実際にアクセスしているホスト名が違う(www の有無、サブパスの綴り) | Access → Applications の Application domain |
Google 側で Error 400: redirect_uri_mismatch | Google Cloud の OAuth クライアントに登録したリダイレクト URI が、Access のコールバック(/cdn-cgi/access/callback)と1文字でも違う | Google Cloud Console → 認証情報 → 承認済みのリダイレクト URI |
| Google ログイン後に「アクセスが拒否されました」になる | ポリシーの Include にそのメールアドレスが当たっていない(個人の Gmail なのに Emails ending in で会社ドメインだけ許可している、など) | Zero Trust → Logs → Access で拒否されたリクエストの理由を見る |
| ログイン画面が何度も出る(ループする) | ブラウザがサードパーティ Cookie をブロックしている、または Application のドメインとアクセス先ホスト名が食い違い、Cookie が別ホストに発行されている | シークレットウィンドウで再現するか試す。Application domain を見直す |
curl や CI からのアクセスだけ常にログイン画面へ飛ばされる | 人間向けの Google ログインは自動化からは通れない | Service Token を発行し、ID とシークレットをヘッダーで送る(次のコマンド) |
自動化からの疎通確認は、Zero Trust → Access → Service Auth でトークンを発行し、ポリシーに Service Auth の許可を足したうえで次のように呼びます。
curl -sI "https://$HOST/" \
-H "CF-Access-Client-Id: $CF_CLIENT_ID" \
-H "CF-Access-Client-Secret: $CF_CLIENT_SECRET" | head -1 200 が返れば、トークン経由で Access を通過しています。ブラウザで 302 が返るのにここで 200 になる状態が正常です。
ログインできたのに「誰が来たか」がアプリで取れない時
Access を通ったリクエストにはヘッダー Cf-Access-Jwt-Assertion が付きます。アプリ側のログにこのヘッダーの有無を1行出力し、空なら「Access を経由していない経路」を疑ってください。オリジンサーバーが IP 直打ちで届く構成では Access は迂回できるので、オリジン側で Cloudflare の IP レンジ以外を拒否するか、Cloudflare Tunnel 経由でオリジンを公開するのが定石です。
アプリ側でログインユーザーを識別する
Accessを通過したリクエストには、Cloudflareが署名付きのJWTを付与します。アプリ側で「誰がログインしているか」を知りたい場合は、リクエストヘッダー Cf-Access-Jwt-Assertion を検証します。簡易的には、Accessが提供するエンドポイントからユーザー情報を取得できます。
GET https://<チーム名>.cloudflareaccess.com/cdn-cgi/access/get-identity これにより、ログインしたユーザーのメールアドレスなどをアプリで受け取り、「さん、ようこそ」のような個別表示も可能になります。
よくあるつまずき(FAQ)
Q. 設定したのに誰でも入れてしまう
ポリシーの Include が広すぎる可能性があります。「Emails ending in」や個別メールなど、絞り込み条件を見直してください。ポリシーが未設定だとアプリは保護されません。
Q. 一部のページだけ保護したい
Applicationのパス指定で example.com/members のようにサブパスを対象にできます。公開部分と会員部分をパスで分けましょう。
Q. ログアウトさせたい
/cdn-cgi/access/logout へのリンクでセッションを終了できます。セッションの有効期間はApplication設定で調整可能です。
Q. Accessだけで会員サイトは完成する?
「限定公開(許可した人だけ見られる)」ならAccessだけで完成します。一方で、一般ユーザーのセルフ登録やプロフィール・課金が必要なら、次の姉妹記事の自作アプローチが適しています。
まとめ
Cloudflare Accessを使えば、コードを書かずに、Googleログインでゲートした限定公開サイトを最短で作れます。要点を振り返ります。
- Accessはアプリの前段で認証を代行し、コード不要
- GoogleをIdPに設定し、ポリシーで許可ユーザーを絞る
- 少人数なら無料枠で始められる
- アプリ側では
Cf-Access-Jwt-Assertionや get-identity でユーザーを識別できる
「まずは限定公開だけで十分」ならAccess、「登録・課金もある本格的な会員サイト」なら次の記事へ進みましょう。
あわせて読みたい:
