二年目エンジニアがOAuth2.0についてまとめる

## はじめに
Qiita初投稿です。
普段はNode.JSやReact、Azureを触っている二年目エンジニアです。
今回はOAuth2.0について自分の理解と整理のためにまとめます。

## アジェンダ
1. 従来の認証モデル
1. OAuth2.0
1. OAuth2.0の登場人物
1. 認可フローについて
1. 認可コードグラントフローについて
1. 認可コードグラントフローのまとめ
1. さいごに

## 従来の認証モデル
従来のクライアント/サーバー認証モデルでは、クライアントがリソースオーナの資格情報を使用し、
サーバーで認証することにより、サーバー上のアクセス制限付きリソース（保護されたリソース）を要求をしていました。  
図は個人資産管理アプリ※1 を想定して作っています。
今後の図は、基本的に個人資産管理アプリを想定し図を書いています。
![Scraping.png](https://qiita-image-store.s3.amazonaws.com/0/351271/467ac647-9e27-1f83-07fd-e4bd4eecaee2.png)

このフローでは以下のような問題が生じます。
1. Fintech企業にID,PWを渡しているため、ずさんな管理を行っているFintech企業から、***ID・PWの漏洩*** する可能性がある
2. リソースオーナはFintech企業に、インターネットバンキングの ***機能を制限*** させることができない
(残高の照会のみさせる、といったことはできない)  

## OAuth2.0の概要
問題点を解決するために、先程洗い出した問題点を逆転の発想でみてみると、 
1.  ***ID、PWをFintech企業に渡さず*** に情報を取得できるようにする
2. リソースオーナが ***許可した機能のみ*** Fintech企業に利用させる (認可)

ことさえできればよさそうです。  
この問題を解決することができる仕様が**OAuth2.0**です。
OAuth2.0はだいたい、以下のフローになっています。

![authorizationFlowOverview.png](https://qiita-image-store.s3.amazonaws.com/0/351271/647631c2-72e2-4ac6-c5f5-ec003e8a383b.png)


1. 銀行システムのクライアントであるFintech企業が、銀行システムの認可サーバと言うアクセストークンを発行してくれるサーバに発行依頼をします
1. 発行依頼を受けた認可サーバは、アクセストークンの発行を行います
1. クライアントは発行したアクセストークンを受け取ります
1. リソースオーナの情報があるリソースサーバに、アクセストークンと一緒にリクエストを送ります
1. 受け取ったアクセストークンが正しいものか検証を行い、オッケーだった場合、
1. クライアントにレスポンスします。

こうすることで、
**ID・PW** を使用せずに情報をやり取りすることができます。  
また、アクセストークンに使用できる機能の情報をもたせることで
**機能を制限させる** ことができます

## OAuth2.0
もう少し詳細にOAuth2.0のフローを見ていきます。  
どのようにして**ユーザのクレデンシャル(ID、PW)を使わず**に **限られたリソースにのみ** 使用可にするのか、をもう少し具体的にまとめて行きます。  <br>
いきなりですが、認可についてはある程度仕様が決まっており、[RFC 6749](https://tools.ietf.org/html/rfc6749)※2に記載されています。

## OAuth2.0の登場人物
OAuth2.0の特性上、たくさんのシステムが出てきます。
そのため、一旦OAuth2.0の登場人物を整理し全体像の把握から行います。

|登場人物|説明|
|:---|:---|
|リソースオーナ|エンドユーザーのこと<br>例) 口座開設者|
|クライアント|APIに接続する何らかのシステム<br>APIを叩く側のシステム(サーバーサイド)<br>例) 家計簿アプリのバックエンド|
|認可サーバ|主にアクセストークンの発行・トークンの検証<br>API提供者が用意する|
|リソースサーバ|リソースオーナのリソースを処理するサーバ<br>例) 残高取得処理や振込処理を行う|
※ 認可フローによって登場人物が変わります。
![Actor.png](https://qiita-image-store.s3.amazonaws.com/0/351271/76b63297-b761-bff8-e1dd-9886afe21191.png)

## 認可フローについて
実はOAuth2.0には４種類のフローが定義されています。  
全部説明をしていると、ながーくなってしまうので、今回はその中でも一番多く実装されているであろうAuthorization Code Grant(認可コードグラント)についてまとめます。  

## 認可コードグラントフローについて
認可フローは以下の順で進んでいきます。  
※誰が何をしているのか分かりやすくするために、RFC6749で定義されていない内容もあえて記載しています。

### フローの目次
0 クライアントの登録
1. リソースオーナーがクライアントを通してAPIプロバイダのサービスを利用するための何らかのアクションを行う
2. 認可リクエスト
3. リソースオーナの認可および認可コードの発行
4. アクセストークンリクエスト
5. リソース処理のリクエスト

### 0.クライアントの登録
![Flow0.png](https://qiita-image-store.s3.amazonaws.com/0/351271/32417247-1563-0509-c162-113fc2bd956e.png)

①フローを開始する前に、クライアントの情報を認可サーバに登録しておきます。 
認可サーバに*誰が*リクエストを行っているのかの判定、3でリダイレクトする先の情報を事前に登録しておくために必要です。  <br>

### 1. リソースオーナーがクライアントを通してAPIプロバイダのサービスを利用するための何らかのアクションを行う
![Flow1.png](https://qiita-image-store.s3.amazonaws.com/0/351271/d544fcd8-4e80-a189-531a-65b796e8cb04.png)
①フローを開始する起因となるアクションをユーザが起こします。  

### 2. 認可リクエスト
![Flow2.png](https://qiita-image-store.s3.amazonaws.com/0/351271/218c527f-d403-b5b2-ad89-35995cbd90e3.png)

ここから認可のフローがスタートします。  
①*フロントアプリケーション*が*クライアントのバックエンド*に認可フローを必要としていることを伝えます。
②リクエストを受け取った*クライアントのバックエンド*は、*リソースオーナー*に*クライアント*がリソースへのアクセス許可をもらうために、認可するか確認する画面(認可画面)のURIをレスポンスします。
③フロントアプリケーションは、取得したURIにリダイレクトを行い、
④認可画面を表示します。  

### 3. リソースオーナの認可および認可コードの発行
![Flow3.png](https://qiita-image-store.s3.amazonaws.com/0/351271/f640f207-aad5-ca82-bba8-af70be678ef4.png)

①認可画面を通して、**リソースオーナ**は**認可サーバに向けて**クライアントが自身のリソースにアクセスする許可を行います。
②クライアントにリソースをアクセスする許可を受けた認可サーバは、
③リダイレクトURIと認可コードを返却します。
④フロントアプリケーションは受け取ったリダイレクトURIに認可コードを持ってリダイレクトします。

### 4. アクセストークンリクエスト
![Flow4.png](https://qiita-image-store.s3.amazonaws.com/0/351271/eaf1eba2-cf62-0a52-4175-a0683d2cd3d3.png)

①*クライアントのバックエンドサーバ*は受け取った*認可コード*をもとに、*認可サーバ*から*アクセストークン*取得リクエストを行います。
②リクエストを受け取った*認可サーバ*はアクセストークン(リソースオーナのリソースにアクセスする権限を持つトークン)を返却します

### 5. リソース処理のリクエスト
![Flow5.png](https://qiita-image-store.s3.amazonaws.com/0/351271/e7dff8f8-d05c-81fe-aa6d-92ddfa103055.png)

①クライントは、リソースサーバにリソースの処理を行うリクエストを投げ、
②リソースサーバーは*送られてきたアクセストークン*が正しいトークンか検証を行います。
③正しい場合はリクエストに対する処理を行った上、結果をクライアントのバックエンドサーバに返却します。  

## 認可コードグラントフローのまとめ
 以上が認可コードグラントフローです。
 伝わりましたかね？  
(というか、間違ってないですかね？ 先輩エンジニアの皆さん。誤っているところがあったら教えてください。)  
 このようにすることで、クライアントは、リソースオーナーのクレデンシャル情報なしに、リソースに関する処理を行うことができ、リソースオーナーの権限で、クライアントにどこまでリソースを処理させるか制限させることができます。

## さいごに
私が初めて認可に触れた際、結局「誰が何やってんねん」となり、「どゆこと！？」ってなってました。
そのため、今回は１リクエストごとに図を分け、誰が何をしているのかがわかりやすくなるようにまとめました。
次回は、体力的にまとめられなかった、他の３つのフローの違いと使いみち、OAuth2.0脆弱性についてまとめようと思います。

### 脚注
※ 1 `家計簿アプリ` とは

```
個人資産管理アプリ(家計簿アプリ)
銀行口座の残高や電子マネーの残高、クレジットカードの利用額等を一元的に管理し、自分の資産をわかりやすく表示してくれるアプリの総称
```

※ 2 `RFC`とは

```
RFCとはRequest For Commentsの略で、IETF(Internet Engineering Task Force)によって、
管理されている、Webに関する標準化についてまとめられたドキュメントです。
RFCに記載されている内容すべてが、標準プロトコルとして確立されているわけではなく、
将来的に標準化されるであろう技術を示し、評価を求める段階のもの(PS:Proposed Standard)、
標準化の仕様として十分運用できる草案段階のもの(DS:Draft Standard)、
十分な運用経験が積まれ標準プロトコルとして確立されたもの(STD:Standard)
の３つが記載されています。

基本的に私達エンジニアが実際に使用するのは、すでに標準プロトコルとして確立している、STDが主となり、
HTTPやIP、OAuth2.0もSTDとしてRFCに記載されています。
```