DEV Community

Alex Spinov
Alex Spinov

Posted on

Cerbos Has a Free API That Decouples Authorization From Your Application Code

Cerbos is the open-source authorization layer that keeps permission logic out of your codebase. Define policies in YAML, check them via API — no hardcoded if/else chains.

What Is Cerbos?

Cerbos is a stateless, self-hosted authorization engine. Your app sends a check request with the principal, resource, and action — Cerbos returns allow or deny based on your policies.

Quick Start

# Docker
docker run --rm -p 3592:3592 -p 3593:3593 \
  -v $(pwd)/policies:/policies \
  ghcr.io/cerbos/cerbos:latest server
Enter fullscreen mode Exit fullscreen mode

Define Policies

# policies/resource_document.yaml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  resource: document
  version: default
  rules:
    - actions: ['read']
      effect: EFFECT_ALLOW
      roles: ['viewer', 'editor', 'admin']

    - actions: ['edit', 'update']
      effect: EFFECT_ALLOW
      roles: ['editor', 'admin']
      condition:
        match:
          expr: request.resource.attr.status != 'archived'

    - actions: ['delete', 'archive']
      effect: EFFECT_ALLOW
      roles: ['admin']

    - actions: ['edit']
      effect: EFFECT_ALLOW
      roles: ['viewer']
      condition:
        match:
          expr: request.resource.attr.ownerId == request.principal.id
Enter fullscreen mode Exit fullscreen mode

Check Permissions

curl -s -X POST 'http://localhost:3592/api/check/resources' \
  -H 'Content-Type: application/json' \
  -d '{
    "principal": {
      "id": "user-123",
      "roles": ["editor"],
      "attr": {"department": "engineering"}
    },
    "resources": [{
      "resource": {
        "kind": "document",
        "id": "doc-456",
        "attr": {"status": "draft", "ownerId": "user-789"}
      },
      "actions": ["read", "edit", "delete"]
    }]
  }' | jq '.results["doc-456"].actions'
# {"read": "EFFECT_ALLOW", "edit": "EFFECT_ALLOW", "delete": "EFFECT_DENY"}
Enter fullscreen mode Exit fullscreen mode

TypeScript SDK

import { GRPC } from '@cerbos/grpc'

const cerbos = new GRPC('localhost:3593', { tls: false })

// Check permission
const decision = await cerbos.checkResource({
  principal: {
    id: userId,
    roles: [userRole],
    attr: { department: userDept },
  },
  resource: {
    kind: 'document',
    id: docId,
    attr: { status: doc.status, ownerId: doc.ownerId },
  },
  actions: ['read', 'edit', 'delete'],
})

if (decision.isAllowed('edit')) {
  // User can edit this document
}
Enter fullscreen mode Exit fullscreen mode

Express.js Middleware

const authorize = (action: string, resourceKind: string) => {
  return async (req, res, next) => {
    const decision = await cerbos.checkResource({
      principal: { id: req.user.id, roles: req.user.roles },
      resource: { kind: resourceKind, id: req.params.id, attr: req.resourceAttrs },
      actions: [action],
    })
    if (!decision.isAllowed(action)) return res.status(403).json({ error: 'Forbidden' })
    next()
  }
}

app.put('/documents/:id', authorize('edit', 'document'), updateDocument)
app.delete('/documents/:id', authorize('delete', 'document'), deleteDocument)
Enter fullscreen mode Exit fullscreen mode

Why Cerbos?

  • Stateless: no database needed, policies are files
  • Fast: sub-millisecond decisions
  • Testable: unit test policies without running your app
  • GitOps: policies in Git, deploy with CI/CD
  • Language agnostic: REST + gRPC SDKs for all languages

Need access control for scraping APIs? Scrapfly provides enterprise web scraping with access management. Email spinov001@gmail.com for secure scraping solutions.

Top comments (0)