skip to content

Access Control Models & Enforcement

Role tables, attribute rules and relation tuples, plus the layer the check runs in and how tenancy cuts across it. Interviewers dig here because a missed check is invisible until someone finds it.

on this pageshow

explore

questions

page 1 of 2

On a claims desk, why must an acting-as session carry both the supervisor acting and the adjuster acted for?

level: juniorimportance: must knowfreq 50%

answer

  1. two principals, not one
  2. who acted versus whose authority
  3. borrowing authority, not becoming someone
  4. actor and subject on every check
  5. the trail must name the supervisor

basics

~20 s

An acting-as session has two principals: the actor doing the work and the subject whose authority is being used. Carry only the subject and every record reads as the adjuster's own work, so nothing shows who really acted.

solid answer

~40 s

Acting as someone is not becoming them. The session has two principals — the **actor**, the supervisor at the keyboard, and the **subject**, the adjuster whose authority is being borrowed — and both belong on the request's principal, in every authorization decision, and on every record the session writes. Mint the supervisor an ordinary session for the adjuster's account and the pair collapses: the trail says the adjuster approved the payout, the adjuster cannot dispute it, and nothing distinguishes a support session from a real sign-in, so rules that should apply only while acting cannot be applied at all. Keeping both principals also keeps the actor's own standing live: suspend the supervisor and the session must end, even though the adjuster's account is perfectly healthy.

code

json · 11 lines
json
{
  "principal": {
    "actingAs": true,
    "actor":   { "id": "supervisor-0082", "territory": "gulf" },
    "subject": { "id": "adjuster-4417",  "territory": "north-coast" },
    "enteredAt": "2026-09-19T09:14:02Z",
    "expiresAt": "2026-09-19T09:44:02Z",
    "reason": "claim file blocked, assigned adjuster on leave",
    "approvedBy": "desk-lead-0031"
  }
}

go deeper

for a junior

Recall that an acting-as session names two people: the one doing the work and the one whose authority is being used. Say both, and say that both are recorded.

for a middle

Explain where the pair travels — on the request's principal, into every authorization decision, onto every record written — rather than being stitched back together from a console log afterwards.

for a senior

Show what a missing actor costs during a review months later: a payout nobody can attribute, an account holder who cannot dispute it, and no way to hold support sessions to rules ordinary sessions do not obey.

for a principal

Argue that the pair is a property of the session itself, not a field some code paths remember to attach. Anything optional on one path will be omitted there, and a trail is worth only what its weakest path records.

