OpenID を勉強しようと、OpenID.ne.jpの説明を読んでみました。素人にはこういう説明でいいんでしょうが、セキュリティの専門家として読むと、これで何が認証されるのか、ブラウザの挙動はどうなるのか、さっぱり分りませんでした。
しょうがないので、バージョン 1.1 の仕様書を読んでみました。これでは RFC にさえなれないぐらい、ひどい質の文章でした。説明が下手だし、言葉が足りないので、まるで分りません。
さらに、バージョン 2.0 の仕様書を読んでみて、ようやく理解できました。はじめから、これを読めばよかったです。(もうちょっと工夫すれば、もっと分りやすくなるとは思いますが。)
認証の手続
結局、Overview の部分が核心をついていました。
登場人物は以下の3人:
認証の手続は、以下の通り。
- ユーザがブラウザを使って、あるサービスにアクセスする。サービスが認証を要求するので、ユーザは URL を打ち込む。これで認証の手続が始まる。
- サービスは、ユーザが打ち込んだ URL を基に、最終的な URL と OpenID サーバを得る。
- (省略可)サービスは、OpenID サーバと Diffie-Hellman を使って秘密の値を共有する。
- サービスは、認証情報と共にブラウザを OpenID サーバへリダイレクトする。
- OpenID サーバは、ユーザにパスワードを要求し、ユーザがパスワードを打ち込む。
- OpenID サーバは、認証結果と共にブラウザを元のサービスへリダイレクトする。
- サービスは、認証結果を検証する。
利用方法
RFC などもそうなのですが、仕様書にはどういうストーリで使うか書かれていないことが多く、理解の妨げになります。補助的な説明が別にあればいいんでしょうが、それも見当たらないので、結局知人と議論して考えてみました。
たとえば、悪意を持ったユーザが自分で OpenID を上げるとします。すると、認証結果は必ず OK になるでしょう。こんな認証機構が信用できるのでしょうか? 結局、なんからの格付けが必要になるはずです。
とうわけで、以下のように利用されるのでしょう。
- あらかじめ登録された ID だけにサービスを公開する
- ユーザを信頼し、ユーザが信頼する OpenID サーバを信頼することになります。
- OpenID サーバのホワイト/ブラックリストを持つ
- 特定の OpenID サーバを信頼し、そこが認証するユーザを信頼する。
もちろん、これら両方を実装してもいいでしょう。
セキュリティ・ホール
まぁ、これだけだといろいろセキュリティ・ホールがあるので、SSL が必須となっています。
僕が疑問に思うのは、nonce と呼ばれる乱数です。OpenID サーバは、6) で発行する認証結果に、この乱数を付けて返します。サービスは乱数を管理し、乱数が1回しか使えないようにして、再送攻撃(replay attack)を防ぎます。
でもこれだと、サービスは永遠に乱数を捨てれませんね。僕なら、4)においてサービスが乱数を生成し、それを戻してもらうように設計します。それなら、一回使われたら捨てればいいし、使われない場合も賞味期限が切れれば捨てることができます。
さて、どうなんでしょう?