fullstackhero/dotnet-starter-kit · error · UnauthorizedException
authenticated user required to toggle status
Error message
authenticated user required to toggle status
What it means
Thrown by BuildToggleContextAsync when currentUser.GetUserId() returns Guid.Empty, meaning there is no authenticated user on the current request (or the claims principal lacks the id claim). Activating/deactivating users requires knowing the acting user.
Solutions
- Re-authenticate so a valid JWT with the user id claim is attached to the request.
- Check the token's claims include the identifier claim mapped by ICurrentUser.
- Confirm the endpoint is behind [Authorize]/authentication middleware.
- For internal calls, run under an authenticated principal rather than none.
Example fix
// before: request sent without auth header
await apiFetch(`/api/v1/users/${id}/toggle-status`, { method: "POST" });
// after
await apiFetch(`/api/v1/users/${id}/toggle-status`, { method: "POST", headers: authHeader() }); Defensive patterns
Strategy: type-guard
Validate before calling
function hasAuthContext(token) {
const claims = decodeJwt(token);
return Boolean(claims && (claims.sub || claims.uid));
} Type guard
function isAuthed(user) {
return typeof user?.id === "string" && /^[0-9a-fA-F-]{36}$/.test(user.id) && user.id !== "00000000-0000-0000-0000-000000000000";
} Try / catch
try { await toggleStatus(userId); } catch (e) {
if (e.status === 401 && /authenticated user required/i.test(e.message)) { await relogin(); return retry(); }
throw e;
} Prevention
- Ensure all calls carry a fresh Bearer token.
- Keep the user-id claim intact when customizing token issuance.
- Keep endpoints behind [Authorize]; don't call user-status services anonymously.
When it happens
Trigger: User activate/deactivate endpoints called without a valid JWT, or with a token missing the standard name/sub identifier claim the ICurrentUser service maps.
Common situations: Expired or anonymous tokens reaching the endpoint because [Authorize] was bypassed; custom token issuance dropping the uid claim; service-layer calls without an HttpContext user.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/10fe7e8ce8d29ff7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Services/UserStatusService.cs:55
}
private void EnsureValidTenant()
{
if (string.IsNullOrWhiteSpace(multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id))
{
throw new UnauthorizedException("invalid tenant");
}
}
private async Task<ToggleStatusContext> BuildToggleContextAsync(
string userId,
bool activateUser,
CancellationToken cancellationToken)
{
var actorId = currentUser.GetUserId();
if (actorId == Guid.Empty)
{
throw new UnauthorizedException("authenticated user required to toggle status");
}
var actor = await userManager.FindByIdAsync(actorId.ToString())
?? throw new UnauthorizedException("current user not found");
var targetUser = await userManager.Users
.Where(u => u.Id == userId)
.FirstOrDefaultAsync(cancellationToken)
?? throw new NotFoundException("User Not Found.");
return new ToggleStatusContext(
ActorId: actorId,
Actor: actor,
TargetUser: targetUser,
ActivateUser: activateUser,
TenantId: multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id);
}
View on GitHub (pinned to 3f2959e683)