Skip to content

User Impersonation in eQual

The impersonation mechanism in eQual allows an authorized user to temporarily operate as another user. It is intended for administrative, support, debugging, and assistance workflows where a trusted user needs to reproduce or inspect the application from the perspective of another account.

Impersonation does not replace authentication. The authenticated user remains the user identified by the access token, while the application may resolve another user as the effective application user.

Core Concepts

Concept Description
Authenticated user The real user identified by the JWT access token or by Basic Auth.
Resolved user The final user returned by the authentication manager after applying impersonation rules.
Target user The user account selected as impersonation target.
Impersonation permission The right for an authenticated user to use impersonation.
Impersonation state Whether impersonation is currently active for the authenticated user.
Impersonation target The user identifier currently configured as the target.

In normal execution, the authenticated user and the resolved user are identical. When impersonation is allowed, enabled, valid, and linked to an existing target user, the resolved user becomes the target user.

flowchart LR
    A[JWT / Basic Auth] --> B[Authenticated User]
    B --> C{Impersonation allowed?}
    C -- No --> D[Resolved User = Authenticated User]
    C -- Yes --> E{Impersonation enabled?}
    E -- No --> D
    E -- Yes --> F{Valid target user?}
    F -- No --> D
    F -- Yes --> G[Resolved User = Target User]

User Identifiers in AuthenticationManager

The authentication manager distinguishes between the authenticated user and the resolved user.

Method / Property Meaning Applies impersonation?
authenticatedUserId() Returns the authenticated user identifier, before impersonation. No
userId() Returns the final resolved user identifier. Yes
getUserId() Compatibility alias of userId(). Yes
$authenticated_user_id Internal cache for the authenticated user. No
$user_id Internal cache for the resolved user. Yes

The authenticated user is the security reference. It is used to determine whether impersonation is allowed, whether it is active, and which user-scoped impersonation settings must be read.

The resolved user is the identity used by the application once authentication and impersonation resolution are complete.

Impersonation Settings

Impersonation is controlled through user-scoped settings under the core.security.impersonation namespace.

These settings must always be read and written using the authenticated user as context.

Setting Type Scope Meaning
core.security.impersonation.allowed Boolean Authenticated user Indicates whether the authenticated user is allowed to use impersonation.
core.security.impersonation.enabled Boolean Authenticated user Indicates whether impersonation is currently active for the authenticated user.
core.security.impersonation.user_id Integer Authenticated user Stores the target user identifier.
core.security.impersonation.expiry Integer timestamp Authenticated user Stores the expiration timestamp of the active impersonation.

The setting impersonation.allowed represents the permission to use impersonation.

The setting impersonation.enabled represents the active state of impersonation. If it is disabled, no impersonation is applied, even if a target user is configured.

The setting impersonation.user_id defines the target user. If it is empty, zero, invalid, or equal to the authenticated user, no impersonation is applied.

The setting impersonation.expiry defines until when the impersonation remains valid. If it is expired, no impersonation is applied.

Optional Policy Settings

The impersonation model may later be extended with group-based or role-based restrictions.

Setting Meaning
core.security.impersonation.allowed_groups Groups allowed to use impersonation.
core.security.impersonation.allowed_roles Roles allowed to use impersonation.
core.security.impersonation.allowed_target_groups Groups that may be targeted by impersonation.
core.security.impersonation.allowed_target_roles Roles that may be targeted by impersonation.

These settings are optional policy extensions. They can be used to restrict who may impersonate users and which users may be selected as targets.

Authentication and Resolution Flow

When the current user is requested, eQual first retrieves the authenticated user from the access token or Basic Auth. The authenticated user is then validated. Only after this validation does eQual apply impersonation rules.

sequenceDiagram
    participant Client
    participant Auth as AuthenticationManager
    participant Settings as Settings
    participant ORM as ORM / User

    Client->>Auth: userId()
    Auth->>Auth: retrieve access token
    Auth->>Auth: verify token signature / expiry / revocation
    Auth->>ORM: validate authenticated user
    ORM-->>Auth: authenticated user is valid
    Auth->>Settings: read impersonation.allowed for authenticated user
    Settings-->>Auth: allowed
    Auth->>Settings: read impersonation.enabled for authenticated user
    Settings-->>Auth: enabled
    Auth->>Settings: read impersonation.user_id and expiry
    Settings-->>Auth: target user id and expiry
    Auth->>ORM: check target user exists
    ORM-->>Auth: target exists
    Auth-->>Client: resolved user id

