{"record":{"id":"dc601de3381ac8f5","repo":"fullstackhero/dotnet-starter-kit","slug":"user-is-deactivated","errorCode":null,"errorMessage":"user is deactivated","messagePattern":"user is deactivated","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Services/IdentityService.cs","lineNumber":268,"sourceCode":"    }\n\n    private void ValidateRefreshTokenExpiry(FshUser user)\n    {\n        var now = _timeProvider.GetUtcNow().UtcDateTime;\n        if (user.RefreshTokenExpiryTime <= now)\n        {\n            _logger.LogWarning(\n                \"Refresh token expired for user {UserId}. Expired at: {ExpiryTime}, Current time: {CurrentTime}\",\n                user.Id, user.RefreshTokenExpiryTime, now);\n            throw new UnauthorizedException(\"refresh token is invalid or expired\");\n        }\n    }\n\n    private static void ValidateUserStatus(FshUser user)\n    {\n        if (!user.IsActive)\n        {\n            throw new UnauthorizedException(\"user is deactivated\");\n        }\n\n        if (!user.EmailConfirmed)\n        {\n            throw new UnauthorizedException(\"email not confirmed\");\n        }\n    }\n\n    private void ValidateTenantStatus(AppTenantInfo tenant)\n    {\n        if (tenant.Id == MultitenancyConstants.Root.Id)\n        {\n            return;\n        }\n\n        if (!tenant.IsActive)\n        {\n            throw new UnauthorizedException($\"tenant {tenant.Id} is deactivated\");","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Services/IdentityService.cs#L250-L286","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar user = await db.Users.FirstAsync(u => u.Email == email); // IsActive = false\n// after (admin reactivation)\nuser.IsActive = true; await db.SaveChangesAsync(ct);","handlingStrategy":"try-catch","validationCode":"// if the API exposes a profile/status endpoint, check before retrying auth\nconst user = await api.get('/api/users/current');\nif (user && user.isActive === false) { showDeactivatedScreen(); return; }","typeGuard":"function isActiveUser(u: { isActive: boolean } | null | undefined): u is { isActive: true } {\n  return u?.isActive === true;\n}","tryCatchPattern":"catch (ApiError e) when (e.StatusCode === 401 && e.Message.includes('deactivated')) {\n  clearTokens();\n  showMessage('This account has been deactivated. Contact your administrator.');\n}","preventionTips":["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."],"tags":["auth","user-deactivated","http-401"],"backgroundTag":"permission-denied","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}