Two things go wrong with role models, and they go wrong in that order.
First, the hierarchy is a tree, and organisations are not trees. A role that should inherit from both the operations side and the analytics side has to pick one parent and duplicate the other, and from then on the two copies drift.
Second, and worse, the role is not the thing being granted. What is being granted is a slice: manager of these regions, buyer in these categories, clinician at these sites. A role name cannot hold that, so it gets encoded in a string, or in a table the application maintains, or in code. Once it is in code, nobody can answer who has access to what without reading the code.
What SkipAuth does
Functional roles are a directed acyclic graph. A role can have several parents. Membership is inherited along every path, and the hierarchy has real paths that appear in the token as group entries, so an application can see the shape it was granted through.
Scopes attach to an assignment and combine cross-product. A scope is a type
and a value. The combining rule is one sentence: values of the same type are
alternatives, values of different types are combined. So an assignment
carrying region = TX, CA and category = produce, dairy resolves to four
grants:
region=TX · category=produce
region=TX · category=dairy
region=CA · category=produce
region=CA · category=dairy
That is "regional manager of locations in Texas and California, in produce and dairy", expressed without a policy engine and without a line of application code.
Resolution happens at issuance. Entitlements and role paths are recomputed every time a token is minted or refreshed, and written into the token. A stale claim is not consulted, because there is no cached claim to consult. Taking a role away takes effect at the next token rather than at the next review.
Two built-in roles exist because every deployment needs them: one that every identity joins at first sign-in, and one that carries tenant administration.
How to check it
The check that matters is not "can I create a role". It is these three:
- Give a role two parents. If the product refuses, it is a tree with a graph in the marketing copy.
- Assign a scoped role and read the token. The entitlements and the group paths should be present and should already be expanded. If the token carries the role name and the expansion happens in your application, the model is yours to maintain and not the product.
- Remove the role and refresh. The next token should be missing the grant. If the grant survives until the token expires, the revocation story is "eventually".
Where it stops
Somebody has to model it. A graph with cross-product scopes will express your organisation, and it will also express a mess if you build one. This model rewards a deliberate design and punishes an accumulation.
It answers per identity, not per object. The console gives you the role tree, the member editor, a scope explorer and a resolved-permission inspector, so the question "what does this person end up with" has one place to ask it. The reverse question, "who can reach this object", is a query against your own data plus the role graph, because SkipAuth holds the graph and your application holds the objects.
Permissions are strings, with wildcards. A permission is a resource and an action, and wildcards are supported. It is deliberately not a policy language. If you need conditions evaluated at request time against request attributes, that is a policy engine and this is not one.
What the alternatives ask of you
| Approach | What it asks of you | SkipAuth |
|---|---|---|
| Nested groups in an identity provider | Model the hierarchy, then encode the slice in group names and parse them everywhere. | The slice is data on the assignment, and the token carries it expanded. |
| A policy engine such as OPA or Cedar | Write and test policy code, and keep a second deployment in the request path. | The common case, hierarchy and scoped assignment, needs no code at all. |
| An authorization model in your own database | Build the model, the resolver, the caching and the audit, then keep it in step with your directory. | The resolver is the same one that issues tokens, so there is nothing to keep in step. |
| Roles in each application separately | Repeat the model per application, and answer "who has access" by asking each team. | One graph per tenant, and one place to ask. |
Read next: per-resource access, managed by your own application, which is the same engine handed to your applications.