Security¶
Every API request passes through a strict access pipeline before reaching your Odoo data.
Authentication¶
Three authentication methods are supported. All requests must use one of them.
Bearer Token (recommended)¶
Include the API key in the Authorization header:
X-API-Key Header¶
Pass the key in a custom header:
Session Cookie¶
If the user is already logged into Odoo in a browser, the session cookie is accepted. This is primarily useful for testing from the Odoo UI or browser-based tools.
Access Pipeline¶
Access checks happen in a strict pipeline on every request:
| Step | Check | Description |
|---|---|---|
| 1 | Authentication | Verify API key, session, or credentials |
| 2 | Global toggle | Is MCP access enabled in Settings? |
| 3 | Credential validity | Is the credential active and not expired? |
| 4 | Credential scope | If readonly, block all write operations |
| 5 | Resource lookup | Is the requested model registered as an MCP resource? |
| 6 | Resource active | Is the resource archived? |
| 7 | Operation check | Does the resource allow this CRUD operation? |
| 8 | Read-only override | If the resource is in read-only mode, block writes |
| 9 | Field filtering | Apply allowlist or denylist to strip unauthorized fields |
| 10 | Domain injection | Merge the resource's record filter into the query |
| 11 | Odoo ACLs | Run under the linked user's native Odoo permissions (ir.model.access, ir.rule) |
| 12 | Multi-company isolation | Resources and credentials are scoped per company via standard Odoo record rules |
Rate Limiting¶
Rate limiting uses a database-backed sliding window (not in-memory), so it works correctly across multiple Odoo workers and server restarts.
Buckets¶
Two separate rate limit buckets are tracked:
| Bucket | Default Limit | Description |
|---|---|---|
| Default | 300/min | General API requests |
| Aggregation | 60/min | Aggregation queries, which are heavier |
Response headers¶
Rate limit headers are included on every response:
Authentication rate limiting¶
Authentication failures are tracked per IP with a separate counter (10 failures per 15 minutes by default) to deter brute-force attacks.
Configuration¶
Rate limits can be adjusted in Settings > General Settings > Alpenglow MCP > Rate Limiting.
Audit Logging¶
When enabled, every MCP operation is logged with:
- Timestamp, event type, user, credential label
- Model name, operation, record count, duration (ms)
- Client IP address
- Freeform detail (truncated at 4,000 characters)
Event types¶
| Event | Description |
|---|---|
auth_success |
Successful authentication |
auth_failure |
Failed authentication attempt |
read |
Read/search operation |
create |
Record creation |
write |
Record update |
unlink |
Record deletion |
search |
Search operation |
schema |
Schema/describe request |
aggregate |
Aggregation query |
access_denied |
Permission denied |
rate_limited |
Request rejected by rate limiter |
error |
Internal error |
Retention¶
Old audit entries are automatically cleaned up by a scheduled action based on the configured retention period (default: 30 days).
Monitoring¶
Active Sessions¶
Go to Settings > Alpenglow MCP > Active Sessions to see connected clients in real time. Each session shows:
- Linked credential and user
- Client info and IP address
- First seen / last activity timestamps
- Total request count
- Active/inactive status
Audit Log Views¶
Go to Settings > Alpenglow MCP > Audit Log. The log supports:
- List view with color-coded event types (red for errors/denials, yellow for rate limiting)
- Graph view — line chart of activity over time by event type
- Pivot view — cross-tabulate activity by day and event type
Built-in filters:
- Today, Last 7 Days
- Authentication events
- Data Operations
- Errors & Denials
Group by: Event Type, User, Model, Day.
Health Endpoint¶
GET /alpenglow/health returns a simple JSON status check suitable for uptime monitors and load balancer health probes. No authentication required.