OAuthとは、webサービスでの認可機能のデファクトとなっている仕様のことを指します。
OAuthは、登場する要素や用語が多い、またそれらの相互の関係が複雑なため、一見理解が難しいです。
しかし、概念を一つずつ整理していけばそこまで難しいものではないことがわかります。
今回は、OAuthで登場する用語や概念について説明をしていきます。
実際のユースケースについては次回の記事で説明しますので、今回の記事では対象外とします。
OAuthを使用することのメリットについては、以下の記事で解説していますので、ご参照ください。
ロール
OAuthにはロールという概念が登場します。
これは、OAuthにおける役割に相当します。
OAuthと言うのは、複数のシステム(サーバ)が連携し合って機能する一つの仕組みになります。
この複数の要素が登場するということが、OAuthの理解を難しくしている要因でもあります。
関係図
まずは個々のロールを解説する前に、それぞれがどのような関係性を持つかを見ておきましょう。
これをはじめに頭に入れておくことで、以降の個々のロールの説明が理解しやすくなるはずです。
ここでは例として、Googleドライブから画像をダウンロードする架空のアプリケーションにおけるロールの関連図を見ていきます。
(※この関係図はあくまで基本的なものです。
厳密には以降に説明するグラントタイプによってそれぞれの関係が多少異なります。
ここでは、理解を優先として単純化した関係図を示すこととします。)
リソースオーナー | リソース(画像)の所有者であり、サードパーティ製のアプリの使用者 |
---|---|
クライアント | サード―パーティ製アプリ。サーバーサイド、ネイティブアプリかは問わない。 |
リソースサーバー | リソースを提供するサーバー。この例だとGoogleDriveのデータがあるサーバー。 |
認可サーバー | クライアントの認可を行うサーバー。リソースサーバーと同じ組織が運営。(この例だとGoogle) |
リソースオーナー
リソース(今回の例だとGoogleDrive上の画像データ)を所有している人物を指します。
また、サード―パーティー製アプリケーションを使用する人でもあります。
要するに、アプリを通じてGoogleDriveから自分の画像をダウンロードしようとしているユーザーですね。
クライアント
サードパーティー製のアプリケーションのことを指します。
このアプリケーションにGoogleDriveの画像をダウンロードする権限を安全に与えることがOAuthの目的になります。
OAuthにおいては、クライアントのアプリの形態は問いません。
サーバーサイドアプリ(webブラウザから実行できるアプリ)、ネイティブアプリ(スマホアプリやデスクトップアプリなど端末にインストールする形態のアプリ)どちらでも構いません。
ただし、アプリの形態によって、以降で説明するグラントタイプが異なります。
グラントタイプとは、認可のフローを定義するもので複数の種類が存在します。
今は深く考えなくて大丈夫です。
また、OAuthにはクライアントタイプと呼ばれる概念が存在します。
これは、クライアントがトークンをセキュアに保存できるかどうかによる区分になります。
一般的には以下のように考えておけば良いです。
コンフィデンシャル | トークンをセキュアに保存できるアプリ。 サーバーサイドアプリなど。 |
---|---|
パブリック | トークンをセキュアに保存できないアプリ。 クライアントアプリ、ネイティブアプリなど。 |
リソースサーバー
リソース(画像)を保持するサーバーを指します。
今回の例だとGoogleDriveのサーバーになります。
認可サーバー
認可を行うサーバーを指します。
認可とは、権限の委譲のことであり、今回の例であれば、「GoogleDriveから画像をダウンローする権限を与えること」になります。
認可サーバはリソースサーバーと同じ組織が運営しています。
この例だと、Googleですね。
また、図ではリソースサーバーと認可サーバーが別れていますが、一つのサーバーにまとまっていることもあります。
リソースサーバーがリソースの提供と認可の両方を行うということです。
提供するリソースが一つの場合は、このような構成でも問題ありません。
Googleのように様々な種類のリソースを提供する場合は、認可の機能を切り出した方が管理しやすいため、サーバーを分割することがあります。
トークン
トークンとは、認可されたことを証明するものになります。
トークンを持っていることで、「GoogleDriveから画像をダウンロードする許可を得た」ということの証明となります。
トークンは以下の情報を持っています。
・スコープ
・有効期限
・リフレッシュトークン
・認可コード
スコープ
スコープはそのトークンが許可する権限の範囲です。
例えば、画像をダウンロードできる、画像をアップロードできる、画像を削除できる、などです。
スコープは、OAuthの仕様で規定値が決められているわけではなく、認可サーバー側で定義する必要があります。
また、スコープはあくまでオーナーに通知するためにトークンに埋め込まれるものにすぎません。
これを認可サーバに渡すことでそのスコープの権限を得られるというわけではありません。
有効期限
トークンの有効期限を示します。
単位は秒になります。
例えば、有効期限が 100 であれば、そのトークンは100秒間有効、100秒後に失効するということになります。
有効期限を超過したアクセストークンを付与したリクエストはリソースサーバーによって拒否されます。
リフレッシュトークン
トークンを再発行するためコードになります。
トークンはセキュリティの関係で通常は有効期限を短く設定します。
トークンが盗聴された際にセキュリティリスクを低減するためです。
しかし、トークンの有効期限が短いと、何回も認可のプロセスを行わないといけないため、利便性に欠けます。
そこでリフレッシュトークンが登場するわけです。
リフレッシュトークンを認可サーバに渡すと、認可サーバで検証が行われます。
正当なリフレッシュトークンであると判断された場合、認可のプロセスが既に行われたものとして新たなトークンを発行します。
つまり、トークンの有効期限が切れても、リフレッシュトークンを渡すことで通常の認可プロセスを簡略化してトークンを得ることができるわけです。
ただし、リフレッシュトークンにも問題があります。
それは、リフレッシュトークンが流出した時に、簡単にトークンを不正取得されてしまうということです。
そのため、リフレッシュトークンの管理は厳重に行わなければいけません。
認可コード
リソースオーナーがクライアントへの権限移譲に同意したことを証明するものです。
認可グラントタイプの認可フローで使用されます。
「権限移譲の同意→クライアントへのリダイレクト」のプロセスは盗聴されてしまう可能性があります。
そのため、このプロセスでアクセストークンを受け渡すことはせず、一時的な有効期限の短い認可コードをやり取りします。
そうすることで、万が一通信を盗聴された際のセキュリティリスクを低減できます。
詳細については、認可グラントタイプの項で説明します。
エンドポイント
OAuthで登場するエンドポイントについて紹介します。
OAuthにおけるそれぞれの要素の通信はエンドポイントを介してHTTPプロトコルで行われます。
例えば、トークンエンドポイントにリクエストを送ると、トークンが返ってきます。
認可エンドポイント
認可サーバーに存在するエンドポイントです。
認可コードグラントタイプにて使用される認可コードの発行を行います。
このエンドポイントにアクセスすると、認証画面が表示されます。
そこにID、パスワードなど入力し、ユーザー認証が完了すると、認可サーバーで用意された権限移譲への確認・同意画面が表示されます。
その画面で同意を行うとクライアントへの権限移譲が承認されたとみなされます。
認可コードが発行され、クライアントのリダイレクトエンドポイントにリダイレクトされます。
トークンエンドポイント
認可サーバーに存在するエンドポイントです。
リダイレクトエンドポイント経由で認可コードを受け取ったクライアントは、トークンエンドポイントにリクエストを行います。
認可サーバーで認可コードの検証が完了すると、アクセストークンが発行されます。
また、トークンエンドポイントにはBasic認証がかかっています。
そのため、リクエストのAuthorizationヘッダーにクライアントIDとクライアントシークレットを含める必要があります。
クライアントIDとクライアントシークレットは、リソースを要求しているクライアントの身元を証明するものだと思ってもらえればいいです。
クライアントIDとクライアントシークレットが正しければ、そのクライアントは認可サーバーが承認した正当なアプリケーションと判断することができます。
クライアントIDとクライアントシークレットは、認可サーバーにクライアントを事前登録する際に発行されます。
リダイレクトエンドポイント
クライアントに存在するエンドポイントです。
クライアントが認可サーバーから認可コードを受け取るために使用されます。
認可サーバーがリソースオーナーによる認証、権限移譲の同意を受けると認可コードを発行します。
認可コードはクライアントに渡される必要がありますが、そのために使用されるのがリダイレクトエンドポイントです。
認可サーバーは、発行した認可コードを含めたレスポンスをリソースオーナーに返しますが、その際リダイレクトURLとしてリダイレクトエンドポイントが指定されます。
認可コードはクエリパラメタとして渡されます。
これにより、認可コードがクライアントにリダイレクトで送信されます。
認可コードを受け取ったクライアントは、それを使ってアクセストークンを取得することができます。