「管理画面のIDとパスワードをください」。納品前の打ち合わせでほぼ必ず出てくる一言ですが、EmDashで作ったサイトには渡せるパスワードがありません。既定のログインはパスキーで、パスワードという入れ物自体を持っていないからです。

では何を渡すのか。そして、クライアントの担当者がパスキーを失くした日、誰がどうやって助けるのか。引き継ぎで詰まるのはこの2点です。どちらも納品前に決めておける話。自分のサイト(tsudzuri.com・EmDash 0.32.0)の設定と、CMS本体の実装を見ながら整理します。

渡す前に決める4つ。招待リンク、本番で登録、復旧の道、入口の方式

渡すのはパスワードではなく招待リンク

管理画面のユーザー画面から、メールアドレスと役割を指定して招待を発行します。リンクは1回使うと無効で、期限は7日(実装値は10080分)。受け取った人はリンクを開いてその場でパスキーを作るので、パスワードを決める画面は最後まで出てきません。

  • メール送信を設定していないサイトでも発行はできる。その場合はリンクをコピーして自分で渡す
  • パスキーは1人10個まで。最後の1個は本人でも削除できないので、追加してから古い方を消す
  • 役割は招待の時点で決まる。どこまで渡すかの判断は権限設計の記事にまとめました

ここで一手間かけて、ノートPCとスマホの2台に登録してもらうところまで見届けます。「PCを買い替えたら入れなくなった」という連絡が、これで来なくなる。

パスキーはドメインに紐づく。検証環境で登録させない

パスキーの登録先(WebAuthnのrpId)は siteUrl に書いたホスト名から決まります。siteUrl が無ければ、リクエストのホスト名がそのまま使われる。つまり検証用URLで作ったパスキーは、本番ドメインでは通りません。

自分のサイトは本番だけ siteUrl: "https://tsudzuri.com" を固定し、ローカル開発では未設定にしています。手元で localhost に登録したパスキーは手元でだけ動き、本番には持ち込めない。設定ファイルのコメントにもそう書いてあります。

複数のホスト名で1つのパスキーを共有したいときは allowedOrigins を使いますが、条件はきついです。指定できるのは siteUrl と同じホスト名か、そのサブドメインだけ。外れていれば設定エラーで起動時に落ちます。プラットフォーム側のドメイン(workers.dev など)や、別に取った検証用ドメインは共有できません。

検証環境を stg.example.com のように本番ドメインのサブドメインへ置けば、この制約に収まります。ドメインの話なので、確認するのは着手前。

失くした日のために、納品前にメールを通す

復旧の正面ルートはマジックリンクです。有効15分・1回だけ。ただしメールプロバイダを設定していないサイトでは、送信リクエストが EMAIL_NOT_CONFIGURED と503で止まります。

送信は同じIPから5分に3回まで。応答は成否にかかわらず「アカウントがあれば送りました」で固定され、どのアドレスが登録済みかは外から分かりません。

問題は、最後のAdminがパスキーを失い、しかもメールが未設定だったとき。残る手段はデータベースを直接触る作業だけになります。クライアントの本番サイトで起こしたい事故ではない。納品前にやることは2つです。

  • メール送信を通しておく(招待もマジックリンクもこれが前提)
  • Adminを2人にする。片方が入れなくなっても、もう片方が復旧リンクを送れる
パスキーを失ったときの復旧手順4段

自分のサイトは編集者が1人なので、Adminを増やす代わりにパスキーを2台へ分散させています。納品先には同じ構成を勧めません。

「会社のアカウントで入りたい」と言われたら

選択肢は3つあります。

  • GitHub / Google でログイン:authProviders に追加するとログイン画面に並び、CMSのユーザーへ紐づく
  • 許可ドメイン:Adminが example.co.jp を登録すると、そのドメインのメールなら招待なしでアカウントを作れる。ドメインごとに既定の役割を持ち、有効な行が1件も無ければセルフサインアップは閉じたまま
  • Cloudflare Access:本番では排他。ログインページ・パスキー・マジックリンク・招待・セルフサインアップがすべて消え、誰が入れるかはCloudflare側のポリシーで決まる。役割はIdPのグループから割り当てられる
入口の決め方2方式の比較。パスキーと招待、Cloudflare Access

社内にIdPがある会社なら、Accessがいちばん静かに収まります。ローカル開発ではAccessの署名付きトークンが飛んでこないため、自動的にパスキーへ戻る設計。デプロイ構成ごと相談したいときはCloudflareへのデプロイの記事もどうぞ。

自分のサイトの現状は、認証モードを返すエンドポイントが signupEnabled: false・providers: [] を返す状態です。入口は招待だけ。

引き継ぐ前に決める4つ

  • 誰にどの役割で招待を出すか
  • パスキーを登録させるドメイン
  • メール送信をどのアドレスから通すか
  • 復旧できる人を2人置くか、IdPに寄せるか

ここまで決めて渡すと、公開後に「入れなくなりました」で止まる時間がほぼ消えます。CMSの引き継ぎまで含めた実装をお探しなら、お問い合わせからご相談ください。運用中サイトの認証まわりの手当てだけでも対応します。

本記事は2026年9月時点の情報です(EmDash 0.32.0 で確認)。