Skip to contentSkip to navigation

Audit Logs

Audit logs record who performed an authentication action, who or what it affected, when it happened, and the available request context. Own Auth writes these events automatically as part of each supported operation.

Recorded events

EventRecorded when
user.signed_upA user signs up or is created through an external provider.
user.signed_inA user signs in with a password, magic link, phone code, OAuth provider, verified external identity, or passkey.
user.signed_outA user signs out with a session token.
user.disabledA user account is disabled.
user.re_enabledA disabled account is enabled again.
external_provider.linkedA provider account is linked to a user.
external_provider.unlinkedA provider account is unlinked from a user.
oauth.startedRedirect OAuth or Google One Tap starts.
oauth.signed_inOAuth or Google One Tap resolves an identity and completes its first factor.
oauth.failedAn OAuth callback or One Tap verification fails.
oauth.credential_storedAn encrypted provider refresh credential is stored.
oauth.credential_refreshedA provider access token is refreshed server-side.
oauth.credential_revokedProvider offline access is revoked and the local credential is deleted.
saml.connection_createdAn organisation owner creates a SAML connection.
saml.connection_updatedAn organisation owner changes a SAML connection.
saml.connection_disabledAn organisation owner disables a SAML connection.
saml.connection_enabledAn organisation owner enables a SAML connection.
saml.startedSAML sign-in or identity linking starts.
saml.signed_inA SAML response resolves an identity and completes its first factor.
saml.failedA SAML response fails protocol, identity, or membership validation.
saml.identity_linkedA SAML identity is linked to a user.
saml.identity_unlinkedA SAML identity is unlinked from a user.
saml.member_provisionedSAML JIT provisioning creates an organisation membership.
scim.connection_createdAn organisation owner creates a SCIM connection.
scim.connection_updatedAn organisation owner changes a SCIM connection.
scim.connection_disabledAn organisation owner disables a SCIM connection.
scim.connection_enabledAn organisation owner enables a SCIM connection.
scim.token_createdAn organisation owner creates a SCIM bearer token.
scim.token_revokedAn organisation owner revokes a SCIM bearer token.
scim.user_createdSCIM creates an organisation-scoped user resource.
scim.user_linkedA SCIM resource deliberately or automatically links to an existing user.
scim.user_updatedSCIM changes supported User attributes.
scim.user_suspendedSCIM sets a User resource inactive and suspends its membership.
scim.user_reactivatedSCIM reactivates a suspended membership.
scim.user_deletedSCIM removes organisation access and creates a tombstone.
scim.user_restoredAn organisation owner explicitly restores a tombstoned SCIM resource.
authorization_server.client_createdAn OAuth client is registered.
authorization_server.client_updatedAn OAuth client's safe configuration changes.
authorization_server.client_secret_rotatedA confidential client receives a replacement secret.
authorization_server.client_revokedA client and its grants are revoked.
authorization_server.authorization_startedAn authorization request starts.
authorization_server.authorization_approvedA user approves an authorization request.
authorization_server.authorization_deniedA user denies an authorization request.
authorization_server.code_exchangedA single-use authorization code is exchanged.
authorization_server.token_refreshedA refresh token rotates successfully.
authorization_server.token_revokedA client revokes one of its tokens.
authorization_server.refresh_reuse_detectedA consumed refresh token is presented again.
authorization_server.grant_revokedAn authorization grant is revoked by the user, client, or reuse detection.
mfa.totp_enrollment_startedTOTP enrollment starts.
mfa.totp_enabledA TOTP factor is confirmed and enabled.
mfa.totp_disabledA TOTP factor is disabled.
mfa.challenge_succeededA pending MFA challenge is completed.
mfa.challenge_failedAn MFA verification attempt fails.
mfa.recovery_code_usedA recovery code is consumed.
mfa.recovery_codes_regeneratedRecovery codes are replaced.
session.elevatedMFA creates an aal2 session.
passkey.registeredA passkey is registered.
passkey.authenticatedA passkey completes primary sign-in or MFA.
passkey.renamedA passkey is renamed.
passkey.revokedA passkey is revoked.
session.createdA session is created.
session.revokedOne session is revoked during signout or from a session list.
session.revoked_otherEvery session except the current one is revoked.
session.revoked_allEvery session for a user is revoked.
magic_link.requestedA magic-link email is requested.
magic_link.usedA magic link is consumed to sign in.
email_verification.requestedAn email-verification link is requested.
email.verifiedAn email-verification link is consumed.
sms_otp.sentAn SMS code is sent.
sms_otp.verifiedAn SMS code is verified.
phone.verifiedA user's phone number is marked as verified.
password_reset.requestedA password-reset link is requested.
password.changedA password is changed or reset.
api_key.createdAn application API key is created.
api_key.usedAn application API key authenticates a request.
api_key.revokedAn application API key is revoked.
organisation.createdAn organisation is created.
organisation.deletedAn organisation is permanently deleted by its owner.
organisation.updatedAn organisation is updated.
member.invitedAn organisation invitation is created.
invite.acceptedAn organisation invitation is accepted.
invite.revokedAn organisation invitation is revoked.
member.removedA member is removed from an organisation.
member.role_changedA member's organisation role is changed.
plugin.{plugin-id}.{event}A configured plugin writes one of its declared audit events.

