OAuth(オー・オース)とは、APIの認証を委譲するオープンプロトコルである。
概要
OpenIDでは満足できない! 俺はもっと! マッシュアップしたいんだ! 俺は! Oh, ASS!
そんなわけで、外部サイトやソフトウェアとのAPIの認可する手段として新たに公表されたものがこれらしい。
歴史
- 2006年11月、当時のTwitterはOpenIDを使用していたが、ソーシャルブックマークサイトの「Ma.gnolia」は、ユーザーがOpenIDを使用して、会員管理画面(ダッシュボード)のウィジェットからサービスにアクセスしようと模索する。
- OpenIDを使ってTwitterやMa.gnoliaのAPIの認証委譲する方法を関係者らが議論した結果、APIの委譲についてのオープン標準はまだ存在しないという結論に達し、それがのちのOAuth誕生となる。
- OAuthのインターネットコミュニティの設立が2007年4月に至る。
- OAuthプロジェクトのことを知った Google が支援を表明する。
- 2007年10月3日、OAuth Core 1.0 の最終草案がリリースされた。
- 2008年11月には、さらなる標準化に向けてIETFにOAuthプロトコルを提案するかどうかを議論した。その結果、IETFで正式にOAUTHワーキンググループを立ち上げることに幅広い支持が得られた。
仕様
一言で言えば、OpenIDの進化形と考えれば良いのではなかろうか。
OAuthを採用したサイトと、外部サイトやソフトウェアとのAPIの認可を与えると言う仕組み。
その際には、発行されたトークン(暗号化された文字列キー)で認証を行い、APIの認可をする。
これにより、外部サイトやソフトウェアなどからのログイン認証や、メッセージの表示や送信などの制御ができる。
だが、それを可能とするのが長所であり短所でもあったりする。
OAuth認証後にユーザーの知らない間になんらかの動作をする危険が危ないことが問題になっている。
というか、OAuthは本来認可のために用いるプロトコルなので、OpenIDとは用途が全く異なる(あちらは認証のために用いる)。よく言われるたとえは「OAuthは合鍵、OpenIDは身分証」というものであり、これを聞けば認証にOAuthを使うのがいかにおかしいかがわかるだろう。
だが、それが横行した結果、最終的に出てきたのがOAuth 2.0とOpenID Connectである。手っ取り早い話がOpenIDの仕組みをOAuthに取り込んでしまったのだ(要するに身分証の発行権限を合鍵に与えたということ)。
というわけで、OAuth 2.0とOpenID Connectを採用している場合は、両者を同時に取り扱って構わない。ただし、それぞれで使うトークンが異なる点には注意。
OAuthの流れ
OAuth 1a(Twitterなどで採用)とOAuth 2.0(Googleなどで採用)では全くフローが異なる。以下、それぞれのフローを順番に見ていくことにする。
OAuth 1aの場合
- まずクライアントがAPIを利用するサーバにログインのURLを発行してくれと依頼する
- サーバはプロバイダ(例えばTwitter)にリクエストに使うための1回限りのトークンを登録する
- 登録完了後、このURLにアクセスせよとサーバはクライアントに指示する(このURLはプロバイダ上の認可画面のURL)
- クライアントはブラウザで3のURLを表示する
- プロバイダは「何の権限を要求しているか」を表示する。それに対して許可/拒否のチョイスが与えられる。拒否したら認可は失敗する。ここでは許可を選んだとする
- コールバックURL(サーバ上にある)へリダイレクトされ、そこにverifier(検証トークン)が渡される。この検証トークンを最初に発行したトークンとともに渡すと、アクセストークンと引き換えができる
- 以後、サーバはアクセストークンを用いて実際にリソースのアクセスを行う
なお、サーバとプロバイダとの間のアクセスには、コンシューマキーとコンシューマシークレットというのが必要になる。コンシューマシークレットは絶対に秘密にしておかなければならないものである。
アプリの場合、サーバはアプリそのものが担い、コールバックURLもアプリ呼び出し用のURLになる。アプリは4でブラウザを起動して許可を求め、許可を選んだらアプリに戻って残りの処理を行うことになる。
一方、ブラウザの場合、サーバは別に必要であるが、4で表示する際には同じウィンドウで開けばよい。
OAuth 2.0
フローはコード・暗黙的・パスワード・クライアントの4種類がある。OAuth 2.0はRFC6749にて定められている。
主な使い分けは以下の通り。
- コード - サーバ側からリソースの操作を行う場合
- 暗黙的 - フロント側からリソースの操作を行う場合
- パスワード - 主にBotなどからBot自身のリソースの操作を行う場合
- クライアント - クライアント(要するにOAuthで構築したアプリ)自身のリソースの操作を行う場合
クライアントIDは公開して構わない情報である。一方、クライアントシークレットは秘密にしておかなければならない情報である。
コードフローの場合
コードフローの場合、認可URLにアクセスする際、response_typeにはcodeを指定する(OpenID Connectを行う場合もcodeである。codeとtoken/id_tokenを一緒に指定するとハイブリッドフローになり、暗黙的フローとコードフローが混じってしまうため面倒)。そのほかに必要なのはクライアントID・認可後のリダイレクト先URI・アクセスするリソースの範囲(OpenID Connectの場合ここにopenidが入っている必要がある)・リプレイ攻撃を防ぐためのトークンである。
ここで認可をもらうと、リダイレクトURIにはコードとリプレイ攻撃防止用のトークンが渡される。この後、トークンエンドポイントにクライアントID・クライアントシークレット・リダイレクトURIとともに、grant_typeにauthorization_codeを渡す。
これにより、アクセストークンとおよびアクセストークンの有効期限(もしOpenID Connectを要求しているならば同時にIDトークンも)、および許可されているならリフレッシュトークンをもらうことができる。IDトークンの説明はこの後、暗黙的フローと一緒に説明する。以後、リソースへのアクセスにはアクセストークンを用いる。
一方、リフレッシュトークンは、アクセストークンの有効期限が切れたとき、アクセストークンと引き換えが可能なトークンである。
暗黙的フローの場合
暗黙的フローの場合、認可URLにアクセスする際、response_typeにはtokenを指定する(なお、OpenID Connectだけを行う場合はid_token、両方を行う場合はtokenとid_tokenの両方を指定する)。残りのパラメータはコードフローと同じである。
ここで認可をもらうと、リダイレクトURIにアクセストークンと有効期限と先ほどのリプレイ攻撃防止用のトークンが渡される(OpenID Connectだけの場合はIDトークンのみ、両方を指定した場合はアクセストークンとIDトークンの両方が渡される)。各トークンの使い道はコードフローと同様。
ページ完結型の場合は、このフローを用いるのがベストである。アプリも、クラックされるリスクを考慮するとこちらを用いるのが通例。
パスワードフローの場合
パスワードフローの場合、トークンエンドポイントにクライアントID・クライアントシークレット・ユーザ名・パスワード・スコープを渡すとともに、grant_typeにpasswordを渡す。これによりアクセストークン(および許可されているならばリフレッシュトークン)をもらうことができる。
ユーザにプラットフォームのユーザ名とパスワードを入力してもらうという構造的問題から、一般的なアプリケーションで用いることはなく、一部プラットフォームのBotなどで用いられる程度である。
クライアントフローの場合
クライアントフローの場合、トークンエンドポイントにクライアントID・クライアントシークレットを渡すとともに、grant_typeにclient_credentialsを渡す。これによりアクセストークンをもらうことができる。
そもそも、ユーザが一切介在しないことからわかる通り、ユーザに関するリソースへのアクセスは一切不可。実際のところ使用例はあまり多くなく、Facebookでのユーザのユーザアクセストークンのデバッグなどで用いられる程度である(発行されたユーザアクセストークンの管理はクライアント側の責務なので、クライアントフローを用いる)。
IDトークンとは何か
IDトークンとは、認証されたユーザが何者であるかなどの情報が入ったトークンである。このIDトークンはJSON Web Tokenの形式になっており、ピリオドで区切られた以下の3つの情報から構成される。
- 署名の仕組み
- クレーム(本文)
- 署名
署名の仕組みを用いて、署名を行い、それを末尾に追加する。それぞれのコンポーネントはBase64を使って符号化されている。
署名の仕組みと署名に関しては割愛するとして、クレームには何が入っているのか。
- 誰が発行したのか(iss)
- 認証されたユーザの識別子は何か(sub)
- 誰のために発行したのか(aud)
- トークンの有効期限はいつまでか(exp)
- いつ発行したのか(iat)
- そのほか、許可されていればユーザに関する情報が入っている場合もある
まず、どのプロバイダが作ったのかをissで確認する。その後、expに指定された有効期限が到来してないかを確認したら、署名の検証を行う。問題がなければ、audで自分宛かどうかを確認し、subでユーザの識別子を取得するとともに、その他の情報と合わせてユーザ情報の登録や更新などを行う。
OAuthを採用してるサイト
など。(これ以上追加してもキリがない)
関連項目
関連リンク
- OAuth.net - 公式サイト(英語)
- OAuth - Googleグループ
- OAuth - 笑ってダマされタメになる!きたみとまなめのIT用語集:selfup
- 図解:OAuth 2.0に潜む「5つの脆弱性」と解決法
- 3
- 0pt