Audit Logs

Track and query authentication events across your application with automatic audit logging.

Better Auth Infrastructure automatically collects audit logs for authentication events in your application. Once you've added the dash() plugin, events are tracked without any additional configuration.

How Audit Logs Are Collected

The dash() plugin hooks into your Better Auth instance and automatically records events as they happen. No manual instrumentation is needed — sign-ups, sign-ins, password changes, and more are all captured.

import { betterAuth } from "better-auth";
import { dash } from "@better-auth/infra";

export const auth = betterAuth({
  plugins: [
    dash(),
  ],
});

That's it. Once dash() is active, audit logs are collected automatically.

Tracked Events

EventTrigger
user_signed_upNew user registration
user_profile_updatedUser updates their profile
user_profile_image_updatedUser changes their avatar
user_email_verifiedEmail verification completed
user_bannedUser is banned
user_unbannedUser is unbanned
user_deletedUser account deleted
EventTrigger
user_signed_inSuccessful sign-in
user_signed_outUser signs out
session_createdNew session created
session_revokedSingle session revoked
sessions_revoked_allAll sessions revoked
user_impersonatedAdmin starts impersonating user
user_impersonation_stoppedAdmin stops impersonating
EventTrigger
account_linkedSocial account linked
account_unlinkedSocial account unlinked
password_changedPassword updated
EventTrigger
password_reset_requestedPassword reset initiated
password_reset_completedPassword reset finished
email_verification_sentVerification email sent

Tracked when using the organization plugin.

EventTrigger
organization_createdNew organization created
organization_updatedOrganization settings changed
member_addedMember added to organization
member_removedMember removed from organization
member_role_updatedMember role changed
member_invitedInvitation sent
invite_acceptedInvitation accepted
invite_rejectedInvitation rejected
invite_cancelledInvitation cancelled
team_createdTeam created
team_updatedTeam updated
team_deletedTeam deleted
team_member_addedMember added to team
team_member_removedMember removed from team

Tracked when using the Sentinel plugin.

EventTrigger
security_blockedRequest was blocked
security_allowedRequest was allowed after challenge
security_credential_stuffingCredential stuffing detected
security_impossible_travelImpossible travel detected
security_geo_blockedGeo-blocking triggered
security_bot_blockedBot detected and blocked
security_suspicious_ipSuspicious IP detected
security_velocity_exceededRate limit exceeded
security_free_trial_abuseFree trial abuse detected
security_compromised_passwordCompromised password detected
security_stale_accountStale account reactivation

Fetching Audit Logs

Client Setup

Add dashClient() to your auth client:

import { createAuthClient } from "better-auth/client";
import { dashClient } from "@better-auth/infra/client";

export const authClient = createAuthClient({
  plugins: [dashClient()],
});

Basic Query

const session = await authClient.getSession();

const logs = await authClient.dash.getAuditLogs({
  session: session.data,
  limit: 50,
  offset: 0,
});

logs.data?.events;  // Array of audit log events
logs.data?.total;   // Total count
logs.data?.limit;   // Page size
logs.data?.offset;  // Current offset

Query Parameters

ParameterTypeDescription
limitnumberResults per page (max 100, default 50)
offsetnumberPagination offset (default 0)
organizationIdstringFilter by organization
identifierstringFilter by identifier
eventTypestringFilter by event type
userIdstringFilter by user ID
userobjectUser object with ID
sessionobjectSession object with user

Filtering

// Filter by event type
const signIns = await authClient.dash.getAuditLogs({
  session,
  eventType: "user_signed_in",
});

// Filter by organization
const orgLogs = await authClient.dash.getAuditLogs({
  session,
  organizationId: "org_123",
});

// Combine filters
const orgSignIns = await authClient.dash.getAuditLogs({
  session,
  organizationId: "org_123",
  eventType: "user_signed_in",
});

Pagination

async function getAllAuditLogs(session: unknown) {
  const limit = 100;
  let offset = 0;
  const allEvents = [];

  while (true) {
    const result = await authClient.dash.getAuditLogs({
      session,
      limit,
      offset,
    });
    
    const events = result.data?.events ?? [];
    allEvents.push(...events);

    if (events.length < limit) break;
    offset += limit;
  }

  return allEvents;
}