## Two principals, not one When a supervisor on an insurance claims desk opens an adjuster's queue "as him" to unblock a claim file, the request carries two identities and only one of them is obvious. - The **subject** is the account whose authority is being borrowed. Here that is the adjuster: his territory and his permissions decide which claim files are even reachable. - The **actor** is the human actually issuing the request. Here that is the supervisor: she is the one who will be asked about it afterwards, and her own authority also bounds what the session may do. An acting-as session *is* that pair. The tempting shortcut is to mint the supervisor an ordinary session for the adjuster's account — a few lines of code, works immediately, and indistinguishable from a real sign-in from that moment on. That indistinguishability is the whole defect. ## What the collapse costs you - **Attribution is gone.** Every row the session touches records the adjuster as the person who touched it. A payout approved during the session is, as far as your system knows, his. - **The account holder cannot dispute anything.** The adjuster has no way to show he was on leave, because the evidence says he was working. - **Acting-as rules become unenforceable.** A shorter lifetime, a refusal to change credentials, a banner on screen — every one of those is a rule about a *kind* of session. You cannot apply a rule to a session you cannot recognise. - **The actor's own standing stops mattering.** Disable the supervisor's account and the minted session keeps working, because nothing in it refers to her. - **The desk cannot be reviewed.** "How many times did support open this claim file, and who did it?" has no answer that a single-principal design can produce. ## Where the pair has to travel It is not enough to note the actor once at the door and move on. The pair rides the whole request: 1. **On the request's principal.** Whatever object your server resolves an incoming request to, it holds two identities and a flag saying this is an acting-as session, not one identity that happens to have been obtained unusually. 2. **Into every authorization decision.** The check takes the actor, the subject, the action and the resource — not just "the current user". This is what later lets the decision differ for an acting-as session. 3. **Onto every record the session writes.** Both the domain row's own last-changed-by field and the trail entry name the pair, so a reader sees "supervisor acting as adjuster", never "adjuster". 4. **Into the interface.** The person acting must be able to see, at any moment, whose account she is inside. Losing track is the ordinary way a well-meaning supervisor does something in someone else's name by accident. ## Reading the trail afterwards | Session shape | What the record says | Who can be held to it | |---|---|---| | One principal, minted as the adjuster | "the adjuster approved the payout" | the adjuster — wrongly | | Two principals, actor and subject | "the supervisor, acting as the adjuster, approved the payout" | the supervisor — correctly | | Actor only, with the adjuster's territory copied across | "the supervisor approved the payout" | the supervisor, but nothing says whose authority was used | The third row is worth dwelling on, because it looks like the safe option. Copying the target's reach onto the acting person's own session keeps attribution honest, but it quietly makes her permanently wider rather than temporarily borrowed, and there is nothing to end, nothing to bound, and no record that a borrowing took place at all. ## Reads count as much as writes The most common support action is looking, and looking is also the most common abuse: a curious employee reading a claim file belonging to someone they know. A trail that names the actor only on writes cannot answer the question that is actually asked after such an incident. Record the pair on reads too. ## Where this stops How the actor travels on an issued credential — there are standardised ways for a token to name an acting party alongside its subject, such as a registered `act` claim — is the credential format's concern, and a separate subject from this one. Likewise, exactly which fields a decision record carries beyond the two principals is its own design question. What belongs here is the rule that governs both: your server never collapses the pair into one identity, at any layer, on any path.

  • The supervisor's own account is suspended while she is acting as an adjuster. What should happen to the session?
    It should end at the next request. The session's power rests on both principals, so the actor's standing is re-read every time, not only at entry. Once her authority is withdrawn there is nothing left for the borrowed half to combine with, and waiting for the session's own expiry leaves a suspended person working inside someone else's account.
  • Does the actor need to be recorded on reads, or only on writes?
    On reads too. Reading someone else's file is the most common support action and the most common abuse, and "who opened this claim file, and when?" is usually the first question asked after a complaint. A trail that names the acting person only when something changed cannot answer it.

A duty manager signing for a delivery in her own name while quoting the shop's account, versus signing the absent cashier's name. Both get the parcel; only one tells you who to ask about it next month.

saying these in an interview costs you the question

  • Acting as a user means becoming that user for a while.
  • Just mint the support agent a session as the customer.
  • The support console's own access log is trail enough.
  • Only writes need the actor recorded; reads are harmless.
  • Once the session starts, the acting person's own account state stops mattering.
open as a page

Why does an authorization check placed only in the HTTP handler miss the nightly job and e-mail intake that also close tickets?

level: juniorimportance: must knowfreq 66%

basics

~20 s

A check in the HTTP handler only runs when a request reaches that handler. A scheduled job, a message consumer or an import script call the ticket-closing code directly, so the guarded path is simply not on their route.

open as a page

A booking service serves many charterers — where does the server get the charterer identifier for a request, and why never from the request body?

level: juniorimportance: must knowfreq 70%

basics

~20 s

The charterer identifier must come from something the caller cannot rewrite: a claim in the verified credential, the hostname the request arrived on, or a header the edge sets and strips. A body field is caller-controlled input.

open as a page

Why does an application store permissions as resource-action strings like establishment:inspect rather than one boolean column per feature?

level: juniorimportance: must knowfreq 72%

basics

~20 s

A permission string names one resource and one action together: establishment:inspect is the inspect action on establishment records. Keeping permissions as rows makes capability data rather than schema, so adding one is an insert instead of a new column and a deployment.

open as a page

In relationship-based access control, what does one relation tuple `object#relation@subject` record, and what replaces a role column?

level: juniorimportance: must knowfreq 45%

basics

~20 s

A relation tuple records one fact — this subject holds this relation on this object, written object#relation@subject. Permission becomes the set of stored tuples plus the schema's rules about which relations imply which, instead of a role value stored on the user row.

open as a page

Why can an endpoint test suite pass every case and still miss that one user reads another user's records?

level: juniorimportance: must knowfreq 62%

basics

~20 s

