Bola Idor in Aspnet with Bearer Tokens
Bola Idor in Aspnet with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Broken Object Level Authorization (BOLA) occurs when an API fails to enforce authorization checks at the object level, allowing one user to act on another user’s resources. In ASP.NET APIs that rely on Bearer Tokens for authentication, BOLA often arises after authentication succeeds but authorization is incomplete or inconsistent. Bearer Tokens typically identify a user or service account, but they do not inherently encode authorization context such as tenant, role, or resource ownership. If endpoints use the token only to confirm identity and then infer object ownership from path or query parameters (e.g., /users/{id}/profile), an attacker can manipulate those parameters to access objects that belong to other users.
In ASP.NET, this can happen when controllers or minimal APIs resolve the user identity from the token (via User.Identity or claims) but then load domain objects using an identifier supplied by the client without verifying that the authenticated subject owns that object. Consider an endpoint like GET /api/users/{userId}. If the server trusts {userId} directly and does not compare it to the user identifier embedded in the token (such as a claim or a database lookup scoped to the authenticated user), any authenticated user can enumerate or modify other users’ records. This is a classic BOLA flaw: authentication is present, but object-level authorization is missing or bypassed.
Specific patterns that exacerbate BOLA with Bearer Tokens in ASP.NET include:
- Using route values or query strings to reference sensitive objects without validating ownership against the authenticated principal.
- Relying on role claims alone (e.g., Admin) without ensuring data-level checks per resource.
- Assuming tenant or organization context is enforced by middleware when it is actually only implied, allowing horizontal privilege escalation across tenants.
For example, an attacker with a valid Bearer Token could increment {userId} or {orderId} to access other users’ orders or sensitive profiles. Because the API returns data or performs actions without confirming that the token’s subject matches the requested resource’s owner, the server effectively leaks or allows tampering across the application’s object graph. This exposes PII, financial data, or business logic depending on the endpoint. BOLA is distinct from authentication failures; here, the token is valid, but the API does not enforce proper authorization checks at the granular object level.
Bearer Tokens-Specific Remediation in Aspnet — concrete code fixes
Remediation focuses on ensuring that every object-level operation validates the relationship between the authenticated subject (from the Bearer Token) and the target resource. In ASP.NET, this means deriving the user identity from the token and enforcing ownership or role-based checks against the data model before returning or modifying records.
Minimal API with explicit ownership check
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://your-auth-provider";
options.Audience = "api1";
// Ensure token validation is strict
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true
};
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/api/users/{userId}", (HttpContext context, string userId, AppDbContext db) =>
{
var subjectId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(subjectId))
{
return Results.Unauthorized();
}
if (subjectId != userId)
{
return Results.Forbid();
}
var profile = db.Profiles.FirstOrDefault(p => p.UserId == subjectId);
return profile is not null ? Results.Ok(profile) : Results.NotFound();
});
app.Run();
Controller-based approach with policy and service
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IOrderRepository _orders;
public OrdersController(IOrderRepository orders)
{
_orders = orders;
}
[HttpGet("{orderId}")]
public async Task<IActionResult> GetOrder(Guid orderId, CancellationToken ct)
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (userId is null)
{
return Unauthorized();
}
var order = await _orders.GetOrderByIdAsync(orderId, userId, ct);
if (order is null)
{
return NotFound();
}
return Ok(order);
}
}
public class OrderRepository : IOrderRepository
{
private readonly AppDbContext _db;
public OrderRepository(AppDbContext db) => _db = db;
public async Task<Order> GetOrderByIdAsync(Guid orderId, string userId, CancellationToken ct)
{
return await _db.Orders
.FirstOrDefaultAsync(o => o.Id == orderId && o.UserId == userId, ct);
}
}
Key remediation practices
- Always resolve the subject from the Bearer Token (e.g., NameIdentifier claim) and compare it explicitly with the resource’s owning identifier.
- Use parameterized queries or an ORM with parameterized inputs to avoid injection when constructing ownership filters.
- Apply consistent policy checks (e.g., requirements with authorization handlers) so that rules are centralized and less error-prone.
- For tenant-aware applications, include tenant or organization ID in both the token claims and the data model, and validate that the requested resource belongs to the same tenant.
- Avoid exposing raw database identifiers in URLs where possible; consider using opaque identifiers mapped server-side to enforce scoping consistently.
These fixes ensure that even with valid Bearer Tokens, each request enforces object-level authorization, preventing BOLA across authenticated sessions.
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 |