Own Auth does not currently write events when sessions merely expire or when a rate limit rejects a request.

Audit event fields

Each AuditEvent contains:

FieldDescription
idUnique event ID.
eventTypeOne of the recorded event names above.
actorUserIdThe user who performed the action, when known.
targetUserIdThe user affected by the action, when known.
organisationIdThe related organisation, when applicable.
apiKeyIdThe related API-key record, when applicable.
ipAddressRequest IP address when supplied through request.
userAgentUser-Agent value when supplied through request.
metadataEvent-specific structured data.
createdAtThe time the event was written.

Query audit logs

Use listAuditEvents. Results are returned as an array with the newest events first.

ts
const events = await auth.listAuditEvents({
  actorUserId: currentUser.id,
});

Filter by API key:

ts
const events = await auth.listAuditEvents({
  actorUserId: currentUser.id,
  apiKeyId,
});

Filters can be combined:

ts
const events = await auth.listAuditEvents({
  userId,
  organisationId,
  apiKeyId,
  actorUserId: currentUser.id,
});

actorUserId is required. The available filters are userId, organisationId, and apiKeyId. A user filter matches events where that user is either the actor or the target. Without an organisation filter, users can read only their own events.

listAuditEvents does not currently support event-type filters, date ranges, limits, offsets, cursors, or total counts.

Response

ts
const [event] = await auth.listAuditEvents({
  actorUserId: currentUser.id,
});

// event -> {
//   id: "evt_...",
//   eventType: "session.created",
//   actorUserId: "usr_...",
//   targetUserId: "usr_...",
//   organisationId: null,
//   apiKeyId: null,
//   ipAddress: "203.0.113.42",
//   userAgent: "Mozilla/5.0...",
//   metadata: { sessionId: "ses_..." },
//   createdAt: Date,
// }

Organisation audit logs

Pass the signed-in user as the actor when loading organisation events:

ts
const events = await auth.listAuditEvents({
  organisationId,
  actorUserId: currentUser.id,
});

Own Auth checks the actor's active membership and view_audit_events permission before returning organisation events.

Request context

Pass request context to auth methods when the audit trail should include an IP address and user agent:

ts
await auth.signInEmailPassword({
  email,
  password,
  request: {
    ipAddress: req.ip,
    userAgent: req.headers["user-agent"],
  },
});

When request context is omitted, ipAddress and userAgent are stored as null.

Event metadata

Metadata depends on the event:

EventExample metadata
session.created{ sessionId: "ses_..." }
session.revoked{ reason: "user_logout" } or { reason: "user_revoked", sessionId: "ses_..." }
session.revoked_all{ reason: "password_reset", revoked: 3 }
user.signed_in{ method: "magic_link" } or { method: "phone_otp" } when applicable
external_provider.linked{ provider: "google" }
oauth.started{ provider: "google", intent: "sign_in", mode: "popup" }
oauth.signed_in{ provider: "google", mode: "redirect" }
saml.started{ connectionId: "samlc_...", intent: "sign_in" }
saml.failed{ connectionId: "samlc_...", error: "saml_response_invalid" }
saml.member_provisioned{ connectionId: "samlc_...", role: "member" }
scim.user_created{ connectionId: "scimc_...", scimUserId: "scimu_..." }
scim.user_updated{ connectionId: "scimc_...", scimUserId: "scimu_...", fields: ["displayName"] }
scim.user_deleted{ connectionId: "scimc_...", scimUserId: "scimu_..." }
mfa.challenge_succeeded{ method: "totp" }
session.elevated{ assuranceLevel: "aal2", method: "passkey" }
passkey.registered{ passkeyId: "psk_...", discoverable: true }
sms_otp.sent{ purpose: "phone_login", otpId: "otp_..." }
api_key.created{ name: "Production", scopes: ["reports:read"] }
api_key.used{ requiredScopes: ["reports:read"] }
organisation.created{ name: "Acme", slug: "acme" }
organisation.deleted{ organisationId: "org_...", name: "Acme", slug: "acme", membersRemoved: 3, apiKeysRemoved: 2, invitationsRemoved: 1 }
member.invited{ email: "bob@example.com", role: "member", invitationId: "inv_..." }
member.role_changed{ previousRole: "member", role: "owner", ownershipTransferredTo: null }
member.removed{ memberId: "mem_...", role: "owner", ownershipTransferredTo: "usr_..." }

Secret handling

Audit events do not contain raw OAuth state, One Tap nonces, provider credentials, access or refresh tokens, session tokens, MFA challenge tokens, TOTP secrets, recovery codes, SMS codes, passkey responses, WebAuthn challenges, SAML responses, assertions, subjects, request IDs, relay state, certificates, signing keys, or raw SCIM bearer tokens. Plugin after-hooks receive secret-redacted results, and plugin audit metadata must also exclude secrets.

Retention

Audit events remain in own_auth_audit_events until they are removed. Own Auth does not delete them automatically.

Delete events older than a chosen cutoff:

ts
const deleted = await auth.cleanupAuditLogs({
  olderThan: new Date("2025-01-01T00:00:00.000Z"),
});

cleanupAuditLogs permanently deletes every audit event created before olderThan and returns the number deleted.

Next step

Read the full Security Model to understand how the security features work together.