Introduction to Groups
$PLACEHOLDER_NAME$ unifies the concepts of permissions, organizations, distribution lists, and membership into a single concept: groups.
Groups can be extremely powerful. They can be used to model permissions for your own employees, external user accounts, B2B organizations, compliance, API keys, JWT access tokens, and much more. In this guide, we'll walk through the basics of groups.
In principle, they are simple. Users can be (direct) members of groups, and groups can also be members of other groups. They work transitively; if group
engineeringInterns
is a member of group engineers
, then all members in engineeringInterns
are indirect members of group engineers
.Defining groups
You can define a group declaratively:
In fact, users are actually nothing else than groups themselves. They are distinguished from other groups by belonging to the
users
group, as described below.There is full CLI support for groups. For example, to see which groups a user (or another group) is a direct member of, you can list them using the CLI:
Permissions
Let's say we want to check whether an employee is allowed to commit code. Permissions like these are not a special concept in $PLACEHOLDER_NAME$. Instead, we just test group membership on a new group
allowCodeCommits
, like this:If we now make our
engineers
group be a member of allowCodeCommits
, all our engineers (and engineering interns) can commit code.Per convention, in documentation and informal language, we call groups that are mostly used for permission management (such as
allowCodeCommits
) "permissions", and groups that are mostly used for organizing members (such as engineeringInterns
) "roles". In many cases, users would be a member of roles, and roles would be a member of permissions or other roles. However, there is no technical difference between the two and it is important to understand that they are all just groups.Because groups are so simple, it is extremely easy to scale and troubleshoot your permission system, both for in-house employees and your customers. For example, to understand why a user has access to a certain resource, you can view the membership graph in the Dashboard or use the following command:
Users
Just like the difference between roles and permissions, there is nothing inherently different about a user compared to other groups.
However, in documentation and informal language, we use the terminology of "user" to refer to any direct member of the
users
group. This means that indirect members (such as access tokens or API keys) are not considered users, even if they are direct members of other users.New members of this group are automatically created when a provider returns with successful authentication. Additionally, $PLACEHOLDER_NAME$ allows any group that is a direct member of the
users
group to have a user profile associated with it.Access expiration
...
Computed groups
...
Trees
For security or compliance reasons, you may want to separate some permissions from others. Group trees are a great way to do this. Note that more complex security & compliance requirements are better served by security invariants.
If you don't create any trees, all your data is in the
default
tree. To create a new tree:Please note that all trees are entirely separate. This yields strong compliance guarantees, but makes interop between trees impossible. If you are not sure whether you should use trees for your application, don't; organizing groups via membership with security invariants is enough for most cases, and you will know when creating total separation is necessary.
Security invariants
TODO I haven't looked at this in detail yet, the approach below won't work
Even inside a tree, it is possible to create strong guarantees with security invariants. Essentially, each invariant ensures that its predicate is always true; if a modification would make it false, the modification is rejected.
For example, if you want to make sure that no one with the
engineeringInterns
role can ever get access to your readInternEvaluations
permission:Please be aware that $PLACEHOLDER_NAME$ rejects any computed group that would allow falsifying a security invariant, even if the predicate is never actually true.