金利0無利息キャッシング – キャッシングできます

 | 

2012-02-14

OAuthにおける「クライアントサイドに対する認可」なのか「サーバーサイドに対する認可」なのか明確でない問題

15:10 | OAuthにおける「クライアントサイドに対する認可」なのか「サーバーサイドに対する認可」なのか明確でない問題 - 金利0無利息キャッシング – キャッシングできます を含むブックマーク はてなブックマーク - OAuthにおける「クライアントサイドに対する認可」なのか「サーバーサイドに対する認可」なのか明確でない問題 - 金利0無利息キャッシング – キャッシングできます

ココらへんの問題について、適当に自分の考えを書いたりします。

個人的に、余計な権限がついてまわるようなOAuth使ってログインさせるサイトが多くて嫌だなーと感じているのだけど、それはそうとして置いといて。俺はいわゆるWebサイトについている「OAuthを使ったログインボタン」に実装上の問題があるケースというのはそんなに多くないと思っている。なぜかというとサーバーサイドに対する認可を求めているなら最初からCode Flow(response_type=code)を使えば良いから、わざわざImplicit Flow(response_type=token)を使う必要がない。だから問題が起こりやすいのは、OAuthによる認可が与えられたのがクライアントサイドなのかサーバーサイドなのかが曖昧になるような、OpenSocialアプリの類だったりとか、スマートフォンアプリだったりだとかではないかと思う。

クライアントサイドに与えられた認可を、サーバーサイドに流用するということについて、そのようなアプリケーションが「邪悪である」というコンセンサスが取れていない(あるいは取る必要があるのか)という問題を含んでいるのではないかと思う。

認可を与えた対象は誰?という問題

OAuth2.0のImplicit Flowというのは、こんな感じでAccess tokenを受け取ることが出来るわけです。

#以降の部分はサーバー側のアクセスログに残らない。例えば、GmailOAuthを使っているクライアントがあったとして、Implicit Flowを使えばAccess tokenが受け渡される相手をアプリケーションのみに限定することが出来る。この場合、メールを読むことが出来るのはアプリケーション(UserAgent)であって、そのアプリケーションの作者ではない。あなたのプライベートな情報を見ることが出来るのは、あくまでも認可を与えたアプリケーションであって、アプリケーション開発者はあなたのデータにアクセス出来ませんよ、ってことが実現できるのが嬉しいわけ。

例えばOAuthを使ったアプリケーションの開発者がいるとして、Aさんとしましょう。Aさんだと分かりにくいので小池さんとしましょう。

  • 小池さんの作る(サーバーサイドの)アプリケーションに対して認可を与えると、あなたの個人情報が小池さんのサーバーから読み取られたりといったそういう問題が発生する(わかりやすい)
  • 小池さんの作る(クライアントサイドの)アプリケーションに対して認可を与えた場合、あなたの個人情報が小池さんから読み取られるかどうかは、実装次第。
  • 小池さんに悪意があれば、やっぱり取得したaccess_tokenをこっそりサーバーに送ったり、クライアントサイドで受信したメールをサーバーに送って、メールを盗み見ることが出来てしまう。
  • しかし、小池さんがアプリケーションのソースを公開していて、信頼出来る人がそれを検証していて、各々のマシンでアプリケーションが改変されずに実行されているのであれば、小池さんがメールを盗み見ていないということが保障できる

地の底までに信用が落ちた小池さんであっても、適切な公開手順や第三者による検査を受けているのであれば、アプリケーション自体を信用することは出来る。

アプリケーションがどこで動いているのかは曖昧になっている

  • プログラムがどこで動いているのかは意識されなくなっている
  • もしくは、プログラムがどんな動作をするのかを、いちいち検証する人は(ユーザー全体からすれば)少なくなっている

人によってはクライアントサイドへの認可なのか、サーバーサイドへの認可なのか「そんな区別には大した意味がない」と言うかもしれない。大多数のユーザーはソース読んだりできないのだから単にサービス提供者であったり、アプリケーション作者を信用するかどうかという問題に帰結してしまう。ただ「曖昧になっているのをいいことに」クライアントサイドで動いているつもりが実はクラウド上で動作していてバリバリ個人情報送信されてました、みたいな状況はよろしく無いと思う。

  • 「どのアプリケーションに対して与えられたtokenなのかを検証する」という解決策だと、検証を忘れた際に脆弱性になる
  • バリデーションが必要な状況が発生したら、その状況そのものを疑うべき
  • access_tokenの値をサーバーに送ってしまうということは、結局サーバーサイドにも認可を与えちゃってるってことだよ。
  • あるいはクライアントサイドで取得した何らかの個人情報をサーバーに送るのであれば、それは結局サーバーサイドへの認可を必要としていると考えるべき。

それが必要なんであれば、最初からCode Flowでやればいいんじゃないの、以上、という話になる。クライアントサイドには完全なフルアクセスの許可を与えた上で、サーバーサイドにはアプリケーション毎に発行される一意の匿名idが取得できる、みたいな使い分けが出来ると便利なんじゃないかと思いました。

2012-03-14追記: 合わせて読みたい

心強いお言葉。

サーバーサイドとクライアントサイドの両方のComponentから構成されている場合、別々で登録しろ!

トラックバック - http://subtech.g.hatena.ne.jp/mala/20120214
 |