仕事で OAuth に詳しくならないといけなくなったので調べてみた。そのメモ。
実際に実装してみると詳しくなりそうだけど、若干めんどうなので想像だけ。以下な感じで実装すればよいと思われる。参考にしたのはOAuth の仕様書と Facebook の実装。
# 以下、仕様書の言葉に合わせて API を使う Web アプリを Client と呼びます
1. Client ID / Secret Key の実装
Web API を使う Client に ID を振り、同時に Secret Key を生成する機能を実装する。また Web API を利用するサイトの URL も登録できるようにする(リダイレクト処理の確認で使用する)。
1. 登録画面とか DB とか
とりあえず Client ID と Secret Key と Web API を利用する URL を登録できるようにしておけばよいはず。そのへんを適当に。
# Facebook でいうところの Facebook Developers みたいなやつ
2. Authorization の実装
Client が Web API 経由でユーザーにひもづく情報にアクセスすることをユーザーに許可してもらう処理を実装する。
# 例えば Facebook API を使って実装されたある Web アプリが Facebook API 経由で Facebook 上の私たちにひもづく情報、友達や写真、Feed にアクセスする場合、私たちは Web アプリが行うその動作を事前に許可するべきですし、実際許可しているはずです。つまるところそれです。
https://hogehoge.com/oauth のような URI で実装するのがよさそう。あと Client の Secret Key がバレたくないので https 使った方がいいはず。処理の流れはおそらく以下。
1. パラメータの取得
リクエストパラメータとして以下を受け取る。
・許可を与える Client ID
・処理完了時にリダイレクトする URI
・許可する Resource (必要に応じて)
2. ユーザーの認証確認
ログインしていることを確認する。もしログインしていなかったらまずログインしてもらう。ログインしてもらわないと、誰に許可を与えようとしているのかこちらで判断できないので。
3. 許可を与えようとしている Client、Resource の提示
受け取ったパラメータをもとに、許可を与えようとしている Client、Resource をユーザーに提示する。ユーザーはその表示を見て、問題がないようなら OK ボタンを押す(はず)。
なおすでに以下の処理を実施済みだったら、生成済みの Authorization Code と一緒にパラメータとして受け取っていた URI へリダイレクトする(つまりは以下の 4 を飛ばして 5 と 6 を実施する)。
4. 許可情報の保持
OK ボタンが押されてリクエストが飛んできたら、もう一回ログインを確かめて、ユーザー、許可する Client、許可する Resource のひもづけの保持する。またこの許可情報にひもづく Authorization Code を生成してこれも保持しておく。
5. リダイレクト先 URI の確認
パラメータとして受け取ったリダイレクト先の URI が事前にアプリとひも付けて登録しておいてもらった URL と一致することを確認する。Client に任意の URI へのリダイレクトを許すと色々と危ないため。
6. Client へリダイレクト
4. で生成しておいた Authorization Code と一緒に、パラメータとして受け取っていた URI へリダイレクトしてあげる(302 を返す)。
3. Access Token の実装
Web API をたたく際の Credential となるのが Access Token 。それを発行する処理を実装する。
# Access Token の仕組みを使えば Client はユーザーの認証情報(ID/Pass)なしでユーザーにひもづく情報にアクセスできる。つまりは ID/Pass が拡散せず、その分危険性が減ったり管理が煩雑にならなかったりと色々いいことがある。そこがポイント。
https://hogehoge.com/oauth/access_token のような URI で実装するのがよさげ。リクエストを受けて Access Token をレスポンスとして返す仕組み。
1. パラメータの取得
リクエストパラメータとして以下を受け取る。
・Access Token を発行したい Client ID
・その Client ID の Secret Key
・ユーザーが許可済みであることを示す Authorization Code
・処理完了時にリダイレクトする URI
2. Client の認証
Client ID と Secret Key で Client を認証する。この認証で Client が正規に登録されたものであることを確認するとともに、なりすましを防ぐ。
3. 許可状況の確認
Authorization Code が Valid なことを確認する。この確認で Client の Authorization が済んでいない Resource へのアクセスを防ぐ。
4. Access Token の生成
Authorization Code(許可された Resource)とひもづけた AccessToken を発行する。つまりはこの Access Token から許可された Resource が特定できるようになっていればよい、はず。
5. URI の確認
リダイレクトする URL が事前に登録されているものと一致することを確認する。確認が必要な理由は Authorization の時と同じ。
6. Access Token の発行
4. で生成した Access Token をレスポンスとして返す。どんなパラメータを返すべきかは仕様書の 5. Issuing an Access Token を参照。
# 参考として Facebook では Access Token と一緒に有効時間を返しています。
3. API の実装
Credential として Access Token を受け取り、指定された API を実行して結果を返す仕組みを実装する。
1. Access Token の確認
Access Token が発行済のものであること、有効時間内であることを確認する。
2. 許可状況の確認
Access Token から Authorization Code をたどり、さらにそこから許可された Resource の情報を取得し、要求されている API が実行可能かどうかを確認する。許可されていない Resource であれば 400 を返す。
4. API の実行
リクエスト、URI などで渡されたパラメータを元に API を実行する。実行した結果をレスポンスとしてユーザーに返す。
# レスポンスの形式としては XML でも JSON でもよい。ちなみに Facebook は JSON。
と、裏で他にやるべきことが色々とありますが、とりあえずこんな感じで実装しておけば OAuth 対応の Web API を公開できるはず。時間あったら実際に実装してみたいな。以上。
参考:
・
Facebook Developers - Authentication
・
The OAuth 2.0 Authorization Protocol