fullstackhero/dotnet-starter-kit · error · UnauthorizedAccessException
Cannot revoke session for another user
Error message
Cannot revoke session for another user
What it means
RevokeSessionAsync throws UnauthorizedAccessException when the target session's UserId does not match the currently authenticated user. Only the session owner may revoke their own session; revoking others' sessions requires an admin path.
Solutions
- Only revoke sessions listed for the current user (fetch the user's sessions first, then revoke from that list)
- Ensure the auth token belongs to the same user as the session
- Use the admin revocation flow with proper permissions for other users' sessions
Example fix
// before await sessionService.RevokeSessionAsync(sessionIdFromOtherUser, ct); // after var mySessions = await sessionService.GetUserSessionsAsync(currentUser.GetUserId().ToString(), ct); if (mySessions.Any(s => s.Id == sessionId)) await sessionService.RevokeSessionAsync(sessionId, ct);
Defensive patterns
Strategy: validation
Validate before calling
var session = await db.UserSessions.FindAsync(new object[] { sessionId }, ct);
var currentUserId = currentUser.GetUserId().ToString();
if (session is null || !string.Equals(session.UserId, currentUserId, StringComparison.OrdinalIgnoreCase))
return Results.Forbid(); Try / catch
try
{
await sessionService.RevokeSessionAsync(sessionId, ct);
}
catch (UnauthorizedAccessException)
{
return Results.Forbid();
} Prevention
- List the current user's sessions first and revoke only from that list
- Never accept cross-user session ids from client input
- Provide an admin endpoint with permission checks for revoking other users' sessions
When it happens
Trigger: Calling RevokeSessionAsync(sessionId, ...) with a sessionId that belongs to another user (or with a token for a different account than the session owner).
Common situations: Client keeps a device/session list cached across account switches; user copies a session id from an admin tool; session row's UserId differs due to cross-tenant data copy.
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 sessions 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/45b3d97db6f23e79.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Services/SessionService.cs:199
Guid sessionId,
string revokedBy,
string? reason = null,
CancellationToken cancellationToken = default)
{
EnsureValidTenant();
var session = await _db.UserSessions
.FirstOrDefaultAsync(s => s.Id == sessionId && !s.IsRevoked, cancellationToken);
if (session is null)
{
return false;
}
var currentUserId = _currentUser.GetUserId().ToString();
if (!string.Equals(session.UserId, currentUserId, StringComparison.OrdinalIgnoreCase))
{
throw new UnauthorizedAccessException("Cannot revoke session for another user");
}
var tenantId = _multiTenantContextAccessor?.MultiTenantContext?.TenantInfo?.Id;
session.Revoke(revokedBy, reason ?? "User requested", tenantId);
await _db.SaveChangesAsync(cancellationToken);
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Session {SessionId} revoked by {RevokedBy}", sessionId, revokedBy);
}
return true;
}
public async Task<int> RevokeAllSessionsAsync(
string userId,
string revokedBy,View on GitHub (pinned to 3f2959e683)