fullstackhero/dotnet-starter-kit · error · UnauthorizedAccessException
Cannot revoke sessions for another user
Error message
Cannot revoke sessions for another user
What it means
RevokeAllSessionsAsync throws UnauthorizedAccessException when the userId argument differs from the authenticated current user (case-insensitive). Bulk revocation is restricted to the session owner; cross-user revocation must go through an admin flow.
Solutions
- Derive userId from the current authenticated principal, not from client input
- If bulk revoking for another user is required, use the admin path with the correct permission
- Re-authenticate as the target user if the intent is to revoke that account's sessions
Example fix
// before await sessionService.RevokeAllSessionsAsync(requestedUserId, null, ct); // after var currentUserId = currentUser.GetUserId().ToString(); await sessionService.RevokeAllSessionsAsync(currentUserId, null, ct);
Defensive patterns
Strategy: validation
Validate before calling
var currentUserId = currentUser.GetUserId().ToString();
if (!string.Equals(userId, currentUserId, StringComparison.OrdinalIgnoreCase))
return Results.Forbid(); Try / catch
try
{
await sessionService.RevokeAllSessionsAsync(userId, exceptSessionId, ct);
}
catch (UnauthorizedAccessException)
{
return Results.Forbid();
} Prevention
- Pass CurrentUser.GetUserId() instead of a client-supplied userId
- Clear cached user state after account switches on shared devices
- Route admin-initiated bulk revocation through a permissioned admin path
When it happens
Trigger: Calling RevokeAllSessionsAsync(otherUserId, exceptSessionId, ...) while authenticated as someone else, commonly after passing a stale or client-controlled userId.
Common situations: Frontend stored the userId from a previous login; shared device where accounts were switched; calling the endpoint with a userId taken from URL parameters.
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
- Cannot revoke session for another user
- Cannot view sessions for another user
- Administrators cannot remove their own admin role.
- invalid tenant
- Only administrators can change user status.
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/e888d31039efa9a0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Services/SessionService.cs:227
_logger.LogInformation("Session {SessionId} revoked by {RevokedBy}", sessionId, revokedBy);
}
return true;
}
public async Task<int> RevokeAllSessionsAsync(
string userId,
string revokedBy,
Guid? exceptSessionId = null,
string? reason = null,
CancellationToken cancellationToken = default)
{
EnsureValidTenant();
var currentUserId = _currentUser.GetUserId().ToString();
if (!string.Equals(userId, currentUserId, StringComparison.OrdinalIgnoreCase))
{
throw new UnauthorizedAccessException("Cannot revoke sessions for another user");
}
var query = _db.UserSessions
.Where(s => s.UserId == userId && !s.IsRevoked);
if (exceptSessionId.HasValue)
{
query = query.Where(s => s.Id != exceptSessionId.Value);
}
var sessions = await query.ToListAsync(cancellationToken);
var tenantId = _multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id;
foreach (var session in sessions)
{
session.Revoke(revokedBy, reason ?? "User requested logout from all devices", tenantId);
}
View on GitHub (pinned to 3f2959e683)