OAuth認証の基本をまとめました。
自分の備忘録として整理したものですが、同じように認証周りで悩んでいる方の参考になれば。図解でフロー別の違いをまとめてみました。📝
はじめに
WebアプリやモバイルアプリでAPI連携をする際、「OAuth認証」という言葉をよく耳にします。この記事では、OAuth認証の基本概念から実装の流れまでを初心者向けにまとめました。何度も調べる手間を省くための備忘録としてもご活用ください。
OAuthとは?
OAuthは「Open Authorization」の略で、ユーザーの認証情報(ID・パスワード)を第三者のアプリケーションに渡すことなく、APIへのアクセス権を付与するための標準プロトコルです。
簡単に言えば:
- あなたがTwitterでログインする際に使うID・パスワードを
- 別のアプリ(例:TweetDeck)に渡さなくても
- そのアプリがあなたのTwitterアカウントでツイートできるようにする仕組み
なぜOAuthが必要なのか?
OAuthがない世界では、以下のような問題があります:
- セキュリティリスク: ユーザーが様々なアプリにID・パスワードを直接入力する必要がある
- アクセス制御の粒度: アプリに全ての権限を与えるか、全く与えないかの二択しかない
- アクセス権の管理: 一度パスワードを渡したら、そのアプリのアクセス権を後から取り消せない
OAuthはこれらの問題を解決するために設計されています。
OAuth 2.0の基本フロー
現在主流のOAuth 2.0には、いくつかの認可フローがありますが、最も一般的な「認可コードフロー」を説明します。
登場人物
- リソースオーナー: サービスを利用するユーザー(あなた)
- クライアント: OAuthを使ってAPIにアクセスしたいアプリ
- 認可サーバー: ユーザー認証と認可を行うサーバー
- リソースサーバー: 保護されたリソース(データ)を持つサーバー
認可コードフローの流れ
+--------+ +---------------+
| |--(A)- 認可リクエスト -------->| |
| | | 認可サーバー |
| |<-(B)- 認可コード ------------+| |
| | +---------------+
| クライアント|
| | +---------------+
| |--(C)- 認可コード+ | |
| | クライアント認証 -------->| トークンエンドポイント|
| |<-(D)- アクセストークン -------+| |
+--------+ +---------------+
+---------------+
| |
| |
+--------+ | リソースサーバー |
| |--(E)- アクセストークン ------->| |
| クライアント| | |
| |<-(F)- 保護されたリソース ------+| |
+--------+ +---------------+
- 認可リクエスト: クライアントはユーザーを認可サーバーにリダイレクト
- ユーザー認証: ユーザーは認可サーバーで認証(ログイン)
- 認可: ユーザーはクライアントに与える権限を確認・承認
- 認可コード発行: 認可サーバーはクライアントに認可コードを発行
- トークン交換: クライアントは認可コードをアクセストークンと交換
- APIアクセス: クライアントはアクセストークンを使ってAPIにアクセス
実装のための基本ステップ
1. アプリケーション登録
OAuthを利用するには、まずOAuthプロバイダ(Google, Twitter, GitHubなど)にアプリケーションを登録します。
例:GitHubの場合
1. GitHub > Settings > Developer settings > OAuth Apps > New OAuth App
2. 以下の情報を入力:
- Application name: あなたのアプリ名
- Homepage URL: アプリのホームページURL
- Authorization callback URL: コールバックURL
登録すると以下が発行されます:
- クライアントID: 公開可能な識別子
- クライアントシークレット: 秘密鍵(漏洩しないように管理)
2. 認可リクエストの作成
ユーザーを認可ページへリダイレクトするためのURLを作成します。
https://[認可サーバーのドメイン]/oauth/authorize?
client_id=[クライアントID]&
redirect_uri=[コールバックURL]&
response_type=code&
scope=[必要な権限の範囲]&
state=[CSRF対策の状態値]
※ state
パラメータはCSRF攻撃から保護するために重要です。ランダムな文字列を生成し、セッションに保存しておきましょう。
3. コールバックの処理
ユーザーが認可を許可すると、指定したリダイレクトURIにコードが付与されます。
https://[あなたのアプリのコールバックURL]?code=[認可コード]&state=[送信した状態値]
このコールバックで行うべき処理:
-
state
パラメータが元の値と一致することを確認(CSRF対策) - 認可コード(
code
)を取得
4. アクセストークンの取得
認可コードを使ってアクセストークンを取得します。これはサーバーサイドで行う必要があります。
POST https://[認可サーバーのドメイン]/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=[取得した認可コード]&
redirect_uri=[コールバックURL]&
client_id=[クライアントID]&
client_secret=[クライアントシークレット]
成功すると、以下のようなレスポンスが返ってきます:
{
"access_token": "ACCESS_TOKEN",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "REFRESH_TOKEN",
"scope": "read write"
}
5. APIの呼び出し
取得したアクセストークンを使って、保護されたAPIを呼び出します。
GET https://[APIエンドポイント]/api/resource
Authorization: Bearer ACCESS_TOKEN
6. トークンの更新(オプション)
アクセストークンには有効期限があります。期限切れになった場合、リフレッシュトークンを使って新しいアクセストークンを取得します。
POST https://[認可サーバーのドメイン]/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&
refresh_token=[リフレッシュトークン]&
client_id=[クライアントID]&
client_secret=[クライアントシークレット]
主要なOAuth 2.0の認可フロー
1. 認可コードフロー(上述)
- Web アプリケーションに最適
- 最も安全なフロー
2. インプリシットフロー
- SPA(シングルページアプリケーション)向け
- リダイレクトURIにアクセストークンが直接付与される
- クライアントシークレットが不要
- ※セキュリティ上の懸念からPKCE付き認可コードフローが推奨されるようになっている
3. クライアントクレデンシャルフロー
- マシン間通信(サーバー間)に使用
- ユーザーの関与なしでアクセストークンを取得
4. リソースオーナー・パスワード・クレデンシャルフロー
- ユーザーのID/パスワードを直接使用
- 高度な信頼関係がある場合のみ使用(非推奨)
セキュリティに関する注意点
- HTTPS: すべての通信でHTTPSを使用する
- state パラメータ: CSRF攻撃対策として必ず使用する
- PKCE (Proof Key for Code Exchange): 公開クライアント向けのセキュリティ拡張
- スコープの最小化: 必要最低限の権限のみを要求する
- クライアントシークレットの保護: 漏洩しないようサーバーサイドでのみ使用する
開発に役立つライブラリ
Node.js
- Passport.js: 認証ミドルウェア
- node-oauth2-server: OAuth 2.0サーバーの実装
PHP
- League OAuth 2.0 Server
- PHP OAuth 2.0 Server
Python
- Authlib
- python-oauth2
Ruby
- Doorkeeper
- OAuth2 gem