0Pricing
C# Academy · レッスン

リフレッシュトークンと有効期限

安全なトークン更新を実装します。

「リフレッシュトークンと有効期限」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

有効期限の問題

有効期間の短いアクセストークンは安全ですが、不便でもあります。15分ごとにユーザーへログインを求めるのは、優れた UX とはいえません。

解決策はリフレッシュトークンです。これは、パスワードを再入力せずに新しいアクセストークンを取得するための、別の有効期間の長い認証情報です。

// access token: 15 minutes
// refresh token: 7-30 days

リフレッシュトークンとは

リフレッシュトークンは通常、不透明なランダム文字列(JWT ではありません)です。有効期間が長いため、失効できるようサーバー側に保存する必要があります。

生成には、暗号学的に安全な乱数生成器を使用してください。

public static string GenerateRefreshToken()
{
    var bytes = new byte[64];
    using var rng = RandomNumberGenerator.Create();
    rng.GetBytes(bytes);
    return Convert.ToBase64String(bytes);
}

リフレッシュトークンの保存

各リフレッシュトークンを、所有者、有効期限、失効フラグとともに永続化します。これにより、ログアウト時や盗難時に無効化できます。

public class RefreshToken
{
    public int Id { get; set; }
    public string Token { get; set; } = default!;
    public int UserId { get; set; }
    public DateTime ExpiresAt { get; set; }
    public bool IsRevoked { get; set; }
}

ログイン時の両方のトークンの発行

ログインが成功したら、有効期間の短いアクセストークンと新しいリフレッシュトークンを返します。リフレッシュトークンはデータベースに保存します。

var access = tokenService.CreateAccessToken(user);
var refresh = new RefreshToken
{
    Token = TokenService.GenerateRefreshToken(),
    UserId = user.Id,
    ExpiresAt = DateTime.UtcNow.AddDays(7)
};
db.RefreshTokens.Add(refresh);
await db.SaveChangesAsync();
return Results.Ok(new { access, refresh = refresh.Token });

リフレッシュエンドポイント

専用の /refresh エンドポイントでリフレッシュトークンを受け取り、有効であればまったく新しいアクセストークンを発行します。

app.MapPost("/refresh", async (RefreshDto dto, AppDb db, TokenService tokens) =>
{
    var stored = await db.RefreshTokens
        .SingleOrDefaultAsync(r => r.Token == dto.RefreshToken);

    if (stored is null || stored.IsRevoked ||
        stored.ExpiresAt < DateTime.UtcNow)
        return Results.Unauthorized();

    var user = await db.Users.FindAsync(stored.UserId);
    var access = tokens.CreateAccessToken(user!);
    return Results.Ok(new { access });
});

リフレッシュトークンのローテーション

ローテーションによってフローを強化できます。リフレッシュトークンが使われるたびにそれを失効させ、新しいトークンを発行します。盗まれたトークンがすでに使用済みであれば、そのトークンは役に立たなくなります。

stored.IsRevoked = true;            // burn the old one
var next = new RefreshToken
{
    Token = TokenService.GenerateRefreshToken(),
    UserId = stored.UserId,
    ExpiresAt = DateTime.UtcNow.AddDays(7)
};
db.RefreshTokens.Add(next);
await db.SaveChangesAsync();

トークンの再利用の検出

ローテーションを使うと盗難を検出できます。すでに失効したトークンが再び提示された場合は、侵害が発生したと判断し、ユーザーのトークンファミリー全体を失効させます。

if (stored.IsRevoked)
{
    // This token was already used - likely stolen.
    await RevokeAllUserTokens(stored.UserId, db);
    return Results.Unauthorized();
}

ログアウトと失効

ログアウトでは、現在のリフレッシュトークンを失効させるだけです。アクセストークンは数分以内に自然に期限切れになります。

app.MapPost("/logout", async (RefreshDto dto, AppDb db) =>
{
    var stored = await db.RefreshTokens
        .SingleOrDefaultAsync(r => r.Token == dto.RefreshToken);
    if (stored is not null) stored.IsRevoked = true;
    await db.SaveChangesAsync();
    return Results.Ok();
}).RequireAuthorization();

クライアントでのトークンの保存場所

ブラウザーでは、JavaScript から読み取れないようHttpOnly、Secure Cookieにリフレッシュトークンを保存するのが最も安全なパターンです。これにより、XSS による盗難を軽減できます。

有効期間の短いアクセストークンはメモリに保持できます。

Response.Cookies.Append("refresh", refresh.Token, new CookieOptions
{
    HttpOnly = true,
    Secure = true,
    SameSite = SameSiteMode.Strict,
    Expires = refresh.ExpiresAt
});

期限切れトークンのクリーンアップ

リフレッシュトークンは蓄積されます。定期的なバックグラウンドジョブ(例: ホステッドサービス)を実行して、期限切れまたは失効したレコードを削除します。

await db.RefreshTokens
    .Where(r => r.ExpiresAt < DateTime.UtcNow || r.IsRevoked)
    .ExecuteDeleteAsync();

有効期間の選択

セキュリティと利便性のバランスを取ります。

  • アクセストークン: 5~15分。漏えいしたトークンの影響を抑えます。
  • リフレッシュトークン: 機密性に応じて、数時間から数週間。
  • 1日を超える場合は、ローテーションを使用します。
AccessTokenLifetime  = TimeSpan.FromMinutes(15);
RefreshTokenLifetime = TimeSpan.FromDays(7);

確認問題

リフレッシュフローについての理解度を確認します。

まとめ

リフレッシュトークンフローを実装しました。

  • 有効期間の短いアクセストークンと、長く不透明でサーバーに保存するリフレッシュトークンを発行します。
  • /refresh エンドポイントで、有効なリフレッシュトークンを新しいアクセストークンと交換します。
  • ローテーションと再利用の検出により、盗難への耐性を高めます。
  • リフレッシュトークンを HttpOnly Cookie に保存し、期限切れのレコードをクリーンアップします。

これで JWT 認証コースは完了です。

よくある質問

「リフレッシュトークンと有効期限」レッスンは無料ですか?

はい。「リフレッシュトークンと有効期限」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「リフレッシュトークンと有効期限」で何を学びますか?

安全なトークン更新を実装します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「リフレッシュトークンと有効期限」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. JWTの構造とクレーム
  2. JWT Bearer認証の設定
  3. トークンの発行
  4. リフレッシュトークンと有効期限
← C# Academyに戻る