Skip to Content
SpiceDB is 100% open source. Please help us by starring our GitHub repo. ↗
SpiceDB DocumentationGetting StartedTutorial: Protecting a Blog Application

Tutorial: Protecting a Blog Application

This guide walks through the steps required to integrate end-to-end an application with SpiceDB. We are going to pretend that our application is a blog.

Instead of introducing an unfamiliar example app and altering various locations in its code, this guide is written such that each step is a standalone snippet of code that demonstrates an integration point and finding where those points exist in your codebase is an exercise left to the reader.

Prerequisites

One of:

# Using the binary spicedb serve --grpc-preshared-key "t_your_token_here_1234567deadbeef" # Using Docker docker run --rm -p 50051:50051 authzed/spicedb serve --grpc-preshared-key "t_your_token_here_1234567deadbeef"

Installing the Client

The first step to integrating any software is ensuring you have an API client. Each client is installed with its ecosystem’s package management tools:

brew install authzed/tap/zed zed context set <name> <endpoint> <token>

If you are using AuthZed Cloud , click on the Connect button on the dashboard to get both the endpoint that you use to connect to your permission system, and the full zed command needed to connect to it.

Writing a Schema

Schemas define the objects in our application, their relations, and their checkable permissions that will be available to be used with the Permission System.

We’ll be using the following schema to model our blog application:

definition user {} definition post { relation reader: user relation writer: user permission read = reader + writer permission write = writer }

This example defines two types of objects that will be used in the permissions system: user and post. Each post can have two kinds of relations to users: reader and writer. Each post can have two permissions checked: read and write. The read permission unions together both readers and writers, so that any writer is implicitly granted read, as well. Feel free to modify and test your own experiments in the playground .

With a schema designed, we can now move on to using our client to write that schema to the Permission System.

zed schema write <(cat << EOF definition user {} definition post { relation reader: user relation writer: user permission read = reader + writer permission write = writer } EOF )

If, later on, you wish to make updates to this schema, please read the migration guide.

Writing Relationships

After a permission system has its schema applied, it is ready to have its relationships created, touched, or deleted. Relationships are live instances of relations between objects. Because the relationships stored in the system can change at runtime, this is a powerful primitive for dynamically granting or revoking access to the resources you’ve modeled. When applications modify or create rows in their database, they will also typically create or update relationships.

Writing relationships returns a ZedToken which is critical to ensuring performance and consistency .

In the following example, we’ll be creating two relationships: one making Emilia a writer of the first post and another making Beatrice a reader of the first post. You can also touch and delete  relationships, but those are not as immediately useful for an empty permission system.

zed relationship create post:1 writer user:emilia zed relationship create post:1 reader user:beatrice

Checking Permissions

Permissions Systems that have stored relationships are capable of performing permission checks. Checks not only test for the existence of direct relationships, but also compute and traverse transitive relationships. For example, in our example schema, writers have both write and read permissions, so there’s no need to create a read relationship for a subject that is already a writer.

Let’s perform some permission checks:

If developing locally against SpiceDB, see this for full details on how to setup credentials. Always switch to secure credentials before launching to production.

zed permission check post:1 read user:emilia # true zed permission check post:1 write user:emilia # true zed permission check post:1 read user:beatrice # true zed permission check post:1 write user:beatrice # false

In addition to checking permissions, it is also possible to perform checks on relations to determine membership.

However, this goes against best practice: permissions can be redefined in backwards compatible ways by changing the schema, so it’s ideal to rely on permissions as the contract between SpiceDB and applications querying SpiceDB.

When doing a permission check, in order to get read-after-write consistency, you must provide a ZedToken from the WriteRelationships response or request full consistency.

Last updated on