User Tools

Site Tools


security:authorization:openfga:authorization-model:keyword-vs-name

OpenFGA DSL Syntax: Keywords vs Names

In the DSL there are two kinds of words: keywords you must type exactly, and names you make up (or point to). Symbols like ​:​ and [ ] are also fixed.

Keywords (fixed — you cannot change them)

Built-in words. Spell them exactly.

Keyword What it does
model Starts the file.
schema Comes with the version, like schema 1.1.
type Starts a new type.
relations Starts the list of relations for a type.
define Starts one relation.
or, and, but not Combine relations.
from Inherit through a link.

Names (values — you choose these)

Words you invent to fit your app.

  • Type names: user, document, folder, organization. You could call them person or file instead.
  • Relation names: owner, editor, viewer, parent, member. You pick these too.

There is a small twist. Sometimes you create a name, and sometimes you refer to a name you already made.

  • define viewer: … → here you create the name viewer.
  • … or owner → here you refer to owner, which must already exist.
  • [user]user must be a type you already defined.

Symbols (fixed punctuation)

  • ​:​ after a relation name — required.
  • [ ] around allowed types — required for a direct relation.
  • # — used in tuples, like group:eng#member (not in the model itself).

One line, broken into parts

Take this line:

define viewer: [user] or owner
Token Kind Note
define keyword fixed word
viewer name you create it here
​:​ symbol required
[ symbol required
user name a type that must already exist
] symbol required
or keyword fixed word
owner name a relation that must already exist

The general shape

Uppercase = keywords (fixed). <…> = names you supply.

MODEL
  SCHEMA 1.1

TYPE <your type name>
  RELATIONS
    DEFINE <your relation name>: [<allowed type>] OR <another relation>

The keywords as concepts

Each keyword plays one clear role. Think of building the model top to bottom: first the file, then a type, then its relations, then each rule.

model

Concept: the start of the whole file. It wraps everything.

You write it once, at the very top. Nothing lives outside it.

model
  schema 1.1

schema

Concept: the DSL version number. It tells OpenFGA which grammar to use.

Always pair it with a version, like 1.1. Put it right under model.

schema 1.1

type

Concept: a kind of thing in your system.

A type is a category of object, like a user, a document, or a folder. You will have one type block for each kind of thing. The name after type is yours to choose.

type document

Read it as: “documents are a kind of thing in this system.”

relations

Concept: the heading that opens the list of links for a type.

It has no rule of its own. It just says “the rules for this type start here.” Everything indented under it belongs to that type.

type document
  relations
    define owner: [user]
    define viewer: [user] or owner

Read it as: “here come the relations that documents can have.”

define

Concept: one single rule (one relation).

Each define line creates one named link and says who can have it. You will have many define lines under relations.

define owner: [user]

Read it as: “define a link called owner; a user can be assigned to it.”

or / and / but not

Concept: ways to combine relations into one rule.

  • or — this or that (widest access).
  • and — this and that (both required).
  • but not — this except that (takes access away).
define editor: [user] or owner
define can_delete: owner and admin
define viewer: [user] but not blocked

from

Concept: inherit access through a link to another object.

It lets access flow between objects. You name a link to follow, then a relation to check on the other side.

define viewer: viewer from parent

Read it as: “you are a viewer here if you are a viewer of the parent.”

How they nest

The keywords stack inside each other, shown by indentation:

model                         ← the whole file
  schema 1.1                  ← the DSL version
                              
  type document               ← a kind of thing
    relations                 ← its links start here
      define owner: [user]    ← one rule
      define editor: [user] or owner   ← one rule, using "or"

<note tip> Reading order: modelschematyperelationsdefine. Outer keywords set the container; inner ones fill in the detail. </note>

More examples to read

The trick to reading a relation is to say it out loud in plain words. Below, the left side is the DSL, the right side is how you say it.

Direct grant

define owner: [user]

Read it as: “a user can be assigned as the owner.”
Keyword: define. Names: owner, user. This one needs a tuple to be true.

Union with ''or''

define editor: [user] or owner

Read it as: “an editor is a user assigned directly, or anyone who is already an owner.”
So every owner is also an editor, for free.

More than one allowed type

define member: [user, group#member]

Read it as: “a member can be a single user, or every member of a group.”
The comma lists two allowed types. group#member means “the members of a group.”

Public access with a wildcard

define viewer: [user:*]

Read it as: “every user can view this.”
The * is a wildcard. Use it for public things.

Both must be true with ''and''

define can_delete: owner and admin

Read it as: “you can delete only if you are both an owner and an admin.”
and means both conditions must hold at the same time.

Take away with ''but not''

define viewer: [user] but not blocked

Read it as: “a viewer is any assigned user, except anyone who is blocked.”
but not removes people, even if they would otherwise qualify.

define viewer: viewer from parent

Read it as: “you can view this if you are a viewer of its parent.”
Follow the parent link, then check viewer on whatever you land on.

Everything combined

define viewer: [user] or editor or viewer from parent

Read it as: “a viewer is a user assigned directly, or an editor, or a viewer of the parent folder.”
This is the common real-world pattern: direct people, higher roles, and inherited folder access all at once.

Quick reading table

DSL Read it as
[user] assigned directly, needs a tuple
[user, team#member] a user, or every member of a team
[user:*] everyone (public)
or owner also counts if you are an owner
and admin only if you are also an admin
but not blocked unless you are blocked
viewer from parent if you are a viewer of the parent

<note tip> Rule of thumb: [ ] means a direct grant (a tuple sets it). A bare relation name means a computed grant (worked out from other relations, no tuple needed). </note>

See also

security/authorization/openfga/authorization-model/keyword-vs-name.txt · Last modified: by phong2018