identifyUser
identifyUser is the core building block. Take a RequestLogger and a Better Auth session, extract safe fields, and call log.set(). Returns true if the user was identified, false otherwise.
import { identifyUser } from 'evlog/better-auth'
const session = await auth.api.getSession({ headers: event.headers })
if (session) {
const identified = identifyUser(log, session)
if (identified) {
log.set({ subscription: 'premium' })
}
}
Options
| Option | Type | Default | Description |
|---|---|---|---|
maskEmail | boolean | false | Mask emails as h***@example.com. |
session | boolean | true | Include session metadata (session.id, session.expiresAt, session.ipAddress, session.userAgent). |
fields | string[] | ['id', 'name', 'email', 'image', 'emailVerified', 'createdAt'] | User fields to extract. |
extend | (session) => Record<string, unknown> | undefined | Add custom fields from Better Auth plugins (organizations, roles, etc.). |
identifyUser(log, session, {
maskEmail: true,
fields: ['id', 'name'],
session: false,
})
Mask emails
Emails are PII. In environments where the audit/log trail might be reviewed by support or third parties, mask them:
identifyUser(log, session, { maskEmail: true })
The maskEmail helper is also exported on its own:
import { maskEmail } from 'evlog/better-auth'
maskEmail('hugo@example.com') // 'h***@example.com'
Capture plugin fields
Better Auth ships with plugins (organizations, 2FA, roles, admin) that add fields to the session. Use extend to surface them on the wide event:
import { createAuthMiddleware } from 'evlog/better-auth'
const identify = createAuthMiddleware(auth, {
extend: (session) => ({
organization: session.user.activeOrganization,
role: session.user.role,
}),
})
Wide event with plugin fields:
{
"userId": "QBX9tPjJQExWawAbNll75",
"user": { "id": "QBX9tPjJQExWawAbNll75", "name": "Hugo Richard" },
"organization": { "id": "org_42", "name": "Acme" },
"role": "admin"
}
extend deterministic — it runs on every request. Avoid heavy computations or extra database calls inside it; query the data Better Auth already loaded into the session.Captured fields
| Field | Source | Description |
|---|---|---|
userId | session.user.id | Top-level user ID (used by PostHog adapter as distinct_id). |
user.id | session.user.id | User ID. |
user.name | session.user.name | Display name. |
user.email | session.user.email | Email (maskable with maskEmail: true). |
user.image | session.user.image | Avatar URL. |
user.emailVerified | session.user.emailVerified | Email verification status. |
user.createdAt | session.user.createdAt | Account creation date (ISO string). |
session.id | session.session.id | Session ID. |
session.expiresAt | session.session.expiresAt | Session expiry (ISO string). |
session.ipAddress | session.session.ipAddress | Client IP from the session. |
session.userAgent | session.session.userAgent | User agent string from the session. |
session.createdAt | session.session.createdAt | Session creation date (ISO string). |
auth.resolvedIn | Measured | Session resolution time in ms. |
auth.identified | Computed | Whether the request was identified. |
Overview
Automatically identify users on every request. Every wide event includes who made the request — userId, user profile, and session metadata — with zero manual work.
Middleware
Framework-agnostic factory with route filtering, session timing, and lifecycle hooks. Call it once at startup and reuse across requests.