Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions acton-docs/src/app/docs/audit/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,14 @@ When `audit_auth_events` is enabled (default), the PASETO and JWT middleware aut

| Event Kind | When Emitted | Severity |
|---|---|---|
| `AuthLoginSuccess` | Token validated successfully | Informational |
| `AuthLoginFailed` | Token missing, invalid, or expired | Warning |
| `AuthTokenRevoked` | Revoked token presented | Warning |
| `AuthLoginSuccess` | Token validated successfully | Notice |
| `AuthTokenMissing` | Bearer token missing or malformed on a protected route | Informational |
| `AuthTokenInvalid` | Bearer token failed validation (bad signature, expired, malformed claims) | Warning |
| `AuthTokenRevoked` | Revoked token presented. Event metadata carries `jti` for SIEM correlation. | Warning |
| `AuthPermissionDenied` | Cedar policy returned `Deny` (HTTP middleware and gRPC tower service) | Warning |
| `HttpRequestDenied` | Rate-limit rejection (`Error::RateLimitExceeded`) | Warning |

> `AuthLoginFailed` is no longer emitted by the auth middleware. It is reserved for application-level login handlers (e.g. `POST /auth/login`) where credentials are submitted. The middleware emits `AuthTokenMissing` or `AuthTokenInvalid` instead, so unauthenticated probes against protected routes (health checks, scanners) no longer drown out real failed-login signal. See the 0.27 release notes for the migration.

No additional code is required. These events include the client IP, user agent, and authenticated subject.

Expand Down Expand Up @@ -248,7 +253,7 @@ The storage implementations create database rules/triggers that prevent any modi
Audit events are automatically formatted as RFC 5424 syslog messages and sent via UDP or TCP:

```text
<109>1 2026-01-15T10:30:00.000Z my-service acton-audit - - [audit@0 event_id="..." kind="AuthLoginSuccess" severity="Informational" sequence="42" hash="abc123..."] User login successful
<109>1 2026-01-15T10:30:00.000Z my-service acton-audit - - [audit@0 event_id="..." kind="AuthLoginSuccess" severity="Notice" sequence="42" hash="abc123..."] User login successful
```

### Syslog Configuration
Expand Down Expand Up @@ -292,7 +297,7 @@ Events are emitted via `tracing::info!` with structured fields:
```text
audit.event_id = "550e8400-..."
audit.kind = "AuthLoginSuccess"
audit.severity = "Informational"
audit.severity = "Notice"
audit.sequence = 42
audit.hash = "abc123..."
audit.service = "my-service"
Expand Down Expand Up @@ -338,7 +343,9 @@ Built-in event kinds for common operations:
| Kind | Description |
|---|---|
| `AuthLoginSuccess` | Successful authentication |
| `AuthLoginFailed` | Failed authentication attempt |
| `AuthLoginFailed` | Failed credential-submission attempt (emit from app login handlers; the middleware no longer emits this) |
| `AuthTokenMissing` | Bearer token missing on protected route (middleware-emitted) |
| `AuthTokenInvalid` | Bearer token failed validation (middleware-emitted) |
| `AuthLogout` | User logout |
| `AuthTokenRefresh` | Token refresh |
| `AuthTokenRevoked` | Revoked token used |
Expand Down
14 changes: 14 additions & 0 deletions acton-docs/src/app/docs/cedar-auth/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,20 @@ let authz = CedarAuthzLayer::builder()
5. **Optimize policy order**: Put most common permits first
6. **Use forbid sparingly**: Permit-based policies are typically faster

## Audit Integration

When the `audit` feature is enabled, the Cedar middleware automatically emits an `AuthPermissionDenied` audit event at `Warning` severity whenever a policy decision is `Deny`. Both the HTTP middleware and the gRPC tower service emit the event.

The event records:

- The authenticated subject (from JWT `sub`)
- Client user-agent and request-id (HTTP picks these up from headers; gRPC picks them up from metadata)
- Client IP (HTTP only; gRPC has no peer IP at this layer)

No additional code is required — emission is on by default when `audit_auth_events: true` is set in the audit configuration (the default). See [Audit Logging](/docs/audit) for storage and SIEM export.

Set `audit_auth_events: false` in your audit configuration if you want to suppress these events — for example, in environments where Cedar denies are expected and noisy and you'd rather route them through application logs instead of the audit chain.

## Security Best Practices

1. **Always use fail-closed in production**: `fail_open = false`
Expand Down
13 changes: 13 additions & 0 deletions acton-docs/src/app/docs/rate-limiting/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,19 @@ Retry-After: 45
}
```

## Audit Integration

When the `audit` feature is enabled, the rate-limit middleware automatically emits an `HttpRequestDenied` audit event at `Warning` severity whenever a request is rejected because the configured limit was exceeded. Only the limit-exceeded path emits — Redis connection failures and other infrastructure errors do not, since they aren't security signal.

The event records:

- The authenticated subject (from JWT `sub`, if claims are present)
- Client user-agent, request-id, and IP (from `X-Forwarded-For` / `X-Real-IP`)

No additional code is required — emission is on by default when `audit_auth_events: true` is set in the audit configuration (the default). See [Audit Logging](/docs/audit) for storage and SIEM export.

This event is well-suited to anomaly-detection rules: a sudden burst of `http.request.denied` events for a single subject is a strong abuse signal that an unauthenticated 429 response alone doesn't surface.

## Choosing the Right Limiter

| Feature | Redis-Backed | Governor |
Expand Down
15 changes: 15 additions & 0 deletions acton-docs/src/app/docs/token-auth/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,21 @@ async fn logout(
- **Permission Changes**: Force re-authentication when roles/permissions change
- **Account Suspension**: Revoke all user tokens immediately

## Audit Emission

When the `audit` feature is enabled, the PASETO and JWT middleware automatically emit audit events for the request lifecycle they manage. By default (`audit_auth_events: true`), every protected request produces one of these:

| Event Kind | When | Severity |
|---|---|---|
| `AuthLoginSuccess` | Token validated successfully | Notice |
| `AuthTokenMissing` | No bearer token, or token header malformed | Informational |
| `AuthTokenInvalid` | Bearer token present but failed validation | Warning |
| `AuthTokenRevoked` | Validated token but the JTI is on the revocation list | Warning |

`AuthTokenRevoked` includes the revoked token's `jti` in the event metadata. SIEM rules and forensic queries that ask "which requests presented this revoked token" can anchor on that field directly.

The middleware no longer emits `AuthLoginFailed`. That event is reserved for application-level login handlers (typically `POST /auth/login`) where credentials are actually submitted. Emit it yourself from those handlers via `logger.log_auth(AuditEventKind::AuthLoginFailed, ...)`. Treating unauthenticated probes against protected routes as failed logins drowns out real signal — see the [audit docs](/docs/audit) for the rationale.

## gRPC Support

Token authentication is available for gRPC services via interceptors:
Expand Down
Loading