社内勉強会に向けて勉強した。
これを読んだまとめ。
- 紙の本だと80ページぐらい。
- コードサンプルはPHPで書かれている。
読んだ動機
- 前から気になっていたから。 OAuth がどうやって動いているのか。アプリケーションとどういうふうに連動しているのか。
- OAuthを使うアプリケーションを、プライベートで作ってみたいと思っているから。
- Oauth をうまく扱ってくれるモジュール等のおかげで、具体的な認証プロセスをあまり意識することが、あまりないから。
- 日頃から個人的にも、色々なサービスで OAuth のお世話になっているから。
OAuth 登場によってなにが変わったか
- 開発者たちの頭痛がやわらいだ。なぜなら100個ものAPIをひとつの技術で扱えるようになったから。(これが一番良いところ)
OAuth の歴史
- Google Calender API が最初にリリースされた頃、ユーザーがアプリケーションに権限を委譲する方法は、「ユーザー名」と「パスワード」を渡すしかなかった。
- その後、Google による AuthSub / Yahoo! による BBAuth などの認証方法が生まれたが、今度はアプリケーション開発者のコストが上がることになってしまった。アプリケーション開発者たちは、複数のAPIについて学習して、その一式をアプリケーションに組み込まなければいけなかった。(パスワード方式に比べると、かなり面倒ですね)
- さらにその後、まったく新しいAPIを作ろうする人たちも、自分たち独自の認証方式なんか揃えたくなかった。このような状況から、主要APIのプロバイダとスタートアップは「ウェブベースで共通の認証方法」を作ることに決めた。
なぜユーザー名とパスワードではダメなのか?
1. 信頼性
そもそもユーザーは、第三者のアプリケーションにパスワードを提供したくないだろう。
2. ユーザーのウェブリテラシーを下げる
もしユーザーが、アプリケーションに喜んでパスワードを提供したとしても。
それは長期的に考えると、他のフィッシング詐欺がはびこる下地になる。
3. 行き過ぎたアクセス権
アプリケーションは必要なデータだけではなく、すべての権限にアクセス出来てしまう。
4. 頼りにならない
ユーザーがパスワードを変えると、アプリケーションはデータにアクセス出来なくなってしまう。
5. 権限取り消しの問題
ユーザーはアプリケーションへのアクセス権を取り消すために、パスワードを変更するしか手段がない。
けれどパスワードを変更したら、ユーザーが他に連携してるアプリケーションも、同時に使えなくなってしまう。
6. 強力な認証を使えない
たとえばログインのためにキャプチャ画面を出すとか、ワンタイムパスワードを使うとか。
より強固な認証方法が使えない。
Oauth の登場人物
- Resouce owner (ユーザー)
- User Agent (ユーザー端末)
- Client (アプリケーション)
- Autorization server ( API - Facebook とか Google とか)
この中で、Resource Owner をのぞいた三者がやり取りをします。
( Resource Owner は「ユーザー」等を示すものなので、技術的なプロセスには関わっていません )
ここでは便宜的に、それぞれ「ユーザー(ユーザー端末)」「アプリケーション」「API」と呼ぶことにします。
サーバーサイド アプリケーション
フロー
- ユーザーはまず、アプリケーションから API にリダイレクトされる。
- ユーザーは Authorization code を持って、アプリケーションに帰ってくる。
- アプリケーションはユーザーから Authorization code を得る。これをAPIに問い合わせて、アクセストークンを得る。
この方法だと、アクセストークンはユーザー端末(ブラウザ)には現れない。ここがセキュリティ的に良いところ(たぶん)。
ユーザーをAPIに送る
client_id
APIがアプリケーションに発行したID。これは固定。
redirect_uri
APIでユーザーがアクセスを許可した時に、アプリケーションに戻ってくるURL。
この redirect_uri で指定したページに、アクセストークンを受け取る処理とかを、いろいろ書けば良い。
scope
アクセスしたいデータのタイプを記述する。
たとえば「Google Docsにアクセスしたい」というのであれば、それをここに記述する。
state
CSRF 攻撃を防ぐためのランダムな文字列。
こんな感じ ( rand(999_9999)
) で適当なものを生成して渡してやれば良い。
これは使い捨てなので「リクエスト」があるたびに、新しいものを生成して渡す必要がある。
URL
実際にはこんな感じになる。
http://www.googleapis.com/auth/tasks/?client_id=xxx&redirect_uri=yyy ...
アプリケーションがアクセストークンを得る
code
ユーザーがAPIから「もらって」きた Authorization code。
アプリケーションはこれを元に、アクセストークンを得る必要がある。
state
「ユーザーをAPIに送る時」に渡したランダムな文字列が、再び返ってくる。
もし両者が一致しなければ、第三者による何らかの攻撃であると考えられる。ここでもセキュリティ対策が出来るようになっている。
アクセストークンを得る
アプリケーションからAPIに問い合わせをおこなう。
Basic認証の「ユーザー名」に client_id を。「パスワード」に client_secret を渡す方法が OAuth 2.0 では最新の方法だ。
だが多くのAPIプロバイダはまだこの方法をサポートしていない。
そのかわりに HTTP POST リクエストを使う方法がある。
- client_id
- client_secret
- access_token
- token_type
- expire_in
- refresh_token
その他
アクセストークンは多くの場合、アプリケーションのデータベースに保存される。が、そう取り決められているわけではない。
アクセストークンをサーバーセッションに記録しておけば、パフォーマンス的に良い感じ。
他に書きたかったこと (時間切れ)
- 認可と認証の違い。認可について。
- エンドポイントとは。
- OAuth 1.0 との違い。
- リフレッシュトークンの仕様。
余談
- オライリーの本はやや格調高いイメージがあったが、この本は非常に読みやすかった。原文だから読みやすいのか、それとも本自体が読みやすいものなのかは不明。おそらくオライリーの中でも易しい部類。ちなみに日本語版は出ていない様子。
- オライリーの良いところは、初学者がつまづいたり、疑問に思う「盲点」をよく理解していて、その概念的な回答をくれる本が多いことだと、改めて感じた。「理解する」という意味では、安くて薄い本を買うより、むしろずっと易しい。
チャットメンバー募集
何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。