Letting one person manage tasks on behalf of another can address a real business need, but it should not require sharing passwords or granting general access to an account. In a PHP application, a secure delegation must make clear who is acting, whom they represent, which resources they can act on, and for how long. It must also be revocable and auditable.
The goal is to authorize a specific action while preserving the identities of both people. This requires more than a screen for granting permissions: it affects the data model, every authorization point, asynchronous operations, and tests. Designing these elements together reduces the risk that a valid delegation on one screen becomes excessive access through an alternative route.
Distinguish delegation, impersonation, and shared access

With delegation, the person initiating the operation remains the authenticated identity. The application also records that they are acting on behalf of another person under limited authorization. The represented person has not signed in and must not appear as the direct author of the request.
Impersonation changes the effective identity the system uses to handle a request, and can conceal who performed the action if it is not implemented with specific controls. Shared access, such as handing over credentials, removes the separation between users and makes activities difficult to revoke or attribute. For an ordinary delegation flow, neither approach replaces an explicit context for the actor and represented principal.
Use clear names for both roles in code and logs. For example, actor_id identifies the person who performed the operation, and principal_id identifies the person on whose behalf it was performed. Avoid ambiguous names such as user_id in logs where they could refer to either person.
Define scope, resources, and validity before implementation
A useful delegation describes precisely what it authorizes. “Manage the account” is usually too broad. Instead, it can be limited to actions such as reviewing tasks, updating their status, or responding to a request. If actions have different consequences, model separate permissions rather than grouping reading, editing, approving, and deleting into a generic capability.
Also define the scope of the resources: an organization, a project, a task inbox, or a specific set of records. Permission to edit tasks in one project should not enable reading data from another project just because the same delegated user can access both through another function.
The validity period should have a clear start and end, as well as a status that allows the delegation to be revoked before it expires. Decide which time zone to use when displaying dates, and keep internal comparisons consistent. If policy requires approval or prohibits chained delegations, make that an explicit, testable rule; do not leave it as a UI convention.
Model authorization and check it for every operation
A relational schema can represent a delegation with fields such as an identifier, authorized actor, represented principal, scope, actions, start date, expiration date, status, creator, and revocation date. The exact structure depends on the domain: actions can be stored in a related table or another validated format, but they must be queryable and verifiable without ambiguous interpretation.
Authorization must distinguish the principal’s authority from the authorization delegated to the actor. For the requested operation, check that the represented principal would have ordinary access to the resource and that the applicable business rules allow it. Then verify that the authenticated actor is the recipient of a valid, unrevoked delegation and that it grants the requested action on that resource. Effective permission is limited by the principal’s access and the delegation’s scope: the delegation cannot grant the actor more actions or resources than the principal can authorize, or more than the delegation itself specifies. Do not require the actor to also have their own access to the resource; they may be able to act precisely because of the delegation. Do apply restrictions that relate to the actor’s identity, such as authentication, membership in the required context, or operation-specific security controls.
In practice, the check should include:
- That the actor is authenticated and the delegation is assigned to them.
- That the represented principal is valid in this context and has ordinary access to the requested resource.
- That the delegation is active at the time of the operation, has not been revoked, and is within its validity period.
- That the requested action and resource are within the granted scope, without exceeding the principal’s authority.
- That the business and security restrictions applicable to the actor and operation are met.
Centralize this decision in an authorization service or reusable policy instead of repeating partial conditions in controllers. Even so, invoke it for every relevant operation: a protected view does not automatically protect an API, a download, a bulk action, or an administration route. In PHP, the controller can retrieve the authenticated actor, resolve the delegation context, and ask the service to authorize the action on the specific resource. The domain layer can also enforce critical invariants when an operation has significant consequences.
Do not trust a principal_id sent by the browser as proof of authorization. The server must verify the relationship between actor, principal, delegation, resource, and action using trusted data. Also, do not assume that hiding a button in the UI prevents direct calls to the endpoint.
Preserve attribution in audit logs and asynchronous operations
A useful log makes it possible to reconstruct what happened without confusing identities. For each relevant event, retain the actor, represented principal, action, resource type and identifier, timestamp, outcome, and reference to the delegation applied. Depending on the risk, also record the reason for the operation or a correlation ID. Avoid storing secrets or unnecessary personal data in the history.
Attribution must survive queues and background jobs. If a delegated request schedules a task, the message should carry a verifiable context containing the actor, principal, and authorization reference, rather than relying on the web session, which will no longer be available. When the job runs, decide whether to check again that the delegation is still active. For an action that can still be canceled, checking at execution time usually prevents a revocation from leaving a pending task with stale permission. If the operation has already become irreversible, document that boundary and record when authorization occurred.
Protect logs against unauthorized modification and limit who can view them. Auditing should support investigation and accountability, but must not become an indiscriminate copy of operational data.
Design expiration and revocation into the workflow
Expiration and revocation are not just status changes on a screen. A session that retains a delegation context may continue to show outdated options, so server-side authorization must check the current status on every request, even if the UI is also updated. If permissions are cached, define how they are invalidated and the maximum delay allowed before a revocation takes effect.
When revoking, record who did it and when. Explicitly assess active sessions, issued tokens, queued jobs, and associated temporary links. Do not assume that ending a session or changing a database value automatically invalidates all of these. The appropriate response depends on the design, but it must be defined before the workflow is released.
Test boundaries and commonly overlooked cases
Tests should verify both allowed and denied actions. At a minimum, include a delegation that is not yet valid, has expired, or has been revoked; an actor other than the authorized one; a resource outside the scope; an ungranted action; an incorrect principal or one without ordinary access to the resource; and direct access to endpoints that the UI does not show. Also include a positive case in which the actor has no independent access to the resource, but the principal does and the delegation covers the action and resource. This verifies that the system does not confuse the actor’s own permissions with delegated authority.
Add tests for time boundaries, concurrent changes, and indirect effects. For example, confirm what happens if a delegation is revoked while an operation is in progress or a job is pending, and whether an action on a task triggers notifications, exports, or secondary changes. Verify that these effects preserve the correct attribution and do not expand the scope.
Separate unit tests for the authorization policy from integration tests that exercise routes, persistence, and queues. A test that checks only the decision method does not prove that every route invokes it; a UI test does not demonstrate that the server is protected either.
Pre-release checklist

- Are the actor and represented principal clearly distinguished in code, the UI, and audit logs?
- Does each delegation limit actions, resources, and validity, and are invalid combinations prevented?
- Does the policy check the principal’s access and limit the actor to the delegated scope without requiring the actor’s own access to the resource?
- Does every server-side operation check identity, status, time, scope, and action?
- Does revocation affect sessions, tokens, caches, and pending jobs according to a defined policy?
- Do the logs support attribution without storing unnecessary information?
- Do tests cover denials, time boundaries, valid delegations where the actor has no independent access, and indirect effects?
Delegation is secure when it is not confused with access to someone else’s account and when each action can be justified by the principal’s authority and a valid, limited delegation. If the team cannot precisely answer who acted, on whose behalf, on which resource, and under what permission, the workflow still needs more design before it reaches production.



