Skip to content

Audit Logging

Bearer automatically logs these events:

  • TokenCreated: When a new token is issued
  • TokenAuthenticated: When a token is used to authenticate a request
  • TokenRevoked: When a token is revoked
  • TokenRotated: When a token is rotated
  • TokenAuthenticationFailed: When authentication fails (expired, revoked, IP blocked, etc.)

No manual intervention needed - just use the package normally:

$token = Bearer::for($user)->issue('sk', 'My Token');
// ^ This automatically logs a TokenCreated event
use Cline\Bearer\Database\Models\TokenAuditLog;
use Cline\Bearer\Enums\AuditEvent;
// Get all audit logs for a token
$logs = $token->accessToken->auditLogs()->get();
// Get logs for specific events
$authLogs = $token->accessToken->auditLogs()
->where('event', AuditEvent::Authenticated->value)
->get();
// Get recent logs
$recentLogs = $token->accessToken->auditLogs()
->where('created_at', '>', now()->subDays(7))
->latest()
->get();
// Get failed authentication attempts
$failedAttempts = TokenAuditLog::query()
->whereIn('event', [
AuditEvent::Failed->value,
AuditEvent::Expired->value,
AuditEvent::IpBlocked->value,
AuditEvent::DomainBlocked->value,
AuditEvent::RateLimited->value,
])
->where('created_at', '>', now()->subHours(24))
->get();

Each audit log contains:

foreach ($logs as $log) {
$log->event; // AuditEvent enum (created, authenticated, revoked, etc.)
$log->ip_address; // IP address of the request
$log->user_agent; // User agent string
$log->metadata; // Additional JSON data
$log->created_at; // Timestamp
}
config/bearer.php
return [
'audit' => [
// Default driver
'driver' => env('BEARER_AUDIT_DRIVER', 'database'),
// Available drivers
'drivers' => [
'database' => [
'class' => DatabaseAuditDriver::class,
'connection' => null, // Uses default database connection
],
'spatie' => [
'class' => SpatieActivityLogDriver::class,
'log_name' => 'bearer', // Spatie activity log name
],
'null' => [
'class' => NullAuditDriver::class, // No-op driver
],
],
// Enable/disable usage logging (every authentication)
'log_usage' => true,
// How long to keep audit logs
'retention_days' => 90,
],
];

If you’re using spatie/laravel-activitylog:

BEARER_AUDIT_DRIVER=spatie

Query logs via Spatie’s API:

use Spatie\Activitylog\Models\Activity;
$activities = Activity::inLog('bearer')
->forSubject($token->accessToken)
->latest()
->get();
use Cline\Bearer\Contracts\AuditDriver;
use Cline\Bearer\Database\Models\PersonalAccessToken;
use Cline\Bearer\Enums\AuditEvent;
use Illuminate\Support\Collection;
class CloudWatchAuditDriver implements AuditDriver
{
public function __construct(
private readonly CloudWatchClient $client,
) {}
public function log(PersonalAccessToken $token, AuditEvent $event, array $context = []): void
{
$this->client->putLogEvents([
'logGroupName' => 'bearer-audit',
'logStreamName' => date('Y-m-d'),
'logEvents' => [
[
'timestamp' => now()->getTimestampMs(),
'message' => json_encode([
'token_id' => $token->id,
'event' => $event->value,
'ip_address' => request()->ip(),
'user_agent' => request()->userAgent(),
'context' => $context,
]),
],
],
]);
}
public function getLogsForToken(PersonalAccessToken $token): Collection
{
// Query CloudWatch logs...
return collect();
}
}

Register in a service provider:

use Cline\Bearer\AuditDrivers\AuditDriverRegistry;
$this->app->make(AuditDriverRegistry::class)
->register('cloudwatch', new CloudWatchAuditDriver($client));

Via Artisan command (schedule this daily):

Terminal window
php artisan bearer:prune-audit-logs --days=90

In app/Console/Kernel.php:

$schedule->command('bearer:prune-audit-logs')->daily();

Or manually:

TokenAuditLog::query()
->where('created_at', '<', now()->subDays(90))
->delete();

For testing or performance, use the null driver:

BEARER_AUDIT_DRIVER=null

Or disable only usage logging (still logs create/revoke/rotate):

config/bearer.php
'audit' => [
'log_usage' => false,
],