Febasidocs
Reference

Audit logs

Every meaningful event Febasi Auth records, what's in each row, and how to query it.

Every authentication and authorization event is appended to the auth_logs table. Logs are tenant-scoped, immutable, and exposed through the GET /auth/logs endpoint to anyone holding the auth:logs:read permission.

What gets logged

ActionWhen it fires
LOGINEvery POST /login — success or failure.
LOGOUTEvery POST /logout.
REFRESH_TOKENEvery POST /refresh — success or failure.
REGISTEREvery POST /register — including failures.
USER_DELETEWhen a user is deleted via /users/:id.
ROLE_ASSIGNPOST /roles/assign.
ROLE_REMOVEPOST /roles/remove.
PERMISSION_GRANTPOST /permissions/grant.
PERMISSION_REVOKEPOST /permissions/revoke.
IP_DENIEDA request was rejected because the source IP is not in the tenant or per-key allowlist. See IP allowlist.
IP_ALLOWLIST_FORCE_UPDATEAn allowlist update used ?force=true to bypass the self-lockout check. High-severity — review periodically.

Failures are logged with success = false and errorMessage populated, so you can spot brute-force attempts, mistyped tokens, and forbidden actions all in the same query.

Row shape

FieldTypeNotes
idUUIDPrimary key.
tenant_idUUIDAlways present. Scopes the row.
user_idUUID (nullable)Null for failed logins where the user was unknown.
actionenumOne of the action codes above.
successbooleantrue for successful events.
error_messagetext (nullable)Reason on failures.
ip_addressstringSource IP from X-Forwarded-For or socket.
user_agentstringClient User-Agent if present.
created_attimestampInsertion time. Indexed for range queries.

Querying the log

GET /api/v1/auth/logs?action=LOGIN&success=false&limit=50&offset=0
Authorization: Bearer <jwt-with-auth:logs:read>

Supported filters: userId, action, success, startDate, endDate (both as ISO 8601 datetimes), plus limit (1–100, default 50) and offset (default 0).

Common query patterns:

GET /api/v1/auth/logs?action=LOGIN&success=false&startDate=2026-05-21T00:00:00Z&endDate=2026-05-22T00:00:00Z

Wire alerts on the count of these. A cluster of failures from a single IP in a 5-minute window is a brute-force fingerprint.

GET /api/v1/auth/logs?action=PERMISSION_GRANT&userId={id}

Useful for compliance reviews — "show me everything that has been granted to this user."

GET /api/v1/auth/logs?userId={id}&startDate=2026-05-15T00:00:00Z&endDate=2026-05-22T00:00:00Z&limit=200

Cross-reference with /tenants/me/metrics/security for IPs flagged as suspicious — then drill in here by userId for the forensic timeline.

Retention

Audit rows are never overwritten. They are kept indefinitely on the production host; a formal retention policy is owned by the operations team. Plan for "rows live forever".

What's not in audit logs

  • Read endpointsGET /users, GET /roles, etc. are not audited by default. If your integration needs read auditing, contact your Febasi account to discuss enabling it for your tenant.
  • JWT secret rotation — captured in tenant metadata, not in auth_logs.
  • Outbound webhook deliveries — Febasi Auth does not emit webhooks. The audit log is the closest thing to an event stream.

Pairing with security metrics

For real-time signals (last 5 min / last 24h aggregates), use:

GET /api/v1/tenants/me/metrics/security

For a forensic timeline of a specific user / IP / action, use the audit log. The two are intentionally separate: one is fast and aggregate, the other is authoritative and granular.

On this page