- この文章は業務時間中に調べた内容も多分に含まれているが、mala個人の文責で書かれている。
- 何か間違ったことが書かれていたらコメントで指摘するなり、twitterとかで教えてください。
- 連携するアプリ単位や開発者単位で、異なる userid を返すような仕組みがあり、PPIDと呼ばれている。
- PPIDの主目的はプライバシーの保護であり、異なるアプリケーション間での名寄せを困難にする。
- PPIDが使われている場合、副作用で、RP(Relying Party)の実装が不適切だった場合に、影響が緩和されることがある(後述)
- Google, Twitter, Yahoo などが該当する。
-
OpenID Configurationエンドポイントで確認することができる https://accounts.google.com/.well-known/openid-configuration
-
GoogleのID連携は、かつては、PPIDを返していた。(分離の粒度はrealmパラメータでの指定) https://ritou.hatenablog.com/entry/20131209/1386579214
-
OpenID Connect への移行のタイミングで、Public なIDを返すようになった(openid_id を取得することで、以前のPPIDから変換、移行が可能)
-
現行のIDは、Google+ のURLで使われていたIDで、今でも Google Mapsのレビュー投稿などで使われている公開されているIDである。例 : https://www.google.com/maps/contrib/112675818324417081103/
-
桁数は非常に長く連番ではない。総当たりするのは現実的ではない。
後述の、FacebookやLINEが、アプリ毎横断の共通のuseridから、PPIDへの移行を進めていったのに対して、Googleは逆にPPIDからpublicなIDへと変更している。
Googleの人に聞いたわけではないので推測ではあるが、理由としては2つぐらい考えられる。
-
- Google+ を始めとしたSocialなAPIとの連携を強化するため
-
- サービス横断で共通の識別子を得ようとして、Emailのパーミッションを求められるのは過剰であるから
-
「Emailはユニークではない可能性があり、ユーザーを識別する主キーとしては適さない」という記述がある。
-
https://developers.google.com/identity/protocols/OpenIDConnect#obtainuserinfo
The user's email address. This may not be unique and is not suitable for use as a primary key. Provided only if your scope included the string "email".
-
誰でも取得可能な public な数字の id が返ってくる。
-
Twitterはusernameは可変だが、HTMLソースやAPIレスポンスなどで、一意のuseridが含まれている。
-
※ Twitterは経緯からして、そもそも認証のためのAPIではないので、PPIDにするモチベーションはないだろう。
-
昔は連番だったが今は違うはず。
- OpenID Configurationエンドポイントで確認することができる https://auth.login.yahoo.co.jp/yconnect/v2/.well-known/openid-configuration
- アプリを横断して共通のIDを返している。このIDは、Yahoo IDとは異なるため、単純に外部からの推測は可能にはなっていない。
- ユーザーから認可された個々のアプリのデベロッパーであれば取れる。
- FacebookやLINEがこれに該当する
-
Graph API v2.0 より、PPIDに切り替わっている、2015年4月30日から切り替えが行われている。
-
Facebook では app scoped id と呼ばれており「アプリ毎」に異なるIDを返している。
-
https://developers.facebook.com/docs/apps/faq#app-scoped-ids
-
同一のデベロッパーであれば、異なるアプリ間でのIDをマッピングさせるAPIが用意されている。
-
https://developers.facebook.com/docs/facebook-login/connecting-accounts
-
数字のIDではあるが桁数はそれなりに長く、総当たりするのは現実的ではない。
- OpenID Configurationエンドポイントで確認することができる https://access.line.me/.well-known/openid-configuration
- 以前は mid というアプリを横断して共通のIDを返していたが、LINEログインv2がリリースされるタイミングで、PPIDに切り替わった。
- mid から userid に変換するAPIが用意されている https://developers.line.biz/ja/docs/line-login/converting-mid-to-userid/
- 事情に詳しい人間に聞いたところ、同一 Provider に対しては同一の userid を返しているらしい。
- あまり明確に解説されているのを見たことがないが、PPIDは副作用として、トークン置換攻撃(token substitution attack)に対する影響が緩和される。
- トークン置換攻撃は、異なるアプリ向けに発行された token をバックエンドサーバーに送信して、バックエンドサーバーが「どのAppに対して発行されたtokenなのか」を検証せずに受け入れてしまうような脆弱性のことだ。
- 取得されるuseridがApp毎に異なるIDになっているので、結果として「既存のユーザーとしてのログイン」には失敗する。(本来はそのAppに対して発行されたtokenではないのに新規ユーザー作成が行われる、などの影響は想定できる)
-
tokenではなく、本当に単純にクライアント側SDKで取得されたuseridのみをバックエンドサーバーに送信してしまうような脆弱性を、ごく稀に耳にする。
-
複数の人に聞いたが、これ自体には明確な名前がついていない。Googleのドキュメントに警告が書かれていたりはする。
-
https://developers.google.com/identity/sign-in/web/backend-auth
-
「任意のユーザーIDをサーバーに送信してユーザーを偽装できるので、ユーザーIDそのものをバックエンドサーバーに送って認証に使うな、代わりに検証可能なID tokenを使え」という注意書きがある。
ID ProviderがPPIDを発行している場合、たまたま攻撃が不可能になるようなケースも有りうる。ただし、useridが秘密の文字列として保たれるかどうかは連携するサービスの仕様次第で、URLに露出したり、他のユーザーのuseridが確認できるようなケースも発生しうる。
そのため「userid のみを送信して認証とみなすのはどんな場合でも推奨されない」
大事なことなので5回ぐらい書いておく。
- 「userid のみを送信して認証とみなすのはどんな場合でも推奨されない」
- 「userid のみを送信して認証とみなすのはどんな場合でも推奨されない」
- 「userid のみを送信して認証とみなすのはどんな場合でも推奨されない」
- 「userid のみを送信して認証とみなすのはどんな場合でも推奨されない」
- 「userid のみを送信して認証とみなすのはどんな場合でも推奨されない」