OAuth 2.0 を徹底解説: 基礎から実践まで


[![Group109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/2fcea97a-faf1-42fa-a77d-c5040ec845c3.png)](https://leapcell.io/?lc_t=q_oauth)


**[Leapcell：Webホスティング、非同期タスク、Redisの次世代サーバレスプラットフォーム](https://leapcell.io/?lc_t=q_oauth)**

# OAuth 2.0の簡潔かつ分かりやすい解説
OAuthは、世界的に広く利用されている認可のためのオープンなネットワーク標準であり、現在のバージョンは2.0です。この記事では、RFC 6749を基に、OAuth 2.0の設計コンセプトと動作プロセスについて、簡潔かつ分かりやすく解説します。

## Ⅰ. 適用シナリオ
OAuthの適用シナリオを理解するために、まず仮想の例を見てみましょう。「クラウド写真プリント」というサイトがあり、ユーザーがGoogleに保存している写真を印刷することができるとします。ユーザーがこのサービスを利用するためには、「クラウド写真プリント」に自分のGoogleに保存されている写真を読み取る許可を与えなければなりません。

ここで重要な問題があります。Googleは、ユーザーの認可を得た後でのみ、「クラウド写真プリント」にこれらの写真を読み取らせることになっています。では、「クラウド写真プリント」はどのようにしてユーザーの認可を得ることができるのでしょうか？

伝統的な方法は、ユーザーが「クラウド写真プリント」に自分のGoogleのユーザー名とパスワードを教えることで、「クラウド写真プリント」がユーザーの写真を読み取ることができるようにするものです。しかし、このアプローチには多くの深刻な欠点があります：
1. **パスワード保存のセキュリティ上の脅威**： 後続のサービスを提供するために、「クラウド写真プリント」はユーザーのパスワードを保存することになりますが、これは大きなセキュリティ上の脅威をもたらします。
2. **ログイン方法のセキュリティ上の問題**： Googleはパスワードによるログイン方法を用いる必要がありますが、単純なパスワードによるログインはセキュリティ性が低いです。
3. **許可制御の欠如**： 「クラウド写真プリント」は、ユーザーがGoogleに保存しているすべての資料にアクセスする権限を持つことになり、ユーザーは「クラウド写真プリント」が得る認可の範囲と有効期間を制限することができません。
4. **権限の取り消しコストの高さ**： ユーザーは、パスワードを変更することでしか、「クラウド写真プリント」に与えた権限を取り消すことができません。しかし、このようにすると、ユーザーの認可を得ていた他のすべてのサードパーティアプリケーションが無効になってしまいます。
5. **データ漏洩の高いリスク**： 1つのサードパーティアプリケーションが不正アクセスされるだけで、ユーザーのパスワードとそのパスワードで保護されているすべてのデータが漏洩することにつながります。

そして、OAuthはまさにこれらの問題を解決するために生まれました。

## Ⅱ. 用語定義
OAuth 2.0を詳細に解説する前に、まずいくつかの専門用語を理解する必要があります。これらの用語は、後続の内容、特に関連する図を理解するために極めて重要です。
1. **サードパーティアプリケーション（Third-party Application）**： この記事では「クライアント」とも呼ばれ、前節の例でいうと「クラウド写真プリント」のようなものです。
2. **HTTPサービス（HTTP Service Provider）**： この記事では「サービスプロバイダー」と略称され、前節の例でいうとGoogleのようなものです。
3. **リソースオーナー（Resource Owner）**： この記事では「ユーザー」とも呼ばれます。
4. **ユーザーエージェント（User Agent）**： この記事ではブラウザを指します。
5. **認可サーバー（Authorization Server）**： すなわち、サービスプロバイダーが認証を処理するために専用に使用するサーバーです。
6. **リソースサーバー（Resource Server）**： すなわち、サービスプロバイダーがユーザーが生成したリソースを保存するサーバーです。認証サーバーと同じサーバーでも、異なるサーバーでもよいです。

以上の用語を理解した後、OAuthの役割を理解するのは難しくありません。つまり、「クライアント」が「ユーザー」の認可を安全かつ制御可能に得ることができ、その後「サービスプロバイダー」とやり取りすることができるようにするものです。

## Ⅲ. OAuthのコンセプト
OAuthは、「クライアント」と「サービスプロバイダー」の間に認可層を設定します。「クライアント」は直接「サービスプロバイダー」にログインすることができず、認可層にログインすることで、ユーザーとクライアントを区別することができます。「クライアント」が認可層にログインするために使用するトークンは、ユーザーのパスワードとは異なり、ユーザーはログイン時に認可層トークンの許可範囲と有効期間を指定することができます。

「クライアント」が認可層にログインした後、「サービスプロバイダー」はトークンの許可範囲と有効期間に基づいて、ユーザーが保存している資料を「クライアント」に公開します。

## Ⅳ. 動作プロセス
OAuth 2.0の動作プロセスは、次の図の通りです（RFC 6749から抜粋）：
1. **(A)**: ユーザーがクライアントを開いた後、クライアントはユーザーに対して認可を要求します。
2. **(B)**: ユーザーはクライアントに対して認可を与えることに同意します。
3. **(C)**: クライアントは前のステップで得た認可を使って、認証サーバーにトークンを申請します。
4. **(D)**: 認証サーバーはクライアントを認証し、問題がなければトークンの発行を同意します。
5. **(E)**: クライアントはトークンを使って、リソースサーバーに対してリソースの取得を申請します。
6. **(F)**: リソースサーバーはトークンが正しいことを確認し、クライアントに対してリソースを公開することに同意します。

これらの6つのステップの中で、ステップBがキーとなります。つまり、ユーザーがどのようにしてクライアントに認可を与えるかということです。この認可があることで、クライアントはトークンを得ることができ、その後トークンを使ってリソースを得ることができます。次に、クライアントが認可を得る4つのモードについて、1つずつ解説します。

## Ⅴ. クライアントの認可モード
クライアントは、トークン（アクセストークン）を得る前に、ユーザーの認可（authorization grant）を得なければなりません。OAuth 2.0は、次の4つの認可方法を定義しています：
1. **認可コードモード（authorization code）**
2. **簡易モード（implicit）**
3. **パスワードモード（resource owner password credentials）**
4. **クライアントモード（client credentials）**

## Ⅵ. 認可コードモード
認可コードモード（authorization code）は、認可モードの中で最も機能が充実し、プロセスが厳密なものです。その特徴は、クライアントのバックグラウンドサーバーを通じて「サービスプロバイダー」の認証サーバーとやり取りすることです。具体的なステップは次の通りです：
1. **(A)**: ユーザーがクライアントにアクセスし、クライアントはユーザーを認証サーバーにリダイレクトします。
2. **(B)**: ユーザーはクライアントに対して認可を与えるかどうかを選択します。
3. **(C)**: ユーザーが認可を与えたと仮定すると、認証サーバーはユーザーをクライアントが事前に指定した「リダイレクトURI」（redirection URI）にリダイレクトし、同時に認可コードを付与します。
4. **(D)**: クライアントは認可コードを受け取り、以前の「リダイレクトURI」を付けて、認証サーバーにトークンを申請します。このステップはクライアントのバックグラウンドサーバー上で完了し、ユーザーには見えません。
5. **(E)**: 認証サーバーは認可コードとリダイレクトURIをチェックします。問題がなければ、アクセストークン（access token）とリフレッシュトークン（refresh token）をクライアントに送信します。

以下は、上記のステップで必要なパラメーターです：
- **ステップA**： クライアントが認証を申請するためのURIには、次のパラメーターが含まれます：
  - **response_type**： 認可タイプを表し、必須パラメーターであり、ここでの値は固定で「code」となります。
  - **client_id**： クライアントのIDを表し、必須パラメーターです。
  - **redirect_uri**： リダイレクトURIを表し、オプションパラメーターです。
  - **scope**： 要求される許可範囲を表し、オプションパラメーターです。
  - **state**： クライアントの現在の状態を表し、任意の値を指定することができます。認証サーバーはこの値をそのまま返します。

  例：
```http
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.leapcell.io
```
- **ステップC**： サーバーがクライアントに応答するURIには、次のパラメーターが含まれます：
  - **code**： 認可コードを表し、必須パラメーターです。このコードの有効期間は非常に短く、通常は10分に設定されており、クライアントはこのコードを1回のみ使用することができ、それ以外の場合は認可サーバーに拒否されます。このコードは、クライアントIDとリダイレクトURIと1対1で対応しています。
  - **state**： クライアントの要求にこのパラメーターが含まれている場合、認証サーバーの応答にもまったく同じパラメーターが含まれていなければなりません。

  例：
```http
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlqweqwWxSbIA&state=xyz
```
- **ステップD**： クライアントが認証サーバーにトークンを申請するためのHTTP要求には、次のパラメーターが含まれます：
  - **grant_type**： 使用する認可モードを表し、必須パラメーターであり、ここでの値は固定で「authorization_code」となります。
  - **code**： 前のステップで得た認可コードを表し、必須パラメーターです。
  - **redirect_uri**： リダイレクトURIを表し、必須パラメーターであり、ステップAでのこのパラメーターの値と一致しなければなりません。
  - **client_id**： クライアントIDを表し、必須パラメーターです。

  例：
```http
POST /token HTTP/1.1
Host: server.leapcell.io
Authorization: Basic czZCaGRrwrqw0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
```
- **ステップE**： 認証サーバーが送信するHTTP応答には、次のパラメーターが含まれます：
  - **access_token**： アクセストークンを表し、必須パラメーターです。
  - **token_type**： トークンの種類を表します。この値は大文字小文字を区別せず、必須パラメーターです。bearerタイプやmacタイプのものがあります。
  - **expires_in**： 有効期限を表し、秒単位です。このパラメーターが省略された場合、有効期限は他の手段で設定する必要があります。
  - **refresh_token**： リフレッシュトークンを表し、次のアクセストークンを取得するために使用され、オプションパラメーターです。
  - **scope**： 許可範囲を表します。クライアントが要求した許可範囲と一致する場合は、この項目を省略することができます。

  例：
```http
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
    "access_token":"2YotnFqwrwqrqwCsicMWpAA",
    "token_type":"example",
    "expires_in":3600,
    "refresh_token":"tGzv3JOqweqweTlKWIA",
    "example_parameter":"example_value"
}
```
上記のコードから分かるように、関連するパラメーターはJSON形式（Content - Type: application/json）で送信されており、HTTPヘッダ情報にはキャッシュを許可しないことが明確に指定されています。

## Ⅶ. 簡易モード
簡易モード（implicit grant type）は、サードパーティアプリケーションのサーバーを通らず、ブラウザで直接認証サーバーにトークンを申請し、「認可コード」のステップをスキップするため、この名前が付けられています。すべてのステップはブラウザで完了し、トークンは訪問者に見える状態となり、クライアントは認証を必要としません。具体的なステップは次の通りです：
1. **(A)**: クライアントはユーザーを認証サーバーにリダイレクトします。
2. **(B)**: ユーザーはクライアントに対して認可を与えるかどうかを決定します。
3. **(C)**: ユーザーが認可を与えたと仮定すると、認証サーバーはユーザーをクライアントが指定した「リダイレクトURI」にリダイレクトし、URIのHash部分にアクセストークンを含めます。
4. **(D)**: ブラウザはリソースサーバーに要求を送信しますが、前のステップで受け取ったHash値は含まれません。
5. **(E)**: リソースサーバーはウェブページを返し、そこに含まれるコードはHash値内のトークンを取得することができます。
6. **(F)**: ブラウザは前のステップで得たスクリプトを実行し、トークンを抽出します。
7. **(G)**: ブラウザはトークンをクライアントに送信します。

以下は、上記のステップで必要なパラメーターです：
- **ステップA**： クライアントが送信するHTTP要求には、次のパラメーターが含まれます：
  - **response_type**： 認可タイプを表し、ここでの値は固定で「token」となり、必須パラメーターです。
  - **client_id**： クライアントのIDを表し、必須パラメーターです。
  - **redirect_uri**： リダイレクトURIを表し、オプションパラメーターです。
  - **scope**： 許可範囲を表し、オプションパラメーターです。
  - **state**： クライアントの現在の状態を表し、任意の値を指定することができます。認証サーバーはこの値をそのまま返します。

  例：
```http
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.leapcell.io
```
- **ステップC**： 認証サーバーがクライアントに応答するURIには、次のパラメーターが含まれます：
  - **access_token**： アクセストークンを表し、必須パラメーターです。
  - **token_type**： トークンの種類を表します。この値は大文字小文字を区別せず、必須パラメーターです。
  - **expires_in**： 有効期限を表し、秒単位です。このパラメーターが省略された場合、有効期限は他の手段で設定する必要があります。
  - **scope**： 許可範囲を表します。クライアントが要求した許可範囲と一致する場合は、この項目を省略することができます。
  - **state**： クライアントの要求にこのパラメーターが含まれている場合、認証サーバーの応答にもまったく同じパラメーターが含まれていなければなりません。

  例：
```http
HTTP/1.1 302 Found
Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600
```
上記の例では、認証サーバーはHTTPヘッダ情報のLocation列を使って、ブラウザがリダイレクトするURLを指定しています。注意すべきは、このURLのHash部分にトークンが含まれていることです。ステップDにより、ブラウザは次のステップでLocationで指定されたURLを訪問しますが、Hash部分は送信されません。次のステップEでは、サービスプロバイダーのリソースサーバーが送信するコードがHash内のトークンを抽出します。

## Ⅷ. パスワードモード
パスワードモード（Resource Owner Password Credentials Grant）では、ユーザーが自分のユーザー名とパスワードをクライアントに提供し、クライアントはこの情報を使って「サービスプロバイダー」に対して認可を要求します。このモードでは、ユーザーはクライアントに自分のパスワードを提供する必要がありますが、クライアントはパスワードを保存することは許されません。これは通常、ユーザーがクライアントに対して非常に高い信頼度を持っている場合に使用されます。たとえば、クライアントがオペレーティングシステムの一部である場合や、有名な会社が開発したものである場合などです。そして、認証サーバーは、他の認可モードが実行できない場合にのみ、このモードを採用すると考えられます。具体的なステップは次の通りです：
1. **(A)**: ユーザーがクライアントにユーザー名とパスワードを提供します。
2. **(B)**: クライアントはユーザー名とパスワードを認証サーバーに送信し、後者にトークンを要求します。
3. **(C)**: 認証サーバーが問題ないことを確認した後、クライアントにアクセストークンを提供します。

ステップBで、クライアントが送信するHTTP要求には、次のパラメーターが含まれます：
- **grant_type**： 認可タイプを表し、ここでの値は固定で「password」となり、必須パラメーターです。
- **username**： ユーザー名を表し、必須パラメーターです。
- **password**： ユーザーのパスワードを表し、必須パラメーターです。
- **scope**： 許可範囲を表し、オプションパラメーターです。

例：
```http
POST /token HTTP/1.1
Host: server.leapcell.io
Authorization: Basic czZCaGRSa3F0gertetewrmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w
```
ステップCで、認証サーバーがクライアントにアクセストークンを送信します。例：
```http
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
    "access_token":"2YotnFZqweqwreqwrpAA",
    "token_type":"example",
    "expires_in":3600,
    "refresh_token":"tGzv3rewrewrtr2TlKWIA",
    "example_parameter":"example_value"
}
```
上記のコード内の各パラメーターの意味は、「認可コードモード」のセクションを参照することができます。このプロセス全体を通じて、クライアントはユーザーのパスワードを保存することは許されません。

## Ⅸ. クライアントモード
クライアントモード（Client Credentials Grant）とは、クライアントがユーザーの名義ではなく、自分自身の名義で「サービスプロバイダー」と認証を行うことを意味します。厳密に言えば、クライアントモードはOAuthフレームワークが解決する必要のある問題に属しません。このモードでは、ユーザーは直接クライアントに登録し、クライアントは自分自身の名義で「サービスプロバイダー」にサービスの提供を要求します。実際には、認可の問題はありません。具体的なステップは次の通りです：
1. **(A)**: クライアントは認証サーバーに対して自分自身のアイデンティティを認証し、アクセストークンを要求します。
2. **(B)**: 認証サーバーが問題ないことを確認した後、クライアントにアクセストークンを提供します。

ステップAで、クライアントが送信するHTTP要求には、次のパラメーターが含まれます：
- **grant_type**： 認可タイプを表し、ここでの値は固定で「client_credentials」となり、必須パラメーターです。
- **scope**： 許可範囲を表し、オプションパラメーターです。

例：
```http
POST /token HTTP/1.1
Host: server.leapcell.io
Authorization: Basic czZCaGRSqeqwewqmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
```
認証サーバーは、ある方法でクライアントのアイデンティティを検証する必要があります。

ステップBで、認証サーバーがクライアントにアクセストークンを送信します。例：
```http
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
    "access_token":"2Yotnqweqwe1zCsicMWpAA",
    "token_type":"example",
    "expires_in":3600,
    "example_parameter":"example_value"
}
```
上記のコード内の各パラメーターの意味は、「認可コードモード」のセクションを参照することができます。

## Ⅹ. トークンの更新
ユーザーがアクセスする際にクライアントの「アクセストークン」が期限切れになっている場合、「リフレッシュトークン」を使用して新しいアクセストークンを申請する必要があります。クライアントがトークンを更新するために送信するHTTP要求には、次のパラメーターが含まれます：
- **grant_type**： 使用する認可モードを表し、ここでの値は固定で「refresh_token」となり、必須パラメーターです。
- **refresh_token**： 以前に受け取ったリフレッシュトークンを表し、必須パラメーターです。
- **scope**： 要求される認可範囲を表し、前回の申請の範囲を超えることはできません。このパラメーターが省略された場合、前回と同じ範囲を意味します。

例：
```http
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzqeqweqwmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
```

# [Leapcell：Webホスティング、非同期タスク、Redisの次世代サーバレスプラットフォーム](https://leapcell.io/?lc_t=q_oauth)

最後に、推奨する最適なデプロイプラットフォーム：**[Leapcell](https://leapcell.io/?lc_t=q_oauth)**

[![barndpic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/af1f4ebd-dfd5-4e49-a135-3afcd851a8fe.png)](https://leapcell.io/?lc_t=q_oauth)


### 1. 多言語対応
- JavaScript、Python、Go、またはRustで開発。

### 2. 無料で無制限のプロジェクトをデプロイ
- 使用量に応じて課金 — リクエストがなければ料金がかかりません。

### 3. 抜群のコスト効率
- 使い捨て型で、アイドル時の料金はかかりません。
- 例：25ドルで平均応答時間60msで694万回のリクエストをサポート。

### 4. 合理化された開発者体験
- 直感的なUIによる簡単なセットアップ。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- アクション可能なインサイトのためのリアルタイムメトリクスとログ。

### 5. 簡単なスケーラビリティと高パフォーマンス
- 高い並行処理を容易に処理する自動スケーリング。
- ゼロオペレーションオーバーヘッド — 構築に集中できます。

[![Frame3-withpadding2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/7271ee15-9e89-4d94-ab77-cb4564b4ea6c.png)](https://leapcell.io/?lc_t=q_oauth)


[ドキュメントをもっと詳しく見る！](https://docs.leapcell.io/)

Leapcell Twitter：[https://x.com/LeapcellHQ](https://x.com/LeapcellHQ)