ZombieMutex
All writing
Engineering#Backend#Observability#Authentication#Mobile Security#Logging
November 6, 20263 min read

Authentication telemetry without leaking tokens or recovery secrets

Design privacy-conscious auth decision logs that help explain failures without recording the credentials that caused them.

By

Share

Send this post or copy the direct link.

Authentication incidents frequently become difficult to investigate because the logs don't distinguish the outcome: rejected credentials, expired sessions, reused refresh tokens, blocked recovery challenges, and temporary dependency errors all become “login failed.”

The opposite extreme is worse: a verbose debug log that captures raw bearer tokens, passwords, one-time codes, or private account payloads. Good observability starts with a restricted event schema and a clear data-handling policy.

Start with decisions, not request dumps

For a security-sensitive endpoint, an event can record the decision and its context without recording the proof itself. Useful fields depend on the threat model, but a small allowlisted schema is easier to audit than arbitrary JSON properties.

json
{
  "event": "auth.decision",
  "operation": "refresh",
  "outcome": "denied",
  "reason": "token_reused",
  "policyVersion": "2026-11",
  "correlationId": "req_7f6e1",
  "environment": "production"
}

All values here are synthetic. There is no token, code, email address, phone number, recovery challenge or unredacted payload. In a real deployment, identifiers and operational metadata can still be sensitive and need access controls, retention limits, and privacy review.

Name errors the operator can act on

Avoid collapsing distinct failures into “network error.” An operator needs to know whether a request was rejected by policy, was invalid, exhausted retry limits, or could not reach an upstream dependency.

DecisionSuggested category
Expired access credentialAuthentication state
Refresh token reusedReplay / token-lifecycle policy
Insufficient object permissionAuthorization decision
App attestation verification unavailableDependency / integrity evidence
Recovery step-up deniedRecovery policy
Backend timed out after an ambiguous writeReliability / reconciliation

The category should describe a stable failure class, not reveal secrets to the end user.

Avoid building a log-based oracle

Detailed internal failure reasons help debugging but can also disclose account state if returned to an untrusted client. Keep the public response appropriately generic where enumeration or side-channel risks apply, and retain detailed diagnostic reasons in protected telemetry.

Aggregate rates by operation, rollout, policy, and failure category before drilling into individual trace IDs. Rate limits and retention policy should protect both the primary system and the observability pipeline.

Test redaction as a security property

Unit tests should generate synthetic token-like values, recovery codes, and PII and assert that serialized events never contain them. Validate logs for success and failure paths, exception handlers, retries, and traces from third-party SDKs.

For a related design exercise, use the authentication state machine to observe named allowed and blocked transitions. The lab history is synthetic and stored only in local component state.

Further reading: OWASP Logging Cheat Sheet and the API authorization review.


Editorial note: General engineering reference prepared with AI assistance; sample telemetry is synthetic and is not taken from customer infrastructure.

Related technical notes with overlapping topics.