OAuth 2.0 についてわかりやすく解説:ゼロからヒーローへ
Daniel Hayes
Full-Stack Engineer · Leapcell

OAuth 2.0 についてわかりやすく解説
OAuth は、グローバルで広く使用されている認証のためのオープンネットワーク標準であり、現在のバージョンは 2.0 です。この記事では、RFC 6749 に基づいて、OAuth 2.0 の設計コンセプトと運用プロセスについて、簡潔でわかりやすい説明を提供します。
I. アプリケーションシナリオ
OAuth の適用可能なシナリオを理解するために、まず仮想的な例を見てみましょう。Google に保存されている写真をユーザーが印刷できる「クラウド写真印刷」という Web サイトがあるとします。ユーザーがこのサービスを使用したい場合、「クラウド写真印刷」が Google に保存されている写真を読めるように許可する必要があります。
ここで重要な問題があります。Google は、「クラウド写真印刷」がユーザーの承認を得た後でのみ、これらの写真を読めるようにします。では、「クラウド写真印刷」はどのようにしてユーザーの承認を得ることができるのでしょうか?
従来の方法では、ユーザーが自分の Google のユーザー名とパスワードを「クラウド写真印刷」に伝え、「クラウド写真印刷」がユーザーの写真を読めるようにします。しかし、このアプローチには多くの深刻な欠点があります。
- パスワードストレージのセキュリティリスク: フォローアップサービスを提供するために、「クラウド写真印刷」はユーザーのパスワードを保存するため、大きなセキュリティリスクをもたらします。
- ログイン方法のセキュリティ問題: Google はパスワードログイン方式を使用する必要がありますが、単純なパスワードログインはセキュリティが低くなります。
- 権限管理の欠如: 「クラウド写真印刷」は、ユーザーが Google に保存したすべての資料にアクセスする権利を持ち、ユーザーは「クラウド写真印刷」が取得した承認の範囲と有効期間を制限できません。
- 権限を取り消すための高いコスト: ユーザーはパスワードを変更することによってのみ、「クラウド写真印刷」に与えられた権限を取り消すことができます。しかし、そうすると、ユーザーの承認を得た他のすべてのサードパーティアプリケーションが無効になります。
- データ漏洩の高いリスク: サードパーティアプリケーションのいずれかがクラックされると、ユーザーのパスワードとパスワードで保護されたすべてのデータが漏洩する可能性があります。
そして、OAuth はまさにこれらの問題を解決するために生まれました。
II. 名詞の定義
OAuth 2.0 を詳細に説明する前に、いくつかの専門用語を理解しておく必要があります。これらの名詞は、特に該当する図を理解するために非常に重要です。
- サードパーティアプリケーション (Third-party Application):この記事では「クライアント」とも呼ばれます。前のセクションの例の「クラウド写真印刷」などです。
- HTTP サービス (HTTP Service Provider):この記事では「サービスプロバイダー」と略されます。前のセクションの例の Google などです。
- リソースオーナー (Resource Owner):この記事では「ユーザー」とも呼ばれます。
- ユーザーエージェント (User Agent):この記事では、ブラウザを指します。
- 認証サーバー (Authorization Server):つまり、サービスプロバイダーが認証を処理するために特別に使用するサーバーです。
- リソースサーバー (Resource Server):つまり、サービスプロバイダーがユーザーが生成したリソースを保存するサーバーです。認証サーバーと同じサーバーでも異なるサーバーでもかまいません。
上記の用語を理解すると、OAuth の役割を理解するのは難しくありません。つまり、「クライアント」が「ユーザー」の承認を安全かつ制御可能な方法で取得し、次に「サービスプロバイダー」とやり取りできるようにすることです。
III. OAuth の概念
OAuth は、「クライント」と「サービスプロバイダー」の間に承認レイヤーを設定します。「クライアント」は「サービスプロバイダー」に直接ログインすることはできませんが、承認レイヤーにログインして、ユーザーとクライアントを区別します。「クライアント」が承認レイヤーにログインするために使用するトークンはユーザーのパスワードとは異なり、ユーザーはログイン時に承認レイヤートークンの権限範囲と有効期間を指定できます。
「クライアント」が認証レイヤーにログインすると、「サービスプロバイダー」はトークンの権限範囲と有効期間に従って、ユーザーが保存した資料を「クライアント」に公開します。
IV. 操作プロセス
OAuth 2.0 の操作プロセスを次の図に示します(RFC 6749 から抽出)。
- (A):ユーザーがクライアントを開くと、クライアントはユーザーに承認を要求します。
- (B):ユーザーは、クライアントに承認を与えることに同意します。
- (C):クライアントは、前のステップで取得した承認を使用して、認証サーバーからトークンを申請します。
- (D):認証サーバーはクライアントを認証し、問題がなければ、トークンを発行することに同意します。
- (E):クライアントはトークンを使用して、リソースサーバーにリソースの取得を申請します。
- (F):リソースサーバーはトークンが正しいことを確認し、クライアントにリソースを公開することに同意します。
これらの 6 つのステップのうち、ステップ B が重要です。つまり、ユーザーがクライアントに承認を許可する方法です。この承認により、クライアントはトークンを取得し、次にトークンを使用してリソースを取得できます。次に、クライアントが承認を得るための 4 つのモードについて、1 つずつ説明します。
V. クライアントの承認モード
クライアントは、トークン (アクセストークン) を取得する前に、ユーザーの承認 (承認付与) を取得する必要があります。OAuth 2.0 は、次の 4 つの承認方法を定義しています。
- 承認コードモード (authorization code)
- 簡易モード (implicit)
- パスワードモード (resource owner password credentials)
- クライアントモード (client credentials)
VI. 承認コードモード
承認コードモード (authorization code) は、承認モードの中で最も機能が完全で、プロセスが最も厳格です。その特徴は、クライアントのバックグラウンドサーバーを介して「サービスプロバイダー」の認証サーバーとやり取りすることです。具体的な手順は次のとおりです。
- (A):ユーザーはクライアントにアクセスし、クライアントはユーザーを認証サーバーにリダイレクトします。
- (B):ユーザーはクライアントに承認を与えるかどうかを選択します。
- (C):ユーザーが承認を与えたと仮定すると、認証サーバーはユーザーをクライアントが事前に指定した「リダイレクト URI」(redirection URI) にリダイレクトし、同時に承認コードを添付します。
- (D):クライアントは承認コードを受け取り、以前の「リダイレクト URI」を添付して、認証サーバーからトークンを申請します。このステップは、クライアントのバックグランドサーバーで完了し、ユーザーには見えません。
- (E):認証サーバーは承認コードとリダイレクト URI をチェックします。問題がなければ、アクセストークン (access token) とリフレッシュトークン (refresh token) をクライアントに送信します。
上記の手順に必要なパラメーターを以下に示します。
-
ステップ A: クライアントが認証を申請するための URI には、次のパラメーターが含まれています。
- response_type: 認証タイプを表します。必須パラメーターであり、ここの値は「code」に固定されます。
- client_id: クライアントの ID を表します。必須パラメーターです。
- redirect_uri: リダイレクト URI を表します。オプションのパラメーターです。
- scope: 要求されたアクセス許可範囲を表します。オプションのパラメーターです。
- state: クライアントの現在の状態を表します。任意の値が指定できます。認証サーバーはこの値を変更せずに返します。
例:
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/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 を表します。必須のパラメーターです。
例:
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: トークンタイプを表します。この値は大文字と小文字が区別されず、必須のパラメーターです。ベアラータイプまたは mac タイプにすることができます。
- expires_in: 有効期限を秒単位で表します。このパラメーターが省略されている場合は、他の方法で有効期限を設定する必要があります。
- refresh_token: リフレッシュトークンを表します。次のアクセストークンを取得するために使用され、オプションのパラメーターです。
- scope: アクセス許可範囲を表します。クライアントがリクエストしたスコープと一致する場合、この項目は省略できます。
例:
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 ヘッダー情報に明確に指定されていることがわかります。
VII. 簡易モード
簡易モード (implicit grant type) は、サードパーティアプリケーションのサーバーを経由せずに、ブラウザで認証サーバーから直接トークンを申請します。「承認コード」のステップをスキップするため、名前の由来となっています。すべてのステップはブラウザで完了し、トークンはビジターに表示され、クライアントは認証される必要はありません。具体的な手順は以下のとおりです。
- (A):クライアントはユーザーを認証サーバーにリダイレクトします。
- (B):ユーザーはクライアントに承認を与えるかどうかを決定します。
- (C):ユーザーが承認を与えたと仮定すると、認証サーバーはユーザーをクライアントが指定した「リダイレクト URI」にリダイレクトし、URI の Hash 部分にアクセストークンを含めます。
- (D):ブラウザはリソースサーバーにリクエストを送信します。これには、前のステップで受信した Hash 値は含まれていません。
- (E):リソースサーバーは Web ページを返し、そこに含まれるコードは Hash 値のトークンを取得できます。
- (F):ブラウザは前のステップで取得したスクリプトを実行し、トークンを抽出します。
- (G):ブラウザはトークンをクライアントに送信します。
上記の手順に必要なパラメーターを以下に示します。
-
ステップ A: クライアントから送信される HTTP リクエストには、次のパラメーターが含まれています。
- response_type: 認証タイプを表し、ここの値は「token」に固定されます。必須のパラメーターです。
- client_id: クライアントの ID を表します。必須のパラメーターです。
- redirect_uri: リダイレクト URI を表します。オプションのパラメーターです。
- scope: アクセス許可範囲を表します。オプションのパラメーターです。
- state: クライアントの現在の状態を表します。任意の値が指定できます。認証サーバーはこの値を変更せずに返します。
例:
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/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 のトークンを抽出します。
VIII. パスワードモード
パスワードモード (Resource Owner Password Credentials Grant) では、ユーザーは自分のユーザー名とパスワードをクライアントに提供し、クライアントはこの情報を使用して「サービスプロバイダー」に承認を要求します。このモードでは、ユーザーは自分のパスワードをクライアントに提供する必要がありますが、クライアントはパスワードを保存できません。これは通常、ユーザーがクライアントを高度に信頼している場合に使用されます。たとえば、クライアントがオペレーティングシステムの一部であるか、有名な企業が製造している場合などです。また、認証サーバーは、他の承認モードを実行できない場合にのみ、このモードの採用を検討します。具体的な手順は以下のとおりです。
- (A):ユーザーはクライアントにユーザー名とパスワードを提供します。
- (B):クライアントは認証サーバーにユーザー名とパスワードを送信し、認証サーバーにトークンを要求します。
- (C):認証サーバーは問題がないことを確認した後、クライアントにアクセストークンを提供します。
ステップ B では、クライアントから送信される HTTP リクエストには、次のパラメーターが含まれています。
- grant_type: 認証タイプを表し、ここの値は「password」に固定されます。必須のパラメーターです。
- username: ユーザー名を表します。必須のパラメーターです。
- password: ユーザーのパスワードを表します。必須のパラメーターです。
- scope: アクセス許可範囲を表します。オプションのパラメーターです。
例:
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/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" }
上記のコードのさまざまなパラメーターの意味については、「承認コードモード」のセクションを参照してください。プロセス全体を通して、クライアントはユーザーのパスワードを保存できません。
IX. クライアントモード
クライアントモード (Client Credentials Grant) とは、クライアントがユーザーの名義ではなく、独自の名義で「サービスプロバイダー」に対して認証を行うことを意味します。厳密に言うと、クライアントモードは OAuth フレームワークが解決する必要がある問題には属していません。このモードでは、ユーザーはクライアントに直接登録し、クライアントは独自の名義でサービスを提供するように「サービスプロバイダー」に要求します。実際には、承認の問題はありません。具体的な手順は以下のとおりです。
- (A):クライアントは、認証サーバーで自分の ID を認証し、アクセストークンを要求します。
- (B):認証サーバーは問題がないことを確認した後、クライアントにアクセストークンを提供します。
ステップ A では、クライアントから送信される HTTP リクエストには、次のパラメーターが含まれています。
- grant_type: 認証タイプを表し、ここの値は「client_credentials」に固定されます。必須のパラメーターです。
- scope: アクセス許可範囲を表します。オプションのパラメーターです。
例:
POST /token HTTP/1.1 Host: server.leapcell.io Authorization: Basic czZCaGRSqeqwewqmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=client_credentials
認証サーバーは、何らかの手段でクライアントの ID を検証する必要があります。
ステップ B では、認証サーバーはクライアントにアクセストークンを送信します。例:
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" }
上記のコードのさまざまなパラメーターの意味については、「承認コードモード」のセクションを参照してください。
X. トークンの更新
ユーザーがアクセスしたときにクライアントの「アクセストークン」が期限切れになっている場合は、「リフレッシュトークン」を使用して新しいアクセストークンを申請する必要があります。クライアントがトークンを更新するために送信する HTTP リクエストには、次のパラメーターが含まれています。
- grant_type: 使用される認証モードを表し、ここの値は「refresh_token」に固定されます。必須のパラメーターです。
- refresh_token: 以前に受信したリフレッシュトークンを表します。必須のパラメーターです。
- scope: 要求された承認範囲を表します。以前の申請の範囲を超えることはできません。このパラメーターが省略されている場合は、以前と同じ意味になります。
例:
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/)
最後に、デプロイに最適なプラットフォームを紹介します。【Leapcell】(https://leapcell.io/)
1. 複数の言語をサポート
- JavaScript、Python、Go、または Rust で開発します。
2. 無制限のプロジェクトを無料でデプロイ
- 使用量に対してのみ料金を支払います - リクエストも料金もありません。
3. 比類のない費用対効果
- アイドル料金なしの従量課金制。
- 例:25 ドルで、平均応答時間 60 ミリ秒で 694 万リクエストをサポートします。
4. 合理化された開発者エクスペリエンス
- 楽なセットアップのための直感的な UI。
- 完全に自動化された CI/CD パイプラインと GitOps 統合。
- 実用的な洞察のためのリアルタイムのメトリクスとログ。
5. 簡単なスケーラビリティと高パフォーマンス
- 高い同時実行性を簡単に処理するための自動スケーリング。
- 運用上の オーバーヘッド なし — 構築に集中してください。
Leapcell Twitter: https://x.com/LeapcellHQ