Skip to main content

Object Types

Object types are the basic building blocks of an authorization scheme in Warrant. They are very flexible, allowing you to express an application's data model as relationships that exist between its resources and its users. This includes the ability to express more complex hierarchical and inherited relationships.

Let's build up object types for a simple eCommerce application. The app has two main object types: stores and items.

{
"type": "store"
},
{
"type": "item"
}

With these object types we can create fine-grained authorization rules for each store, item, and user to enforce access in the app by answering questions like:

Does [user1] have access to edit [itemx]?
Does [user2] have access to edit [store3]?

Relations

To help answer questions like the ones above, we need to add relations to our object types. Relations define the relationships that are possible between users and object types.

In our app, stores can have owners, editors, and viewers. owners and editors have more privileged access (ex. being able to modify details about a store) than viewers (who have read-only access).

Items have the same three relations as stores plus a fourth relation called parent. A store can be the parent of an item, meaning that item belongs to that store. We'll use this relation to implement inherited privileges later. Let's add these relations to our object types:

{
"type": "store",
"relations": {
"owner": {},
"editor": {},
"viewer": {}
}
},
{
"type": "item",
"relations": {
"parent": {},
"owner": {},
"editor": {},
"viewer": {}
}
}

Now we can create authorization rules using these object types to specifically define which users are owners, editors, viewers, etc. of each store and item.

Rules

Explicitly defining relations like we did above (owners, editors, etc.) might work for many cases. However, in practice, it's common for relations to overlap. In our app, an owner is also both an editor and a viewer. An editor is also a viewer. We need to tell Warrant that some of these relations can be inherited and how exactly they can be inherited. We do this via userset and object userset rules.

Userset Rule

A userset rule allows you to inherit relations by specifying the inherited relation. Let's define a rule specifying that owners are editors and editors are viewers in our object types:

{
"type": "store",
"relations": {
"owner": {},
"editor": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "owner"
}
]
},
"viewer": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "editor"
}
]
}
}
},
{
"type": "item",
"relations": {
"parent": {},
"owner": {},
"editor": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "owner"
}
]
},
"viewer": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "editor"
}
]
}
}
}
note

Each relation spec has a type parameter that defines how to treat the rules defined in the rules array. Currently, only the anyOf type is supported. This means that the relation is valid if any of the rules in the array match (this is equivalent to the boolean OR operator). In our example above, the user is an editor if they are an owner.

Object Userset Rule

With object userset rules, we can define inherited relations between objects. We now want to define that an editor of a store is also an editor on items that belong to that store (parent). We specify this dual-inheritance by defining an object userset rule on the editor relation of the item object type:

{
"type": "store",
"relations": {
"owner": {},
"editor": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "owner"
}
]
},
"viewer": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "editor"
}
]
}
}
},
{
"type": "item",
"relations": {
"parent": {},
"owner": {},
"editor": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "owner"
},
{
"type": "objectUserset",
"relation": "parent",
"userset": {
"type": "userset",
"relation": "editor"
}
}
]
},
"viewer": {
"type": "anyOf",
"rules": [
{
"type": "userset",
"relation": "editor"
}
]
}
}
}

In other words, the user is an editor of an item if that user is an editor of the parent store of that item. Now we don't always have to create an access rule for every item in our application.

Creating and Managing Object Types

Currently, object types can be created directly in the Warrant dashboard or via API. Check out the API Reference for more details.