The important rule is that the authenticated user must be validated before impersonation is applied. The target user only needs to exist.

This allows an administrator to operate as a user account that is inactive, unvalidated, unconfirmed, or otherwise unable to authenticate.

Resolution Rules

The resolved user is computed from the authenticated user and the impersonation settings.

Condition Result
No authenticated user No resolved user
Authenticated user invalid Authentication fails
impersonation.allowed is false Resolved user = authenticated user
impersonation.enabled is false Resolved user = authenticated user
No target user configured Resolved user = authenticated user
Target user equals authenticated user Resolved user = authenticated user
Impersonation expired Resolved user = authenticated user
Target user does not exist Resolved user = authenticated user
Impersonation is allowed, enabled, not expired, and target exists Resolved user = target user
flowchart TD
    A[Authenticated user] --> B{User active and valid?}
    B -- No --> X[Reject authentication]
    B -- Yes --> C{impersonation.allowed?}
    C -- No --> R1[Return authenticated user]
    C -- Yes --> D{impersonation.enabled?}
    D -- No --> R1
    D -- Yes --> E{target user_id set and exists?}
    E -- No --> R1
    E -- Yes --> F{target != authenticated user?}
    F -- No --> R1
    F -- Yes --> G{expiry valid?}
    G -- No --> R1
    G -- Yes --> R2[Return target user]

Starting Impersonation

A dedicated protected action starts impersonation for the authenticated user.

The action receives a target user identifier and an optional duration. It verifies whether the authenticated user is allowed to impersonate and whether the target user exists.

sequenceDiagram
    participant Client
    participant Action as impersonate action
    participant Auth as AuthenticationManager
    participant Settings as Settings
    participant User as User model

    Client->>Action: request impersonation target id
    Action->>Auth: authenticatedUserId()
    Auth-->>Action: authenticated user id
    Action->>Settings: read impersonation.allowed for authenticated user
    Settings-->>Action: permission value
    Action->>User: check target user exists
    User-->>Action: target exists
    Action->>Settings: set impersonation.enabled = true
    Action->>Settings: set impersonation.user_id
    Action->>Settings: set impersonation.expiry
    Action-->>Client: reset/reload required

Start Preconditions

Check Purpose
Authenticated user exists Ensures the action is executed by a real authenticated user.
Target user id is valid Prevents invalid target identifiers.
Target user differs from authenticated user Avoids meaningless self-impersonation.
impersonation.allowed is true for authenticated user Enforces the permission to use impersonation.
Target user exists Ensures the resolved user can reference a valid account.

The target user is intentionally not required to be active, validated, confirmed, or allowed to authenticate.

Start Effects

Setting Value
core.security.impersonation.enabled true
core.security.impersonation.user_id Target user identifier
core.security.impersonation.expiry Current timestamp + duration

The action should return a response indicating that the client must reload or reset the application state.

Stop Effects

Setting Value
core.security.impersonation.enabled false
core.security.impersonation.user_id 0 or empty
core.security.impersonation.expiry 0 or empty
core.security.impersonation.allowed Unchanged

After stopping impersonation, the client must reload or reset the application state so that user-specific data is recomputed for the authenticated user.

Client-Side Impact

The resolved user affects multiple parts of the application. A partial refresh may leave inconsistent state in the frontend.

When impersonation starts or stops, the frontend should perform a full reload or reset of the application state.

Application area Reason
User information The displayed user context changes.
Menus Available menus may depend on the resolved user.
Permissions Access rights must be recomputed.
Views View availability and behavior may differ per user.
Actions Available actions may depend on permissions.
User settings Settings are commonly resolved for the current resolved user.
Frontend cache Cached state may belong to the previous resolved user.
flowchart LR
    A[Start / Stop Impersonation] --> B[Backend updates settings]
    B --> C[Client receives reset response]
    C --> D[Full reload]
    D --> E[Userinfo reloaded]
    D --> F[Menus reloaded]
    D --> G[Permissions reloaded]
    D --> H[Views and actions reloaded]
    D --> I[User settings reloaded]