Attribute-based access control (ABAC) evaluates policies against attributes of the user, the resource, and the request context. This quickstart walks through setting up ABAC with Rego policies.
Prerequisites
- An Authdog account with at least one tenant and environment
- Familiarity with basic Rego syntax (Open Policy Agent's language)
When to use ABAC
ABAC shines when access decisions depend on data that doesn't fit cleanly into roles:
- "Managers can approve expenses under $5,000 in their own department"
- "Users can edit resources they own"
- "Access is allowed only during business hours from approved IP ranges"
- "Documents marked 'confidential' are visible only to users with clearance level 3+"
1. Enable ABAC for the environment
Console: Authorization → Model → select ABAC
The environment now evaluates Rego policies instead of checking role assignments.
2. Create your first policy
Policies are written in Rego and evaluated at the edge. The policy receives input with the user, resource, action, and context.
Console: Authorization → Policies → Create Policy
Example policy — department-scoped approval:
package authdog.authz
default allow = false
allow {
input.action == "approve"
input.user.department == input.resource.department
input.resource.amount < 5000
}API:
curl -X POST https://api.authdog.com/v1/tenants/{tenantId}/environments/{envId}/abac-policies \
-H "Authorization: Bearer $AUTHDOG_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "Department approval policy",
"slug": "dept-approval",
"regoSource": "package authdog.authz\n\ndefault allow = false\n\nallow {\n input.action == \"approve\"\n input.user.department == input.resource.department\n input.resource.amount < 5000\n}",
"enabled": true
}'3. Validate the policy
Before enabling a policy, validate its syntax.
API:
curl -X POST https://api.authdog.com/v1/tenants/{tenantId}/environments/{envId}/abac-policies/validate \
-H "Authorization: Bearer $AUTHDOG_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"regoSource": "package authdog.authz\n\ndefault allow = false\n\nallow { input.action == \"read\" }",
"slug": "read-policy"
}'
# → {"valid": true}4. Understand the input schema
Every policy receives an input object with:
{
"user": {
"id": "user_abc123",
"email": "[email protected]",
"department": "engineering",
"clearanceLevel": 2,
"roles": ["editor"],
"groups": ["engineering-team"],
"metadata": { ... }
},
"resource": {
"type": "expense",
"id": "exp_456",
"department": "engineering",
"amount": 3500,
"owner": "user_abc123",
"metadata": { ... }
},
"action": "approve",
"context": {
"ip": "192.168.1.100",
"timestamp": "2026-11-09T14:30:00Z",
"userAgent": "Mozilla/5.0 ...",
"environment": "production"
}
}Your application supplies resource, action, and any custom context fields when making a check request.
5. Check authorization in your app
SDK (Node.js):
import { Authdog } from "@authdog/node"
const authdog = new Authdog({ apiSecret: process.env.AUTHDOG_API_SECRET })
app.post("/expenses/:id/approve", requireAuth, async (req, res) => {
const expense = await getExpense(req.params.id)
const allowed = await authdog.abac.check({
userId: req.user.id,
action: "approve",
resource: {
type: "expense",
id: expense.id,
department: expense.department,
amount: expense.amount,
},
context: {
ip: req.ip,
},
})
if (!allowed) {
return res.status(403).json({ error: "Not authorized to approve this expense" })
}
await approveExpense(expense.id)
res.json({ approved: true })
})REST API via AuthZEN:
curl -X POST https://api.authdog.com/access/v1/evaluation \
-H "Authorization: Bearer $AUTHDOG_ENV_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"subject": {"type": "user", "id": "user_abc123"},
"action": {"name": "approve"},
"resource": {
"type": "expense",
"id": "exp_456",
"properties": {
"department": "engineering",
"amount": 3500
}
}
}'
# → {"decision": true}Example policies
Owner can edit:
package authdog.authz
default allow = false
allow {
input.action == "edit"
input.resource.owner == input.user.id
}Business hours only:
package authdog.authz
default allow = false
allow {
hour := time.clock(time.parse_rfc3339_ns(input.context.timestamp))[0]
hour >= 9
hour < 17
}Clearance level check:
package authdog.authz
default allow = false
allow {
input.action == "view"
input.resource.classification == "confidential"
input.user.clearanceLevel >= 3
}IP allowlist:
package authdog.authz
default allow = false
allowed_networks = {"10.0.0.0/8", "192.168.0.0/16"}
allow {
some network
allowed_networks[network]
net.cidr_contains(network, input.context.ip)
}6. List and manage policies
List policies:
curl https://api.authdog.com/v1/tenants/{tenantId}/environments/{envId}/abac-policies \
-H "Authorization: Bearer $AUTHDOG_API_SECRET"Delete a policy:
curl -X DELETE https://api.authdog.com/v1/tenants/{tenantId}/environments/{envId}/abac-policies/{policyId} \
-H "Authorization: Bearer $AUTHDOG_API_SECRET"CLI usage
CLI support for ABAC commands is coming soon. For now, use the generic API command:
# List policies
authdog api GET /v1/tenants/{tenantId}/environments/{envId}/abac-policies
# Create a policy
authdog api POST /v1/tenants/{tenantId}/environments/{envId}/abac-policies \
--data '{"name":"Owner edit","slug":"owner-edit","regoSource":"package authdog.authz\n\ndefault allow = false\n\nallow { input.action == \"edit\"; input.resource.owner == input.user.id }","enabled":true}'
# Validate a policy
authdog api POST /v1/tenants/{tenantId}/environments/{envId}/abac-policies/validate \
--data '{"regoSource":"package authdog.authz\n\ndefault allow = false","slug":"test"}'Next steps
- Authorization concepts — compare ABAC with RBAC and FGA
- Rego language reference — full Rego documentation
- AuthZEN API — vendor-neutral decision endpoint