Skip to main content

Audit Logs

nauth-toolkit records an audit trail of every authentication and security event --- logins, signups, password changes, MFA operations, social auth, and suspicious activity. Audit logging is enabled by default and requires no additional setup.

How It Works​

Non-Blocking Design

Audit recording never interrupts authentication flows. If an audit write fails, the error is logged but the auth operation completes normally.

Event Types​

nauth-toolkit records 60+ event types across 12 categories. Every event has a status of SUCCESS, FAILURE, INFO, or SUSPICIOUS.

Authentication​

EventStatusWhen
LOGIN_ATTEMPTINFOCredentials validated, risk assessed
LOGIN_SUCCESSSUCCESSUser authenticated
LOGIN_FAILEDFAILUREInvalid credentials, account locked
LOGIN_BLOCKEDFAILUREIP blocked or account locked

Sessions​

EventStatusWhen
SESSION_CREATEDINFOAfter successful authentication
SESSION_REVOKEDINFOLogout, security violation, or admin action
GLOBAL_SIGNOUTINFOAll sessions revoked

Passwords​

EventStatusWhen
PASSWORD_CHANGEDSUCCESSUser changed password
PASSWORD_RESET_REQUESTEDINFOReset email/SMS sent
PASSWORD_RESET_COMPLETEDSUCCESSReset successful
PASSWORD_FORCE_CHANGE_SETINFOBy admin or policy
PASSWORD_FORCE_CHANGE_COMPLETEDSUCCESSUser completed forced change
ADMIN_PASSWORD_RESET_INITIATEDINFOAdmin sent reset code to user
ADMIN_PASSWORD_RESET_COMPLETEDSUCCESSAdmin reset completed
ADMIN_PASSWORD_RESET_FAILEDFAILUREInvalid code, expired

MFA​

EventStatusWhen
MFA_ENABLEDINFOMFA enabled for account
MFA_DISABLEDINFOMFA disabled for account
MFA_DEVICE_ADDEDINFONew device registered (TOTP, SMS, Passkey)
MFA_DEVICE_REMOVEDINFODevice removed
MFA_DEVICE_UPDATEDINFODevice name/primary flag changed
MFA_VERIFICATION_SUCCESSSUCCESSCorrect MFA code
MFA_VERIFICATION_FAILEDFAILUREInvalid code, expired
MFA_EXEMPTION_GRANTEDINFOAdmin exempted user from MFA
MFA_EXEMPTION_REVOKEDINFOExemption removed
MFA_BACKUP_CODES_GENERATEDINFOBackup codes created
MFA_BACKUP_CODE_USEDINFOBackup code consumed
MFA_PREFERRED_METHOD_UPDATEDINFODefault method changed
DEVICE_TRUSTEDINFOUser opted to remember device
DEVICE_UNTRUSTEDINFOTrusted device revoked/expired

Adaptive MFA​

EventStatusWhen
ADAPTIVE_MFA_RISK_ASSESSEDINFORisk evaluation completed
ADAPTIVE_MFA_TRIGGEREDINFOMFA required due to risk
ADAPTIVE_MFA_BYPASSEDINFOLow risk, MFA skipped

Verification​

EventStatusWhen
EMAIL_VERIFIEDSUCCESSEmail address confirmed
EMAIL_VERIFICATION_REQUESTEDINFOVerification code sent
EMAIL_VERIFICATION_FAILEDFAILUREInvalid code, expired
PHONE_VERIFIEDSUCCESSPhone number confirmed
PHONE_VERIFICATION_REQUESTEDINFOSMS code sent
PHONE_VERIFICATION_FAILEDFAILUREInvalid code, expired

Account Management​

EventStatusWhen
ACCOUNT_CREATEDINFONew signup
ACCOUNT_DISABLEDINFOAdmin locked the account (disable)
ACCOUNT_ENABLEDINFOAdmin cleared the lock (enable)
ACCOUNT_DELETEDINFOAccount deleted

Account lock and unlock are audited as ACCOUNT_DISABLED and ACCOUNT_ENABLED, so alert on those. A failed-login lockout is IP-based and produces LOGIN_FAILED rows rather than any lock event.

Profile Updates​

EventStatusWhen
PROFILE_UPDATEDINFOGeneral profile update
EMAIL_CHANGEDINFOEmail address changed
PHONE_CHANGEDINFOPhone number changed
USERNAME_CHANGEDINFOUsername changed
EMAIL_VERIFICATION_STATUS_UPDATEDINFOAdmin updated verification status
PHONE_VERIFICATION_STATUS_UPDATEDINFOAdmin updated verification status

Social Authentication​

EventStatusWhen
SOCIAL_LOGINSUCCESSAuthenticated via social provider
SOCIAL_ACCOUNT_LINKEDINFOSocial account linked
SOCIAL_ACCOUNT_UNLINKEDINFOSocial account unlinked

Challenge Flow​

