Back to blog

Authentication audit logs that help during an incident


An Own Auth audit event identifies a supported security event, its actor, target, organisation context, and server timestamp. The event set includes completed changes as well as selected started and failed flows. It must not copy the credential that authorised the action. Passwords, session tokens, API keys, one-time codes, auth links, Authorization headers, and complete auth request bodies do not belong in the audit store.

Use stable, queryable fields

Stable event names such as session.revoked, member.role_changed, and api_key.created let incident tooling filter behavior without parsing display copy. Each record needs a unique event ID, server-generated timestamp, event type, actor identifiers, target identifiers, and typed metadata. Include organisation, user, session, or API-key record IDs only when they describe the action.

  • Keep an unauthenticated actor null instead of replacing it with a misleading system identity.
  • Resolve client IP addresses through the configured trusted proxy chain.
  • Limit and encode user-agent and request-context fields before display or export.
  • Use a non-secret key prefix or database ID when an event must identify a credential.

Request context is not automatically trustworthy. A forwarded address can be forged when the proxy trust configuration is wrong, and a user-agent string can contain attacker-controlled content. Treat both as bounded evidence rather than authoritative identity. Store times in UTC and keep server clocks synchronized so events from several components can be ordered during an incident.

Record decisions, not raw inputs

Security-relevant records include session creation and revocation, credential changes, recovery completion, email or phone verification, organisation membership changes, invitation changes, and API-key creation or revocation. Store the normalized result and safe identifiers. An internal failure category may support detection, but it should never reproduce the submitted password, token, link, SMS code, or API key.

OWASP specifically recommends excluding session identifiers, access tokens, passwords, database connection strings, encryption keys, and primary secrets. Partial masking is insufficient when the remaining value can still authenticate. Redaction must apply at the application, proxy, error-reporting, and log-export layers because any one of them can otherwise create a second credential archive.

Separate the audit trail from diagnostic telemetry

A diagnostic log explains why code failed. An audit event records a supported security event, including selected starts and failures. They may share transport, but they need separate schemas, access rules, and retention. A stack trace can be restricted to engineers and deleted quickly; an organisation audit event may be visible to authorised administrators for a defined product retention period.

Own Auth audit coverage

Own Auth stores its documented event types with the authentication data. It can include IP address and user agent when the application passes those fields in RequestContext. auth.listAuditEvents requires actorUserId as authorization context and returns the newest events first. Available filters are userId, organisationId, and apiKeyId; the user filter matches events where that user is the actor or target.

Organisation reads require an active membership with view_audit_events. The method does not currently support event-type or date filters, pagination, cursors, limits, or total counts. Application-specific authorization events remain the application's responsibility, so product operations should use the same stable identifier and redaction conventions rather than pretending the package observes data it does not own.

Coverage is operation-specific. Own Auth records oauth.failed, saml.failed, and mfa.challenge_failed, but an invalid email-and-password attempt, permission denial, or expired-session lookup does not create an audit event. With an OpenTelemetry SDK configured, operation errors appear in traces and rate-limit denials increment own_auth.rate_limit.denial.count. Application telemetry can add product-level authorization context that the package does not own.

Retention and access

Audit records remain until the application calls auth.cleanupAuditLogs with an olderThan cutoff. Set that cutoff from incident-response needs, customer commitments, privacy obligations, and storage volume. IP addresses, user agents, and account activity can be personal data, so indefinite retention increases breach impact without automatically improving investigations.

Restrict reads by tenant and job function, prevent ordinary roles from editing records, and protect backups and exports. Where the threat model includes application-database compromise, export events to a separately controlled security system. Preserve which component asserted each field: a record written by a compromised service is evidence, not automatic non-repudiation.

Release verification

Create and revoke an API key, change a member role, accept an invitation, and revoke a session in the release environment. Confirm that each supported event contains the expected actor, target, organisation, identifier, and request context without a credential. Then trigger an invalid password, an OAuth failure, a permission denial, and a rate-limit denial. Verify the documented audit event, trace, metric, or application signal for each path before relying on it during an incident.