JWT とリフレッシュトークンの完全設計テンプレート
安全な認証基盤を構築するための「実務レベルの完全テンプレート」をまとめました。 初心者でも理解できるように、ステップバイステップで構造化しながら、 そのまま業務システムに組み込める形で解説します。
全体像:JWT とリフレッシュトークンの役割
JWT(アクセストークン)
- 有効期限が短い(5〜30分)
- API にアクセスするためのトークン
- 改ざん防止の署名付き
- サーバー側で状態を持たない(ステートレス)
リフレッシュトークン
- 有効期限が長い(数時間〜数日)
- 新しい JWT を発行するためのトークン
- DB に保存して管理する(ステートフル)
- 盗まれた場合のリスクが高いため厳重に扱う
設計ステップ
JWT とリフレッシュトークンの設計は次の 5 ステップで構築します。
- JWT を発行する
- リフレッシュトークンを発行する
- リフレッシュトークンを DB に保存する
- JWT が期限切れのときにリフレッシュトークンで再発行する
- ログアウト時にリフレッシュトークンを無効化する
JWT とリフレッシュトークンのデータモデル
RefreshToken テーブル(例)
| 項目 | 説明 |
|---|---|
| UserId | ユーザー識別子 |
| TokenHash | リフレッシュトークンのハッシュ値 |
| ExpiresAt | 有効期限 |
| CreatedAt | 発行日時 |
| Revoked | 無効化フラグ |
※ リフレッシュトークンは 平文で保存してはいけません。 必ずハッシュ化して保存します。
JWT 発行ユーティリティ(テンプレート)
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
public static class JwtService
{
public static string GenerateAccessToken(string userId, string secretKey, int expireMinutes = 15)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim("userId", userId),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(
issuer: "your-app",
audience: "your-app",
claims: claims,
expires: DateTime.UtcNow.AddMinutes(expireMinutes),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
C#リフレッシュトークン生成ユーティリティ(テンプレート)
using System;
using System.Security.Cryptography;
public static class RefreshTokenService
{
public static string GenerateRefreshToken(int byteLength = 64)
{
byte[] bytes = RandomNumberGenerator.GetBytes(byteLength);
return Convert.ToBase64String(bytes);
}
public static string HashToken(string token)
{
using var sha256 = SHA256.Create();
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(token));
return Convert.ToBase64String(hash);
}
}
C#リフレッシュトークン発行フロー(実務コード例)
string accessToken = JwtService.GenerateAccessToken(user.Id, secretKey);
string refreshToken = RefreshTokenService.GenerateRefreshToken();
string refreshTokenHash = RefreshTokenService.HashToken(refreshToken);
// DB に保存
SaveRefreshToken(user.Id, refreshTokenHash, DateTime.UtcNow.AddDays(7));
C#JWT 検証ユーティリティ(署名検証)
public static ClaimsPrincipal ValidateAccessToken(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
};
return new JwtSecurityTokenHandler().ValidateToken(token, parameters, out _);
}
C#リフレッシュトークンによる再発行フロー(重要)
1. クライアントが「JWT が期限切れ」と判断
2. リフレッシュトークンを送信
3. サーバー側で次を確認
- DB に保存されているハッシュと一致するか
- 有効期限が切れていないか
- 無効化されていないか
4. 新しい JWT とリフレッシュトークンを発行
5. 古いリフレッシュトークンを無効化
再発行処理テンプレート(実務コード)
public TokenResponse Refresh(string refreshToken, string secretKey)
{
string hash = RefreshTokenService.HashToken(refreshToken);
var stored = GetRefreshTokenFromDb(hash);
if (stored == null || stored.Revoked || stored.ExpiresAt < DateTime.UtcNow)
throw new SecurityException("Invalid refresh token");
// 新しいトークン発行
string newAccessToken = JwtService.GenerateAccessToken(stored.UserId, secretKey);
string newRefreshToken = RefreshTokenService.GenerateRefreshToken();
string newRefreshTokenHash = RefreshTokenService.HashToken(newRefreshToken);
// 古いトークンを無効化
RevokeRefreshToken(stored.Id);
// 新しいトークンを保存
SaveRefreshToken(stored.UserId, newRefreshTokenHash, DateTime.UtcNow.AddDays(7));
return new TokenResponse(newAccessToken, newRefreshToken);
}
C#ログアウト処理(リフレッシュトークン無効化)
public void Logout(string refreshToken)
{
string hash = RefreshTokenService.HashToken(refreshToken);
RevokeRefreshTokenByHash(hash);
}
C#セキュリティの深掘りポイント
リフレッシュトークンは必ずハッシュ化して保存する
盗まれた場合のリスクが高いため、 パスワードと同じ扱いをします。
JWT は短命にする
推奨:5〜30分 理由:盗まれても被害を最小化できるため。
リフレッシュトークンは長命にする
推奨:数時間〜数日 理由:ユーザーが頻繁にログインしなくて済むため。
HTTPS は必須
JWT とリフレッシュトークンは平文で送られるため、 HTTPS がないと盗聴されます。
完全設計図まとめ
このテンプレートを使うことで、次の機能が揃います。
- JWT の安全な発行
- JWT の署名検証
- リフレッシュトークンの安全な生成
- リフレッシュトークンのハッシュ化保存
- JWT の再発行
- リフレッシュトークンの無効化
- ログアウト処理
業務システムにそのまま組み込めるレベルの 「完全な認証基盤」が構築できます。
