C# Tips | セキュリティ:API トークンの完全な認証システム設計図

C# C#
スポンサーリンク
スポンサーリンク

API トークンの完全な認証システム設計図

API トークン方式の認証は、JWT よりもシンプルでありながら、設計を誤ると重大なセキュリティ事故につながります。 ここでは、業務システムでそのまま使える 完全な認証システム設計図 を、初心者にも理解できるようにステップバイステップで解説します。

API トークンの生成、保存、検証、失効、再発行までをすべて網羅した「実務レベルの完全テンプレート」です。

API トークン認証の全体像

API トークン方式は次の 5 つの要素で構成されます。

  1. トークン生成(暗号学的乱数)
  2. トークンの安全な保存(ハッシュ化)
  3. API 呼び出し時のトークン検証
  4. トークンの有効期限管理
  5. トークンの失効(ログアウト・強制無効化)

この 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 トークン認証システム」が構築できます。

タイトルとURLをコピーしました