fullstackhero/dotnet-starter-kit · error · UnauthorizedException
Session has been revoked.
Error message
Session has been revoked.
What it means
Handle throws UnauthorizedException("Session has been revoked.") when the refresh token itself validates but the associated session fails _sessionService.ValidateSessionAsync (hashed token no longer maps to a live session).
Solutions
- Send the user through fresh login to create a new session
- Don't cache the refresh token beyond the session lifetime
- Check session-store retention/TTL configuration if sessions die too early
Example fix
// before
catch (e) { console.error(e); }
// after
catch (e) {
if (e.message === 'Session has been revoked.') logoutAndRedirectToLogin();
else throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
// nothing callable pre-API; ensure you only refresh while the user is marked 'signed in' client-side if (!store.sessionActive) return; // don't refresh a session you already know is gone
Try / catch
try { return await refreshAsync(token); }
catch (UnauthorizedException e) when (e.Message.Contains("revoked")) { await logout(); redirectToLogin("session-expired"); return null; } Prevention
- Treat session revocation as final — do not retry the refresh
- Clear local auth state as soon as logout/password-change happens
- Monitor session TTL configuration so clients don't outlive their sessions
When it happens
Trigger: User logged out / admin killed the session; session expired server-side while the client still holds a valid refresh token; session store (DB/Redis) entry purged.
Common situations: Password change or 'sign out all devices' invalidating sessions; long-idle client with revoked session; stale cached client retrying after revocation.
Related errors
- Cannot create a ticket without an authenticated reporter.
- Cannot post a comment without an authenticated author.
- Invalid credentials.
- Invalid refresh token.
- no current user
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/e4bc414bfb1967ae.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Tokens/RefreshToken/RefreshTokenCommandHandler.cs:65
// Validate refresh token and rebuild subject + claims
var validated = await _identityService
.ValidateRefreshTokenAsync(request.RefreshToken, cancellationToken);
if (validated is null)
{
await _securityAudit.TokenRevokedAsync("unknown", clientId!, "InvalidRefreshToken", cancellationToken);
throw new UnauthorizedException("Invalid refresh token.");
}
var (subject, claims) = validated.Value;
// Check if the session associated with this refresh token is still valid
var refreshTokenHash = Sha256Short(request.RefreshToken);
var isSessionValid = await _sessionService.ValidateSessionAsync(refreshTokenHash, cancellationToken);
if (!isSessionValid)
{
await _securityAudit.TokenRevokedAsync(subject, clientId!, "SessionRevoked", cancellationToken);
throw new UnauthorizedException("Session has been revoked.");
}
// Optionally, cross-check the provided access token subject
var handler = new JwtSecurityTokenHandler();
JwtSecurityToken? parsedAccessToken = null;
try
{
parsedAccessToken = handler.ReadJwtToken(request.Token);
}
catch (Exception ex)
{
_logger.LogDebug(ex, "Failed to parse access token during refresh; relying on refresh-token validation only");
}
if (parsedAccessToken is not null)
{
var accessTokenSubject = parsedAccessToken.Claims
.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.ValueView on GitHub (pinned to 3f2959e683)