Googleが出したOpenID 2.0からOpenID Connectへの移行のプラクティスについての補足

こんばんは、ritouです。

OpenIDファウンデーションのブログにこんなことが書いてありました。

OpenID 2.0 から OpenID Connect への移行のプラクティス @ Google (追記あり) | 事務局ブログ | OpenID ファウンデーション・ジャパン

これについてちょっとだけ補足します。

OpenID 2.0とOpenID Connectの識別子のカンケイ

GoogleOpenID Connectの実装で返されるユーザー識別子は、文字列です。

An identifier for the user, unique among all Google accounts and never reused. A Google account can have multiple emails at different points in time, but this value is never changed. You should use this within your application as the unique-identifier key for the user.

OpenID Connect  |  Google Identity Platform  |  Google Developers

まぁ、↑の説明読んでも文字列だっては書いていませんが、とりあえずそうなってます。こいつがID Tokenに含まれたり、UserInfo Endpointで返されてRP側はユーザーの識別に利用します。

それに対し、OpenID 2.0では"claimed_id"と呼ばれるものが識別子として利用されています。
これの形はURIだったりXRIだったりして、AuthZ Responseに含まれてRPに渡されます。

こんな感じで、OpenID Connectで返す識別子とOpenID 2.0で返される識別子が変わる場合は単純に移行ってわけにはいきません。なので、OpenID Connect側のAPIもしくはID Tokenで返してあげましょうという話です。

Googleが渡してるOpenID 2.0の識別子はPPID

今回はGoogleの話ですがあえてmixiが返すclaimed_idを紹介すると、こんな感じになります。

https://id.mixi.jp/[ログインしたユーザーの ID]

仕様 << mixi Developer Center (ミクシィ デベロッパーセンター)

識別子を受け取るRPに対して共通の値を返します。
こんな仕様であれば、単純にID Tokenに含んでやればいいだけですね。

それに対してGoogleの場合は、RP単位、正確にはAuthN Requestに含まれるrealmパラメータ単位でにこの値が変わるPairwise Pseudonymous Identifier(PPID)を採用しています。

むかーし自分のアカウントで試したときは、こんな感じでした。

この仕様のおかげで、RPが途中でドメインが変わって大変なことになったみたいな話を聞いたことがあります。対策として属性情報を一緒にもらう拡張により取得したGmailを使ってなんとかしたり、"なんとなくユニークなURL取得する方法見つけたけどundocumentなので怖くて使えない" みたいなことがありました。

ということで、Googleの場合はOpenID ConnectでRPが自分向けの識別子をもらえるように、realmパラメータが必要なため、AuthZ Requestに含む必要があるということです。

実際に試してみる

ここにOpenID ConnectのデモClient(RP)があります。
http://demo-client.openidconnect.info/

Googleにも対応しているので、手動でごにょごにょしてAuthZ Requestにopenid.realmパラメータを追加します。

なんとなくhttp://rp.example.com/を指定したかったのですが、OpenID Connect(OAuth 2.0)のredirect_uriとのチェックが走ってエラーになりました。OpenID 2.0とOpenID Connectそれぞれを実装したドメインが異なるRPの場合どうなるのでしょう。ちょっと工夫が必要かもしれません。

redirect_uriドメインに揃えたら、処理が進みました。
取得できたID Tokenには"openid_id"という値が含まれています。
openid_idって・・・id_idってとこがなんかジワジワ来ませんか?来ませんね。

{
 "exp":1386580570,
 "iss":"accounts.google.com",
 "email_verified":"true",
 "openid_id":"https://www.google.com/accounts/o8/id?id=AItOawnlsqN5H5eKPha4fWLjNDFhlwIO6VUtpt4",
 "email":"ritou.06@gmail.com",
 "sub":"(略)",
 "azp":"1058421314966-9i0d7t4lkrs7k57t21apt62e4dsfvv09.apps.googleusercontent.com",
 "iat":1386576670,
 "at_hash":"(略)",
 "aud":"1058421314966-9i0d7t4lkrs7k57t21apt62e4dsfvv09.apps.googleusercontent.com"
}

という感じです。

ちょっと気になること

OpenID 2.0の識別子を返すという目的を果たすにはこれで十分なのでしょうけど、ユーザーへの説明は必要ないのでしょうか?もちろん前提としてユーザーは同じサービスを使い続けているわけで、ほとんどのユーザーは識別子が違うことも認識していないでしょう。
Googleの場合はPPIDなので名寄せ可能なのがそのrealmを使っていたRPだけなので良いのかもしれませんが、mixiとかの場合は他の全てのOpenID RPとデータの突合せが可能になるわけで、けっこうインパクトはでかいと思っています。

では具体的にどう説明すればいいの?ってところで私も答えは出ておりませんが、自分が同じようなものを実装するのであれば何かしらのユーザーへの説明や専用scopeの追加をしたい気がします。

以上、ファウンデーションの記事に対する軽い補足記事でした。

ではまた!