fullstackhero/dotnet-starter-kit · error · UnauthorizedException
user is deactivated
Error message
user is deactivated
What it means
ValidateUserStatus throws UnauthorizedException("user is deactivated") when the FshUser's IsActive flag is false. This check runs on credential login, refresh-token validation, and claim building, so a deactivated user cannot obtain or renew tokens.
Solutions
- Re-activate the user (admin endpoint or set IsActive=true on the FshUser row) if deactivation was unintended.
- If deactivation is correct, stop the client from retrying and switch to a valid active account.
- For service accounts, provision an active dedicated user instead of reusing offboarded accounts.
Example fix
// before var user = await db.Users.FirstAsync(u => u.Email == email); // IsActive = false // after (admin reactivation) user.IsActive = true; await db.SaveChangesAsync(ct);
Defensive patterns
Strategy: try-catch
Validate before calling
// if the API exposes a profile/status endpoint, check before retrying auth
const user = await api.get('/api/users/current');
if (user && user.isActive === false) { showDeactivatedScreen(); return; } Type guard
function isActiveUser(u: { isActive: boolean } | null | undefined): u is { isActive: true } {
return u?.isActive === true;
} Try / catch
catch (ApiError e) when (e.StatusCode === 401 && e.Message.includes('deactivated')) {
clearTokens();
showMessage('This account has been deactivated. Contact your administrator.');
} Prevention
- Surface deactivation state in the admin UI so offboarding is visible to integrators.
- Give automated jobs their own active service accounts, not human accounts.
- Notify users/sessions on deactivation instead of letting clients retry blind.
When it happens
Trigger: Login or refresh with credentials of a user whose IsActive column is false — typically after an admin deactivated the user, a DeleteUser soft-delete, or a self-deactivation flow.
Common situations: Offboarding: admin deactivates an account whose session tokens are still in use by a client; automated jobs authenticating with a deactivated service user; a user re-activated but the client still holds tokens issued while deactivated and refreshes fail.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Unauthorized
- refresh token is invalid or expired
- email not confirmed
- tenant is deactivated
- no current user
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/dc601de3381ac8f5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Services/IdentityService.cs:268
}
private void ValidateRefreshTokenExpiry(FshUser user)
{
var now = _timeProvider.GetUtcNow().UtcDateTime;
if (user.RefreshTokenExpiryTime <= now)
{
_logger.LogWarning(
"Refresh token expired for user {UserId}. Expired at: {ExpiryTime}, Current time: {CurrentTime}",
user.Id, user.RefreshTokenExpiryTime, now);
throw new UnauthorizedException("refresh token is invalid or expired");
}
}
private static void ValidateUserStatus(FshUser user)
{
if (!user.IsActive)
{
throw new UnauthorizedException("user is deactivated");
}
if (!user.EmailConfirmed)
{
throw new UnauthorizedException("email not confirmed");
}
}
private void ValidateTenantStatus(AppTenantInfo tenant)
{
if (tenant.Id == MultitenancyConstants.Root.Id)
{
return;
}
if (!tenant.IsActive)
{
throw new UnauthorizedException($"tenant {tenant.Id} is deactivated");View on GitHub (pinned to 3f2959e683)