パスキーのRP IDについて考える
この記事は「Digital Identity技術勉強会 #iddance Advent Calendar 2025」の6日目です。
はじめに
パスキーをサポートするとなった場合に、RP IDをどう設定するかが課題の一つです。
本記事ではRP IDの設定で考慮が必要な事項について解説していきます。
RP IDとは?
Relying Party Identifier(RP ID)は、パスキー(WebAuthn)における「サービスを識別するためのドメイン名」です。
RP ID は、認証器(デバイス・ブラウザ・セキュリティキー)が「どのサイトのために登録されたクレデンシャルか?」を判断するために利用されます。
重要なのは RP ID は自由な文字列ではなく、必ずホストのドメイン名に基づく という点です。
スキーム(https://)やポート番号(:443, :3000 など)は含めません。
WebAuthn が扱うのは「オリジン」ではなく RP ID=ドメインです。
RP IDを設定する際の制約
RP ID には、次のようなルールが課せられています。
- オリジンのeffective domainと一致するか、
- またはそのregistrable domainのサフィックスであること
つまり、RP ID はそのサイトのドメイン階層の範囲内でなければならないということです。
例として、以下のようなオリジンがあるとします。
https://login.example.com
この場合に設定できるRP IDは以下の通りになります。
| RP ID | 有効か? | 理由 |
|---|---|---|
| login.example.com | 〇 | オリジンの effective domain と一致 |
| example.com | 〇 | registrable domain のサフィックス |
| m.login.example.com | × | オリジン側より「深い」サブドメインは不可 |
| com | × | registrable domain ではない |
また、RP IDがlocalhost以外の場合は、オリジンは必ずHTTPSである必要があります。
誤ったオリジンからRP IDを指定して認証器が呼び出された場合にはブラウザで次のようなエラーが発生します。
ERROR SecurityError: The relying party ID is not a registrable domain suffix of, nor equal to the current domain. Subsequently, an attempt to fetch the .well-known/webauthn resource of the claimed RP ID failed.
なぜRP IDが重要となるのか?
RP ID はユーザの認証器(ブラウザ・OS・セキュリティキー)側に保存される「このパスキーはどのドメインのためのものか?」という識別子です。そのため、サーバ側の設定を変えたからといって、ユーザの認証器に保存された RP ID が自動的に更新されることはありません。強制的にサーバ側で設定を変更した場合や、適切なオリジンからパスキーを呼び出さなかった場合に既存のユーザはログインができなくなってしまいます。
WebAuthnにおけるRP IDの取り扱いはCookieのDomainやオリジンの概念と似ていますが、Cookieとは違いパスキーは移行が難しいのでプラスαの考え方が必要になります。
オリジンhttps://login.example.comを例として、RP IDがlogin.example.comの場合、RP IDがexample.comの場合でそれぞれどのようなメリットデメリットがあるかを見ていきましょう。
RP IDをlogin.example.comとした場合
メリット
- サブドメインを明確に分離できる
-
evil.example.comのような意図しないサブドメインで認証器が呼び出されない - 同じドメインで複数アカウント体系がある場合に、サブドメインで住み分けができる
デメリット
- スコープが狭すぎるため、
account.example.comのようなサブドメインから呼び出せない。 - 将来的なドメイン変更に弱い
RP IDをexample.comとした場合
メリット
- パスキーをすべてのサブドメインで共有できる
- 将来的なサービス追加や移行に強い
デメリット
- スコープが広いため、境界が緩くなる
- 別のアカウント体系ができた場合に、後続のサービスでRP IDの選択肢が狭まる
どちらを選ぶべきか?
異なるサブドメインでの別のアカウント体系のサービスを運用している・運用する予定がある場合を除いては、可能であればRP IDはexample.comのように広くとり、サーバ側のオリジン検証でログイン画面やパスキーの登録のドメイン以外をはじく仕様にするのが筆者としては便利だと思います。
ログインページとユーザのポータルサイトが別のサブドメインで運用されている場合を考えます。
RP IDがポータルサイトのサブドメインで作成してしまったものは、ログインページで利用することができません。effective domainでRP IDを設定するか、パスキーの登録だけ認証ページのドメインで呼び出す必要が出てきます。セキュリティ面では、RP IDでサブドメインを指定した方が高まる一方で、利便性を考えると広く付けるケースの方が多い印象です。
RP IDをexample.comにしたときのセキュリティへの懸念
RP IDをexample.comとした場合のセキュリティ的な問題も考えておきましょう。
サブドメインに縛りがないため、サブドメインハイジャックなどでevil.example.comのような攻撃者が用意したサブドメインでもパスキーの認証器は呼び出せてしまいます。ただ、認証サービス側でパスキーの認証時に利用したオリジンの検証を入れているはずなので、正規のサービスログイン後セッションを窃取することは難しいと考えます。しかし、ユーザとしてはパスキーで認証した正規のサイトと騙すことができるので、重要な情報を誤って攻撃者のサイトに入力してしまうことも考えられます。このリスクを許容とみなすかもRP IDを設定する上でのポイントになります。
追記: Signal APIが利用できるため、パスキーをユーザの端末から削除するような攻撃も考えられます。
既存サービスのRP ID
既存のサービスに注目するとGoogleだと、google.com、GitHubはgithub.comのようにサブドメインを含まないものが多いように見受けられます。逆にサブドメインまで含めているケースだと、マネーフォワードがid.moneyforward.com、メルカリがjp.mercari.com、MIXI Mだとaccount.mixi.comが採用されています。
Googleはaccount.google.comのドメインで認証を行いますが、パスキーの設定ページはmyaccount.google.comで運用されていました。Googleはサブドメインごとに認証サービスやアカウント管理のサービスを分けているようだったので、利便性をとってRP IDを広くとったものだと思います。GitHubは認証ページとパスキーの設定ページがそもそもgithub.comドメインで展開されていたので、RP IDの選択肢は一つだけのようでした。
マネーフォワードではログイン画面とパスキーの設定ページがid.moneyforward.comであったので、RP IDの範囲を狭めているようです。MIXIもそうですが、サービスの特性上アカウント体系が複数考えられる場合やログイン画面とパスキー設定画面が同ドメインである場合には、狭くRP IDをつけて置くことが多そうです。
メルカリの場合はやや特殊で、ログイン画面はlogin.jp.mercari.comで運用されていました。
ただ、パスキーの登録やサービス自体はjp.mercari.comでした。複数アカウント体系を持っているため、サブドメインごとにアカウント体系を分けたうえで、ドメインに階層を設けてさらにサービス分離といった折衷案を採用しているように見えます。
RP IDをミスったら本当に詰みなのか?
別のドメインでもパスキーを使いたい場合にはRelated Origin Requests(ROR)という仕組みが利用できます。簡単に説明すると、本来なら該当オリジンから呼び出せないようなRP IDのパスキーを呼び出せるような仕組みです。
しかし、このRORは比較的新しい仕様であるため、すべての端末で対応しているわけではありません。
古い端末に関しては、ドメインが変更されるとそのパスキーではログインができなくなってしまいます。
また、RP IDをつけなおしているわけではない事には注意が必要です。
RP IDのつけ方をミスった場合や、ドメイン移行の際には詰む可能性は考えられます。
最近のニュースだと、twitter.comがx.comになった際に既存のパスキーは無効化されました。
このようにRORは現時点では、銀の弾丸にはなりえません。
まとめ
パスキーはユーザの端末に情報が保存されているので、サービス側で変更することはなかなかできません。後悔しないようなRP IDをつけましょう。ではまた!
Discussion