A suite that authenticates as the record's owner only ever exercises the allow path. Catching a cross-user read needs a second principal in the fixtures, holding the same role in a different scope, and an explicit assertion that their request is refused.

open as a page

Your authorization rule reads a researcher's affiliation, an animal's embargo date and the wall clock — where must each value come from?

level: middleimportance: must knowfreq 58%

basics

~20 s

The affiliation from the verified credential or a live store, the embargo date from the record the response is built from, the instant from the evaluating server's clock. Nothing the rule believes about the caller may come from the caller's own request.

open as a page

How should an acting-as session's authority be bounded when a supervisor works an adjuster's claim queue?

level: middleimportance: must knowfreq 44%

basics

~20 s

Give the session the intersection of the acted-for account's authority and the acting person's own — never the union — and subtract a denylist of account-takeover actions: credential changes, second-factor enrolment, recovery-address changes, role grants and bulk export.

open as a page

Which class of authorization rule belongs at the edge, which in the service, and which where the ticket is loaded?

level: middleimportance: must knowfreq 74%

basics

~20 s

Coarse route admission belongs at the edge, which knows the caller but not the ticket. Operation-level authority belongs in the service operation. A rule that depends on the ticket's own building can only be evaluated where that ticket is loaded.

open as a page

Why must a field-level permission name an action, not just a field, for a role that may read what it cannot change?

level: middleimportance: must knowfreq 55%

basics

~20 s

Read and write rights over the same field are independent. A pastoral lead may read a pupil's predicted grade while only the class teacher may set it, so the unit of a field-level rule is the field and the action together.

open as a page

A matters listing must hide matters walled off by a separate permissions store — how do you build page seven?

level: middleimportance: must knowfreq 55%

basics

~20 s

Get the permission predicate and the rows into the same place. Either fetch the permitted identifiers and push them into the query, or replicate the permission data beside the matters, or batch-check a candidate page in one call.

open as a page

Your booking service derives the charterer at the edge — how do you make that value reach every layer, including cache keys and log fields?

level: middleimportance: must knowfreq 58%

basics

~10 s

Bind the derived charterer once to a request-scoped context any layer can read without being passed it, immutable for the request, cleared when it ends, and required in every cache key and log field.

open as a page

In a food-safety inspectorate, which tables and indexes let an inspector hold a supervisor role in one district only?

level: middleimportance: must knowfreq 78%

basics

~20 s

Three definition tables — role, permission, role_permission — plus a grant table joining a principal to a role with the district on the grant row itself. The hot check reads grants by principal and district, so that pair is the composite index it needs.

open as a page

How do userset rewrites let a relation-tuple store grant every component of an airframe to its inspectors without one tuple per component?

level: middleimportance: must knowfreq 40%

basics

~20 s

The schema declares a component's signoff relation as the inspector relation of the airframe its own tuple names. Derived grants are computed during the check, so fitting or moving a component costs one tuple write.

open as a page

Your service deletes a sign-off tuple then re-checks; how do you choose between demanding your own write is visible and taking a cheaper possibly-stale read?

level: seniorimportance: must knowfreq 35%

basics

~20 s

A tuple write returns a consistency token naming the version it landed at; pass it back to demand a snapshot at least that fresh. Stale grants self-heal, stale revocations allow silently, so revocation paths carry it.

open as a page

A request-time authorization rule permits reading an animal's precise collar coordinates only after its embargo date passes — which inputs does the evaluator need?

level: juniorimportance: should knowfreq 52%

basics

~20 s

Four groups of named values: the subject (who is asking, and their affiliations), the resource (the animal record, including its embargo date), the action (read precise coordinates), and the environment (the current instant). Most rules read two of the four.

open as a page

What can a relation-tuple store's expand call answer that its check call cannot, and when do you need it?

level: middleimportance: should knowfreq 32%

basics

~20 s

Check answers one boolean for a subject, object and relation, and says nothing about why. Expand takes no subject and returns the rule tree — unions, rewrite hops, userset leaves — so a human can justify a grant.

open as a page

What must an authorization decision record contain so a disputed read can still be explained eighteen months later?

level: middleimportance: should knowfreq 48%

basics

~20 s

A usable record lets a reader recompute the verdict rather than merely read it: subject, the acting principal when it differs, resource identity, action, verdict, the rule or grant that fired, that rule set's version, the inputs it turned on, and the request correlation identifier.

