Impersonation Audit Trail
1. What does this feature do? (High-Level Overview)
Section titled “1. What does this feature do? (High-Level Overview)”The Impersonation Audit Trail provides comprehensive logging and tracking of all impersonation activities. It records who impersonated whom, when, where, what actions they performed, and maintains a complete audit history for security, compliance, and troubleshooting purposes.
2. Who is this for? (Roles & Permissions)
Section titled “2. Who is this for? (Roles & Permissions)”- Superadmin: Full access to all audit logs and impersonation history.
- Security Auditors: Can review impersonation activities for compliance and security monitoring.
- Compliance Officers: Can access historical records for regulatory compliance.
Note: Audit log access permissions may vary based on organizational security policies.
3. Business Rules & Enforcements
Section titled “3. Business Rules & Enforcements”- Rule 1: All impersonation activities are automatically logged - logging cannot be disabled for impersonation actions.
- Rule 2: Audit logs are immutable - they cannot be edited or deleted through normal application operations.
- Rule 3: Sensitive data (passwords, tokens, API keys) is automatically filtered from audit logs.
- Rule 4: Both the actor (impersonator) and effective user (target) are recorded for every action.
- Rule 5: Audit logs include complete request/response details for troubleshooting.
- Rule 6: Token hashes (not plain tokens) are stored for security.
- Rule 7: Expired impersonation tokens are retained in the database for audit purposes before being cleaned up (default: 7 days after expiration).
4. UI Placement
Section titled “4. UI Placement”API Endpoints (example - actual endpoints may vary):
- Audit logs are stored in the database and can be accessed through administrative tools
- Activity logs visible through activity log viewing interfaces
Database Tables:
impersonation_tokens- Token lifecycle trackingaudit_logs- Detailed request/action loggingactivity_log- Spatie Activity Log entries for token changes
5. How-To Guide (Step-by-Step)
Section titled “5. How-To Guide (Step-by-Step)”Scenario A: Understanding what gets logged
Section titled “Scenario A: Understanding what gets logged”When an impersonation session is created:
The system logs the following information:
In impersonation_tokens table:
token_hash- SHA-256 hash of the JWT tokenimpersonation_id- Unique session identifier (UUID)user_id- Target user being impersonatedcreated_by- Impersonator user IDscopes- Permission scopes for the sessionexpires_at- Token expiration timestampip_address- Client IP addressuser_agent- Client user agent stringcreated_at- Session creation timestamp
In Spatie activity_log table:
- Event type: “created”
- Log name: “impersonation_tokens”
- Subject: ImpersonationToken model
- Causer: Impersonator user
- Description: “Impersonation token created: {impersonator} impersonating {user}”
- Properties: Impersonated user details, creator details, active status
In Laravel logs:
- Level: INFO
- Message: “Impersonation started”
- Context: Impersonator ID/name, target user ID/name, impersonation ID, location ID, IP address, reason
When requests are made with an impersonation token:
The system logs each request in the audit_logs table:
{ "actor_id": 1, // Impersonator user ID "effective_user_id": 123, // Target user ID "impersonation_id": "uuid", // Session identifier "action_type": "view", // view|list|create|update|delete "resource_type": "Client", // Resource being accessed "resource_id": 456, // Specific resource ID "description": "Viewed client details", "request_method": "GET", "request_route": "/api/clients/456", "request_url": "https://api.example.com/api/clients/456", "request_payload": {"..."}, // Filtered request data "response_status": 200, "response_data": {"..."}, // Filtered response (truncated if large) "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0...", "duration_ms": 245, // Request processing time "created_at": "2026-03-31T13:15:00Z"}Usage tracking in impersonation_tokens table:
usage_count- Incremented with each requestlast_used_at- Updated to current timestamp
When a session is stopped or revoked:
In impersonation_tokens table:
revoked_at- Revocation timestamprevoked_by- User who revoked (if external revocation)revoke_reason- Reason for revocation
In Spatie activity_log table:
- Event type: “updated”
- Properties: Shows changes to revoked_at, revoked_by, revoke_reason fields
In Laravel logs:
- Level: INFO (stop) or WARNING (revoke)
- Message: “Impersonation stopped” or “Impersonation revoked”
- Context: Full session details including reason
Scenario B: Retrieving impersonation history for a specific session
Section titled “Scenario B: Retrieving impersonation history for a specific session”Using the Service Layer (for developers):
use App\Services\AuditService;
// Get all audit logs for a specific impersonation session$auditService = app(AuditService::class);$logs = $auditService->getImpersonationLogs($impersonationId);
// Result includes:// - All actions performed during the session// - Actor and effective user for each action// - Request/response details// - Timestamps and durationsScenario C: Retrieving all impersonation activities by an administrator
Section titled “Scenario C: Retrieving all impersonation activities by an administrator”Using the Service Layer (for developers):
// Get all actions performed by a specific impersonator$actorLogs = $auditService->getActorLogs($administratorUserId);
// Get all impersonation sessions where a user was the target$effectiveUserLogs = $auditService->getEffectiveUserLogs($targetUserId);Scenario D: Understanding token lifecycle through audit logs
Section titled “Scenario D: Understanding token lifecycle through audit logs”- Creation: Activity log “created” event + Laravel INFO log
- Usage: Multiple audit_logs entries for each request + usage tracking updates
- Expiration: No explicit log entry, but next validation attempt logs failure
- Revocation: Activity log “updated” event + Laravel WARNING log
- Cleanup: Token deleted from database (after 7 days by default), but audit_logs remain
6. What happens if…? (Edge Cases / FAQ)
Section titled “6. What happens if…? (Edge Cases / FAQ)”-
Q: How long are audit logs retained?
- A:
- Activity logs: Retained indefinitely by default (Spatie Activity Log configuration)
- Audit logs: Retained based on organizational policy (no automatic cleanup)
- Impersonation tokens: Deleted 7 days after expiration (configurable), but audit logs remain
- Laravel logs: Retained according to log rotation configuration
- A:
-
Q: Can audit logs be deleted or modified?
- A: Audit logs are designed to be immutable. Standard application operations do not allow modification or deletion. Only database administrators with direct database access could modify them, which would be a serious security violation.
-
Q: What sensitive data is filtered from audit logs?
- A: The system automatically filters the following keys from request/response data:
- password, password_confirmation
- token, api_token, api_key
- secret, client_secret
- authorization header values
- Any custom sensitive keys configured in
config/impersonation.php
- A: The system automatically filters the following keys from request/response data:
-
Q: What happens to audit logs if a user is deleted?
- A: Audit logs are preserved even after user deletion. The
actor_idandeffective_user_idfields remain, providing historical context even if the user record no longer exists.
- A: Audit logs are preserved even after user deletion. The
-
Q: How can I see what changed during an impersonation session?
- A: Query the
audit_logstable filtering byimpersonation_id. This will show all requests made during that session, including what resources were accessed and what data was modified.
- A: Query the
-
Q: Are read operations (GET requests) logged?
- A: Yes, all requests made with an impersonation token are logged, including read operations. This provides complete visibility into what data was accessed during the session.
Audit Log Structure
Section titled “Audit Log Structure”Impersonation Tokens Table
Section titled “Impersonation Tokens Table”Purpose: Tracks token lifecycle and metadata
| Field | Description |
|---|---|
id | Primary key |
token_hash | SHA-256 hash of JWT (unique) |
impersonation_id | UUID session identifier (unique) |
user_id | Target user ID (FK to users) |
created_by | Impersonator user ID (FK to users) |
scopes | JSON array of permission scopes |
expires_at | Token expiration timestamp |
revoked_at | Revocation timestamp (NULL if active) |
revoked_by | User who revoked (FK to users, NULL if not revoked) |
revoke_reason | Text reason for revocation |
ip_address | Client IP at token creation |
user_agent | Client user agent at creation |
last_used_at | Last usage timestamp |
usage_count | Number of requests made with token |
created_at | Record creation timestamp |
updated_at | Record update timestamp |
Indexes: token_hash, impersonation_id, user_id, created_by, expires_at, revoked_at
Audit Logs Table
Section titled “Audit Logs Table”Purpose: Detailed request-level logging for impersonation sessions
| Field | Description |
|---|---|
id | Primary key |
actor_id | Impersonator user ID |
effective_user_id | Target user ID |
impersonation_id | Session UUID |
action_type | view, list, create, update, delete |
resource_type | Model/resource being accessed |
resource_id | Specific resource identifier |
description | Human-readable action description |
request_method | HTTP method (GET, POST, etc.) |
request_route | Route pattern |
request_url | Full request URL |
request_payload | JSON filtered request data |
request_headers | JSON relevant headers |
response_status | HTTP status code |
response_data | JSON filtered response (truncated if > 10KB) |
ip_address | Client IP address |
user_agent | Client user agent |
duration_ms | Request processing time (milliseconds) |
created_at | Log entry timestamp |
Activity Log Table (Spatie)
Section titled “Activity Log Table (Spatie)”Purpose: Model-level change tracking for impersonation tokens
| Field | Description |
|---|---|
id | Primary key |
log_name | ”impersonation_tokens” |
description | Human-readable description |
subject_type | ”App\Models\ImpersonationToken” |
subject_id | Token ID |
causer_type | ”App\Models\User” |
causer_id | User who caused the change |
properties | JSON metadata (tracked fields, user details, status) |
created_at | Activity timestamp |
Properties JSON structure:
{ "attributes": { "impersonation_id": "uuid", "user_id": 123, "created_by": 1, "scopes": ["impersonation"], "expires_at": "2026-03-31T14:30:00Z", "revoked_at": null, "revoked_by": null, "revoke_reason": null }, "old": {...}, // For updated events "user": { "id": 123, "name": "John Doe", "email": "john.doe@example.com" }, "creator": { "id": 1, "name": "Admin User" }, "status": "active|expired|revoked", "revoked_by_user": {...}, // If revoked "changed_by_admin": true // If changed by admin}Security and Compliance
Section titled “Security and Compliance”Data Protection
Section titled “Data Protection”- Token Security: Only SHA-256 hashes stored, never plain tokens
- Sensitive Data Filtering: Automatic filtering of passwords, tokens, secrets
- Response Truncation: Large responses truncated to prevent log bloat (> 10KB)
- Encryption: Audit logs encrypted at rest (database-level encryption)
Compliance Features
Section titled “Compliance Features”- Immutable Logs: Cannot be modified through application
- Complete Audit Trail: Every action tracked with actor and effective user
- Timestamp Accuracy: All timestamps use server timezone consistently
- User Attribution: Both impersonator and target user recorded
- Reason Tracking: Optional reason field for compliance documentation
Retention and Cleanup
Section titled “Retention and Cleanup”- Impersonation Tokens: Deleted 7 days after expiration (configurable)
- Audit Logs: No automatic cleanup (retain per policy)
- Activity Logs: Retained indefinitely (can be configured)
- Laravel Logs: Rotated according to logging configuration
Monitoring and Alerting
Section titled “Monitoring and Alerting”Consider implementing monitoring for:
- High frequency of impersonation sessions from a single admin
- Impersonation of sensitive user accounts (e.g., other admins)
- Long-duration impersonation sessions
- Impersonation sessions that access sensitive resources
- Failed impersonation attempts
Cleanup Command
Section titled “Cleanup Command”Command: php artisan impersonation:cleanup
Purpose: Delete old expired impersonation tokens to maintain database health
Options:
--days=N- Delete tokens expired for more than N days (default: 7)--force- Skip confirmation prompt
What it does:
- Queries tokens where
expires_at < now() - N days - Deletes matching tokens from database
- Logs deletion count to Laravel log
- Preserves audit logs (audit_logs table) even after token deletion
Recommended Schedule:
// In routes/console.phpSchedule::command('impersonation:cleanup --force') ->daily() ->at('03:00') ->timezone('America/New_York');Example:
# Delete tokens expired for more than 7 daysphp artisan impersonation:cleanup
# Delete tokens expired for more than 30 daysphp artisan impersonation:cleanup --days=30
# Run without confirmationphp artisan impersonation:cleanup --forceBest Practices
Section titled “Best Practices”- Always provide a reason: When starting an impersonation session, include a clear reason for audit purposes
- End sessions promptly: Stop impersonation sessions as soon as the task is complete
- Review audit logs regularly: Monitor impersonation activities for security anomalies
- Use appropriate TTL: Set shorter TTLs for sensitive operations
- Document policy: Establish organizational policies for when impersonation is appropriate
- Train administrators: Ensure admins understand the audit trail and their responsibilities
- Monitor high-risk actions: Flag when impersonation sessions access sensitive data or perform destructive operations
- Implement alerts: Set up notifications for unusual impersonation patterns