Delegated Administration: The Feature Nobody Scopes Correctly

The request arrives, in every enterprise deal, in almost identical words:

The request arrives, in every enterprise deal, in almost identical words:

"We don't want to file a ticket with you every time someone joins. Our IT team should be able to add users themselves."

The engineering estimate that follows is usually two weeks. An admin flag on the user record, a handful of screens behind it, an invite email. Ship it.

What has actually been agreed to is a second authorization system — with its own permission model, its own scoping rules, its own escalation risks, its own audit trail, and its own set of questions about what happens when the last person holding it leaves. It is not a feature. It's a subsystem, and it's one your existing application RBAC almost certainly cannot express, for a reason that's worth being precise about.

Your application RBAC answers "what may this user do to business objects?" — read invoices, approve expenses, close tickets. Delegated administration answers "what may this user do to the identity system itself, and to which subset of its subjects?" Those are different object graphs. One is about resources; the other is about principals and the policies that govern them. Modelling the second as a role in the first is the original sin from which most of the following problems descend, because a permission like users.write has no way to express "for the 40 people in the Frankfurt office and nobody else."

The scoping question is the whole problem

can_manage_users is not a permission. It's the beginning of a sentence.

Manage which users? Every real enterprise wants a different answer, and every answer is legitimate:

  • All users in the tenant. The simple case, and the only one most implementations support.
  • Users in a department, region, or business unit. The regional IT lead manages the Frankfurt office. Not sales. Not the board.
  • Users below them in the reporting hierarchy. Managers approving their own reports' access, which is what most access-governance processes actually want.
  • Users in a specific subsidiary. A holding company where the subsidiaries are legally distinct, with data-sharing constraints that are contractual rather than preferential.
  • Users, but not administrators. The helpdesk can reset a salesperson's MFA. It must not be able to reset the CFO's.

The last one is the sharp one, and it generalizes into the rule that matters: an administrative scope must be able to exclude principals more privileged than the administrator holding it. A helpdesk role that can reset any user's authentication factors, where "any user" includes the global admin, is a complete privilege-escalation path. Reset the global admin's MFA, enrol your own factor, log in as them. That is one of the most reliably exploitable paths in enterprise identity deployments, and it exists not because anyone decided it was acceptable but because the scope model had no way to say "except those."

So the primitive you need isn't a role. It's a (role, scope) pair, where scope is a predicate over principals — and it needs to support both inclusion and exclusion, because "everyone in EMEA except the executive group" is a requirement you will get.

Attribute predicates are more durable than enumerations here. "Users whose department = engineering" survives people joining and leaving; a hand-picked list of 40 user IDs does not, and it is the version that silently stops being correct. That does mean your scope model depends on the quality of attribute data arriving from HR or SCIM — which is a real dependency, and one worth naming out loud, because the day someone's department is misspelled in the source system, an administrative boundary moves.

The five escalation paths

Each of these has produced real breaches. They share a structure: an administrative capability that appears bounded but composes into unbounded authority.

Granting a role you don't hold. If an admin can grant billing_admin without holding it, they have billing_admin — they can grant it to themselves, or to an account they control. The rule is that the set of roles an administrator may grant must be a subset of the roles they hold, or must be an explicitly enumerated, separately-governed list. The second option is what most large deployments need, because the person who administers access is often deliberately not the person who has it. But then that grantable-set is itself a privileged configuration, and modifying it needs to be a governed operation rather than a dropdown.

Widening your own scope. An admin scoped to Frankfurt who can edit scope assignments can assign themselves EMEA. Scope modification must be a distinct permission from user management, held by a smaller set of people, and — this is the part that gets missed — an administrator must never be able to modify their own scope or role assignment, even if their permission set nominally allows it. Self-modification is a special case that needs its own guard, because it's the one edit where the check "does the actor have permission" returns true for the wrong reason.

Editing the user who administers you. Symmetric to the above. If A can edit B's group memberships, and B's memberships determine B's administrative scope, then A controls B's authority. Administrative relationships form a graph, and permission checks that only look at one edge miss the cycle.

Credential reset as impersonation. Covered above, and worth restating as a design rule: resetting authentication factors is the most powerful thing a helpdesk can do, because it converts "manage a user" into "become a user." Treat it as a distinct, higher-tier permission from ordinary user management, exclude more-privileged targets, and require the reset to notify the target through a channel the resetter cannot control.

Weakening the policy that constrains you. The subtle one, and the subject of the next section.

Configuration authority needs floors, not just switches

Here is the failure that separates platforms that have thought about delegation from those that have added an admin flag.

You give a tenant administrator control over their own security policy — session lifetime, MFA requirement, password rules, allowed authentication methods. This is correct and customers demand it; a bank and a games studio genuinely need different settings, and routing every change through your support queue is the thing you were trying to avoid.

Then a tenant administrator sets session lifetime to 90 days, turns MFA off because a VP complained, and permits password authentication for administrative accounts. Six months later that tenant is breached through a 90-day session on an unprotected admin account, and the incident is, in every way that matters to you — press coverage, contractual liability, the other customers' security teams asking questions — your incident.

The fix is that delegated configuration authority must be bounded, not binary. Every setting a tenant administrator controls needs a permitted range, and the range is set at a level above them:

  • Session lifetime: adjustable between 15 minutes and 12 hours. Not 90 days.
  • MFA: required for administrative roles, non-negotiable. Optional for end users, tenant's choice.
  • Password policy: the tenant may make it stricter than the platform baseline. Never weaker.

