Securing .NET Applications with JWT Refresh Token Rotation
These articles are AI-generated summaries. Please check the original sources for full details.
JWT Refresh Token Rotation in .NET — Why Your Auth is Probably Broken
Standard JWT implementations often leave accounts vulnerable for up to 7 days if a refresh token is compromised. Token rotation mitigates this risk by revoking and replacing tokens on every use, enabling immediate detection of theft through token lineage tracking.
Why This Matters
In many production environments, developers rely on long-lived static refresh tokens, creating a persistent attack vector. While ideal models assume secure storage, technical reality involves risks like XSS or physical device access; rotating tokens ensures that even if a token is stolen, its utility is limited to a single transaction before triggering an automated security alert that can revoke the entire token family.
Key Insights
- Default ClockSkew in .NET is 5 minutes, which allows expired tokens to remain valid unless explicitly set to TimeSpan.Zero during configuration.
- Token lineage tracking via the ReplacedByToken field creates a chain of custody that identifies compromised token reuse and triggers automated revocation.
- Cryptographically secure token generation using RandomNumberGenerator.GetBytes(64) ensures high entropy for refresh tokens compared to standard GUIDs.
- Short-lived access tokens (15 minutes) minimize the potential damage window if a bearer token is intercepted in transit.
Working Examples
The RefreshToken entity includes a ReplacedByToken field to create a chain for rotation tracking and compromise detection.
public class RefreshToken
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Token { get; set; }
public DateTime ExpiresAt { get; set; }
public bool IsRevoked { get; set; }
public DateTime? RevokedAt { get; set; }
public string? ReplacedByToken { get; set; }
public Guid UserId { get; set; }
public ApplicationUser User { get; set; }
public bool IsExpired => DateTime.UtcNow >= ExpiresAt;
public bool IsActive => !IsRevoked && !IsExpired;
}
Implementation of secure refresh token generation using 64-bit random byte arrays.
public async Task<RefreshToken> GenerateRefreshTokenAsync(
Guid userId, CancellationToken ct = default)
{
var refreshToken = new RefreshToken
{
Token = Convert.ToBase64String(
RandomNumberGenerator.GetBytes(64)),
ExpiresAt = DateTime.UtcNow.AddDays(7),
UserId = userId
};
_context.RefreshTokens.Add(refreshToken);
await _context.SaveChangesAsync(ct);
return refreshToken;
}
Practical Applications
- Use Case: Storing refresh tokens in httpOnly cookies to prevent JavaScript-based XSS attacks that target localStorage.
- Pitfall: Failing to invalidate all refresh tokens upon a password change, which leaves existing sessions active for potential attackers.
- Use Case: Enforcing environment-specific JWT secrets to ensure that a compromise in a development environment does not affect production security.
References:
Continue reading
Next article
LangChain Deep Agents: A Structured Runtime for Multi-Step AI Agent Orchestration
Related Content
Securing Remote Access: A Technical Guide to ssh-keygen
Learn how to use ssh-keygen to implement public-key authentication and secure server access using RSA, ECDSA, and Ed25519 algorithms.
Secure SSH Shell Applications - Planning Guide
Secure SSH apps with restricted shell configs, preventing unauthorized access and escape paths.
Secure Local AI Agents: Mitigating the Risks of Agentic Identity Theft
1Password CTO Nancy Wang discusses securing local AI agents against identity theft and unauthorized tool access as open-source agent adoption surges.