Get listed

Application Security

Authorization Libraries Compared: Casbin, OpenFGA, and SpiceDB

Check the object, not only the group name. role == admin will still serve another tenant’s id.

Expertise: Application Security · Level: Intermediate · 6 min read

A handler that only checks role == admin still serves tenant 2’s object. The JWT on the gateway already validated, so the request looks authorized. OWASP’s Authorization Cheat Sheet treats that as a different question from authentication: permission has to be checked on the specific object, not only on the role in the token. Changing acct_id from 901 to 523 is the CWE-639 case the sheet names.

That is the wrong assumption. A valid token is not an object check. In-process libraries sit next to the handler. A relationship graph is a query on every request. A policy language lives beside the app. Those shapes differ on where the tuple lives, not on whether TLS already terminated.

The hop that terminates TLS and authentication is on API gateways. This list is the object check in the handler. Read the matrix for which library owns that check, and which one assumes you already have a graph.

How we evaluated

We read first-party docs, source, licenses, and release notes, and we treat a marketing page as a claim, not as proof that two products do the same work.

We cared about whether the check can name an object, whether you run the decision in-process or as a service, whether the policy is a file you can review, and whether the docs show a relationship, not only a role string. Cerbos missed because Oso and Casbin already cover that in-process job.

We read first-party docs, licenses, and release notes. Unless a write-up says otherwise, we did not run a paid tenant.

ToolBest forWhat to check
CasbinEmbeddable ACL ABAC RBAC in-processIn-process ACL ABAC RBAC ยท Apache-2.0 ยท model file you read
OpenFGAOpen Zanzibar-style checksRelationship tuples ยท Apache-2.0 ยท you host the store
SpiceDBZanzibar-shaped store from AuthzedSchema plus relationships ยท Apache-2.0 ยท self-host or Authzed
OsoPolar policies next to the appPolar next to the app ยท Apache-2.0 library / commercial cloud ยท facts from your objects
CedarAmazon policy language you can runDeterministic policy language ยท Apache-2.0 ยท embed it or AWS Verified Permissions
Open Policy AgentSidecar policy for more than the appRego sidecar or library ยท Apache-2.0 ยท same engine as Gatekeeper
How the tools differ
Relation store
Central serviceNone on this list
Library in-process
Sidecar
1

Casbin

Best for embeddable ACL ABAC RBAC in-process

Casbin

Casbin is a library. Models are CONF files. Policies are rows. Ports exist for Go, Java, Node, and others.

You do not need a new network hop. You still load the policy, because a wrong model is a silent allow. It is not a hosted Zanzibar.

Key features

  • Multiple model types
  • Adapters for stores
  • In-process check
  • Apache-2.0

Why we like it

An embeddable check you can call in the handler is the practical no-hop buy.

Limits

You still load the policy. A wrong model is a silent allow. It is not a hosted relation store.

2

OpenFGA

Best for open Zanzibar-style checks

OpenFGA

OpenFGA is a relationship store. Auth0 and Okta opened it. Checks are whether user U can do relation R on object O.

When the org chart is the policy, a tuple store is the practical model. You can run it yourself. Modeling is the hard part, and it will not invent object checks you never wrote.

Key features

  • Relationship tuples
  • HTTP and SDKs
  • You can host it
  • Modeled on Zanzibar ideas

Why we like it

A check shaped like a relation matches permission that is already a graph.

Limits

You operate the store. Modeling is the hard part. Latency is a new dependency.

3

SpiceDB

Best for zanzibar-shaped store from Authzed

SpiceDB

SpiceDB is Authzed’s Zanzibar-inspired database. The engine is Apache-2.0. Authzed Cloud is paid.

If you want that paper as running software, this is the open engine with a company behind it. You still write the schema. Cloud is a different bill.

Key features

  • Schema and relationships
  • Consistency options
  • Self-host or Authzed
  • gRPC API

Why we like it

Consistency options and a gRPC API are a real store, not a policy file you hope stays in sync.

Limits

You still write the schema. Cloud is commercial. Latency is a new dependency.

4

Oso

Best for polar policies next to the app

Oso

Oso Polar is a policy language that can talk to your objects. The library is open. Oso Cloud is paid.

When the policy must read a field on the invoice, Polar can say that without a second hop if you embed it. Do not confuse the library with the SaaS.

Key features

  • Polar language
  • Library in several languages
  • Facts from your app
  • Cloud option

Why we like it

A policy that can see a field on the object matches checks that were never a role table.

Limits

Polar is a language your team must own. Cloud terms are commercial. The library and the SaaS are different products.

5

Cedar

Best for amazon policy language you can run

Cedar

Cedar is Amazon’s policy language, opened under Apache-2.0. Verified fragments exist. AWS uses it in Verified Permissions.

A policy language with a verification story is rare. You can run the engine without buying a SIEM. The AWS service is a different bill, and it is not a drop-in for a legacy role table.

Key features

  • Deterministic policy language
  • Apache-2.0
  • AWS Verified Permissions as a host
  • Analysis tools in the repo

Why we like it

A language you can analyze is the practical pick when the policy must be deterministic.

Limits

The AWS service is a different bill. Embedding Cedar is on you. It will not migrate a role column by itself.

6

Open Policy Agent

Best for sidecar policy for more than the app

Open Policy Agent

Open Policy Agent evaluates Rego. It started as a sidecar for clusters and APIs. It can decide an HTTP request if you feed it the input.

If the decision must be the same in CI, on the gateway, and in the app, one engine is the point. The authorization list is the app check. Platform owns admission. Rego is easy to write badly.

Key features

  • Rego language
  • Sidecar or library
  • Same engine as Gatekeeper
  • Apache-2.0

Why we like it

One language across the gateway and the app is why teams already run it.

Limits

Rego is easy to write badly. A sidecar is a hop. This is not a user directory.

What we left out

  • Cerbos. Teams want policy-as-code they can run next to the app. Oso and Casbin already cover that in-process job.
  • Permit.io. People want a hosted control plane on top of an open engine. It is a commercial wrapper, and you still call the library or store.

OpenFGA threads treat the mapping table as the thing that rots. A role column is not an object check.

Questions before you buy

Ask these before the trial clock starts. Vague answers usually mean a neighboring category.

  1. Can this engine say no when I pass another tenant’s object id?
  2. Does the check stay in the request process, or are we adding a store we must staff?
  3. Is the policy a graph of relations or a language next to the code, and which one matches how we already think?

If the handler only checks a role name, you do not have authorization. Pick a model you can test with two tenants.

FAQs

Does a library replace object-level tests?

No. The library is the decision. You still write a test that uses another user’s id. Open the IDOR guide.

Is OPA an IdP?

No. OPA does not log anyone in. Identity owns the session. This page owns the object check.

Should I pick Zanzibar or Polar?

Zanzibar if the graph is the product. Polar or Casbin if the check must stay in the request path without a new store.

Is this a scored bake-off?

No. Order is editorial. We did not load-test the stores.

Application Security resources