これは「関連記事表示 by Vector Search 2.0」のデモサイトです。記事コンテンツはソリューションブログから引用しています。
Craft AuthとCraft Sitesを使ってカスタム管理画面を構築する

Craft AuthとCraft Sitesを使ってカスタム管理画面を構築する

こんにちは、Customer Engineerのgamiです!最近、池袋にある「ちいかわパーク」に行きました。無難にハチワレが好きです。

さて、Craft Sitesを使って様々なWebサイトを構築できることは、これまでも多くの記事で紹介してきました。その中でも特に要望が多いのが、「特定のユーザーだけがアクセスできる管理画面を作りたい」というニーズです。

たとえば次のようなカスタム管理画面の構築ニーズがあります。

カスタム管理画面のニーズ例:

  • KARTEに蓄積されたデータを従業員向けに可視化するダッシュボード画面を構築したい
  • CMS用に提供された専用の管理画面を使わず、機能を絞ったコンテンツ入稿画面を独自に構築したい
    • 例: 自社メディア内で数千人いる自社スタッフの投稿内容を掲載したいが、自社スタッフ全員にKARTEのアカウントを発行するのは現実的ではないので、よりシンプルな独自管理画面をスタッフ向けに構築したい
  • データベースのちょっとした閲覧や更新に使える運用支援ツールを構築したい
    • 例: キャンペーン情報を自社システムからKARTE側のアクションテーブルやCraft KVSに定期連携しているが、更新に失敗したときのリカバリーのために手動更新用の管理画面を用意しておきたい

このような管理画面を構築するとき、当然ながらその画面にアクセスできるユーザーは社内メンバーや特定のユーザーに限定する必要があります。そういった認証機能をゼロから実装するのは意外と大変で、セキュリティを考慮したパスワード管理、トークン管理、ロールベースアクセス制御など、様々な要素を考慮する必要があります。

しかし、簡単にWebサイト構築ができるCraft Sitesと、簡易的な認証サービスを提供するCraft Authを組み合わせて利用することで、一見すると構築が大変そうなカスタム管理画面の実装ハードルを大きく下げることができます。

そこで今回は、Craft AuthとCraft Sitesを組み合わせて、認証付きのカスタム管理画面を構築する方法をご紹介します。

アウトプットイメージ

今回構築するシステムの最終的なアウトプットイメージは次の通りです。

まず、ユーザーはCraft Authに事前登録されたユーザーのメールアドレスとパスワードを使って、ログイン画面で認証を行います。

認証に成功するとカスタム管理画面にリダイレクトされます。この画面はログイン成功時に発行される「署名付きCookie」を保持しているブラウザからしかアクセスできません。

なお、Craft Auth側に登録されたユーザーの中でも、指定したロールを持っていないユーザーには次のようにアクセス制限されたページが表示されるようになっています。

今回のテンプレートをカスタマイズすることで、「このロールを持っているユーザーにはここまでの操作しか許可しない」といったロールベースの認可処理を自由に実装できます。

全体の構成は次のようになります。

主要なコンポーネントは以下の通りです。

コンポーネント説明
Publicなサイト (login.example.com)ログイン画面をホスティング。誰でもアクセス可能
認証付きのサイト (admin.example.com)カスタム管理画面をホスティング。署名付きCookieを持つユーザーのみアクセス可能
ファンクションCraft Authと連携して認証処理を実行し、署名付きCookie発行、token発行、コンテンツ返却を担う
Craft Authユーザー認証やロール管理の機能を提供

認証フローは次のようになります。

  1. [Webブラウザ側] ユーザーがPublicなサイト上のログイン画面でメールアドレスとパスワードを入力
  2. [ファンクション側] Craft Authにsignin処理をリクエスト
  3. [ファンクション側] 認証に成功したらidToken、refreshToken、署名付きCookieを返却
  4. [Webブラウザ側] 受け取ったデータをそれぞれCookieに書き込み、認証付きサイト上のカスタム管理画面にリダイレクト
  5. [Webブラウザ側] Craft Functionsに対してidTokenを含めてコンテンツをリクエスト
  6. [ファンクション側] Craft AuthにidTokenの検証をリクエスト
  7. [ファンクション側] idTokenの検証に成功したらコンテンツを返却
    • 「idTokenは有効だが必要なロールが無い場合」は、アクセス制限がかかったコンテンツが返却される

