Better Auth

Better Auth Integration

Automatically identify users on every request. Every wide event includes who made the request — userId, user profile, and session metadata — with zero manual work.

evlog/better-auth turns anonymous wide events into identified ones. Every request automatically includes who made it — no manual log.set({ user }) needed.

Prerequisites

Use Better Auth as a direct dependency in your app. evlog does not bundle Better Auth. The integration is tested against Better Auth >=1.6.9 (same major as the playground).

pnpm add better-auth

Add Better Auth user identification

Quick Start

One middleware, all requests identified:

import { createAuthMiddleware } from 'evlog/better-auth'

const identify = createAuthMiddleware(auth, {
  exclude: ['/api/auth/**'],
})

export default defineEventHandler(async (event) => {
  if (!event.context.log) return
  await identify(event.context.log, event.headers, event.path)
})

Your wide event now includes the user:

{
  "level": "info",
  "method": "POST",
  "path": "/api/checkout",
  "status": 200,
  "duration": "120ms",
  "requestId": "a5669202-7765-4f59-b6f0-b9f40ce71599",
  "cart": { "items": 3, "total": 9999 }
}

How It Works

request → wide event·anonymous
request flow
  1. middleware

    route check · skip auth/**

  2. getSession(headers)

    reads cookie · 12ms

    db read · 0ms
  3. identifyUser(log, session)

    safe-fields whitelist

  4. emit wide event

    all fields drained

wide event
$POST/api/checkout200· 120ms
requestId: "a566ef91-…"
cart: { items: 3, total: 9999 }
added by better-auth
userId: "QBX9tPjJQExWawAbNll75"
user.id: "QBX9tPjJQExWawAbNll75"
user.name: "Hugo Richard"
user.email: "hugo@example.com"
session.id: "Xhmh6TxKJQrVKFX0Y0II"
session.expiresAt: "2024-01-22T10:00:00Z"
auth.resolvedIn: 12
auth.identified: true
resolved0ms
fields added0 / 8
manual log.set calls0

The integration resolves the Better Auth session from request cookies, extracts a safe whitelist of user and session fields, sets them on the logger, then fires the onIdentify (or onAnonymous) hook. Auth routes are skipped by default. Resolution timing is captured on auth.resolvedIn, so you can chart auth latency alongside the rest of the wide event.

Where to next

Identify User

The core building block — extract safe fields, mask emails, capture plugin data (organizations, roles, 2FA).

Middleware

Filter routes with include/exclude, react to identification with lifecycle hooks, and tune behaviour per app.

Client Sync

Mirror the user identity into client-side logs with setIdentity and the Better Auth client.

Performance

Watch session resolution time, enable session caching, and combine with the AI SDK integration.

Public API

ExportDescription
identifyUser(log, session)Core helper — extracts safe fields from a session and sets them on the logger. Returns true if identified.
createAuthMiddleware(auth)Returns an async (log, headers, path?) => Promise<boolean> function with route filtering, timing, and hooks.
createAuthIdentifier(auth)Nitro request hook factory for standalone Nitro apps. See Performance.
maskEmail(email)Mask an email: hugo@example.comh***@example.com.