Insecure Direct Object Reference in Aspnet with Bearer Tokens
Insecure Direct Object Reference in Aspnet with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Insecure Direct Object Reference (BOLA/IDOR) occurs when an API exposes internal object references such as database IDs or sequential keys in requests and relies only on the presence of a Bearer token for authorization. In ASP.NET APIs, this typically manifests as an endpoint like /api/orders/{orderId} that validates the token but does not verify that the authenticated user is allowed to access the specific orderId they provided. An attacker with a valid Bearer token (stolen, leaked, or belonging to a low-privilege account) can increment or manipulate the orderId and access other users' data because the server skips ownership checks.
Bearer tokens in ASP.NET are often handled via authentication middleware that sets User.Identity and adds claims to the current principal. If authorization logic uses only the token’s validity and does not bind the resource to the user (e.g., missing tenant or user identifier checks), the API treats the request as authorized. For example, an endpoint that retrieves a document by ID without confirming the document’s UserId matches the token’s subject enables horizontal IDOR. Vertical privilege escalation can occur if role or claim checks are similarly omitted, allowing a standard user to access admin-only endpoints by changing an ID or a path parameter.
A common vulnerable pattern in ASP.NET Core is relying on route values alone:
// Vulnerable: no check that the retrieved entity belongs to the caller
[Authorize(AuthenticationSchemes = "Bearer")]
[HttpGet("{documentId}")]
public async Task<IActionResult> GetDocument(Guid documentId)
{
var doc = await _context.Documents.FindAsync(documentId);
if (doc == null) return NotFound();
return Ok(doc);
}
An attacker with a valid Bearer token can enumerate documentId values and read documents belonging to other users. OWASP API Top 10 identifies this as BOLA/IDOR, and PCI-DSS, SOC2, HIPAA, and GDPR all require controls ensuring subjects can only access their own resources. Since middleBrick scans test unauthenticated attack surfaces and include Bearer-token scenarios, such endpoints are flagged when resource-level authorization is absent.
SSRF and unsafe consumption risks can compound IDOR when an attacker uses controlled IDs to trigger internal requests or access sensitive files. For instance, if the ID maps to a file path or external service call, manipulating it may lead to data exposure or server-side request forgery. Proper remediation requires tying each resource to the authenticated identity and validating on every request, not just at the gateway.
Bearer Tokens-Specific Remediation in Aspnet — concrete code fixes
Remediation centers on ensuring that every data access operation validates ownership or tenant context derived from the Bearer token’s claims. Do not trust sequential or predictable IDs alone; enforce a rule that the subject of the token must own or be allowed to interact with the requested resource.
1) Include user or tenant identifier in the query and verify it matches the token claims:
// Secure: bind resource to user claim
[Authorize(AuthenticationSchemes = "Bearer")]
[HttpGet("{documentId}")]
public async Task<IActionResult> GetDocument(Guid documentId)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (userId == null) return Unauthorized();
var doc = await _context.Documents
.FirstOrDefaultAsync(d => d.Id == documentId && d.UserId == userId);
if (doc == null) return NotFound();
return Ok(doc);
}
2) Use route or policy-based authorization with requirements that inspect resource ownership:
// Define a requirement that the resource’s UserId matches the token’s subject
public class ResourceOwnershipRequirement : IAuthorizationRequirement
{
public string ResourceIdClaimType { get; set; } = ClaimTypes.NameIdentifier;
}
public class ResourceOwnershipHandler : AuthorizationHandler<ResourceOwnershipRequirement, Document>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ResourceOwnershipRequirement requirement, Document resource)
{
var userId = context.User.FindFirstValue(requirement.ResourceIdClaimType);
if (userId != null && resource.UserId.ToString() == userId)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
// In Startup or Program.cs: services.AddAuthorization(options =>
// {
// options.AddPolicy("IsOwner", policy =>
// policy.Requirements.Add(new ResourceOwnershipRequirement()));
// });
// Usage on endpoint
[Authorize(Policy = "IsOwner", AuthenticationSchemes = "Bearer")]
[HttpGet("{documentId}")]
public async Task<IActionResult> GetDocument(Guid documentId)
{
var doc = await _context.Documents.FindAsync(documentId);
if (doc == null) return NotFound();
return Ok(doc);
}
3) For tenant-aware applications, include a tenant identifier claim and filter by it:
var tenantId = User.FindFirstValue("tenant_id");
var data = await _context.Items
.Where(i => i.TenantId == tenantId && i.Id == resourceId)
.SingleOrDefaultAsync();
4) Avoid exposing sequential keys in URLs where possible; use opaque identifiers (GUIDs or hash IDs) and still validate ownership. Combine with rate limiting to reduce enumeration risk. The GitHub Action can enforce a minimum security score and fail builds if scans detect missing ownership checks, while the dashboard and MCP Server help track and explore these findings during development.
Always pair these fixes with input validation and output encoding appropriate to your data types. These changes ensure that possession checks align with the authentication provided by Bearer tokens, mitigating BOLA/IDOR in ASP.NET APIs.
Related CWEs: bolaAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-250 | Execution with Unnecessary Privileges | HIGH |
| CWE-639 | Insecure Direct Object Reference | CRITICAL |
| CWE-732 | Incorrect Permission Assignment | HIGH |