API トークンの完全な認証システム設計図
API トークン方式の認証は、JWT よりもシンプルでありながら、設計を誤ると重大なセキュリティ事故につながります。 ここでは、業務システムでそのまま使える 完全な認証システム設計図 を、初心者にも理解できるようにステップバイステップで解説します。
API トークンの生成、保存、検証、失効、再発行までをすべて網羅した「実務レベルの完全テンプレート」です。
API トークン認証の全体像
API トークン方式は次の 5 つの要素で構成されます。
- トークン生成(暗号学的乱数)
- トークンの安全な保存(ハッシュ化)
- API 呼び出し時のトークン検証
- トークンの有効期限管理
- トークンの失効(ログアウト・強制無効化)
この 5 つが揃って初めて「安全な API 認証システム」が成立します。
API トークンの特徴と JWT との違い
API トークン方式
- サーバー側でトークンを保存する(ステートフル)
- トークンはただのランダム文字列
- 改ざん防止の署名はない
- 有効期限や失効をサーバー側で管理できる
JWT 方式
- サーバー側で保存しない(ステートレス)
- 改ざん防止の署名付き
- 有効期限はトークン内に埋め込まれる
- 失効が難しい
API トークン方式は「サーバー側で完全に管理できる」ため、 セキュリティ要件が厳しい業務システムでよく使われます。
API トークン認証のデータモデル
Token テーブル(例)
| 項目 | 説明 |
|---|---|
| UserId | ユーザー識別子 |
| TokenHash | ハッシュ化されたトークン |
| ExpiresAt | 有効期限 |
| CreatedAt | 発行日時 |
| Revoked | 無効化フラグ |
※ トークンは 平文で保存してはいけません。 必ずハッシュ化して保存します。
ステップ 1:API トークンを生成する
API トークンは「暗号学的乱数」で生成します。
using System.Security.Cryptography;
public static class ApiTokenGenerator
{
public static string GenerateToken(int byteLength = 32)
{
byte[] bytes = RandomNumberGenerator.GetBytes(byteLength);
return Convert.ToBase64String(bytes);
}
}
C#ステップ 2:API トークンを安全に保存する(ハッシュ化)
高速ハッシュ(SHA256)は総当たり攻撃に弱いため、 PBKDF2 / bcrypt / Argon2 のような「安全なハッシュ」を使います。
ここでは PBKDF2 を使います。
using System.Security.Cryptography;
using System.Text;
public static class ApiTokenHasher
{
public static string HashToken(string token, int iterations = 100_000)
{
byte[] salt = RandomNumberGenerator.GetBytes(16);
byte[] hash = PBKDF2(token, salt, iterations);
return $"{Convert.ToBase64String(salt)}.{Convert.ToBase64String(hash)}";
}
public static bool VerifyToken(string token, string storedHash, int iterations = 100_000)
{
var parts = storedHash.Split('.');
byte[] salt = Convert.FromBase64String(parts[0]);
byte[] stored = Convert.FromBase64String(parts[1]);
byte[] computed = PBKDF2(token, salt, iterations);
return CryptographicOperations.FixedTimeEquals(stored, computed);
}
private static byte[] PBKDF2(string token, byte[] salt, int iterations)
{
using var pbkdf2 = new Rfc2898DeriveBytes(token, salt, iterations, HashAlgorithmName.SHA256);
return pbkdf2.GetBytes(32);
}
}
C#ステップ 3:トークン発行処理(実務コード)
public TokenResponse IssueToken(string userId)
{
string token = ApiTokenGenerator.GenerateToken();
string hash = ApiTokenHasher.HashToken(token);
SaveTokenToDatabase(userId, hash, DateTime.UtcNow.AddHours(12));
return new TokenResponse(token);
}
C#ステップ 4:API 呼び出し時のトークン検証
public bool ValidateToken(string userId, string receivedToken)
{
string storedHash = GetTokenHashFromDatabase(userId);
if (storedHash == null)
return false;
bool valid = ApiTokenHasher.VerifyToken(receivedToken, storedHash);
if (!valid)
return false;
var tokenInfo = GetTokenInfo(userId);
if (tokenInfo.Revoked || tokenInfo.ExpiresAt < DateTime.UtcNow)
return false;
return true;
}
C#ステップ 5:トークンの失効(ログアウト・強制無効化)
public void RevokeToken(string userId)
{
UpdateTokenRevokedFlag(userId, true);
}
C#ステップ 6:トークンの再発行(ローテーション)
public TokenResponse RotateToken(string userId, string oldToken)
{
if (!ValidateToken(userId, oldToken))
throw new SecurityException("Invalid token");
RevokeToken(userId);
return IssueToken(userId);
}
C#セキュリティの深掘りポイント(重要)
トークンは必ずハッシュ化して保存する
平文保存は重大事故につながります。
トークンは短命にする
推奨:1〜24時間 理由:漏洩時の被害を最小化できるため。
トークンはローテーションする
古いトークンを無効化し、新しいトークンを発行します。
トークンをログに出力しない
ログ漏洩は非常に多い事故原因です。
HTTPS は必須
API トークンは平文で送られるため、HTTPS がないと盗聴されます。
完全設計図まとめ
このテンプレートを使うことで、次の機能が揃います。
- 暗号学的乱数によるトークン生成
- PBKDF2 による安全なハッシュ化保存
- API 呼び出し時のトークン検証
- 有効期限管理
- トークン失効(ログアウト)
- トークンローテーション(再発行)
業務システムにそのまま組み込めるレベルの 「完全な API トークン認証システム」が構築できます。