EventStatusWhen
CHALLENGE_CREATEDINFOChallenge session started
CHALLENGE_COMPLETEDSUCCESSChallenge passed
CHALLENGE_ATTEMPT_FAILEDFAILUREWrong code, max attempts

OpenID Connect Provider​

Only when @nauth-toolkit/oidc-provider is installed.

EventStatusWhen
OIDC_LOGIN_COMPLETEDSUCCESSA completed login was released to a relying party
OIDC_CONSENT_GRANTEDSUCCESSThe user approved an application's request
OIDC_CONSENT_DENIEDINFOThe user refused it
OIDC_ACCESS_DENIEDFAILUREThe account may not be vouched for (disabled, locked)

Each carries authMethod: 'oidc' and a clientId in metadata, so you can answer "which application signed this user in?" --- the ordinary LOGIN_SUCCESS cannot, because the authorization request is still parked when the user types their password.

Security​

EventStatusWhen
SUSPICIOUS_ACTIVITYSUSPICIOUSToken reuse, impossible travel
TOKEN_REFRESHED Excluded

Token refreshes are intentionally not audited --- they occur too frequently and would create excessive noise. Only security-relevant token operations (reuse detection, revocation) are recorded.

Data Model​

Every audit record captures:

Core Fields​

FieldTypeDescription
idnumberAuto-increment primary key
userIdnumberInternal user ID (foreign key)
eventTypestringEvent type from catalog above
eventStatusstringSUCCESS, FAILURE, INFO, or SUSPICIOUS
createdAtDateWhen the event occurred

Client Information (Auto-Captured)​

These fields are automatically populated from request context --- no manual input required:

FieldTypeExample
ipAddressstring203.0.113.42
ipCountrystringUS
ipCitystringSan Francisco
ipLatitudenumber37.7749
ipLongitudenumber-122.4194
userAgentstringMozilla/5.0 (Macintosh; ...)
platformstringmacOS, iOS, Android, Windows
browserstringChrome, Safari, Firefox
deviceIdstringUUID device identifier
deviceNamestringiPhone 15 Pro, Chrome on MacBook
deviceTypestringmobile, desktop, tablet
Geolocation Required

ipCountry, ipCity, ipLatitude, and ipLongitude are only populated when Geolocation is configured.

Context Fields​

FieldTypeDescription
sessionIdnumberRelated session (if applicable)
challengeSessionIdnumberRelated challenge (if applicable)
authMethodstringpassword, google, apple, facebook
performedBystringWho performed the action (auto-populated)

Event Details​

FieldTypeDescription
reasonstringWhy it happened (security events, locks)
descriptionstringHuman-readable event summary
metadataJSONEvent-specific data (flexible, no schema changes needed)

Risk Assessment Fields​

FieldTypeDescription
riskFactornumberRisk score 0--100 (adaptive MFA)
riskFactorsstring[]Contributing factors: new_device, new_ip, new_country, impossible_travel
adaptiveMfaTriggeredbooleanWhether MFA was required due to risk

Metadata Examples​

The metadata field stores event-specific details as flexible JSON:

// Account creation
{
email: 'user@example.com',
verificationMethod: 'email',
gracePeriodActive: true,
gracePeriodEndsAt: '2025-02-01T00:00:00.000Z',
}

// Social login
{
provider: 'google',
isNewUser: true,
}

// MFA device added
{
deviceType: 'totp',
deviceName: 'iPhone Authenticator',
}

// Token reuse (suspicious)
{
tokenFamily: 'abc123',
action: 'token_family_revoked',
}

// Admin action on another user
{
performedByName: 'Jane Admin',
reason: 'Security review',
}

// OIDC_CONSENT_GRANTED --- which application, and what it may see
{
clientId: 'partner',
interactionUid: 'kPz3Q8sLm2',
requestedScopes: ['openid', 'email', 'profile'],
grantedScopes: ['openid', 'email'],
}

performedBy Field​

The performedBy field tracks who performed each action:

ScenarioperformedBy value
User changes own passwordUser's sub (UUID)
Admin disables user accountAdmin's sub (UUID)
System auto-locks accountsystem
CLI migration scriptcli-migration-2025

When an admin performs an action on another user, metadata.performedByName is automatically enriched with the admin's name or email.

Query Methods​

AuthAuditService provides four query methods:

MethodPurposeFilters
getUserAuthHistory()Full history for a userEvent types, status, date range, pagination
getEventsByType()All events of a specific typeDate range, pagination
getSuspiciousActivity()Events with SUSPICIOUS statusOptional user filter
getRiskAssessmentHistory()Adaptive MFA risk eventsPer user

All query methods accept sub (UUID) and resolve to userId internally for efficient database queries.

Database Indexes​

Audit records are indexed for common query patterns:

IndexUse Case
userId + createdAtUser history queries
eventType + createdAtEvent type filtering
eventStatus + createdAtStatus filtering
riskFactor + createdAtRisk analysis
userId + eventType + createdAtUser-specific event queries
userId + ipAddressIP-based risk detection

What's Next​