2章
webアプリケーションフロー(認可コードフロー)
リソース所有者が、アプリケーションによってAPIプロバイダのOAuth認可サーバへリダイレクト。リダイレクト先の認可サーバはユーザがアクティブなセッションを持ているかどうかを確認。その後認可サーバが要求データに対するアクセウを認可するように促す。ユーザはアクセス認可すると最初のwebアプリケーションにリダイレクトで戻されるが、URLにはcodeクエリパラメータとして認可コードが付加されている。
codeクエリパラメータとして渡されるため、webブラウザからOAuthクライアントであるwebサーバにも送られる。この認可コードがwebサーバと認可サーバ間のやりとりで使用するアクセストークンと交換される。クライアントがAPI呼び出しを行う際にこのアクセストークンが使われる。
セキュリティ特性
アクセストークンはリソース所有者のブラウザからみえることはない。認可を行うために認可コードが使われるがこれはブラウザを通して受け渡される。保護されたAPIを呼び出す際は認可コードをアクセストークンに変換しておかなければならない。この変換プロセスはリクエストと共に、client_secretが渡された場合のみ成功する。このため、クライアンのセキュリティが守られている場合はアクセストークンの機密性が確保できる。アクセストークンの機密性はリソース所有者に対しても守られる。つまり、アクセストークンを使って生成されたAPIリクエストは、クライアンとその開発者の直接的な管理下にあるということ。
アクセストークンはブラウザを介していないので、履歴、refererヘッダ、jsなどから漏洩するリスクを軽減できる。
アクセストークンの漏洩リクスは小さいが、このフローを利用するアプリケーションの多くが、データベースあキーストアに有効期限の長いリフレッシュトークンを保持しておき、データへのオンラインアクセスを実現するが、アプリケーションが長期に渡るオフラインアクセスを要求するとさらなると、多数のユーザデータに対し、攻撃され得るアクセスポイントを一箇所に集約した状態で持つことになるのでリスクが生まれる。この問題はクライアントサイドwebアプリケーションフローのような他のフローでは存在しない。このようなリスク増加があっても、構造上、新しいアクセストークンを得るためのにユーザのブラウザと通信するのが簡単ではないため、多くのwebサイトはオフラインデータアクセスを使用する。
もろもろステップ
APIプロバイダにアプリケーションを登録、OAuthクライントIDとクライアントシークレットを入手し、コードを書く。
1.ユーザにこれから実行する内容を知らせ、認可を求める
認可を得るためにAPIプロバイダのサイトにリダイレクトするので、ユーザにこれからどんな内容を実行するのか予め知らせておくべき。メッセージを表示して、 add tasks to your unko みたいなのをつけてくとか
エラー処理
リクエストパラメータに無効なものが含まれていた場合、エラー状態となる。
redirect_uri,client_id、その他のリクエスト情報に問題があった際は、認可サーバはユーザにエラーメッセージを表示し、アプリケーションへのリダイレクトを中止する
ユーザがアクセス要求を認めなかった場合もエラー応答が生成され access_denied型のエラーを表すパラメータと共にredirect_uriにリダイレクトされる。認可サーバはerror_description(エラー情報メッセージ)、error_uri(エラー情報を掲載したページのURL)などを送ることもできる。
OAuth2.0の仕様では下記のエラーが定義されている
invalid_request
リクエストに必要なパラメータ不足、サポート外の値指定、その他の不正な形式unauthorized_client
認可コード要求が認められていないクライアントからのリクエストunsupported_response_type
認可サーバがサポートしていない形式で認可コードをの取得をしたinvalid_scope
したいされたスコープが無効/未定義/不正な形式server_error
認可サーバで想定外のエラーが発生し、リクエストを実行できないtemporarily_unavailable
一時的な高負荷などにより処理できない
2.認可コードをアクセストークンに交換する
認証プロセスにエラーがなければ、認可サーバはユーザをredirect_urlで指定されたURLにリダイレクトする。ユーザがアクセスを認証した場合、webアプリケーションにリダイレクトで戻る差異、2つのクエリパラメータが付加される
code
認可コード。ユーザがアクセス要求を承認したことを示すstate
認可サーバに最初にリクエストを送った時に渡したstateパラメータの値
このstate値を最初に作成sた値と比較し、一致しなければCSRF攻撃の可能性がある。この場合はOAuthを中断すべき。
送られてきたコードをAPIリクエストに使用するOAuthアクセストークンに交換する必要があるが、ライブラリなどを使用しない場合は、トークンエンドポイントに対するHTTP POSTリクエストをじぶんで 生成する。今回の場合、生成には下記パラメータが必要
code
アプリケーションに渡された認可コードredirect_uri
リダイレクトURI。あらかじめ登録された、認可エンドポイントへの最初のリクエスト時に指定した場所grant_type
グランとタイプ。authorization_codeという値を指定する。認可コードをアクセストークンに交換することを示す。
このHTTP POSTリクエストはアプリケーション等r9時に与えられたclient_idとclient_secretによる認証を受けなければならない。OAuth2.0の仕様には、リクエストを認証する方法が主に2種類定義されている。
AuthorizationヘッダによるHTTP Basic認証(client_idをユーザ名、client_secretをパスワード)を利用する方法とclient_idとclient_secretをHTTP POSTパラメータに追加する方法
Authorizationヘッダの場合は
Authorization: Basic
MDAwMDAwMDA0NzU1REU0MzpVRWhrTDRzTmVOOFlhbG50UHhnUjhaTWtpVU1nWWlJNg
HTTP POSTパラメータの場合はcode、stateと一緒に下記パラメータが必要
client_id
クライアントID。アプリケーション登録時に割り当てられたIDclient_secret
クライントシークレット。アプリケーション登録時に割り当てられた秘密の文字列。
リクエストの認証が終わり、パラメータが適切な場合は、認可サーバからのレスポンスとしてOAuthアクセストークンを生しjsonで返す。
access_token
APIリクエストを認可するときに使用するトークンtoken_type
発行されたアクセストークンの種類。大体「bearer」expires_in
アクセストークンの有効期限の残り秒数
- refresh_token リフレッシュトークン。現在のアクセストークンが死んだ際に新しいアクセストークンを取得するために使うトークン
アクセストークンとリフレッシュトークンが必要な理由
OAuth2.0では通常ベアラートークンが使われるが、保護されたAPIサービスがセキュリティ上危険になると、クライアントから受け取ったアクセストークンが攻撃者にさらされることになりかねない。OAuthでは、複数の異なるAPIに対するアクセスをアプリケーションに与える場合も考えられる。そうなると1つのサービスが危険になった場合に他のサービスも影響を受ける可能性がある。有効期限が短いアクセストークンだけがAPiサービスにアクセスできるようなっていれば、攻撃された際の影響範囲を狭めることができる。
APIサービスはクライアントからアクセストークンを受け取った時に、要求するアクセスに対して、正しいトークンかどうか確認する必要がある。受け取ったトークンが自分で検証できない場合はAPIサービスのOAuth認証サービス内部へのリクエストを行うか、データベースを参照しトークンの有効性が判断される。ただ、これによってAPIリクエストに対し遅延が発生する可能性があるので、OAuthの代わりにアクセストークンとして署名付き文字列や暗号化文字列を使うプロバイダもある。
APIの呼び出し
ベアラートークンが使われている場合は、アプリケーションからのAPIリクエストが認可済みであることを示す際に、リクエストにアクセストークンを含めるだけでオッケー。デジタル署名は要らない。
(アクセストークンの送付はやっぱりAuthorizationヘッダがいいよ)
アクセストークンの更新(リフレッシュ)
トークンのエンドポイントに対し grant_typeとしてrefresh_tokenを指定し、refresh_tokeんを付加したHTTP POSTを実する。このリクエストに対しても認証は必要
アクセス権限の取り消し
アカウントの管理インターフェースで明示的にアクセス取り消しを指定してもうらう方法が一般的。Facebookとかはパスワードをユーザが変更したら即無効になるらしい。
googleとかはリフレッシュトークンとかの取り消し用のプログラムを用意していて、それを叩くと無効にできる。