ここ最近のAIの動きから、自分しか使わないWebアプリケーションが気軽に作れるようになりました。
特に、Cloudflare Workersでもフロントエンドを持つアプリが作成できるようになったため、まずはCloudflare Workersの利用を考えることが多いです。
フロントエンド、バックエンド、データベースが1つのCloudflare Workerに
自分しか使わないとはいえ、データベース的なものがある場合はセキュリティ的な面から認証を設定したいのですが、アプリごとに認証機能を付けるのも手間です。
認証まわりを調べてみたところ、Cloudflare Accessを使うことで、GoogleなどのIdPによる認証に加え、「特定のGoogleアカウントのみアクセスを許可する」もできそうでした。
Overview · Cloudflare One docs
事例を調べたところ、Cloudflare PagesのアプリにAccessで制限をするのような記事がいくつかありました。
- Cloudflare Pages でプレビュー画面に Google 認証を設定する
- Cloudflare Pages に Cloudflare Access をつける - そばちゃ
- Cloudflare Access + Pagesで自分のみアクセスできるようにする - notebook
そこで、「Cloudflare Workersで作ったページに対して、特定のGoogleアカウントだけアクセス可能にする」を試してみたときのメモを残します。
目次
環境
- 各種アカウントは取得済
- Cloudflareアカウント
- Googleアカウント
- Cloudflare One
- 設定を追加する際、無料プランであってもクレカ情報の登録が必要
- PayPalやStripeのアカウントを紐づける形でも可
- 設定を追加する際、無料プランであってもクレカ情報の登録が必要
- Hono 4.11.0
- jose 6.1.3
- Node.js 24.12.0
- Cloudflare C3 2.59.0
- Wrangler 4.54.0
Webアプリの準備
Hono製アプリの作成
今回は「Webアプリにアクセスできるかどうか」だけを確認できればよいです。そこで、Hello, world的なHono製アプリをCloudflare Workersで用意します。
HonoでCloudflare Workers向けWebアプリを作る場合、HonoのドキュメントとCloudflareのドキュメントの2つが参考になります。
Cloudflareのドキュメントでは「テンプレートを使ってHono + Reactなアプリを作る」方法しか書かれていません。しかし、CLIのページを読むとテンプレートなしでHonoも作れそうでした。
Get started - CLI · Cloudflare Workers docs
本当にCreate Cloudflare CLI (C3)でHonoを使えるか気になったので、今回はCloudflareのドキュメントに従って進めます。
ちなみに、C3を使った場合、途中で create-hono@0.19.3のインストール確認がありました。そのため、最終的にはCloudflareのドキュメントのやり方は、Honoのドキュメントのやり方を包含してそうです。
C3を実行するときのプロジェクト名でアンダースコア(_)を使うと
ERROR Error: Project names must only contain lowercase characters, numbers, and dashes.
とエラーになるため、ハイフン区切りのプロジェクト名 hello-worker-with-accessでWebアプリを作ります。
% npm create cloudflare@latest -- hello-worker-with-access > npx > "create-cloudflare" hello-worker-with-access ────────────────────────────────────────────────────────────────────────────────────────────────────────── 👋 Welcome to create-cloudflare v2.59.0! 🧡 Let's get started. 📊 Cloudflare collects telemetry about your usage of Create-Cloudflare. Learn more at: https://github.com/cloudflare/workers-sdk/blob/main/packages/create-cloudflare/telemetry.md ────────────────────────────────────────────────────────────────────────────────────────────────────────── ╭ Create an application with Cloudflare Step 1 of 3 │ ├ In which directory do you want to create your application? │ dir ./hello-worker-with-access │ ├ What would you like to start with? │ category Framework Starter │ ├ Which development framework do you want to use? │ framework Hono │ ├ Select your deployment platform │ platform Workers with Assets │ ├ Continue with Hono via `npx create-hono@0.19.3 hello-worker-with-access --template cloudflare-workers --install --pm npm` │ Need to install the following packages: create-hono@0.19.3 Ok to proceed? (y) create-hono version 0.19.3 ✔ Using target directory … hello-worker-with-access ✔ Cloning the template ✔ Installing project dependencies 🎉 Copied project files Get started with: cd hello-worker-with-access ├ Copying template files │ files copied to project directory │ ╰ Application created ╭ Configuring your application for Cloudflare Step 2 of 3 │ ├ Installing wrangler A command line tool for building Cloudflare Workers │ installed via `npm install wrangler --save-dev` │ ├ Retrieving current workerd compatibility date │ compatibility date 2025-12-13 │ ├ Adding Wrangler files to the .gitignore file │ updated .gitignore file │ ├ Updating `package.json` scripts │ updated `package.json` │ ├ Generating types for your application │ generated to `./worker-configuration.d.ts` via `npm run cf-typegen` │ ├ Do you want to use git for version control? │ yes git │ ├ Initializing git repo │ initialized git │ ├ Committing new files │ git commit │ ╰ Application configured ╭ Deploy with Cloudflare Step 3 of 3 │ ├ Do you want to deploy your application? │ no deploy via `npm run deploy` │ ╰ Done ──────────────────────────────────────────────────────────── 🎉 SUCCESS Application created successfully! 💻 Continue Developing Change directories: cd hello-worker-with-access Deploy: npm run deploy 📖 Explore Documentation https://developers.cloudflare.com/workers 🐛 Report an Issue https://github.com/cloudflare/workers-sdk/issues/new/choose 💬 Join our Community https://discord.cloudflare.com ────────────────────────────────────────────────────────────
生成されたアプリのディレクトリへ移動した上で起動してみます。
# ディレクトリの移動 % cd hello-worker-with-access # 起動 % npm run dev > dev > wrangler dev ⛅️ wrangler 4.54.0 ─────────────────── Your Worker has access to the following bindings: Binding Resource Mode env.ASSETS Assets local ╭──────────────────────────────────────────────────────────────────────╮ │ [b] open a browser [d] open devtools [c] clear console [x] to exit │ ╰──────────────────────────────────────────────────────────────────────╯ ⎔ Starting local server... [wrangler:info] Ready on http://localhost:8787
表示されたURLにアクセスすると、Hello Hono! が表示されました。
ログも出力されていました。
[wrangler:info] GET / 200 OK (23ms) [wrangler:info] GET /message 200 OK (8ms) [wrangler:info] GET /favicon.ico 404 Not Found (2ms)
Cloudflare Workersへのデプロイ
ローカルで動作確認ができたため、次はCloudflare Workersへデプロイして動作確認を行います。
C3でプロジェクトを作成するとWranglerがインストールされたため、Wranglerを使って、Cloudflare Workersへデプロイします。
% npx wrangler deploy ⛅️ wrangler 4.54.0 ─────────────────── Attempting to login via OAuth... Opening a link in your default browser: https://dash.cloudflare.com/*** Successfully logged in. 🌀 Building list of assets... ✨ Read 1 file from the assets directory /path/to/hello-worker-with-access/public 🌀 Starting asset upload... 🌀 Found 1 new or modified static asset to upload. Proceeding with upload... + /index.html Uploaded 1 of 1 asset ✨ Success! Uploaded 1 file (0.88 sec) Total Upload: 60.58 KiB / gzip: 14.79 KiB Your Worker has access to the following bindings: Binding Resource env.ASSETS Assets Uploaded hello-worker-with-access (7.28 sec) Deployed hello-worker-with-access triggers (1.93 sec) https://hello-worker-with-access.***.workers.dev Current Version ID: 7c74e6fd-7d03-424d-8047-859ce08471fe
デプロイで作成されたURLへアクセスすると、ローカル同様のページが表示されました。
Cloudflare AccessによるGoogle認証制御の追加
続いて、Cloudflare Accessを使って、特定のGoogleアカウントのみアクセスを許可します。
Cloudflare Oneにチームを作成
まずは、Cloudflare Oneにチームを作ります。
Settings > Team name and domain にてチームを追加します。
team nameは任意の値Add payment methodでクレカ情報を設定- 今回はPayPalアカウントを紐づけ
Google Cloud Consoleでプロジェクトを作成
Google認証をWebアプリケーションへ追加するには、Google Cloud Consoleにてプロジェクトの作成が必要です。ただし、「プロジェクトを作成したGoogleアカウントのみGoogle認証を使える」わけではなく、すべてのGoogleアカウントに対するGoogle認証が使えます。
どのようなプロジェクトを作ればよいかについては、Cloudflareのドキュメントに記載があります。
Google · Cloudflare One docs
今回もCloudflareのドキュメントに従い、次の流れで設定を行いました。
- Google Cloud Consoleでプロジェクトを作成
- 名前は任意
APIとサービス> サイドバーの認証情報で移動同意画面を構成ボタンをクリック開始ボタンをクリック- アプリ情報で以下を設定
- アプリ名
- 任意
- ユーザーサポートメール
- ドロップダウンで選択
- アプリ名
- 対象にて、
外部を選択 - 連絡先情報は、任意のメールアドレスを入力
Google APIサービスに同意して完了
設定が終わるとOAuthの概要ページになるため、引き続きOAuthクライアントを作成します。
- 指標にある
OAuthクライアントを作成をクリック - 以下を設定し、
作成ボタンをクリック- アプリケーションの種類
- 名前
- 任意
- 承認済みの JavaScript 生成元
URIを追加ボタンをクリックし、以下の内容を追加https://<Cloudflareのチーム名>.cloudflareaccess.com
- 承認済みのリダイレクト URI
URIを追加ボタンをクリックし、以下の内容を追加https://<Cloudflareのチーム名>.cloudflareaccess.com/cdn-cgi/access/callback
以上でGoogle Cloud Consoleでの作業は終わりです。
Cloudflare OneでIdpを登録
次に、Cloudflare AccessでGoogle認証を使えるよう、GoogleのIdPを登録します。
Identity providers · Cloudflare One docs
- 左メニューの
Integrations>Identity providers Add an identity providerをクリックGoogleを選択App IDにClient ID、Client secretにClient Secretを設定- 合わせて、
PKCEをONにする
- 合わせて、
Saveをクリック
IdPが登録できたところで動作確認をします。
Cloudflare Oneでアプリケーションを追加
続いて、Googleアカウントでの認証を要求するアプリケーションを追加します。公式ドキュメントによると、追加するアプリケーションの種類は Self-hosted になるようです。
Add web applications · Cloudflare One docs
Self-hostedの設定手順は以下のドキュメントになります。
Publish a self-hosted application to the Internet · Cloudflare One docs
左メニューの Access controls > Application をクリックし、Add an application をクリックします。
ウィザード形式で設定を行います。なお、記載されていないものはデフォルト設定のままとします。
- What type of application are you adding?
Self-hosted
- Configure application
- Basic information
- Application name
- 任意
- Session Duration
- デフォルト
- 24h
- デフォルト
- Public hostname
- Domainには、先ほどデプロイしたドメインを選択
- Subdomainには、アプリ名
hello-worker-with-accessを設定
- Application name
- Login methods
- Accept all available identity providers
- Off
- One-time PINは無効化する
- 表のProviderでは
Googleのみ選択
- Off
- Instant Auth
- On
- 1つしか選択できないので、プロバイダーの選択は表示しない
- On
- Accept all available identity providers
- Nextボタン
- Basic information
- Experience settings
- Application Appearance
- Application logo
- Default
- Application domain
- Default
- Application logo
- Tags
- デフォルトのまま、何も選択しない
- Custom pages
- Identity failure block page
- Cloudflare default
- Non-identity failure block page
- Cloudflare default
- Identity failure block page
- Nextボタン
- Application Appearance
- Advanced settings
- 特に設定しない
- Save
Cloudflare Oneでポリシーを追加・適用
アプリケーションを追加しただけでは、まだ誰もアクセスできない状態です。
ポリシーを作成・紐づけを行うことで、特定のGoogleアカウントのみアクセスできるようになります。
Manage Access policies · Cloudflare One docs
まず、ポリシーを作成し、アクセスできるGoogleアカウントの設定を行います。
Applicationsをクリックし、追加されたものの3点リーダーからEditPoliciesタブをクリックAdd a policyをクリック- Basic Information
- Policy name
- 任意
- Action
- Allow
- Session duration
- Same as application session timeout
- Policy name
- Add rules
- Selector
- Emails
- Value
- アクセスを許可したいメールアドレス
- Selector
- Saveボタンをクリック
次に、Policyタブにて、Select existing policies から先ほど作成したポリシーを選択し、アプリとの紐づけを行います。
アクセストークンのバリデーション
ここまででも、特定のGoogleアカウントでのみアクセスを許可できました。
しかし、Cloudflareのドキュメントでは、アクセストークン検証の必要性についても記載されています。
Publish a self-hosted application to the Internet · Cloudflare One docs
そこで今回もアクセストークンの検証を実装します。
ちなみに、アクセストークンはJWT形式です。また、検証の方法はCloudflareのドキュメントに記載されています。
Validate JWTs · Cloudflare One docs
AUDタグの取得
アクセストークンを検証するときには AUD タグが必要になります。
ドキュメントにある通り、以下の方法で取得できます。
- 左メニューの
Access controls > Applicationsをクリック - 3点リーダーより、
Editをクリック - 下の方にある
Appilcation Audience (AUD) Tagにある、AUDタグの値をコピーして取得
Cloudflare Workersの環境変数へ設定
続いて、Cloudflare Workersの環境変数に
- Cloudflare AccessのteamのURL
- AUDタグ
をそれぞれ設定します。
% npx wrangler secret put CF_ACCESS_TEAM_DOMAIN ⛅️ wrangler 4.54.0 ─────────────────── ✔ Enter a secret value: … *** 🌀 Creating the secret for the Worker "hello-worker-with-access" ✨ Success! Uploaded secret CF_ACCESS_TEAM_DOMAIN % npx wrangler secret put CF_ACCESS_AUD ⛅️ wrangler 4.54.0 ─────────────────── ✔ Enter a secret value: … *** 🌀 Creating the secret for the Worker "hello-worker-with-access" ✨ Success! Uploaded secret CF_ACCESS_AUD
Honoアプリでアクセストークンの検証を追加
Honoアプリを以下の内容で修正します。
import { Hono } from "hono"; import { jwtVerify, createRemoteJWKSet } from 'jose' /** * Hono アプリで Cloudflare Access の JWT を検証する。 * Cf‑Access‑Jwt‑Assertion ヘッダーから取得した JWT を公開鍵で検証し、issuer と audience を照合する。 * https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/validating-json/ */ type EnvBindings = { CF_ACCESS_TEAM_DOMAIN: string // https://<team>.cloudflareaccess.com CF_ACCESS_AUD: string // アプリケーションの AUD タグ } type CfAccessVars = { cfAccessJwt?: { payload: Record<string, unknown> } } const app = new Hono<{ Bindings: EnvBindings; Variables: CfAccessVars }>(); // アプリ全体に適用するミドルウェア app.use(async (c, next) => { const teamDomain = c.env.CF_ACCESS_TEAM_DOMAIN const aud = c.env.CF_ACCESS_AUD // 必須の環境変数が設定されているかチェック if (!teamDomain || !aud) { return c.text('Missing required environment variables', 500) } // Cloudflare Access が付与する JWT を取得 const token = c.req.header('cf-access-jwt-assertion') if (!token) { return c.text('Missing CF Access JWT', 403) } // 公開鍵のリモートセットを取得 const jwks = createRemoteJWKSet(new URL(`${teamDomain}/cdn-cgi/access/certs`)) try { // JWT の検証 const { payload } = await jwtVerify(token, jwks, { issuer: teamDomain, audience: aud, }) // 検証成功時は payload をコンテキストに保存し次の処理へ c.set('cfAccessJwt', { payload: payload as Record<string, unknown> }) await next() } catch (err) { // 検証失敗時は 403 を返す return c.text('Invalid CF Access JWT', 403) } }) app.get("/message", (c) => { // ミドルウェアで保存した payload からメールアドレスなどを取り出す const jwt = c.get('cfAccessJwt') const payload = jwt?.payload || {} const email = (payload as any).email as string | undefined return c.text(`Hello ${email}`); }); export default app;
修正を終えたらデプロイします。
% npx wrangler deploy
以上でアクセストークンの検証も完了です。
動作確認
動作確認として、Cloudflare Accessが有効な状態の場合と無効な状態の場合を試してみます。
Cloudflare Accessが有効な状態の場合
アプリケーションのURLへアクセスすると、Google認証が求められます。
アクセスを許可したGoogleアカウントの場合、Cloudflare Workersの画面にメールアドレスが表示されました。
一方、アクセス許可を与えていないGoogleアカウントの場合、エラーになりました。
Cloudflare Accessが無効な状態の場合
Cloudflare Accessのドメイン設定が不適切だった場合など、Cloudflare Accessが無効な状態になっている想定で動作確認します。
今回の動作確認では、Cloudflare Accessのドメイン設定にてサブドメインの末尾に 2 を追加して、不適切な状態にします。
この状態でアプリへアクセスするとエラーになりました。画面に表示されたエラーメッセージから、Honoでのアクセストークン検証が失敗したようです。
これにより、何らかの原因でCloudflare Accessが無効になっていた場合も、アプリケーション側で防御できていると分かりました。
ソースコード
GitHubに上げました。
https://github.com/thinkAmi-sandbox/hello_cloudflare_worker_with_cloudflare_access-example





