設計案 v1.1 ・ 2026年10月23日
フォークリフト部門のダッシュボードを、使う人それぞれが自分の kintone アカウントでログインして見る仕組みの設計案です。アプリには特定の人の権限(APIトークンやパスワード)を持たせず、見ている人本人が kintone で閲覧できる範囲だけを表示します。次回の打ち合わせでは、6. 確認・決めることを中心にご相談させてください。
このページの設計どおりにログインの仕組みを実装したダッシュボードを、検証用の模擬 kintone(架空のユーザー・データ)につないで公開しています。ユーザーを切り替えて見える範囲が変わるか、トークンが切れても自動で取り直すか、利用者の設定から外す・停止するとどうなるかを、画面で試せます。
ダッシュボード側のプログラムは、つなぎ先の URL を本物の kintone に変えるだけで同じように動く作りです。本物の kintone での確認(6 の項目2・手順6)は、別途必要です。
kintone のレコード取得 API は、ログインした人に閲覧権限のあるレコード・フィールドだけを返します 公式に記載。ダッシュボード側で権限を作り直す必要がありません。
ID・パスワードは kintone(cybozu.com)のログイン画面で入力します。アプリが受け取るのは、読み取り専用で1時間で切れる「鍵」(アクセストークン)だけです。
Cloudflare Pages の無料プランと、kintone の標準機能(OAuth)で組めます。ただし kintone で IP アドレス制限を使っている場合は構成が変わります(5)。
いまの API 連携アプリは、アプリを作った人の鍵(APIトークンなど)でデータを取る作りです。使う人全員が同じ鍵を使うため、人ごとに見える範囲を変えられません。
| 項目 | いまの作り(作った人の鍵を使う) | 新しい作り(各自の kintone でログイン) |
|---|---|---|
| 誰の権限で取るか | アプリを作った人・鍵を発行した人 | 画面を見ている本人 |
| 見えるもの | 使う人全員に同じ範囲が見える | 本人が kintone で見られるものだけ |
| 鍵の置き場所 | アプリの中(コード・設定ファイル) | 共通の鍵は Cloudflare の Secret、本人の鍵は本人のブラウザ(暗号化した Cookie) |
| 異動・退職のとき | アプリ側でも手当てが必要 | kintone の権限・ユーザーを変えれば反映 テストで確認 |
| 記録 | すべて鍵の持ち主の操作として残る | REST API の実行は kintone の監査ログに残る 公式に記載。本人の名前で残るかはテストで確認 |
図は横にスクロールできます。
Cookie の暗号化には SESSION_KEY(Secret)を使います。トークンはサーバー側のどこにも保存しないため、データベース(KV など)は使いません。
cybozu.com 共通管理で IP アドレス制限を使っている場合、OAuth で API を使うには「クライアントアプリケーションの IP アドレス」を許可する必要があります 公式に記載。一方、Cloudflare の Pages Functions(Workers)が外へ通信するときの送信元 IP を固定する方法は、通常のプランでは公式ドキュメントに見当たりません。固定 IP は有料の追加製品(Smart Shield の専用 IP、Zero Trust Enterprise の専用 egress IP)の扱いです 公式に記載。
案B の通信経路(④⑦の部分だけが変わります)
| # | 確認・決めること | なぜ必要か |
|---|---|---|
| 1 | 共通管理の IP アドレス制限を使っているか | 案A/案B が決まります(5) |
| 2 | 2要素認証・SAML(シングルサインオン)を使っているか | ログイン画面の動きが変わる可能性があります。2要素認証はパスワード認証の API を止めますが、OAuth は別の方式なので使える見込みです 推測・テストで確認 |
| 3 | cybozu.com 共通管理者はどなたか | OAuth クライアントの追加は共通管理者しかできません(手順2) |
| 4 | 対象のアプリ(フォークリフト整備スペースのどのアプリか)と、見たい数字・グラフ(3〜5個) | 画面の設計と、受け付けるアプリ番号を決めます |
| 5 | 使う人と端末(人数、PC かスマホか、社外から見るか) | 「利用者の設定」に入れる人と、Cloudflare Access を付けるかを決めます(Access の無料プランは50人まで) |
| 6 | 見るだけでよいか(kintone への書き込みは不要か) | 読み取りだけの権限(k:app_record:read)に絞ります。書き込みの権限(k:app_record:write)には、レコードの削除も含まれます 公式に記載 |
| 7 | Cloudflare のどのアカウントで作るか、URL をどうするか | 車両アプリと同じアカウントで、別プロジェクトにするのが管理しやすい形です。URL は ○○.pages.dev のままでも使えます |
| 8 | いまのアプリが使っている API トークン・パスワードの扱い | 切り替え後に無効化します(手順7) |
担当は案です。御社=開発のご担当者、共通管理者=cybozu.com 共通管理者、デジライズ=設計・プロンプト・確認。
各手順の[Claude Code に打つプロンプト]を開いてコピーし、<>の部分を置き換えて貼り付けます。どのプロンプトも、作業の前に内容を日本語で説明させ、承認してから実行させる形にそろえています。
6 の8項目を確認します。IP アドレス制限の有無で案A/案B を決めます。あわせて、いまのアプリが kintone の鍵(API トークン・パスワード)をどこに持っているかを Claude Code に調べさせます(項目8の材料)。
これから、各自の kintone アカウントでログインして見るダッシュボードを作ります。その前に、いまのアプリの状態を調べてください。 作業の前に、何を調べるかを日本語で説明し、私の承認を待ってから実行してください。ファイルの変更・削除はしないでください。 【調べること】 1. このフォルダのコードで、kintone に接続している箇所(URL・アプリ番号・使っている API)を一覧にする 2. kintone の API トークン・パスワード・ログイン名が、どのファイルのどこに書かれているかを一覧にする (値そのものは表示しない。ファイル名と行番号だけ) 3. kintone をブラウザから直接呼んでいるのか、サーバー側から呼んでいるのかを分けて書く 【出力】 - 上の3点を表にまとめる - 新しい仕組みに切り替えたあとで、無効化・削除が必要になるもの(トークン・パスワード・ファイル)の候補を最後に並べる
案と対象アプリ、使う人の範囲が決まり、いまのアプリの鍵の置き場所が一覧になっている
見たい数字ごとに「どのアプリのどのフィールドから、どう集計するか」の対応表と、ダミーデータで動く画面の下書きを作ります。御社で確認いただいてから実装に入ります。フィールドの一覧は、kintone のアプリの[設定]→[フォーム]で、フィールド名とフィールドコードを確認して貼り付けます。
フォークリフト整備のダッシュボードの「対応表」と「画面の下書き」を作ります。 作業の前に、何を作るかを日本語で説明し、私の承認を待ってから実行してください。 【材料】 - kintone のアプリ:<アプリ名・アプリ番号> - フィールドの一覧(フィールド名とフィールドコード):<貼り付け> - 見たい数字・グラフ:<3〜5個を貼り付け> 【作るもの】 1. 対応表:見たい数字ごとに「どのフィールドを使い、どう集計するか(件数・合計・期間・絞り込み)」を表にする。 必要なフィールドがない数字は「不足」と書く 2. 画面の下書き:mock/index.html に、ダミーデータで動く1枚の HTML を作る(kintone にはまだ接続しない) 【守ること】 - 実データ・お客様名・社員名は使わない。ダミーデータは架空の値にする - 外部のライブラリは使わず、グラフは SVG で描く - スマホの幅でも崩れないようにする
対応表と画面の下書きに御社の了承がある
この手順は kintone の画面での操作です。Claude Code には、共通管理者への依頼メモを作らせます。クライアントシークレットはメール・チャットに貼らず、手順3で Cloudflare に直接登録します。
cybozu.com 共通管理者に、OAuth クライアントの追加をお願いするための依頼メモを作ってください。 ファイルは作らず、チャットに本文を出してください。 【入れる内容】 - 操作の場所:cybozu.com 共通管理 →[OAuth]→「高度な連携を設定する」→[OAuthクライアントの追加] - クライアント名:<例:フォークリフト ダッシュボード> - リダイレクトエンドポイント:https://<プロジェクト名>.pages.dev/auth/callback - 保存後に、編集アイコンからクライアント ID とクライアントシークレットを確認していただくこと - [利用者の設定]でチェックを入れる人:<名前の一覧> (あとから入社・異動した人は、その都度追加が必要なこと) - クライアントシークレットはメールやチャットに貼らず、Cloudflare の管理画面に直接入力すること 【守ること】 - 推測で手順を足さない。分からない点は「確認事項」として最後に分けて書く
クライアント ID・シークレットが発行され、利用者が設定されている
新しい Pages プロジェクトを作り、次の値を登録します。CLIENT_SECRET だけは、Claude Code を通さず、御社が Cloudflare の管理画面([Settings]→[Variables and Secrets])で入力します。
Cloudflare Pages に、ダッシュボード用の新しいプロジェクトを作り、設定値を登録します。
作業の前に、実行するコマンドを日本語で説明し、私の承認を待ってから実行してください。
【前提】
- Cloudflare アカウント:<車両アプリと同じアカウント>
(npx wrangler whoami で確認する。アカウントが複数あるときは、どれを使うか私に確認する)
- プロジェクト名:<プロジェクト名>
- kintone の URL:https://<サブドメイン>.cybozu.com
- クライアント ID:<手順2のクライアント ID>
- 受け付けるアプリ番号:<番号>
【やること】
1. フォルダを作る:public/(画面)、functions/(サーバー処理)、wrangler.toml
2. wrangler.toml に次を書く
- name = <プロジェクト名>、pages_build_output_dir = "public"
- [vars] に KINTONE_BASE、CLIENT_ID、REDIRECT_URI(https://<プロジェクト名>.pages.dev/auth/callback)、APP_IDS
3. npx wrangler pages project create <プロジェクト名> --production-branch=main でプロジェクトを作る
(Workers への切り替えを勧める表示で止まったときは、私に報告してから --force を付けて作り直す)
4. SESSION_KEY を、値を画面に出さずに作って登録する
node -e "process.stdout.write(require('crypto').randomBytes(32).toString('base64url'))" | npx wrangler pages secret put SESSION_KEY --project-name <プロジェクト名>
【変えてはいけないこと】
- CLIENT_SECRET は扱わない。私が Cloudflare の管理画面で入力する
- 生成した SESSION_KEY を、ファイル・チャット・ログに残さない
本番 URL が決まり、手順2のリダイレクトエンドポイントと一致している。Secret が2つ登録されている
4 つの入口(/auth/login・/auth/callback・/api/records・/auth/logout)と、ログイン状態を返す /api/session を作ります。動作モックのダッシュボードと同じ作りです。
kintone の OAuth(認可コードグラント)を使い、各自の kintone アカウントでログインして見るダッシュボードのサーバー処理を、Cloudflare Pages Functions で作ります。
作業の前に、どのファイルに何を書くかを日本語で説明し、私の承認を待ってから実行してください。
【作るファイル】
1. functions/_lib/session.js(共通の処理)
- Cookie の暗号化と復号:Web Crypto(crypto.subtle)の AES-GCM。鍵は SESSION_KEY、IV は毎回ランダムな12バイト
- 復号できない Cookie(改ざん・鍵の差し替え後)は「未ログイン」として扱う
- トークンの取得:KINTONE_BASE/oauth2/token に POST
(Authorization: Basic base64(CLIENT_ID:CLIENT_SECRET)、Content-Type: application/x-www-form-urlencoded)
2. functions/auth/login.js
- ランダムな state を作り、HttpOnly・Secure・SameSite=Lax・Path=/auth・有効10分の Cookie に入れる
- KINTONE_BASE/oauth2/authorization へ移動させる
(client_id、redirect_uri、state、response_type=code、scope=k:app_record:read)
3. functions/auth/callback.js
- Cookie の state と URL の state が一致しなければ、400 の画面で止める
- URL に error が付いていたら、/ に戻してメッセージを出す
- 一致したら grant_type=authorization_code、redirect_uri、code でトークンを受け取る
- access_token・refresh_token・期限(今の時刻+expires_in 秒)を暗号化し、HttpOnly・Secure・SameSite=Lax の Cookie に入れて / へ戻す
4. functions/api/records.js
- アプリ番号が APP_IDS にないときは 400
- Cookie がなければ 401
- 期限の60秒前を過ぎていたら、grant_type=refresh_token で取り直す
(このとき新しいリフレッシュトークンは返らないので、手元のものを使い続ける)
- Authorization: Bearer で GET KINTONE_BASE/k/v1/records.json を呼び、結果をそのまま返す(query はそのまま渡す)
- kintone が 401 を返したら、1回だけ取り直して再実行する。取り直せなければ Cookie を消して 401
5. functions/api/session.js
- ログインしているか、アクセストークンの残り秒数、スコープだけを返す(トークンそのものは返さない)
6. functions/auth/logout.js
- Cookie を消して / へ戻す
【変えてはいけないこと】
- CLIENT_SECRET と SESSION_KEY はコードに書かず、context.env から読む。ログにも出さない
- トークンを localStorage など、画面の JavaScript から読める場所に置かない
- kintone への書き込み・削除の処理は作らない(スコープは k:app_record:read だけ)
- 集計はブラウザ側で行い、Functions は中継だけにする
【確認すること】
- ログインして、自分に見えるレコードの件数が kintone の画面と一致するか
- ログアウト後に /api/records が 401 になるか
- state を書き換えたアクセスが 400 になるか
ログインして、自分に見えるレコードの件数が kintone の画面と一致する
手順1の下書きを、本物のデータで動く画面にします。サーバー処理は中継だけにして、無料プランの処理時間の上限(1リクエストあたり CPU 10ミリ秒)に収めます。kintone から1回に取れるのは500件までなので、分けて取ります。
手順1で作った mock/index.html をもとに、本物のデータで動くダッシュボード画面を public/index.html に作ります。 作業の前に、画面の構成と処理の流れを日本語で説明し、私の承認を待ってから実行してください。 【作り方】 - 開いたら /api/session を呼び、ログインしていなければ「kintone でログイン」ボタン(/auth/login へのリンク)だけを出す - ログインしていたら /api/records?app=<アプリ番号>&query=... でデータを取る - query は「order by $id asc limit 500 offset N」とし、返った件数が500件未満になるまで N を500ずつ増やす - offset の上限は10,000件。超えそうなときは「$id > 前回の最後の値」で区切って取る形にする - 集計とグラフは、手順1の対応表どおりにブラウザ側で行う - 右上にログアウト(/auth/logout へのリンク)を置く 【権限による表示の違い】 - 401 が返ったら、ログインの画面に戻して「もう一度ログインしてください」と出す - 403 が返ったら、「このアプリを見る権限がありません」と出す - 権限で項目(フィールド)が返ってこないときは、その項目を使うグラフの場所に「この項目を見る権限がありません」と出す(エラーにしない) 【守ること】 - 外部のライブラリは使わず、グラフは SVG で描く - スマホの幅でも崩れないようにする
見たい数字が、kintone で手集計した値と一致する
ログインしなくても確かめられる項目は Claude Code に確認させ、人が確かめる項目はチェック表にします。
公開した https://<プロジェクト名>.pages.dev/ のテストをします。
作業の前に、何を確かめるかを日本語で説明し、私の承認を待ってから実行してください。
【ログインしなくても確かめられる項目(curl で確認して、結果を表にする)】
1. /auth/login が 302 で、移動先が https://<サブドメイン>.cybozu.com/oauth2/authorization になっている
- URL に state と scope=k:app_record:read が含まれる
- Set-Cookie に HttpOnly・Secure・SameSite=Lax が付いている
2. /auth/callback?code=dummy&state=tampered が 400 になる
3. Cookie なしの /api/records?app=<アプリ番号> が 401 になる
4. 受け付けていないアプリ番号(例:app=999)が 400 になる
5. Cookie なしの /api/session が {"loggedIn":false} を返し、トークンを含まない
【人が確かめる項目(チェック表を作る)】
- 次の項目ごとに「手順」「期待する結果」「結果」「確認日」「確認者」の列を持つ表にする
権限の違う2人で見える範囲/閲覧権限のないアプリ・項目/利用者の設定にない人/1時間後の自動の取り直し/ユーザーの停止と権限変更の反映までの時間/許可の画面が毎回出るか/11回以上ログインしたときの動き/スマホでの表示/監査ログの記録
【守ること】
- kintone のパスワードやトークンを、コマンドやファイルに書かない
すべての項目の結果が記録されている
本番 URL を使う人に案内します。新しい画面で問題がないことを確かめたら、いまのアプリが使っていた API トークン・パスワードを無効化します。
ダッシュボードを本番に公開し、いまのアプリからの切り替えを進めます。 1つ終わるごとに結果を報告し、次に進む前に私の承認を待ってください。 1. npx wrangler pages deploy public --project-name <プロジェクト名> --branch=main で公開し、 https://<プロジェクト名>.pages.dev/ が開くことを確かめる 2. 使う人への案内文をチャットに出す (URL、kintone でログインする手順、[許可]を押すこと、見える範囲は kintone の権限どおりであること) 3. 手順0で一覧にした「無効化・削除が必要なもの」について、止める順番の案を出す 【変えてはいけないこと】 - kintone の API トークンの無効化は、kintone の画面で私が行う - コードからトークン・パスワードを消すのは、新しい画面で問題がないと私が確認したあと - 削除や変更は、私が承認した項目だけ行う
古い鍵が無効化され、いまのアプリからはデータが取れない
このダッシュボードの運用手順を、担当者が見て作業できる形で docs/運用手順.md にまとめてください。 作業の前に、目次を日本語で説明し、私の承認を待ってから書いてください。 【入れる場面】 - 入社・異動:kintone の権限に加えて、OAuth クライアントの「利用者の設定」に追加する(共通管理者の作業) - 退職:kintone のユーザーを停止する(ダッシュボード側の作業は不要) - クライアントシークレットが漏れた疑いがあるとき:共通管理でシークレットを再発行し、 Cloudflare の Secret(CLIENT_SECRET)を差し替える。差し替えたあとに再公開が必要かも確かめて書く - SESSION_KEY を変えたとき:全員がログインし直しになること - 月1回の確認:Cloudflare の利用件数(無料プランは1日10万リクエスト)と、 kintone のアプリごとの API 件数(スタンダードコースは1日10,000件) 【守ること】 - 推測で手順を書かない。公式の手順を確かめられなかったところは「要確認」と書く - シークレットやパスワードの値を書かない
2026年10月23日時点の公式ドキュメントで確認した値です。
| 項目 | 上限・料金 | この設計での見込み |
|---|---|---|
| Pages の画面配信 | 静的ファイルへのリクエストは無料・無制限 | 費用なし |
| Pages Functions | Workers のリクエストとして数える。無料プランはアカウント全体で1日10万件(日本時間の毎朝9時にリセット)、CPU は1リクエスト10ミリ秒 | 例:30人×1日10回表示×2件=1日600件程度 人数・回数は仮置き |
| Cloudflare Access(任意) | 無料プランはユーザー50人まで | 使う人数しだい(6 の項目5) |
| kintone REST API | 1アプリあたり1日10,000件(スタンダードコース)/100,000件(ワイドコース)。同時接続は1ドメイン100まで。1回の取得は500件まで | アプリ単位の上限なので、同じアプリを使うほかの連携の分と合算になります |
| OAuth クライアント | 20個まで。リフレッシュトークンは1クライアントあたり1ユーザー10個まで | 1クライアントで足ります |