注意点

前提として、次の点に注意をしてください。

  • Craft Functions、Craft Sitesおよび「サイトの認証」機能、Craft Authが利用できるKARTEプロジェクトが必要です
  • 今回紹介する実装例は基本的なものであり、実際に利用する際は追加の機能実装やセキュリティ対策が必要な場合があります

設定手順

設定の手順は次の通りです。

  1. Craft Sitesでサイトを2つ作成する
  2. 署名鍵が登録されたシークレット名を確認する
  3. Craft Functionsを作成する
  4. ログイン画面を作成する
  5. カスタム管理画面を作成する
  6. Craft Auth管理画面からユーザーとロールを追加する

順番に見てみましょう。

1. Craft Sitesでサイトを2つ作成する

まず、ログイン画面を配置するPublicなサイトと、カスタム管理画面を配置する認証付きサイトの2つを作成します。すでに作成済みの場合はスキップしてください。

なお作成する2つのサイトでは認証用のCookieを共有したいので、独自ドメインを設定する場合は、たとえば login.example.comadmin.example.com のようにサブドメイン以外が共通であるようなドメインを利用してください。

「Publicなサイト」の作成

  • [すべてのメニュー > Craft > サイト]からサイト一覧画面を開きます
  • [新規作成]から作成モーダルを開き、以下の設定でサイトを作成してください
    • サイト名: 任意の名前(例: login
    • 証明書ドメイン: [自動でドメインを払い出す]を選択、または独自ドメインを設定
    • サイトの認証を有効にする: 無効のまま
    • キャッシュTTL: 検証中は0を設定
    • TLSバージョン: TLS 1.2を設定

「認証付きサイト」の作成

  • 同様に[新規作成]から、もう1つサイトを作成します
  • 以下の設定でサイトを作成してください:
    • サイト名: 任意の名前(例: admin-console
    • 証明書ドメイン: [自動でドメインを払い出す]を選択、または独自ドメインを設定
    • サイトの認証を有効にする: 有効にする
    • キャッシュTTL: 0を設定
    • TLSバージョン: TLS 1.2を設定

サイトの認証を有効にすると、署名付きCookieを持つWebブラウザからのみコンテンツを取得できるようになります。

2. 署名鍵が登録されたシークレット名を確認する

作成した認証付きサイトの閲覧許可を与えるためには、「署名鍵」が必要になります。これは、「サイトの認証」が有効化されたサイトを作成するとCraft Secret Manager上のシークレットに自動保存されます。

  • [すべてのメニュー > Craft > シークレット] からシークレット一覧画面を開きます
  • CSP_{{サイト名(大文字)}} という名前のシークレットを探します
    • 先ほど作成した認証付きサイトのサイト名が使われます
  • [名前をコピー] からシークレット名をコピーしておきます

このシークレット名は、ファンクション作成時の設定で利用します。

3. Craft Functionsを作成する

Craft Authと連携した認証処理やコンテンツ返却を担うCraft Functionsを作成します。

  • [すべてのメニュー > Craft > ファンクション] からファンクション一覧画面を開きます

  • [新規作成 > テンプレートから作成] を選択します

  • Craft Authを使った認証付きカスタム管理画面 」というテンプレートを検索し[取得]ボタンをクリックします

  • [反映] ボタンをクリックします

  • [設定 > ファンクションのタイプ] で「HTTPタイプ」を選択します

  • [変数] タブで次の変数の値を設定します

    • AUTH_KEY_SECRET
      • 先ほどコピーした認証付きサイトの「認証鍵」が保存されたシークレット名を指定します
    • URL_PREFIX
      • 発行する署名付きCookieによって閲覧を許可する範囲を、URLの前方一致で指定します
      • たとえば「認証付きサイト」のドメインが admin.example.com の場合、サイト全体の閲覧を許可するなら https://admin.example.com/ のように指定します
      • 設定を変えることで、サイト内の特定ディレクトリ配下だけ閲覧を許可することもできます
    • REQUIRED_ROLE
      • カスタム管理画面の制限付きコンテンツにアクセスできるロール名を指定します
      • ここでは例として viewer と指定しておきましょう
    • EXPIRES_MINUTES
      • 署名付きCookieの有効期限(分)です
      • ここでは1440(1日)と指定しておきましょう
    • ALLOWED_ORIGINS
      • このファンクションのエンドポイントへのアクセスを許可するWebサイトのURL(オリジン)をカンマ区切りで指定します
        • 例: https://admin.example.com
      • 指定したオリジンに対してCORSリクエストが許可されます
      • すべてのオリジンを許可する( * )設定もできますが、本番運用中の利用は推奨されません
    • その他の変数は、ひとまずデフォルト値のままで問題ありません
  • 適当なファンクション名をつけて [デプロイ] します

  • [設定 > ファンクションのタイプ > エンドポイント] にあるURLをコピーして控えておきます

なお、テンプレートのソースコードはGitHubで公開されています。

craft-codes/craft-functions/sites-authentication-with-craft-auth at main · plaidev/craft-codes

4. ログイン画面を作成する

次に、Publicなサイトにログイン画面を作成します。

  • [すべてのメニュー > Craft > サイト]から、サイト一覧画面を開きます

  • 先ほど作成した「Publicなサイト」を開きます

  • [Copilot > テンプレート]を開きます

  • Craft Authを使った認証付きカスタム管理画面」というテンプレートを検索し、[コピー]ボタンをクリックします

  • テンプレートにはloginフォルダとadmin-consoleフォルダが含まれています。まずloginフォルダ配下のファイルをサイトのルートディレクトリに移動します

    • ファイル構成
      • /login/index.html
      • /login/index.js
      • /login/style.css
  • index.jsを編集し、冒頭にある次の定数値を実際の値に置き換えてください

    • CRAFT_FUNCTIONS_ENDPOINT
      • 作成したCraft FunctionsのHTTPエンドポイントURLを指定します
    • DOMAIN
      • 認証用の各種Cookieを付与するドメインを指定します
      • Publicなサイトと認証付きサイトに共通するドメインを記載してください
        • 例: 両ドメインが login.example.comadmin.example.com であれば、 example.com の部分を指定
    • REDIRECT_URL
      • ログイン成功時にリダイレクトする先のカスタム管理画面URLを指定します
        • 例: 認証付きサイトのドメインが admin.example.com であれば https://admin.example.com/admin-console/index.html と指定
    • その他の定数は、ひとまずデフォルト値のままで問題ありません
// Craft FunctionsのエンドポイントURL
const CRAFT_FUNCTIONS_ENDPOINT = 'https://xxx.yyy.karte.io/functions/zzz';
// Cookieを付与するドメイン. ログインページと認証付きページに共通するドメインを指定
const DOMAIN = 'example.com';
// 認証後のリダイレクト先URL
const REDIRECT_URL = 'https://admin.example.com/admin-console/index.html';
  • 変更を保存します
  • 追加した全てのファイルに対して、 [公開する] からコンテンツを公開します
    • ※ ページが全世界に公開されるので、内部情報を意図せず公開していないか十分に確認した上で公開作業を実施してください

5. カスタム管理画面を作成する

次に、認証付きサイトにカスタム管理画面を作成します。

  • [すべてのメニュー > Craft > サイト]から、サイト一覧画面を開きます

  • 先ほど作成した「認証付きサイト」を開きます

  • [Copilot > テンプレート]を開きます

  • 先ほども使用した「Craft Authを使った認証付きカスタム管理画面」というテンプレートを検索し、[コピー]ボタンをクリックします

  • 今度はadmin-consoleフォルダ配下のファイルをサイトのルートディレクトリに移動します

    • ファイル構成
      • /admin-console/index.html
      • /admin-console/index.js
      • /admin-console/style.css
  • index.jsを編集し、冒頭にある次の定数値を実際の値に置き換えてください

    • CRAFT_FUNCTIONS_ENDPOINT
      • 作成したCraft FunctionsのHTTPエンドポイントURLを指定します
    • DOMAIN
      • 認証用の各種Cookieを付与するドメインを指定します
      • Publicなサイトと認証付きサイトに共通するドメインを記載してください
        • 例: 両ドメインが login.example.comadmin.example.com であれば、 example.com の部分を指定
      • /login/index.jsで設定したのと同じ値でOKです
    • LOGIN_URL
      • 先ほど作成したログイン画面のURLを指定します
        • 例: Publicなサイトのドメインが login.example.com であれば https://login.example.com/login/index.html と指定
    • その他の定数は、ひとまずデフォルト値のままで問題ありません
// Craft FunctionsのエンドポイントURL
const CRAFT_FUNCTIONS_ENDPOINT = 'https://xxx.yyy.karte.io/functions/zzz';
// Cookieを付与するドメイン. ログインページと認証付きページに共通するドメインを指定
const DOMAIN = 'example.com';
// ログインページのURL(認証エラー時のリダイレクト先)
const LOGIN_URL = 'https://login.example.com/login/index.html';
  • 変更を保存します
  • 追加した全てのファイルに対して、 [公開する] からコンテンツを公開します

6. Craft Auth管理画面からユーザーとロールを追加する

最後に、Craft Auth管理画面からログイン用のユーザーを追加します。

  • [すべてのプロダクト > Craft > 認証]を選択し、Craft Authのユーザー一覧画面を開きます

  • 右上のプルダウンから [ロール] を選択し、ロール一覧画面を開きます

  • [ロールを追加]をクリックし、viewerというロールを作成してください

    • 先ほど作成したCraft Functionsの変数 REQUIRED_ROLE の値と一致させる必要があります
  • 右上のプルダウンから [ユーザー] を選択し、ユーザー一覧画面を開きます

  • [ユーザーを追加]をクリックし、ログインで使用するメールアドレスとパスワードを入力してユーザーを作成してください

    • メールアドレスは、実際にメールを受け取れるメールアドレスを指定します
    • ここで入力したパスワードはログインで利用するので控えておいてください
  • 作成したユーザーの […] から [ロールの割り当て] を選択し、作成した viewer ロールを割り当てます

これで、カスタム管理画面のコンテンツ閲覧に必要な viewer ロールを持ったログインユーザーを作成することができました。

実際に動かしてみる

実際に動作を確認してみましょう。

  • [すべてのメニュー > Craft > サイト]からサイト一覧画面を開きます

  • 先ほど作成したPublicなサイトを開き、login/index.htmlの [サイトで見る] からログイン画面をWebページとして開きます

  • 先ほど作成したユーザーのメールアドレスとパスワードを入力し、[ログイン]ボタンをクリックします

  • ログインに成功すると、自動的にカスタム管理画面にリダイレクトされます

  • なお、 [すべてのプロダクト > Craft > 認証] から対象ユーザーの viewer ロールを削除し、カスタム管理画面に再度アクセスすると、次のようにアクセス制限されたページが表示されます

  • また、右上の[ログアウト]ボタンを押すと、認証用のCookieが削除され、ログイン画面にリダイレクトされます

補足

ここまでで紹介できなかった補足事項について、いくつか記載します。

実際にカスタム管理画面を構築するには?

今回の記事で紹介したCraft FunctionsおよびCraft Sitesのテンプレートは、あくまでも最低限の機能しか実装されていません。実際に便利な管理画面を構築するときのヒントを記載します。

ここでシステム構成図を再掲します。

このシステム構成においては、ログイン後のユーザーに対して、Craft Sitesの「サイトの認証」機能を使った認証と、Craft Functionsへのリクエスト送信時の認証が組み込まれています。

認証の種別説明
Craft Sites側での認証署名付きCookieが付与されたWebブラウザからのリクエストでしか、Craft Sites上のHTMLファイル等を取得できないようにする
Craft Functions側での認証Craft Authの機能で発行したidTokenを含むコンテンツリクエストに対してしか、Craft Functionsから正常なレスポンスを返さないようにする

認証付きサイトにおいては、Craft Sites上のファイルの取得時は全て自動的に認証チェックが入るようになります。そのため、Craft Sites側を編集してカスタム管理画面に必要なHTMLや画像などのファイルを追加した場合も、特に認証について気にする必要はありません。

他方Craft Functions側では、たとえば次のような機能が必要な場合は追加の実装をする必要があります。

Craft Functions側での追加実装が必要な管理画面機能の例:

  • Craft KVSなどのデータベースにあるデータを動的に取得して、Webサイト上に表示したい
  • カスタム管理画面での入力内容を元にCraft KVSなどのデータベースを更新したい

Craft Functions側で実装した機能をファンクションのエンドポイント経由でフロントエンドから利用するときには、現状のテンプレート実装を参考に、必ずリクエストにidTokenを含めるようにして、ファンクション側の処理を実行する前にidTokenを検証するようにしてください。今回のテンプレートでは認証処理と管理画面のコンテンツ取得処理を1つのファンクションにまとめていますが、別々のファンクションで実装してもかまいません。

さらに、もしユーザー毎に利用できる機能を細かく制限したい場合は、制限をかけたいパターン毎にロールを作成して、ユーザーが必要なロールを保持しているかを各機能の呼び出し時にCraft Functions側でチェックしてください。

ロール設計の例:

ロール名説明
viewer管理画面の閲覧だけができる
writer管理画面経由でデータベースの値を編集できる
admin管理者にのみ許された特別な操作も実施できる

ログイン時にWebブラウザに保存される認証情報

今回のテンプレートでは、ログインに成功したタイミングで次の3種類の認証情報がCraft Functionsから返却され、WebブラウザのCookieに書き込まれます。

名称対象機能有効期限説明
署名付きCookieCraft Sitesファンクションの変数EXPIRES_MINUTESで設定した値Craft Sitesの認証付きサイトのコンテンツを取得するのに必要です
idTokenCraft Auth1時間ファンクションのエンドポイントに対するリクエストに含めて、Craft Functions側での認証に利用します
refreshTokenCraft Auth無期限idTokenが失効したときの再取得に利用されます

特にrefreshTokenの扱いについては、注意が必要です。refreshTokenについてはidTokenの再発行時のみリクエストに含めるようにし、それ以外のリクエストには含めないようにしてください。また、発行済みのrefreshTokenを無効化したい場合は、Craft Authのユーザー一覧画面から [リフレッシュトークンを無効化] を実施してください。

また、セキュリティ観点でXSS攻撃によるCookie盗難のリスクを下げたい場合は、コンテンツセキュリティポリシー (CSP)の導入もご検討ください。

Firebase SDKの利用について

Craft Authは、内部的にFirebase Authenticationの機能を利用しています。

そのため、今回のテンプレートでは利用していませんが、Firebase Client SDKを直接使用してクライアントサイドで認証することも可能です。

詳細については、次のドキュメントをご覧ください。

Firebase Client SDKを使う場合、次のようなメリットとデメリットがあります。

  • メリット
    • idTokenやrefreshTokenを独自Cookieで管理する必要が無くなります
  • デメリット
    • refreshTokenがブラウザのIndexedDBに保存されるため、異なるサブドメイン間でログイン状態を共有できません
      • もし実装する場合は、auth.createCustomToken()で一時的なカスタムトークンを生成して、別ドメイン遷移後にauth.signInWithCustomToken()で再ログインをさせるような追加実装をする必要があります

なお2026年2月現在、Craft Authを使ったOIDC認証やSAML認証ではFirebase Client SDKを直接利用する必要があります。そのためFirebase Client SDKを利用した認証機能の実装については、OIDC認証やSAML認証に関する別の記事で解説する予定です。

おわりに

今回は、Craft AuthとCraft Sitesを組み合わせて、認証付きのカスタム管理画面を構築する方法について紹介しました。

この方法を使うと、従来のKARTEの管理画面や権限管理の機能制約を受けずに、各社の業務フローを想定した独自管理画面を構築することができます。

使い所が見つかればとても強力なソリューションなので、ぜひ試してみてください!