【WebAuthn】ドメイン設定でパスキーが死んだ話と復旧法

今回は EmDash ブログに独自ドメインを設定したら、それまで使えていたパスキーで管理画面に入れなくなった話です。原因は WebAuthn の rpId 固定。メール復旧も塞がれた僕が、本番トークンだけで復旧した手順を解説します。

こんにちは。ダタク @iQeeeda です。

このブログは EmDash というヘッドレス CMS で動かしていて、管理画面へのログインはパスキー (WebAuthn) にしています。
先日、独自ドメイン iqeda.com を設定したら、そのパスキーで管理画面に入れなくなりました…
そのときの対処法を備忘録として残しておきます。

結論: パスキーは登録ドメインに縛られている

先に結論です。

  • パスキー (WebAuthn) は、登録したときのドメイン (rpId) に固定される
  • ドメインを変えると、旧ドメインで作ったパスキーは新ドメインでは使えない
  • これはサーバ設定では回避できない (ブラウザが強制する仕様)
  • メール復旧が塞がっていても、admin トークン (PAT)があれば復旧できる

原因と、本番トークンだけでやった復旧手順を、順番に見ていきます。

なぜ独自ドメインを設定するとパスキーが使えないのか

パスキー (WebAuthn) は、登録したときのドメイン名 (rpId) に紐づきます。
このブログだと siteUrl のホストがそのまま rpId です。

  • 登録時: *.workers.dev の URL → rpId は workers.dev
  • 設定後: origin は iqeda.com → rpId と一致せず、ブラウザが弾く

WebAuthn の仕様で、資格情報は登録したドメインでしか使えません。
別ドメインへの盗用を防ぐ仕組みなので、サーバ側では回避できない。

「じゃあ workers.dev の URL に戻ればいいのでは?」とも思いました。
でもカスタムドメインを設定すると、workers.dev 側は自動で無効化されて 404 になります。
パスキーを登録した古い住所には、もう戻れないわけです。

メール復旧も塞がっていた

「パスキーがダメでも、メールでログインし直せばいいのでは?」
普通はそうです。でもこのサイトは email プロバイダを設定していません。

  • magic-link ログイン → 503 (email プロバイダ未設定)
  • メールでのアカウント復旧 → 同じく使えない
  • パスキー → rpId 不一致でブラウザが拒否

ログイン手段が全部塞がっている。これは一瞬ヒヤッとしました。

admin トークンでパスキーを登録し直す

残った手段は一つ。admin の PAT (Personal Access Token) です。
.env に入れてある、本番フルアクセスのトークンですね。

なぜこれで行けるかというと、

  • EmDash のパスキー登録 API は「ログイン済みユーザか」だけを見ている
  • それは Bearer トークン認証でも満たせる
    • トークン認証なら CSRF チェックも不要

なので、新ドメインを開いたブラウザのコンソールから PAT で登録 API を叩けば、
既存の admin アカウントに、新しい rpId のパスキーを「追加」できます。

使うエンドポイントは 3 つ。

  • POST /_emdash/api/auth/passkey/register/options
  • navigator.credentials.create(ブラウザ側で資格情報を生成)
  • POST /_emdash/api/auth/passkey/register/verify

新しいアカウントを作る必要も、旧パスキーを消す必要もありません。

コンソールに貼るだけのスニペットにした

コピペ用のスニペットを scripts/recover-passkey.js に置いてあります。やることは、

  1. 管理画面を新ドメインで開いて、ログイン画面を出す
  2. PAT をスニペットに貼る
  3. コンソールで実行する

これだけです。options → create → verify を順番にやってくれます。

// 前提: 管理画面 (/_emdash/admin) を新ドメインで開いている状態
const EMDASH_TOKEN = "ここに本番 PAT を貼る";
const BASE = location.origin;

// 1) 登録オプションを取得(token 認証で CSRF もバイパス)
// 2) rpId を新ドメインに合わせて navigator.credentials.create
// 3) verify に POST して登録を確定

PAT は使ったらローテーションする

PAT は本番フルアクセスの鍵です。
コンソールに貼った時点で、画面共有や履歴に残るリスクがある。
復旧できたら、管理画面でトークンを失効・再発行して .env を差し替えておきましょう。お忘れなく。

独自ドメインを設定する前に知っておきたかった

siteUrl が変わる = rpId が変わる = 既存パスキーが全部無効、という因果は、一度踏むまで気づきにくい。

同じように EmDash や WebAuthn を使うサイトを移行する人は、「パスキーは作り直しになる」「メール復旧の経路が生きているか」を先に確認しておけば、僕みたいに慌てずに済みます。

AI Agent に任せれば解決できる範囲だとは思いますが、もし同じところで行き詰まった方の参考になれば。

関連記事

まだコメントはありません