認証・認可学んでみた

こんにちは、kazuです。  
今回は認証・認可（主にOAuthを中心に）に学んだときのメモを元に書いてみようと思います。  
先日、[実務体験](https://qiita.com/kazu24z/items/1b4f5a985deccbd02e4c)をさせていただく機会があり、その折に認証周りどうしようかと全くわからない状態から色々調べたことがありまして。  
その際に結構苦労した記憶があったので、僕と同じような初学者の方の足掛かりになれば幸いです。  

## 書くこと
この記事では認証・認可の概念とそのプロトコルであるOAuthやOpenID Connectについて、イメージを掴むところをゴールとします。  

## 認証・認可の違い  

まずは「認証」と「認可」の違いを明確にしておく必要があります。 
というのも、言葉的に似ており混同しがちですが、指すものは明確に異なるため、キチンと理解していないとセキュリティ的に問題のあるものを作ってしまう...なんてことに繋がりかねません。

- 認証＝「誰」  
- 認可＝「何を」

つまり、認証とは「〇〇さんである」ことを認める行為で、認可とは「××できる」ことを認める行為と言えます。

## イメージ  
上記だけだと少しわかりづらいので、認証と認可の違いを図示すると以下になります。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/41bd5b09-6f49-7a90-e152-137fbacf306a.png)

認証は「誰か」をチェックし、認可は「何を（どうできるか）」をチェックしています。  

+@で、認可は「第三者がその人の権限を使えることもある」点も重要になります。  
これだけだとわかりづらい表現なので、以下の図と文章を見ていきます。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/b0c1513c-eed4-ce00-03f0-af329a3bb1a4.png)

この図のように、アカウント（とそれに紐づく権限）を持っている人自身でなくても、その人の権限を使うことが可能になることもあります。 
このイメージが結構重要で、これを掴めたらOAuthの理解もかなり早くなると思います。

## なぜ「認証」「認可」を分けるの？
ここまで認証・認可のイメージを見てきましたが、そもそもなぜこれらを分けて考えるのでしょうか。  
とりあえずAさんかBさんか識別できたらよくね？って思うことはないでしょうか。  （僕は初めそう思っていました）

結論から言うと、```その方が柔軟性が増すから```です。  
逆を考えれば一発で分かります。もし認証・認可が分かれていなかった場合、一律で同じことができるユーザーしかできず、必要以上の権限を持ったユーザーで溢れかえる可能性があります。  
また、後から「やっぱりこの人にはこの権限は持たせたくない」と言った運用時の変更が困難になります。

## OAuth
OAuthとは認可の中でも```「IDやパスワードを第三者に渡さず」```に行う「認可」の流れを定義したものです。  
上に載せた図を再度用いて見ていきます。  
※この記事内でのOAuthはOAuth2.0を指します。

まずは「第三者にアカウント情報を渡している例から。  

- 第三者にログイン情報を引き渡している例  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/8c7115b1-a80b-49b3-d5cb-e9a6cb1dc753.png)

これはあまり好ましくない状態です。  
というのも、第三者アプリ（呟き代行君）（やその管理者）が「善良」であればよいのですが、そうではなく「悪意」がある場合、アカウント情報を悪用されることに繋がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/79d773a6-fe51-b2dd-f042-556a316405a6.png)

このような事態を避けるためにOAuthは活躍します。  
まず、OAuthを説明する上で重要になる登場人物を紹介します。  
- リソースオーナー
- リソースサーバ
- クライアント 
- 認可サーバ

### リソースオーナー
これはリソース（ここでは『情報』）を持っている人を指します。つまり「Aさん」ですね。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/6daa07ba-fd15-9e06-776c-4d922f0cbc25.png)

### リソースサーバ  
これはリソースを提供しているサービスを指します。つまり「Twitter」ですね。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/34f7de4d-78a8-054f-f26a-b6de77478929.png)

### クライアント  
これはリソースサーバへアクセスするサービスを指します。つまり「呟き代行君」ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/db59d586-b1a0-8f4a-67c4-e9c126df2b96.png)

### 認可サーバ
これは今までに出て来なかったやつですね。アクセストークン（後述）を提供するサーバです。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/de1b5a7a-8df5-5398-d018-2375f45547b0.png)

以上で主要人物は出そろったので、OAuthの認可フローを見ていきます。
1. クライアント→認可サーバへ「アクセストークン」要求  
まず「アクセストークン」について。
これは、リソースサーバへアクセスするために用意されたもので、クライアントとサーバはこの情報を用いてやり取りをします。そのため、クライアントに「リソースオーナーの認証情報（IDやパスワード）を知らせる必要がなくなります。  

このアクセストークンを取得するために、クライアントは認可サーバへアクセストークンを要求します。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/fe99a6ed-a067-4821-2bb2-e6c163d03263.png)

2. 認可サーバ→リソースオーナーへ「許可」申請
クライアントからの要求を受けとった認可サーバは、クライアントがリソースオーナーとして振る舞うことをリソースオーナーに許可を求めます。
この時、リソースオーナーは許可ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/068cf646-af39-55e3-e793-cc6f337288c1.png)

3. 認可サーバ→クライアントへ「アクセストークン」付与
リソースオーナーの承認が取れたのでクライアントへアクセストークンを渡します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/e6680cfd-bf88-6c13-111b-6e657e8b8641.png)

4. クライアント→リソースサーバへアクセス
リソースサーバはクライアントが提示するアクセストークンの確認をし、問題なければそのリソースオーナーとして振る舞うことを許可します。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/25c95661-1f66-98f0-3f34-dd7d67454562.png)

※少し表現を修正すると、「Aとして振る舞う」と言うより「Aが持つ○○権限を使っていいよ」の方が「認可」という意味では適切かもしれません。

## OpenID Connect  
これは端的に言えば、「認可」に加え「認証」もできるフローです。 
OAuthとの関係性は、独立したものではなく「OAuthを拡張したもの」とのことです。  
上述のOAuthでは「アクセストークン」が出てきましたが、ここでは認証用の「IDトークン」と言うものが登場します。  
これは実際のユーザー情報そのものではないけれど、その人であることを示すトークンです。  

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/1548128e-6062-ef94-b284-cd181d5843ae.png)

IDトークンは「確かにそのユーザー」であることの証明になるため、これを他でも利用することができます。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2009552/10f289c8-f250-5a83-c9d3-2fcf439f109e.png)

## で、これをどう使うん？
ここまでで認証・認可の概要やそのプロトコルであるOAuthやOIDCをざっくり見てきました。
ただ、これらってあくまで「概念」なんですよね。  
なのでこれをどう実装するかは「各人に任せます」と言うのが答えです。 
OAuthのフローをフルスクラッチで書いていくもよし、認証・認可機能を有した既存サービスを導入&連携するもよしと言った感じのようです。　

## おわりに  
実務体験をしたのは結構前ですが、自分の中で「そもそも」や「違い」などを意識して調べていたおかげで、数か月たった今でも自分の中に残ってくれていてよかったです。