Interview question
Test a resource ownership boundary
Proves that one authenticated user cannot read or modify another user's private resource.
TL;DR
Proves that one authenticated user cannot read or modify another user's private resource.
Object-level authorization, ownership queries, information disclosure, privileged capabilities, and multi-user test data.
Practice the problem like a real interview: restate, reason, implement, and test.
Seed two users and one private practice record in an isolated test store. The owner can read and update it. An ordinary non-owner receives the product's deliberate denial status. A support user succeeds only with the explicit recovery capability.
Next in API Testing Labs: Validation Contract
User B cannot infer or modify user A's record by changing a route id. The API returns the chosen 404-style concealment response, while audit-worthy support access requires a distinct capability.
I test object authorization through HTTP because route binding, current-user resolution, query filters, and policies all participate. The most important assertion after a denied PUT is that the owner record did not change.
[Fact]
public async Task Non_owner_cannot_read_or_update_private_practice()
{
await using var factory = await ApiTestFactory.CreateWithPracticeAsync(
ownerId: "user-a",
practiceId: PracticeIds.PrivateOne);
var client = factory.CreateAuthenticatedClient("user-b", "practice.write.own");
var read = await client.GetAsync($"/api/practice/{PracticeIds.PrivateOne}");
Assert.Equal(HttpStatusCode.NotFound, read.StatusCode);
var write = await client.PutAsJsonAsync(
$"/api/practice/{PracticeIds.PrivateOne}",
new { Notes = "overwritten" });
Assert.Equal(HttpStatusCode.NotFound, write.StatusCode);
var stored = await factory.ReadPracticeAsync(PracticeIds.PrivateOne);
Assert.NotEqual("overwritten", stored.Notes);
Assert.Equal("user-a", stored.UserId);
}
This test needs isolated multi-user state. An in-memory repository is acceptable for policy orchestration; use a disposable relational database when ownership is enforced by EF filters or query shape that must be verified.
Spot a weak answer, missing edge case, or clearer explanation? Send it in.