Posted by & filed under いろいろ.


最近、「Facebookのことが分からないので教えてください」とよく頼まれます。ごめんなさい、嘘を言いました。よく、は頼まれません。よくある、とか、しばしばある、は実体以上に良く見せようとする時に使う常套句です。気をつけて使おうと思います。

それはともかくとして。

Facebookは確かに難しいです。REST API(名前がRESTですがまったくRESTfulではないWeb API)からGraph APIへの変遷、FBMLからXFBML(参照)への変遷、そしてXFBMLの存在を隠蔽するプラグインへの変遷、更に今をときめくLikeボタンからDislikeボタン(Dislike)への変遷、など諸々まとめて、「Facebook vs. OpenSocial」のお題で社内勉強会をしようと思っています。

しかし内容が多すぎるので、これらの技術の中で基盤となるOAuth 2.0(まだドラフト段階です)を取り出して、先にありえるえりあで文書を公開しようと思っていました。

と思っていたら、@ITでOAuth 2.0の記事を見つけました。通信プロトコルのフロー図も、アスキーアートで説明するつもりでしたが、@ITは綺麗な絵で説明しています。今更劣化版のフロー図を公開するのも気がひけるので、フロー図の説明は@ITの記事に譲ります。代わりに、OAuthまわりのもやもや感を払拭する記事を書きます。

説明の前に公式文書へのリンクを並べておきます。

OAuthまわりで一番(個人的に)困惑するのが次の説明です。

「OAuthは認可のためのプロトコルで認証のためのプロトコルではない」

特にOpenIDとの比較の文脈でこの説明を見ます。

しかし現実を見るとOAuthは事実上認証に使えている気がして困惑します。何が困惑の元なのか、結局実体は何なのかについて説明します。

最初に用語の定義です。認証(authentication)と認可(authorization)のふたつです。教科書的には次の定義です(昔、どこかから引き写した定義ですが、引用元を忘れました)。

認証
身元を判断するために個人やプロセスが提示する資格情報の検証
認可
何かを行う、またはある場所に存在するための権限を個人に与えること

抽象的な定義で分かりにくいので、多少厳密さを犠牲にして具体的に言い換えます。

Webアプリのユーザ認証は事実上ログイン処理のことです。ユーザIDとパスワードを入力してログインします。パスワードはその本人しか知りえない秘密情報です。その本人しか知りえない秘密情報を知っていればその人だ、という理屈です。パスワード以外にも、本人しか知りえない(持ちえない)秘密情報として、生体認証や秘密鍵認証(PKI認証)などもありますが、Webアプリに限ればパスワード認証がデファクト標準です。一般的なWebアプリの場合、ログイン中はセッションIDをクッキーなどで送ることでユーザ認証をします。いわば、セッションIDが一時的な秘密情報の肩代わりをします。

認可は、ログイン後に何ができるかを決めることです。他人の書いた文書を書き換える権限だったり、文書のコメントを削除する権限だったりします。

ここまでが認証と認可の話ですが、ここまでは、あるサービスと利用者の間の1対1の間の話です。

OpenIDやOAuthは違います。OpenIDは「認証伝達プロトコル」であり、OAuthは「認可伝達プロトコル」です。つまりサービスAで認証されたことをサービスBに伝達したり、サービスAで認可されたことをサービスBに伝達するためのプロトコル規格です。これらを「認証プロトコル」や「認可プロトコル」と呼ぶのは混乱の元なのでやめた方がいいと思います。認証プロトコルと呼ぶと、BASIC認証やフォーム認証のように、ユーザIDやパスワードを送信するやりとりを想起する危険があるからです。

OpenIDの話は別の機会に譲ります。OpenID終わったとまで言う人がいますが、これは言い過ぎだと思います。ただこれから書くようにOAuthで事実上の認証伝達ができるとOpenIDの存在価値に疑問符がつくのも事実です。

何を認可されたかの伝達そのものにはたいして意味がありません。OAuthの実体は認可された権限の委譲です。つまりOAuthは「権限委譲プロトコル」と呼ぶ方が適切です。サービスA(Facebookやtwitterを想定してください)で許可された権限を別のサービスBに委譲できます。この時、ユーザとサービスAの間の秘密情報(パスワードやセッションIDのクッキー値)をサービスBに渡しません。秘密情報を渡すことなく、サービスBに権限を委譲する実現方法は@ITの記事のフロー図や規格文書などを見てください。

どことどこの間で権限情報を伝達するかや、そのために事前にどこまで信頼関係を結んでおくか(事前に2者間で秘密情報を共有しておく)、などいくつか権限伝達のフローには派生があります。その辺が今回のOAuthで整理されています。OAuth 2.0を紹介する文書では6通りのフローとして列挙しています。

さて、冒頭の説明「OAuthは認可のためのプロトコルで認証のためのプロトコルではない」に戻ります。

OAuthが権限委譲(認可伝達)プロトコルなのは事実です。認証プロトコルでもないですし認証伝達プロトコルでもありません。しかし、サービスによっては、サービスAが誰々の文書への全権限を与える認可をサービスBに伝えたとしたら、事実上、そのユーザはサービスA上の誰々に他ならないと見なせます。サービスAの部分をFacebookやtwitterに読み替えて、誰々の部分をそれらのサービス上のIDに読み替えると、理解できると思います。Facebook上の誰々、twitterのidが何々の人、という形で認証伝達しています。事実追認の形でこれを「OAuth認証」と呼びます。ただ、これはOAuthの規格の範囲外で、どう利用するかの話です。なぜなら、誰々の文書への全権限を与えたことが誰々に他ならないかはサービス側の都合であって、権限委譲プロトコルのひとつの利用方法に過ぎないからです。

権限委譲プロトコルOAuthで、事実上、認証伝達ができることの説明は終わりです。以下、蛇足。

この手の話をすると、認証伝達は、要はSSO(シングルサインオン)のことですか、とよく聞かれます。ごめんなさい、よくは聞かれません。

これに対しては、強く関連はしても厳密に言えば認証伝達とSSOは別概念です、が回答になります。認証伝達を使いSSOを実現できますが、使わなくても実現できるからです。簡単な例を挙げると、サービスAとサービスBが同じディレクトリサービスを使う場合を考えます。ディレクトリサービスでユーザパスワードを管理して、ふたつのサービスへのログイン処理をなんらかの仕組みで透過に見せられればSSOを実現できます。サービスAで認証されたことをサービスBに伝達する仕組みがなくても透過に見せることは可能です。

同じく、ディレクトリサービスはSSOですか、の質問に対しても、ディレクトリサービスを構成要素としたSSOは実現できるが、使わなくてもSSOは実現できる、が回答になります。


関連文書:

  • 関連文書は見つからんがな

Comments are closed.