open as a page

Your service caches authorization decisions to cut per-request evaluation cost — what must the cache key contain, and what does the TTL cost you?

level: seniorimportance: should knowfreq 45%

basics

~20 s

The key must carry every input the rule read — caller identity, action, resource identity and version, and the rule-set version — or entries collide. The TTL is the worst-case lag on a revocation: a cached allow keeps answering until it expires.

open as a page

A supervisor's acting-as session on an adjuster's queue has run for three days; what should entry, lifetime and exit have enforced?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Entry should have required a recorded reason and an approval, the session should have carried a short absolute lifetime that activity cannot extend, and exit should be explicit, visible throughout, and shared with the expiry path so in-flight work lands the same way either way.

open as a page

When is a declarative authorization marker the right choice, and which rules must be an explicit call inside the operation?

level: seniorimportance: should knowfreq 56%

basics

~20 s

Declare rules that need only the principal and the operation name, on entry points that always cross the interception boundary. Write an explicit call for any rule needing the loaded record, and for code reachable from a job, a consumer or another method.

open as a page

In a field-level read denial, what does omitting the field, returning it masked, or refusing the whole response each tell the caller?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Each shape leaks a different amount. Omission is the quietest, a masked placeholder confirms the field exists and holds content, and refusing the whole response confirms the same while also denying the caller data they are entitled to read.

open as a page

A lawyer pages through matters while ethical walls open and close mid-walk — what should the cursor and the total do?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Page by position, not by count: a keyset cursor naming the sort key and identifier of the last row survives a set that moves, while an offset skips and repeats rows. Offer a total only after the permission predicate, or not at all.

open as a page

A scheduled job and a retried queue message run with no charterer bound in the request context — what must happen, and why is 'all charterers' the dangerous default?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Unbound must mean refuse, not proceed. A data-access layer that drops the charterer predicate when nothing is bound returns every charterer's rows, so make the read raise; background work binds a charterer explicitly, per message, and clears it afterwards.

open as a page

Your role-administration endpoint lets a district supervisor grant roles to inspectors — what must it refuse, and what happens when it does not?

level: seniorimportance: should knowfreq 54%

basics

~20 s

It must refuse any grant whose permissions exceed the granter's own effective set, and any grant outside the unit the granter administers. Without both bounds, a district supervisor can hand themselves or a colleague a role carrying more than they hold, and walk up to service-wide in a step or two.

open as a page

A sign-off check on a deeply nested component reaches 300 ms at p99; what in a relation-tuple check causes that, and how do you bound it?

level: seniorimportance: should knowfreq 30%

basics

~20 s

A check expands rules against stored tuples: each level adds sequential lookups and each hop multiplies, so the cost is round trips. Bound it with a declared maximum depth, flatter chains, and wide relations reached in one hop.

open as a page

Your authorization log records only denials to keep volume down — what does that cost you when an access is later disputed?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Denials are the system working; the event a dispute is about is an access that was wrongly allowed, and a deny-only log has no record of it. The fix is not logging every allow, but recording every deny plus the allows that are not routine.

open as a page

Every request for precise collar coordinates needs an authorization decision within a few milliseconds — do you embed the evaluator, run it beside the service, or call a shared decision service?

level: principalimportance: should knowfreq 42%

basics

~20 s

Embed for latency and blast radius, run a co-located process for language independence, call a shared service only where central control outweighs a network hop on every request. A remote evaluator makes its availability a hard dependency of every guarded request.

open as a page

Your platform wants every authorization decision made at the API gateway so services stay simple - what do you accept, and which rule would you still enforce inside each service?

level: principalimportance: should knowfreq 47%

basics

~20 s

Accepting gateway-only authorization makes the network the trust boundary: anything reaching a service by another path is unguarded. Keep coarse admission at the gateway for cheap refusal and blast-radius control, and keep the operation-level and object-level rules inside each service.

open as a page

How do you keep per-field rules reviewable as a pupil record grows from twelve fields to two hundred?

level: principalimportance: should knowfreq 36%

basics

~20 s

Attach rules to a small set of named sensitivity classes rather than to individual fields. Each field is assigned to exactly one class, so adding a field becomes a classification decision reviewed once instead of a new rule per role.

open as a page

showing 1–30 of 34