Spring Security OAuthで認可コードグラントフローを体感しよう -第１回：OAuth 2.0のおさらい編

今回から数回（たぶん３〜５回位）にわけて、Spring Security OAuth(+Spring Boot)を利用してOAuth 2.0の認可コードグラントフローを利用したREST APIの認証・認可を実現する方法を説明します。といいつつ・・・わたしもOAuth 2.0に詳しいわけではないので・・・間違った説明があるかもしれません（悪しからず・・・） :sweat_smile: 間違った説明があったら是非コメント（修正リクエスト）をお願いします！！

で、第１回の今回は・・・OAuth 2.0ってなんだっけ（＝おさらい）をざっくり説明していきたいと思います。ちなみに・・・今回はSpring Security OAuthとSpring Bootの話はないで〜す :stuck_out_tongue_winking_eye:


* [第２回：とりあえずアプリを作る編](http://qiita.com/kazuki43zoo/items/9cc00f0c92c7b0e1e529)

# OAuth 2.0ってなんだっけ？

まず、簡単にOAuth 2.0のおさらいをしておきましょう。
OAuth 2.0は、「サードパーティー製のアプリケーション（以降、クライアント）」に対してサービスプロバイダがWEBリソースを提供する際に、クライアントに対して適切なアクセス範囲（スコープ）を設けることができる認可フレームワークで、いくつかのRFCで技術仕様が決められています。

* [RFC 6749 The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749)
* [RFC 6750 The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://tools.ietf.org/html/rfc6750)
* [RFC 6819 OAuth 2.0 Threat Model and Security Considerations](https://tools.ietf.org/html/rfc6819)

上記以外にも、アクセストークンとしてJWT(JSON Web Token)を利用する際のRFCもあります。

本エントリーでは、OAuth 2.0を使うなら最低限知っていた方がよいだろうと思われ内容（ロール、認可グラント、スコープ、アクセストークン、リフレッシュトークンなど）に絞ってOAuth 2.0のアーキテクチャをざっくり説明したいと思います。

# ロール(役割)

OAuth 2.0では、認証・認可を行う際に登場するロールとして以下の4つを定義しています。


| ロール | 説明 |
| ----- | ---- |
| Resource Owner | リソースの所有者で、リソースへのアクセスを認可する（認可グラントを提供する）役割を担う。サービス利用者（人間）がこの役割を担うことが多い。 |
| Resource Server | リソースオーナのリソースを適切なアクセス制御（アクセストークンに割り当てられているスコープを利用したアクセス制御）の元で提供する役割を担う。サービスプロバイダのWebサーバがこの役割を担う。 |
| Authorization Server | リソースオーナの認証、リソースオーナからの認可(認可グラントの取得)、認可グラントに対応するアクセストークンの発行を行う役割を担う。サービスプロバイダのWebサーバがこの役割を担う。 |
| Client | リソースオーナから提供された認可グラントに対応するアクセストークンを使用して、リソースオーナの代理で保護されたリソースにアクセスする役割を担う。Webアプリケーション、ユーザーエージェントベースのクライアントアプリケーション(JavaScriptなど)、ネーティブアプリケーションなどがこの役割を担う。 |

ロール間のやりとり（プロトコルフロー）を絵で表すと以下のような感じになります。

![spring-security-oauth-oauth2.0.png](https://qiita-image-store.s3.amazonaws.com/0/117313/1b2b0104-cf7e-56aa-edb6-7c217737d2b1.png)

# 認可グラント

OAuth 2.0では、リソースへのアクセスを認可することを「認可グラント」と呼び、グラントタイプとして以下の4つのタイプを定義しています。

| グラントタイプ | 説明 |
| ----- | ---- |
| Authorization Code | リソースオーナが認可サーバを介して認可コード（リソースへのアクセスを認可したことを示すコード）を発行してクライアントへ提供する。クライアントはリソースオーナから提供された認可コードとアクセストークンを交換するため、リソースオーナのクレデンシャル（ユーザ名やパスワード）がクライアントに渡ることがなく、最もセキュアなグラントタイプといえる。 |
| Implicit | リソースオーナが認可サーバを介してリソースへのアクセスを許可する点は認可コードグラントと同じだが、インプリシットグラントの場合は認可後に直接アクセストークンを発行する。認可コードグラントと同様にリソースオーナのクレデンシャル（ユーザ名やパスワード）がクライアントに渡ることはないが、クライアントの認証が行われないため認可コードグラントに比べるとセキュア度は下がる。 |
| Resource Owner Password Credential | 認可グラントとしてリソースオーナのクレデンシャル（ユーザ名やパスワード）を渡してアクセストークンを発行する。クライアントにリソースオーナのクレデンシャルを渡す必要があるため、信頼できない又は悪意のあるクライアントの場合はリソースオーナのクレデンシャルが悪用されるリスクが高くなる。 |
| Client Credential | 認可グラントとしてクライアントのクレデンシャル（クライアントIDやパスワード）を渡してアクセストークンを発行する。 クライアント自身がリソースオーナのような場合に使うグラントタイプである。 |


# スコープ

OAuth 2.0では、スコープという概念を使用して、クライアントがアクセスできるリソースを制限する仕組みになっています。扱えるスコープは認可サーバで管理しており、クライアントは認可コードまたはアクセストークンの発行依頼時に「認可してほしいスコープ」を指定することができます。

# アクセストークン

OAuth 2.0では、リソースオーナから提供された認可グラントとアクセストークンを交換し、リソースへアクセスする際はアクセストークンを渡して認証・認可を行う仕組みになっています。
アクセストークンには有効期限を設けることができ、有効期限がきれると再度リソースオーナからの認可を取得する必要があります。有効期限が短いとアプリケーション利用者のユーザビリティが低くなり、逆に有効期限を長くするとアクセストークンの漏洩・漏洩に伴う悪用のリクスが高くなってしまいます。

# リフレッシュトークン

アクセストークンの漏洩のリスクを上げずにユーザビリティをさげない方法はないのでしょうか？・・・もちろんあります！！この問題を一気に解決してくれるのが「リフレッシュトークン」なのです。
リフレッシュトークンは、アクセストークンの有効期限が切れた時にアクセストークンを再発行する際に使用するトークンです。リフレッシュトークンを利用すると、アクセストークン取得時と同じスコープのアクセストークンを新たに発行することができるため、リソースオーナに対して再認可を求める手間を省くことができるのです。リフレッシュトークンにも有効期限を設けることができ、リフレッシュトークンの有効期限がきれるとアクセストークンの再発行ができなくなります（＝再度リソースオーナからの認可を取得する必要があります）。

# アクセストークンとリフレッシュトークンの有効期限戦略

アクセストークンの有効期限はできるだけ短くし、リフレッシュトークンの有効期限を長くすることで、アクセストークンの漏洩のリスクを上げずに利用者のユーザビリティをキープするのが常套手段のようです。


# 認可コードグラントフローの流れ

やや前置きが長くなりましたが、ここからは、本エントリーで扱う「認可コードグラントフロー」を使用した場合にどのような流れでリソースへアクセスするかを見ていきましょう。

![spring-security-oauth-oauth2.0-code-grant.png](https://qiita-image-store.s3.amazonaws.com/0/117313/4fd23ef8-fecd-63a4-bb6f-a88c063b455a.png)

| 項番 | 説明 |
| ---- | --- |
| (1) | リソースオーナは、ユーザエージェントを介してクライアントが提供する任意のページ（リソースサーバにアクセスするページ）の表示要求を行う。 クライアントは、リソースオーナからの認可を取得するために、認可サーバの認可画面へのリダイレクト指示を応答する。 |
| (2) | ユーザエージェントは、クライアントから指示されたページ(認可サーバの認可画面)の表示要求（リダイレクト）を行う。認可サーバは、ユーザエージェントを介してリソースオーナからの認可を取得するための画面を応答する。 |
| (3) | リソースオーナは、ユーザエージェントを介してクライアントが要求した認可依頼の承認要求を行う。 認証サーバは、リソースオーナがリソースへのアクセスを認可したことを示すコード（認可コード）を発行し、再度(1)でリソースオーナが表示要求を行ったクライアントのページへのリダイレクト指示を応答する。なお、認可コードはリダイレクト用のURLにパラメータに付加して連携する。 |
| (4) | ユーザエージェントは、認可サーバから指示されたページ（リソースオーナが最初に表示要求したクライアントのページ）の表示要求（リダイレクト）を行う。クライアントは、リソースサーバからリソースオーナのリソースを取得（詳細は5,6を参照）した後に、取得したリソースの情報を埋め込んだページを応答する。 |
| (5) | クライアントは、リクエストパラメータから認可コードを取得し、取得した認可コードを指定してアクセストークンの発行要求を行う。認可サーバは、認可コードの妥当性を検証した後にアクセストークンを発行し、クライアントへアクセストークンを応答する。 |
| (6) | クライアントは、認可サーバから取得したアクセストークンを指定してリソースサーバのREST APIを呼び出す。リソースサーバは、アクセストークンとスコープの妥当性を検証した後にREST APIの処理を呼び出し、REST APIから返却されたリソースをクライアントへ応答する。 |

# まとめ

第１回は、OAuth 2.0についてざっくりおさらいしてみました。本エントリーに記載した内容はOAuth 2.0で決められている仕様のほんの一部ですが、認可コードグラントフローの流れをざっくりイメージして頂けて入れば幸いです。（しょうじき自信ないけど・・・:sweat_smile:）
次回は、Spring Security OAuth(+Spring Boot)を使用して、実際に認可コードグラントフローを利用したREST APIの認証・認可を体感したいと思っています。（いつになるかわかりませんが、また次回〜）