C# Tips | セキュリティ:JWTの署名を検証する

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

JWT の署名検証は「トークンが改ざんされていないことを保証するための最重要ステップ」です

読者のみなさんが Web API や業務システムを開発する際、 JWT(JSON Web Token)を安全に扱うためには 署名の検証(Signature Validation) が必須です。

署名検証は、次のことを保証します。

  • トークンが第三者に書き換えられていない
  • 正しい秘密鍵(または公開鍵)で署名されている
  • 信頼できる発行者(Issuer)が作ったトークンである

ここでは、初心者でも理解できるように ステップバイステップで思考しながら、 実務で使える C# の JWT 署名検証ユーティリティを丁寧に解説します。

JWT の署名検証とは何か

JWT の構造を理解する

JWT は次の 3 つの部分で構成されています。

  1. Header(署名方式)
  2. Payload(ユーザー情報・有効期限)
  3. Signature(改ざん防止の署名)

例: xxxxx.yyyyy.zzzzz

署名部分(zzzzz)は、Header と Payload を秘密鍵または公開鍵で署名したものです。

なぜ署名検証が必要なのか

署名を検証しないと、攻撃者が次のようなことをできます。

  • Payload を書き換えて権限を偽装
  • 有効期限を延長
  • 別ユーザーの ID に書き換え

署名検証は JWT の安全性の中心 です。

C# で JWT の署名を検証するためのライブラリ

.NET では公式ライブラリが用意されています。

  • System.IdentityModel.Tokens.Jwt
  • Microsoft.IdentityModel.Tokens

これらを使うことで、安全な署名検証ができます。

署名方式(アルゴリズム)を理解する

HS256(対称鍵方式)

  • 秘密鍵を共有する方式
  • 単一サービス向け
  • API サーバーが署名と検証の両方を行う

RS256 / ES256(公開鍵方式)

  • 公開鍵で検証
  • 複数サービス間での認証に向いている
  • Identity Provider が署名し、API サーバーが公開鍵で検証する

実務で使える JWT 署名検証ユーティリティ(HS256)

まずは最も一般的な HS256 の検証テンプレートです。

csharp

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

public static class JwtValidator
{
    public static ClaimsPrincipal Validate(string token, string secretKey)
    {
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));

        var parameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,

            ValidIssuer = "your-app",
            ValidAudience = "your-app",
            IssuerSigningKey = key
        };

        var handler = new JwtSecurityTokenHandler();
        return handler.ValidateToken(token, parameters, out _);
    }
}

署名検証の使い方(実務コード例)

csharp

string secretKey = "your-very-strong-secret-key-1234567890";
string token = "受け取ったJWTトークン";

try
{
    var principal = JwtValidator.Validate(token, secretKey);
    string userId = principal.FindFirst("userId")?.Value;

    Console.WriteLine($"認証成功: {userId}");
}
catch (Exception ex)
{
    Console.WriteLine("署名検証に失敗しました: " + ex.Message);
}

公開鍵方式(RS256 / ES256)の署名検証(深掘り)

外部サービス(Auth0、Azure AD、Google、LINE Login など)から JWT を受け取る場合は 公開鍵方式(RS256 / ES256) を使います。

公開鍵は X.509 証明書として提供されることが多いです。

RS256 の検証テンプレート

csharp

using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;

public static class JwtValidatorRs256
{
    public static ClaimsPrincipal Validate(string token, X509Certificate2 cert)
    {
        var key = new X509SecurityKey(cert);

        var parameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,

            IssuerSigningKey = key,
            ValidIssuer = "your-issuer",
            ValidAudience = "your-audience"
        };

        var handler = new JwtSecurityTokenHandler();
        return handler.ValidateToken(token, parameters, out _);
    }
}

署名検証でよくある失敗と対策(重要)

Issuer / Audience が一致しない

検証側の設定とトークンの値が一致しないと必ず失敗します。

公開鍵が古い・間違っている

Identity Provider が鍵をローテーションする場合があります。 最新の公開鍵を取得する必要があります。

有効期限切れ

exp が過ぎていると検証に失敗します。

Clock Skew(時刻のズレ)

サーバーの時刻がずれていると有効期限判定が誤ります。

実務的ベストプラクティス

  • HS256 の秘密鍵は 32 文字以上にする
  • RS256 / ES256 の公開鍵は定期的に更新する
  • JWT は短命(15〜30 分)にする
  • リフレッシュトークンを併用する
  • HTTPS を必ず使う
  • JWT をログに出力しない
  • ペイロードに機密情報を入れない

まとめ:JWT の署名検証は「改ざん防止の中心技術」

署名検証の本質は次の 3 つです。

  • 正しい鍵で署名されているか確認する
  • 改ざんされていないことを保証する
  • 有効期限や発行者をチェックする

これらを正しく実装することで、 攻撃者がトークンを偽造したり、書き換えたりするのを防げます。

読者のみなさんが業務システムを開発する際、 このユーティリティを使うだけでセキュリティレベルが大幅に向上し、 ユーザーの安全を確実に守ることができます。

必要であれば「JWT とリフレッシュトークンの完全設計テンプレート」も作成できます。

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