ブログ一覧

独自ドメイン移行でパスキーのログインができなくなる原因

更新: Web開発者向け

Cloudflare Workers でサイトを立ち上げるとき、まず *.workers.dev のステージング URL で動かして、仕上げに独自ドメインへ切り替える流れはよくあります。

このとき管理画面の認証がパスキー(WebAuthn)だと、切り替えで必ず次の問題が起きます。workers.dev 上で登録したパスキーは、独自ドメインでは一切使えません。パスキーが唯一のログイン手段のままドメインを切り替えると、管理画面から完全に締め出されます。

本記事では、workers.dev で登録したパスキーが使えなくなるのは WebAuthn の仕様(RP ID へのバインド)によること、締め出されたときの復旧経路、切り替え前にやっておくべきことをまとめます。

前提: パスキー認証を採用した Web アプリ全般の話です。例は Cloudflare Workers(workers.dev → 独自ドメイン)ですが、Vercel の *.vercel.app や Netlify の *.netlify.app からの移行でも同じことが起きます。

パスキーは「RP ID」に紐づく

WebAuthn のクレデンシャル(パスキー)は、登録時に RP ID(Relying Party ID) というドメインに紐づけられます(W3C WebAuthn 仕様 §5.1.1 rp.id)。認証時には「今アクセスしているオリジンのドメイン」と RP ID の対応が検証され、一致しないパスキーはそもそも候補として出てきません。

example.com で登録したパスキーが examp1e.com(偽サイト)で使えたらフィッシングを防げないので、ドメインへの束縛は仕様が意図した動作です。

つまり:

  • mysite.workers.dev で登録したパスキー → RP ID は mysite.workers.dev
  • サイトを mysite.com に移す → RP ID が違うので、そのパスキーは存在しないのと同じ

パスキーを新しいドメインへ移行したり引き継いだりする仕組みは無く、新しいドメインで登録し直すしかありません(passkeys.dev の Relying Party ID の解説)。

workers.dev では「親ドメインに広く登録」もできない

RP ID を workers.dev にして全サブドメインで使えるパスキーを作ることもできません。workers.dev は Public Suffix List に登録されており、パブリックサフィックス(.com などと同格の扱い)を RP ID にすることはできません。*.workers.dev の各サブドメインは、それぞれ完全に独立した「サイト」です。

workers.dev 配下には無数の他人のサイトが同居しているので、サイトをまたいで使えるクレデンシャルを作れないこの設計は妥当です。

締め出しの典型パターン

危険な手順はこうです。

  1. mysite.workers.dev でセットアップし、管理者パスキーを登録
  2. 独自ドメイン mysite.com に切り替え(DNS・ルーティング変更)
  3. mysite.com/admin にアクセス → パスキーが出てこない
  4. 「メールでログインリンクを送る」→ メールプロバイダを設定していないので送れない
  5. 詰み

厄介なのは 4 です。パスキーは「メール基盤が不要」なのが利点なので、導入したサイトはメール送信手段を持っていないことが多く、フォールバックのマジックリンク認証はコードとしては存在するのに配送手段がなくて使えない状態になります。

なお、データベースを直接触っての復旧も基本的にできません。まともな認証システムはログイントークンをハッシュ化して保存するので、DB からログイン URL を再構成することは不可能です。初期セットアップウィザードも「ユーザーが 1 人でも存在したら再実行不可」のようにガードされているのが普通で、このガードを無理に越えようとすると既存データを壊すことになります。

復旧: メールの配送先を Slack にすげ替える

締め出された状態からは、メール送信をチャット Webhook への送信に差し替えて実際に復旧できました。

  1. 認証システムのメール配送フックに、Slack Incoming Webhook へ POST するプロバイダを差し込む(メール配送を差し替え可能なプラグイン機構があるシステムなら、これができます)
  2. マジックリンクの送信をリクエスト → ログインリンクが Slack に届く
  3. リンクからログイン → 新ドメインでパスキーを登録し直す

メールサーバーの契約や DNS 設定(SPF/DKIM)なしで即日復旧できるのがこの方法の利点です。ただし Slack にワンタイムトークン付き URL を流すときは、リンクプレビューのクローラーがトークンを先に消費するという別の罠があります。この罠はSlack に送ったログインリンクが、人間が踏む前に無効化されるにまとめました。

予防: ドメイン切り替えの正しい順序

締め出されてから復旧するより、切り替え前に 10 分使う方が圧倒的に安いです。

  1. 切り替え前に、パスキー以外のログイン経路を 1 本確保する(メールプロバイダ設定、またはチャット Webhook 配送。動作確認まで)
  2. ドメインを切り替える
  3. アプリのサイト URL 設定を新ドメインに更新する。多くの実装では、この設定が新規パスキー登録時の RP ID の元になります。サイト URL 設定を更新せずに手順 4 に進むと、新しく登録したパスキーが旧ドメインに紐づきます
  4. フォールバック経路でログインし、新ドメインでパスキーを登録
  5. 旧ドメインのパスキーを削除(もう何にも使えないので)

まとめ

  • パスキーは RP ID(ドメイン)に束縛されるので、ドメインが変わったら登録し直すしかない。フィッシングを防ぐ仕様の代償
  • workers.dev はパブリックサフィックスなので、親ドメインを RP ID にして全サブドメインで使うこともできない
  • パスキーを唯一のログイン手段にしたままドメインを切り替えると締め出される。切り替え前にフォールバック経路(メールまたはチャット Webhook 配送)を確保する
  • 新パスキーの登録前に、サイト URL 設定を新ドメインへ更新する

この記事をシェア