The general principle, and it applies to every level of a delegation hierarchy: a delegate may constrain further but never relax. Policy composes by intersection going down the tree. If the platform requires MFA for admins, no tenant can turn it off; if a tenant requires MFA for everyone, no business unit within it can exempt themselves.

This is also where most homegrown implementations discover they've modelled configuration wrongly. A settings table with per-tenant rows can express a value, but it cannot express a permitted range inherited from a parent, intersected with a tenant-level narrowing. You need policy objects with inheritance and a merge rule, and retrofitting that onto a flat settings table after you have four hundred tenants is a migration nobody enjoys. It is worth getting right early, because it's the difference between "our customers configure their own security" being a selling point and it being an unbounded liability.

Transitive delegation, and where to stop

The next request after "let our IT team manage users" is "let our regional leads manage their own regions, without going through central IT." Now you have delegation of delegation, and a set of questions with no default answers:

Can a delegate grant a scope broader than their own? No. Ever. A delegated scope must be a subset of the granting scope, enforced at grant time and re-checked when the parent's scope narrows.

What happens when the parent's scope narrows? This is the question that reveals whether you've modelled delegation or copied it. Central IT scopes a regional lead to EMEA. Later, central IT's own scope is reduced to Germany. Is the regional lead still administering France?

Two defensible answers. Derived scopes re-evaluate against the parent at check time, so narrowing cascades automatically — correct, safe, and it means a scope change can silently strip authority from people who are unaware. Snapshot scopes are copied at grant time and persist independently — predictable, auditable, and it means revoking someone's authority does not revoke what they handed out, which is how orphaned administrative authority accumulates.

Pick one deliberately and document it, because the two behave identically until the day they don't, and that day is usually an offboarding. If you pick snapshots, you need a reconciliation report that surfaces delegations whose granting authority no longer holds the scope — otherwise you're accumulating exactly the invisible privilege the model was supposed to prevent.

How deep can it go? Bound it. Two or three levels covers essentially every real organizational structure, and unbounded depth gives you cycles, performance problems in permission evaluation, and a UI nobody can render. A depth limit is a small, honest constraint that removes a large class of problems.

flowchart TD
    P["Platform<br/><i>sets policy floors</i>"] --> T["Tenant Admin<br/><i>scope: all of tenant</i>"]
    T --> R1["Regional Lead — EMEA<br/><i>⊆ tenant, may not relax policy</i>"]
    T --> R2["Regional Lead — APAC"]
    R1 --> H["Helpdesk — Germany<br/><i>reset factors, excl. admins</i>"]
    T -.->|"cannot grant"| X["Roles the tenant admin<br/>does not hold"]

The operational cases that are always missing from the spec

The last administrator. Can a tenant delete its only admin? Can that admin delete themselves? Both must be blocked, and the check must be atomic — two concurrent deletions each passing a "there is another admin" check will happily leave you with zero. An orphaned tenant with no administrator is a support escalation that requires a privileged out-of-band operation to fix, and the frequency with which this happens in production is much higher than anyone expects: it's usually an offboarding script working exactly as designed.

Support impersonation. Your own support staff will need to act inside a customer tenant, and the honest position is that this is the most sensitive capability in your entire system — it is, by construction, cross-tenant administrative authority. It needs: explicit customer-visible consent or notification, a time-bounded session, an unambiguous audit record with the support engineer's identity as actor and the customer identity as subject, read-only by default with write requiring a second approver, and a distinguishable marker in every event so that "who did this" never resolves to the customer when it was you.

The audit modelling point generalizes: every administrative event needs actor, subject, and on-behalf-of as separate fields. Collapse actor and subject and you cannot answer "did the user change their own email, or did a helpdesk agent change it?" — which is the first question asked in any account-takeover investigation.

Cross-tenant users. A consultant who belongs to three tenants. An administrator in one, an ordinary user in the others. If your permission model resolves roles by user ID rather than by (user, tenant), you have just granted administrative authority in the wrong places. Every administrative check must be tenant-qualified, and the session must carry which tenant context it's operating in.

Invitations as a privilege operation. An invitation is a pre-authorized grant. If a scoped admin can invite a user with a role, then the invitation is a role grant with a delay, and it must be subject to the same subset rule — checked at acceptance time as well as at send time, because the sender's authority may have changed in between. Long-lived invitations are a quiet escalation path: an invite sent by an admin who has since been offboarded should not still confer a role.

Break-glass. When the tenant's SSO is broken and nobody can log in to fix it, someone needs a path in. Design it: a separately-credentialed emergency account, MFA that doesn't depend on the broken component, alerting on every use, and a mandatory post-use review. If you don't design it, it will exist anyway, as a shared password in a document.

Sizing it honestly

If you take one thing from this: when a customer asks for delegated administration, the estimate is not "an admin flag and some screens." The work is a permission model over principals with scope predicates, a policy-inheritance model with floors, a grant-subset rule with self-modification guards, a full administrative audit trail with actor/subject/on-behalf-of, and a set of operational safeguards around last-admin, impersonation, and break-glass.

That's a subsystem. It is also, for what it's worth, one of the highest-leverage subsystems you can build, because it's the difference between your support team being a bottleneck on every customer's routine operations and not being one — and because every enterprise customer will eventually need it, so it is never wasted.

The mistake is not building it. The mistake is building the first version as a boolean and discovering the model you actually needed after four hundred tenants have opinions about it — because by then, the escalation paths above are not design questions. They're findings in someone's penetration test report.