🔑 API Key認証の実装:クライアントにAPIを有料で提供する
これまでの章では、私たちは「他人のAPIを呼び出す」側の役割を果たしてきました(Stripeや緑界、OpenAIなどへのリクエスト)。 しかし、もしあなたが超高性能なAI画像生成モデルや、極めて正確な株価予測アルゴリズムを開発した場合、それをAPIとして世界中のエンジニアに有料で提供したいと思いませんか?
そのためには、**「API Key認証システム」**を構築する必要があります!
この章では、ビジネスレベルのAPI Keyロジックをゼロから実装する方法を解説します。キーの生成、認証、使用量の計算までを網羅します!
1. API Keyとは何か?
API Keyとは、推測が困難な長い文字列(例:sk_live_abc123def456...)です。
クライアントが料金を支払った後、このKeyを発行します。以後、クライアントがあなたのAPIを呼び出す際には、HTTP HeaderにこのKeyを含める必要があります。バックエンドはこのKeyを見ることで「これは王大明さんのリクエストだ、1ポイント消費しよう」と判断します。
データベース設計 (PostgreSQL例)
API Keyを管理するためには、関連テーブルをデータベースに作成する必要があります:
CREATE TABLE api_keys (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES users(id), -- このKeyの所有者
key_value VARCHAR(255) UNIQUE NOT NULL, -- 実際の文字列 (例: sk_live_...)
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
last_used_at TIMESTAMP WITH TIME ZONE,
is_active BOOLEAN DEFAULT TRUE,
usage_count INTEGER DEFAULT 0 -- 呼び出し回数の統計
);
2. 安全なAPI Keyを生成する
API Keyは決して連番(001, 002など)にしてはいけません。そうするとハッカーに簡単に推測されてしまいます。
Node.jsの組み込みモジュールcryptoを使用して、ランダムで安全な文字列を生成しましょう。
// src/app/api/generate-key/route.ts
import { NextResponse } from 'next/server';
import crypto from 'crypto';
import { db } from '@/lib/db'; // あなたのデータベース接続
// ランダム文字列生成のヘルパー関数
function generateApiKey() {
// 32バイトのランダムな16進数文字列を生成し、カスタムプレフィックスを付加
const randomStr = crypto.randomBytes(32).toString('hex');
return `vibe_sk_${randomStr}`;
}
export async function POST(request: Request) {
// ユーザーがログインしていると仮定
const userId = 'user-123';
const newKey = generateApiKey();
// データベースに保存
const insertedKey = await db.api_keys.insert({
user_id: userId,
key_value: newKey,
is_active: true
});
return NextResponse.json({
message: "API Keyが正常に生成されました!この機会に必ず保存してください。二度と表示されません。",
apiKey: newKey
});
}
⚠️ セキュリティプラクティス:業界で最も厳格な実装では、データベースにAPI Keyを平文で保存せず、
hash(API Key)を保存します。これはパスワードと同様で、万が一データベースが侵害されても、ハッカーは元のKeyを取得できません。ただし小規模なプロジェクトでは、平文や暗号化して保存することも許容されるトレードオフです。
3. コアAPIに「認証ゲート」を実装する
クライアントがvibe_sk_xxx...というKeyを取得しました。
彼らが有料の「AI株価予測API」を呼び出す際には、入り口でガードマンによるチェックが必要です。
業界標準の方法は、クライアントにAPI KeyをHTTP HeaderのAuthorization: Bearer <API_KEY>に入れてもらうことです。
// src/app/api/stock-predict/route.ts
import { NextResponse } from 'next/server';
import { db } from '@/lib/db';
export async function POST(request: Request) {
// 1. HeaderからAuthorizationフィールドを取得
const authHeader = request.headers.get('Authorization');
// 形式が正しいか確認 (Bearer vibe_sk_...)
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return NextResponse.json({ error: "API Keyの形式が不正です。'Bearer <YOUR_KEY>'形式で指定してください" }, { status: 401 });
}
// 実際のKey文字列を抽出
const providedKey = authHeader.split(' ')[1];
// 2. データベースでKeyを照合
const keyRecord = await db.api_keys.findUnique({
where: { key_value: providedKey }
});
// Keyが存在しない、または無効化されている場合
if (!keyRecord || !keyRecord.is_active) {
return NextResponse.json({ error: "無効または非アクティブなAPI Keyです" }, { status: 403 });
}
// 3. ユーザーの利用可能残高を確認(オプション)
const user = await db.users.findUnique({ where: { id: keyRecord.user_id }});
if (user.credits <= 0) {
return NextResponse.json({ error: "残高不足です。アカウントにチャージしてください。" }, { status: 402 });
// 402 Payment Requiredはこの場面にぴったり!
}
// ------------------------------------
// あなたの価値あるビジネスロジックを実行
// ------------------------------------
const predictionResult = { stock: "TSLA", trend: "UP", confidence: 0.95 };
// 4. 処理完了後、ポイントを減算し統計を更新
await db.users.update({
where: { id: user.id },
data: { credits: user.credits - 1 }
});
// Keyの最終使用日時と回数も記録
await db.api_keys.update({
where: { id: keyRecord.id },
data: {
usage_count: keyRecord.usage_count + 1,
last_used_at: new Date()
}
});
// 5. 充実したResponseを返却!
return NextResponse.json({
data: predictionResult,
meta: {
credits_remaining: user.credits - 1
}
});
}
4. クライアントはどうやってAPIを呼び出すか?
この完璧なゲートを実装したことで、あなたは堂々とAPI公式ドキュメントを書くことができます! クライアントには以下の方法でAPIを呼び出すように指導しましょう:
Fetchを使用する場合 (JavaScript/TypeScript):
const response = await fetch('https://api.yourdomain.com/stock-predict', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// ここにクライアントが購入したAPI Keyを設定!
'Authorization': 'Bearer vibe_sk_abc123...'
},
body: JSON.stringify({ symbol: "TSLA" })
});
const data = await response.json();
cURLを使用する場合 (ターミナル):
curl -X POST https://api.yourdomain.com/stock-predict \
-H "Content-Type: application/json" \
-H "Authorization: Bearer vibe_sk_abc123..." \
-d '{"symbol": "TSLA"}'
素晴らしい!これで完全なB2B(企業間)SaaSビジネスアーキテクチャが完成しました!価値あるアルゴリズムを開発し、このAPI Key認証システムと組み合わせれば、自宅にいながら呼び出し回数(usage_count)が増えるのを見守り、毎月クライアントから料金を徴収できるようになります!💸