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
/auth-logs endpoint to anyone holding the auth:logs permission.
What gets logged
| Action | When it fires |
|---|---|
LOGIN | Every POST /login — success or failure. |
LOGOUT | Every POST /logout. |
REFRESH_TOKEN | Every POST /refresh — success or failure. |
REGISTER | Every POST /register — including failures. |
USER_DELETE | When a user is deleted via /users/:id. |
ROLE_ASSIGN | POST /roles/assign. |
ROLE_REMOVE | POST /roles/remove. |
PERMISSION_GRANT | POST /permissions/grant. |
PERMISSION_REVOKE | POST /permissions/revoke. |
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
| Field | Type | Notes |
|---|---|---|
id | UUID | Primary key. |
tenant_id | UUID | Always present. Scopes the row. |
user_id | UUID (nullable) | Null for failed logins where the user was unknown. |
action | enum | One of the action codes above. |
success | boolean | true for successful events. |
error_message | text (nullable) | Reason on failures. |
ip_address | string | Source IP from X-Forwarded-For or socket. |
user_agent | string | Client User-Agent if present. |
created_at | timestamp | Insertion 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>Common query patterns:
GET /api/v1/auth-logs?action=LOGIN&success=false&since=24hWire 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?ip=203.0.113.42&limit=200Cross-reference with the security metrics endpoint — IPs flagged as suspicious deserve a closer look here.
Retention
Audit rows are never overwritten. They are kept indefinitely on the production host today; the operations team will publish the retention policy once it's formalized. Plan for "rows live forever" until proven otherwise.
What's not in audit logs
- Read endpoints —
GET /users,GET /roles, etc. are not audited by default. If a tenant needs read auditing, request it through the platform team; the infrastructure exists, the events are simply not emitted today. - JWT secret rotation — captured in tenant metadata, not in
auth_logs. - Outbound webhook deliveries — Febasi Auth does not yet emit webhooks. The audit log is the closest thing to an event stream right now.
Pairing with security metrics
For real-time signals (last 5 min / last 24h aggregates), use:
GET /api/v1/tenants/me/metrics/securityFor 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.