Safeguard
Security Guides•

Does the Authorize attribute in ASP.NET Core check the object?

The Authorize attribute and fallback policy check who is calling, not who owns the record. What to look for in a controller review and the resource check.

Safeguard Security Team
4 min read

No. The Authorize attribute and a fallback policy decide whether a caller may reach an endpoint. They do not decide whether this caller may touch this record. For that, ASP.NET Core code needs an explicit resource check, and a reviewer should look for it on every endpoint that takes an id.

What the OWASP guidance says

The OWASP DotNet Security Cheat Sheet says to prefer a fallback policy requiring authentication, and to mark intentionally public endpoints with AllowAnonymous. Two limits follow. The fallback policy covers just the requests that reach the authorization middleware, so static files served earlier are not protected. And named policies do not inherit the fallback policy, so a named policy must include the authentication requirement itself.

On object level permissions the same cheat sheet is direct: use IAuthorizationService.AuthorizeAsync with the resource and the requested operation before returning or changing it, and neither the fallback policy nor an Authorize attribute alone performs this resource check.

A controller that looks fine

[Authorize]
[HttpGet("documents/{id}")]
public async Task<IActionResult> Get(int id)
{
    var doc = await _db.Documents.FindAsync(id);
    return doc is null ? NotFound() : Ok(doc);
}

The attribute stops anonymous callers. It does nothing about a signed-in user changing the id and reading someone else's document. This is the object level authorization gap that OWASP's IDOR guidance describes.

What a fixed version looks like

[Authorize]
[HttpGet("documents/{id}")]
public async Task<IActionResult> Get(int id)
{
    var doc = await _db.Documents.FindAsync(id);
    if (doc is null) return NotFound();

    var result = await _authz.AuthorizeAsync(User, doc, "CanRead");
    return result.Succeeded ? Ok(doc) : Forbid();
}

The CanRead requirement lives in one place and compares the caller with the document. The alternative is scoping the query itself to the caller's records, which has the benefit that an unauthorized id behaves like a missing one.

Reviewer checklist for a controller change

  1. Does every new endpoint either carry a policy or fall under the fallback policy?
  2. Is each public endpoint intentionally marked AllowAnonymous, and is that visible in the diff?
  3. For named policies, does the policy still require an authenticated user?
  4. For any action that takes an id, is there a resource check or an owner scoped query?
  5. Are privileged operations guarded by a role or named policy, not merely by sign-in? The cheat sheet says authentication alone does not grant permission.
  6. Do state changing endpoints that rely on cookies have antiforgery validation? The cheat sheet says to protect them, and warns against adding the ignore attribute merely to make a failing request succeed.
  7. Does a redirect use LocalRedirect or an allowlist, not a raw return URL?

Other flags from the same guidance

  • Raw SQL: prefer parameterised APIs, and never concatenate untrusted values into text passed to FromSqlRaw.
  • Razor: do not bypass encoding with Html.Raw for untrusted content.
  • Serialization: the cheat sheet says not to use BinaryFormatter, because it cannot be made secure.

Testing it

Add the two-user test: create a record as one user, request it as another, expect a refusal. It is a dependable way to prove the check exists, because the code that is missing leaves nothing to read.

Quick check

Does a fallback policy protect every route?

No. It covers requests that reach the authorization middleware. OWASP notes that static files served earlier are not protected by it.

Is returning NotFound better than Forbid?

Either can be correct. Returning NotFound avoids confirming an id exists. Apply the choice consistently.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.