Microsoft.IdentityModel.JsonWebTokens による JWT 生成移行ガイド
問題:新しい JsonWebTokens パッケージで JWT を生成する方法
古い System.IdentityModel.Tokens.Jwt
パッケージのコードを、新しい高性能パッケージ Microsoft.IdentityModel.JsonWebTokens
に移行する必要がある。具体的には以下の従来コードを変換したい:
// 旧パッケージを使用したJWT生成
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("キー文字列"));
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "Testuser"),
// 他のクレーム...
};
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
var token = new JwtSecurityToken(
"発行者",
"対象者",
claims,
expires: DateTime.UtcNow.AddMinutes(120),
signingCredentials: credentials
);
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
主な変更点の課題:
JwtSecurityToken
からJsonWebTokenHandler
へのインターフェース変更- クレーム情報の記述方法の差異
- トークンハンドラーの設定オプション追加
解決策: JsonWebTokenHandler を使った最新実装
移行後の完全なコード例と主要変更点:
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
// 秘密鍵の生成(変更なし)
var securityKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("SomeStringFromConfig1234")
);
// クレームの定義方法変更:List<Claim> → Dictionary<string, object>
var claims = new Dictionary<string, object>
{
[ClaimTypes.Name] = "Testuser",
[ClaimTypes.GroupSid] = "Tenant1",
[ClaimTypes.Sid] = "3c545f1c-cc1b-4cd5-985b-8666886f985b"
};
// トークン記述子の設定
var descriptor = new SecurityTokenDescriptor
{
Issuer = "MyIssuer", // 発行者
Audience = "MyAudience", // 対象者
Claims = claims, // クレーム辞書
NotBefore = DateTime.UtcNow, // 有効開始時刻
Expires = DateTime.UtcNow.AddMinutes(120), // 有効期限
SigningCredentials = new SigningCredentials(
securityKey,
SecurityAlgorithms.HmacSha256Signature // 署名アルゴリズム
)
};
// 新しいハンドラーの初期化
var handler = new JsonWebTokenHandler();
handler.SetDefaultTimesOnTokenCreation = false; // 自動時間設定を無効化
// JWTの生成
string tokenString = handler.CreateToken(descriptor);
変更点の詳細解説
1. クレーム定義方法の変更
従来の List<Claim>
から Dictionary<string, object>
へ移行:
// 従来方式
var claims = new List<Claim> {
new Claim(ClaimTypes.Name, "値")
};
// 新しい方式
var claims = new Dictionary<string, object> {
[ClaimTypes.Name] = "値"
};
理由:
新しいパッケージではクレームをより柔軟に扱えるため、ディクショナリ形式が要求されます。既存の ClaimTypes
はそのまま利用可能。
2. トークン記述子 (SecurityTokenDescriptor) の活用
JwtSecurityToken
コンストラクタの代わりに、SecurityTokenDescriptor
でプロパティベースの設定をします:
- var token = new JwtSecurityToken(issuer, audience, ...);
+ var descriptor = new SecurityTokenDescriptor {
+ Issuer = issuer,
+ Audience = audience,
+ ...
+ };
利点:
設定項目が明確になり、オプションの追加・変更が容易になります。
3. ハンドラー設定 SetDefaultTimesOnTokenCreation
重要な設定オプション:
handler.SetDefaultTimesOnTokenCreation = false;
この設定が必須な理由
デフォルト値 true
の場合:
IssuedAt
(iat) クレームが自動追加NotBefore
(nbf) が現在時刻-5分に設定
false
に設定することで、旧実装との互換性を保ち、明示的に指定した時刻だけを使用します。
4. トークン生成プロセスの統合
最終的な生成プロセスが簡素化:
- var handler = new JwtSecurityTokenHandler();
- var tokenString = handler.WriteToken(token);
+ var tokenString = handler.CreateToken(descriptor);
新旧実装のJWTペイロード比較
新旧で生成されたペイロードの構造は完全に一致:
{
"aud": "MyAudience",
"iss": "MyIssuer",
"exp": 1709078400,
"nbf": 1708992000,
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "Testuser",
"...": "..."
}
{
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "Testuser",
"...": "...",
"nbf": 1708992000,
"exp": 1709078400,
"iss": "MyIssuer",
"aud": "MyAudience"
}
クレーム順序の差異:
JSONのプロパティ順序は仕様上意味を持たないため、実質的に同等です。
実装時の注意点
NuGetパッケージの依存関係
Microsoft.IdentityModel.JsonWebTokens
は独立したパッケージです。互換性のために以下をアンインストール:System.IdentityModel.Tokens.Jwt
時刻設定の検証
有効期限を設定しない場合、Expires
プロパティを明示的にnull
設定:csdescriptor.Expires = null; // 有効期限なし
非対称鍵の使用
RSA鍵などを使う場合も同じパターンで実装可能:csvar rsaKey = new RsaSecurityKey(rsaParameters); var credentials = new SigningCredentials(rsaKey, "RS256");
移行後はパフォーマンス向上と拡張性のメリットを得られます。新しいAPIはトークン処理をより直感的に制御できる設計となっています。