DEV Community

Alex Spinov
Alex Spinov

Posted on

OpenFGA Has a Free API: Google Zanzibar-Inspired Authorization for Any Application

What is OpenFGA?

OpenFGA is an open-source authorization engine inspired by Google's Zanzibar — the system that powers authorization for Google Drive, YouTube, and Google Cloud. Built by the Auth0/Okta team.

It answers the question: "Can user X do action Y on resource Z?" — at massive scale.

Quick Start

docker pull openfga/openfga
docker run -p 8080:8080 -p 3000:3000 openfga/openfga run
Enter fullscreen mode Exit fullscreen mode

Define Your Authorization Model

{
  "schema_version": "1.1",
  "type_definitions": [
    {
      "type": "user"
    },
    {
      "type": "document",
      "relations": {
        "owner": { "this": {} },
        "editor": {
          "union": {
            "child": [
              { "this": {} },
              { "computedUserset": { "relation": "owner" } }
            ]
          }
        },
        "viewer": {
          "union": {
            "child": [
              { "this": {} },
              { "computedUserset": { "relation": "editor" } }
            ]
          }
        }
      },
      "metadata": {
        "relations": {
          "owner": { "directly_related_user_types": [{ "type": "user" }] },
          "editor": { "directly_related_user_types": [{ "type": "user" }] },
          "viewer": { "directly_related_user_types": [{ "type": "user" }] }
        }
      }
    },
    {
      "type": "folder",
      "relations": {
        "owner": { "this": {} },
        "viewer": {
          "union": {
            "child": [
              { "this": {} },
              { "computedUserset": { "relation": "owner" } }
            ]
          }
        },
        "parent": { "this": {} }
      },
      "metadata": {
        "relations": {
          "owner": { "directly_related_user_types": [{ "type": "user" }] },
          "viewer": { "directly_related_user_types": [{ "type": "user" }] },
          "parent": { "directly_related_user_types": [{ "type": "folder" }] }
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

This creates a Google Drive-like permission model: owners can edit, editors can view.

Write Relationships

# Alice owns document:readme
curl -X POST http://localhost:8080/stores/STORE_ID/write \
  -H "Content-Type: application/json" \
  -d '{
    "writes": {
      "tuple_keys": [
        {"user": "user:alice", "relation": "owner", "object": "document:readme"},
        {"user": "user:bob", "relation": "editor", "object": "document:readme"},
        {"user": "user:charlie", "relation": "viewer", "object": "document:readme"}
      ]
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Check Permissions

# Can Bob view the readme?
curl -X POST http://localhost:8080/stores/STORE_ID/check \
  -H "Content-Type: application/json" \
  -d '{
    "tuple_key": {
      "user": "user:bob",
      "relation": "viewer",
      "object": "document:readme"
    }
  }'
# Response: {"allowed": true}
# Bob is an editor, and editors can view (inherited)
Enter fullscreen mode Exit fullscreen mode

Node.js SDK

import { OpenFgaClient } from "@openfga/sdk";

const fga = new OpenFgaClient({
  apiUrl: "http://localhost:8080",
  storeId: "YOUR_STORE_ID",
  authorizationModelId: "YOUR_MODEL_ID",
});

// Check permission
const { allowed } = await fga.check({
  user: "user:alice",
  relation: "viewer",
  object: "document:readme",
});
console.log(`Alice can view: ${allowed}`); // true

// Write relationship
await fga.write({
  writes: [
    { user: "user:dave", relation: "editor", object: "document:readme" },
  ],
});

// List objects user can access
const { objects } = await fga.listObjects({
  user: "user:alice",
  relation: "viewer",
  type: "document",
});
console.log(objects); // ["document:readme", "document:notes"]

// List users who can access an object
const { users } = await fga.listUsers({
  object: { type: "document", id: "readme" },
  relation: "viewer",
  user_filters: [{ type: "user" }],
});
Enter fullscreen mode Exit fullscreen mode

Express Middleware

import { OpenFgaClient } from "@openfga/sdk";

const fga = new OpenFgaClient({ apiUrl: "http://localhost:8080", storeId: "..." });

function authorize(relation: string, getObject: (req) => string) {
  return async (req, res, next) => {
    const { allowed } = await fga.check({
      user: `user:${req.user.id}`,
      relation,
      object: getObject(req),
    });
    if (!allowed) return res.status(403).json({ error: "Forbidden" });
    next();
  };
}

// Usage
app.get("/documents/:id",
  authorize("viewer", (req) => `document:${req.params.id}`),
  (req, res) => { /* handler */ }
);

app.put("/documents/:id",
  authorize("editor", (req) => `document:${req.params.id}`),
  (req, res) => { /* handler */ }
);
Enter fullscreen mode Exit fullscreen mode

Why OpenFGA?

Feature OpenFGA RBAC ACL
Fine-grained Yes No Partial
Relationship-based Yes No No
Scale Millions of checks/sec Depends Depends
Inherited permissions Yes Manual No
Zanzibar model Yes No No

Need fine-grained authorization for your app?

📧 spinov001@gmail.com
🔧 My tools on Apify Store

RBAC or relationship-based auth — what do you use?

Top comments (0)