API キー、JWT、OAuth2: API に適切な認証を選択してください
API キー、JWT、OAuth2 を 7 つの基準にわたって比較します。 実際に動作する CURL の例を使用して、サーバー間の呼び出し、ユーザー セッション、サードパーティのアクセスにどれが適しているかを学びます。
API を構築しています。 エンドポイントは機能します。 データは流れます。 ここで 1 つ答える必要があります 発送前の質問: 発信者はどのようにして本人であることを証明しますか?
API 認証では、API キー、JWT、OAuth2 という 3 つのアプローチが主流です。 それぞれが解決します 別の問題。 間違ったものを選択すると、単純な統合を過剰に設計することになります あるいは、複雑なセキュリティのギャップを残すこともできます。
このガイドでは、7 つの基準にわたって 3 つすべてを比較し、実際のコード例と決定を示します。 表と、API のユースケースに基づいた明確な推奨事項。
API キー認証: 直接的なアプローチ
API キーは、呼び出し元を識別して承認する長いランダムな文字列です。 クライアントが送信する すべてのリクエストでそれを検索し、それが有効なキーと一致する場合、リクエストは 通ります。
Botoi API を使用した API キー呼び出しは次のようになります。
# API key in a custom header
curl -s -X POST https://api.botoi.com/v1/dns/lookup \\
-H "Content-Type: application/json" \\
-H "x-api-key: your_api_key_here" \\
-d '{"domain": "example.com", "type": "A"}'
応答:
{
"success": true,
"data": {
"domain": "example.com",
"type": "A",
"records": [
{ "type": "A", "value": "93.184.216.34", "ttl": 86400 }
]
}
}
の x-api-key ヘッダーには資格情報が含まれます。 ネゴシエートするトークンやリダイレクトは必要ありません。
認証サーバーはありません。 1 つのヘッダー、1 つの検索、1 つの応答。
API キーが勝った場合
- サーバー間の呼び出し。 バックエンドが別のバックエンドを呼び出します。 ユーザーはいません 関与している。 cron ジョブは IP 地理位置情報 API をクエリします。 CI パイプラインは DNS チェックを実行します。 電話をかけてきた人 は常に信頼できるサーバーです。
- ユーティリティ API。 ステートレスな操作 (ハッシュ、エンコーディング、 検証、検索など)、すべてのリクエストが独立しています。 botoi は次の理由で API キーを使用します。 150 以上のエンドポイント、すべてステートレス、すべてサーバー間。
- 迅速な統合。 開発者はキーをコピーし、ヘッダーを 1 つ追加して開始します。 呼んでいます。 OAuth ダンス、トークン更新ロジック、構成する JWKS エンドポイントはありません。
Node.js での同じ呼び出しを次に示します。
const response = await fetch("https://api.botoi.com/v1/hash", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.BOTOI_API_KEY,
},
body: JSON.stringify({ text: "hello world", algorithm: "sha256" }),
});
const result = await response.json();
// result.data.hash = "b94d27b9934d3e08..."
API キーが不足している箇所
- ユーザー ID がありません。 API キーはユーザーではなくアカウントを識別します。 もし 3 人の開発者が 1 つのキーを共有しているため、誰がどのリクエストを行ったのかわかりません。
- 取り消しには往復が必要です。 キーを取り消すということは、サーバーのキーを更新することを意味します 鍵屋。 キャッシュが更新されるまで、古いキーは引き続き機能します。
- 委任されたアクセスはありません。 サードパーティのアプリに制限付き、一時的な機能を与えることはできません API キーのみを使用してユーザーのリソースにアクセスします。
JWT 認証: ステートレス ユーザー セッション
JSON Web Token (JWT) は、呼び出し元に関するクレームを伝える署名付き JSON オブジェクトです。 認証 サーバーはログイン時にそれを作成します。 クライアントはリクエストごとにそれを送信します。 リソースサーバー 認証サーバーを再度呼び出さずに署名を検証します。
// Header
{
"alg": "RS256",
"typ": "JWT"
}
// Payload
{
"sub": "user_12345",
"email": "dev@example.com",
"role": "admin",
"iat": 1775000000,
"exp": 1775000900 // 15 minutes
}
// Signature
RSASHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
privateKey
)
サーバーは公開キーを使用して署名を検証します。 署名がチェックアウトされた場合、
exp 合格していない場合、リクエストは承認されます。 データベースの検索は必要ありません。
JWT が勝つとき
- トラフィックの多いユーザー向け API。 モバイル アプリはすべての場合に JWT を送信します。 リクエスト。 API ゲートウェイは、セッション ストアにクエリを実行するのではなく、ローカルで署名を検証します。 すべての通話で。 1 秒あたり 10,000 リクエストの場合、スキップしたデータベース呼び出しは重要です。
- マイクロサービス アーキテクチャ。 サービス A は、JWT を使用してサービス B を呼び出します。 サービスB ローカルで検証し、クレームからユーザーの ID とロールを抽出します。 共有セッションなし サービス間のデータベース。
- 有効期間が短い承認。 ファイルアップロード用の 15 分のトークン。 5分 支払い確認用のトークン。 有効期限はトークン自体に組み込まれています。
JWT を検証する Express ミドルウェアは次のとおりです。
import jwt from "jsonwebtoken";
function authMiddleware(req, res, next) {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) return res.status(401).json({ error: "Missing token" });
try {
const decoded = jwt.verify(token, process.env.JWT_PUBLIC_KEY, {
algorithms: ["RS256"],
});
req.user = decoded;
next();
} catch (err) {
return res.status(401).json({ error: "Invalid or expired token" });
}
}
JWT では不十分な点
- トークンの取り消しは困難です。 JWT は有効期限が切れるまで有効です。 ユーザーがログインした場合 アクセスを取り消す必要がある場合は、サーバー側のブロックリストが必要です。 避けようとしていたデータベース呼び出し。
- ペイロードサイズ。 クレームごとにバイトが追加されます。 ユーザーの役割、権限、 メタデータは 1 ~ 2 KB に達する場合があります。 これは、すべての単一リクエスト、すべてのヘッダーで 1 ~ 2 KB になります。
-
キーのローテーションの複雑さ。 署名キーをローテーションすると、古いトークンは署名されます
以前のキーは期限切れになるまで有効なままにする必要があります。 これは複数のサービスを提供することを意味します
JWKS エンドポイント経由の公開鍵とその処理
kidヘッダークレーム。
OAuth2: サードパーティへのアクセスの委任
OAuth2 は認証フレームワークであり、認証プロトコルではありません。 これにより、ユーザーは次のことを許可できます。 サードパーティのアプリケーションは、共有せずに、別のサービス上のリソースへのアクセスを制限しました 彼らのパスワード。
典型的な例: ユーザーがプロジェクト管理ツールに GitHub を読み取る権限を与える リポジトリ。 ユーザーが GitHub にログインし、特定のスコープを承認すると、ツールは これらの権限にスコープされたアクセス トークン。
# Step 1: Redirect user to authorization server
GET https://auth.example.com/authorize?
response_type=code&
client_id=your_app_id&
redirect_uri=https://yourapp.com/callback&
scope=read:repos+write:issues&
state=random_csrf_token
# Step 2: Exchange authorization code for tokens
POST https://auth.example.com/token
grant_type=authorization_code&
code=AUTH_CODE_FROM_CALLBACK&
client_id=your_app_id&
client_secret=your_app_secret&
redirect_uri=https://yourapp.com/callback
# Step 3: Call the API with the access token
curl -H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \\
https://api.example.com/v1/repos
OAuth2が勝ったとき
- サードパーティの統合。 プラットフォームを運営していて外部開発者が必要な場合 ユーザーのデータにアクセスするアプリを構築します。 OAuth2 により、ユーザーは各アプリの内容を制御できるようになります にアクセスできます。
-
きめ細かいスコープ。
read:reposしかしそうではありませんdelete:repos。write:issuesしかしそうではありませんadmin:org。 OAuth2 スコープを使用すると、ユーザーは特定の権限を承認できます。 - 「Xでサインイン」が流れます。 アプリが Google、GitHub、または Microsoft を使用する場合 ログインすると、OAuth2 (多くの場合、OpenID Connect が最上位にあります) を使用して ID トークンを取得します。
OAuth2 が不十分な点
- 複雑。 OAuth2 には、リフレッシュ トークン、認可の 4 つの付与タイプがあります。 サーバー、リダイレクト URI、PKCE、およびトークン イントロスペクション エンドポイント。 ユーティリティ API の場合 ユーザー コンテキストがないため、これはオーバーヘッドであり、何のメリットもありません。
- 統合の摩擦。 ハッシュエンドポイントを呼び出したい開発者 OAuth アプリの登録、リダイレクト URI の設定、および承認の交換をしたくない コード。 彼らはキーとcurlコマンドを必要としています。
- トークン管理の負担。 アクセス トークンの有効期限が切れます。 リフレッシュトークンは循環します。 クライアントには 401 応答の再試行ロジックが必要です。 単純なサーバー間の呼び出しの場合、これは次のようになります。 不要な機械。
比較表
| 基準 | APIキー | JWT | OAuth2 |
|---|---|---|---|
| 積分時間 | 分 | 営業時間 | 日数 |
| ユーザーID | アカウントレベル | ユーザーレベル (クレーム) | ユーザーレベル (スコープ) |
| ステートレス検証 | いいえ (サーバー検索) | はい(署名チェック) | トークンの形式に依存する |
| 失効速度 | 即時(キーの削除) | 遅延(有効期限まで) | 即時 (トークンの取り消し) |
| 委任されたアクセス | いいえ | いいえ | はい |
| サードパーティのサポート | 貧しい | 良い | 素晴らしい |
| ブラウザに適しています | いいえ (キー露出) | はい (短命) | はい (認証コード + PKCE) |
意思決定の枠組み: ユースケースに基づいて選択する
「どれが最も安全ですか?」という質問はやめてください。 正しく使用すれば、これら 3 つはすべて安全です。 右 質問: 「私の API を呼び出しているのは誰ですか?なぜ?」
- サーバーはサーバーを呼び出しますが、ユーザーは関与しません: APIキー。 バックエンドは DNS ルックアップ、ハッシュ、またはデータ検証用のユーティリティ API。 1 つのキー、1 つのヘッダーが完了しました。
- 独自のアプリは独自のユーザーを認証します。 JWT。 モバイルアプリまたはSPA ログインしているユーザーに代わってリクエストを送信します。 ログイン時に有効期間の短い JWT に署名し、それを検証します セッションストアを使用しないすべてのリクエストで。
- サードパーティ アプリはユーザー データにアクセスします。 OAuth2。 外部開発者によるビルド プラットフォームとの統合。 ユーザーは、各アプリがスコープを介してアクセスできるものを制御します 同意画面。
多くの実稼働システムでは、これらのアプローチが組み合わされています。 GitHub はサードパーティ アプリに OAuth2 を使用します サーバー側スクリプト用の API キー (個人アクセス トークン)。 Stripe は API キーを使用して、 マーケットプレイス プラットフォーム向けの直接統合と OAuth2 (Stripe Connect)。
Unkey を使用して API キーを大規模に管理する
API キーは、ハッシュ化したり、レート制限を適用したり、有効期限を設定したりする必要があるまでは、単純に思えます。 日付を管理し、キーごとの使用状況を追跡し、ダウンタイムなしでキーをローテーションします。 これらすべてを構築する スクラッチには数週間かかります。
アンキー オープンです 作成、検証、レート制限、および 分析。 botoi は Unkey を使用して、150 以上のエンドポイント全体のすべての API キーを管理します。
レート制限が組み込まれたスコープ付きキーを作成します。
import { Unkey } from "@unkey/api";
const unkey = new Unkey({ rootKey: process.env.UNKEY_ROOT_KEY });
// Create a scoped API key with built-in rate limiting
const key = await unkey.keys.create({
apiId: "api_your_api_id",
prefix: "botoi",
meta: { userId: "user_12345", plan: "pro" },
expires: Date.now() + 90 * 24 * 60 * 60 * 1000, // 90 days
ratelimit: {
type: "fast",
limit: 100,
refillRate: 10,
refillInterval: 1000,
},
});
// key.result.key = "botoi_3xK9m2..."
ミドルウェアでそれを確認します。
import { verifyKey } from "@unkey/api";
async function authMiddleware(req, res, next) {
const apiKey = req.headers["x-api-key"];
if (!apiKey) return res.status(401).json({ error: "Missing API key" });
const result = await verifyKey(apiKey);
if (!result.result.valid) {
return res.status(result.result.code === "RATE_LIMITED" ? 429 : 403)
.json({ error: result.result.code });
}
req.keyMeta = result.result.meta; // { userId, plan }
next();
}
Unkey は、キーをハッシュ化して (決してプレーン テキストではない) 保存し、エッジでレート制限を強制し、 キーごとの使用状況を示す分析ダッシュボードが表示されます。 キーのローテーションが必要な場合は、新しいキーを作成します そして古いものに有効期限を設定します。 ダウンタイムやコードの変更はありません。
各アプローチのセキュリティ チェックリスト
APIキー
- HTTPS のみで送信します。 URL やクエリ文字列にキーを埋め込まないでください。
- ハッシュ化されたものをサーバーに保存します。 生のキーをログに記録しないでください。
- キーのスコープを特定の権限 (読み取り専用、書き込み、管理者) に設定します。
- 有効期限を設定します。 90 日ごとにローテーションを強制します。
- カスタムヘッダーを使用します(
x-api-key) の代わりにAuthorizationに ブラウザーの認証情報のキャッシュを回避します。
JWT
- 非対称署名 (RS256 または ES256) を使用します。 共有シークレットを含む HS256 は決して使用しないでください。 分散システム。
- トークンの有効期間は短くしてください: アクセス トークンの場合は 5 ~ 15 分です。
- 検証する
iss、aud、 そしてexpあらゆるものについての主張 リクエスト。 - JWKS エンドポイント経由で公開キーを公開します。 スケジュールに従って署名キーをローテーションします。
- 機密データをペイロードに保存しないでください。 JWT は暗号化されず、エンコードされます。
OAuth2
- SPA やモバイルを含むすべてのクライアントに対して PKCE で認証コード フローを使用する アプリ。
- 暗黙的なフローは決して使用しないでください。 これは正当な理由により OAuth 2.1 で非推奨になりました。
- クライアント シークレットはサーバー上にのみ保存します。 モバイルアプリやフロントエンドでは決して配布しないでください コード。
- 検証する
stateパラメータを使用して、コールバック URL に対する CSRF 攻撃を防ぎます。 - リフレッシュ トークンのローテーションで有効期間の短いアクセス トークンを使用します。
重要なポイント
- APIキー サーバー間ユーティリティ API には正しい選択です。 彼らは 統合が速く、管理が簡単で、ユーザー ID が必要ない場合には十分です。 ボトイ 管理のために Unkey を使用して 150 以上のエンドポイントにわたってそれらを使用します。
- JWT ステートレス ユーザー セッションには正しい選択です。 彼らは排除します セッション ストアの検索は大規模ですが、トークンの取り消しには追加のインフラストラクチャが必要です。
- OAuth2 サードパーティ製アプリが対象範囲を限定したアクセスを必要とする場合、これは正しい選択です。 ユーザーリソース。 この複雑さは、提供されるセキュリティ モデルによって正当化されます。
- 誇大広告ではなく、発信者に基づいて選択してください。 OAuth2 を使用したユーティリティ API はオーバーエンジニアリングされています。 あ API キーのみを含むプラットフォーム API では、委任されたアクセスを許可できません。
- 製品で必要な場合は、アプローチを組み合わせます。 直接統合用の API キー、OAuth2 マーケットプレイス パートナーの場合は JWT、ログイン ユーザー セッションの場合は JWT。
FAQ
- OAuth2 の代わりに API キーを使用する必要があるのはどのような場合ですか?
- 呼び出し元がユーザーではなくサーバーである場合は、API キーを使用します。 API キーは、すべてのリクエストが信頼できるバックエンドから送信されるサーバー間統合、CI/CD パイプライン、ユーティリティ API に適しています。 OAuth2 は、エンドユーザーの同意やアクセスの委任が関与しない場合、不必要な複雑さを追加します。
- JWT と OAuth2 を併用できますか?
- はい。 OAuth2 は認証フローを定義します。 JWT はトークンの形式を定義します。 多くの OAuth2 プロバイダーは JWT をアクセス トークンとして発行します。 JWT には、リクエストごとに認証サーバーを呼び出すことなく、リソース サーバーが検証するクレーム (ユーザー ID、スコープ、有効期限) が含まれます。
- API キーは運用環境に十分安全ですか?
- API キーはパスワードのように扱うと安全です。 HTTPS のみを介して送信し、ハッシュ化してサーバーに保存し、特定の権限に限定し、有効期限を設定し、スケジュールに基づいてローテーションします。 Unkey のようなサービスは、ハッシュ、レート制限、有効期限を自動的に処理します。
- 有効期限が切れる前に JWT を取り消すにはどうすればよいですか?
- JWT はステートレスであるため、失効には追加のインフラストラクチャが必要です。 一般的なアプローチには、リクエストごとにチェックされるサーバー側のブロックリスト、リフレッシュ トークンと組み合わせた短期間のトークン (5 ~ 15 分)、またはデータベースに対して検証されたトークン バージョンの要求が含まれます。 各アプローチでは、ステートレスの利点を部分的に無効にするサーバー側のチェックが追加されます。
- 認証と認可の違いは何ですか?
- 認証では、「あなたは誰ですか?」という身元を確認します。 権限によってアクセスが決定されます。「何ができるか?」 API キーは多くの場合、両方を 1 つの認証情報に結合します。 OAuth2 は設計上これらを分離し、ユーザー (認証) がパスワードを共有せずにサードパーティ アプリに限定的なアクセス許可 (承認) を付与できるようにします。
botoiで開発を始めよう
150以上のAPIエンドポイント。検索、テキスト処理、画像生成、開発者ユーティリティに対応。無料プラン、クレジットカード不要。