Authorization
Magistrala's authorization model — Atom's Permission Blocks, Roles, and Direct Policies, and how Magistrala services (including Enterprise ones) check access against Atom.
SpiceDB is gone — authorization now runs through Atom
No SpiceDB container exists in docker-compose.yaml, and the old per-entity relations/permissions
schema and REST role management API (/<entity_type>/<entity_id>/roles) no longer apply.
Authorization is now owned entirely by Atom — see Auth.
The model
Atom answers one question: can subject S perform action A on object O?
Subject gets a Role.
Role contains Permission Blocks.
Direct Policy gives a Subject one Permission Block directly.
Permission Block is the only place where scope and actions are defined.| Term | Meaning |
|---|---|
| Subject | The entity or principal group receiving access — in Magistrala terms, a User, Device, or Gateway. |
| Action | An operation name such as read, write, publish, manage. Atom seeds 13 common ones; tenants can add more. |
| Action Applicability | A valid action/object-kind-and-type pairing (e.g. publish is applicable to resource:channel) — governs which actions are even selectable for a given object. |
| Permission Block | Scope + actions + effect (allow/deny) + optional ABAC conditions. The only place access is actually defined. |
| Role | A friendly name bundling one or more Permission Blocks, assignable to subjects. |
| Direct Policy | Gives one Permission Block directly to one subject — narrower and more auditable than a full role. |
| Assignment Guardrail | An assignment-time rule blocking/allowing a given action from being granted to a given entity kind at all. |
| Principal Group | A who-container — members inherit role assignments made to the group. |
| Object Group | A where-container — permission blocks can target everything inside it. |
Every new tenant (Workspace) gets a seeded tenant-admin role with the full administrative permission set — the successor to the old built-in admin role.
Decision flow
Deny-by-default, deny-overrides-allow:
- Load the subject and the object being acted on.
- Resolve the action and validate it's applicable to that object kind/type.
- Collect the subject's role assignments and direct policies (expanding principal group membership).
- Evaluate every matching Permission Block.
- Any matching
deny→ Deny, full stop, regardless of anyallow. - Otherwise, any matching
allow→ Allow. - No match at all → Deny (the default).
Permission Block shape
This is what Magistrala's Go code sends/receives:
type PermissionBlock struct {
ID string
TenantID string
ScopeMode string
ObjectKind string // e.g. "entity", "resource", "group", "tenant", "role", "policy"
ObjectType string // namespaced, e.g. "resource:rule", "resource:invoice"
ObjectID string // set only for an exact-object scope
GroupID string // set only for group-scoped modes
Effect string // "allow" or "deny"
Conditions map[string]any // ABAC, {} for unconditional
Actions []Capability
}ScopeMode is one of nine values: the tenant itself; all objects of a kind; all objects of a type; one exact object (by ObjectKind/ObjectType/ObjectID); an object group itself; direct objects in a group; objects in subgroups; direct child groups; or descendant groups.
DirectPolicy (one Permission Block → one subject) and GroupGrant (one Permission Block → every member of a principal group, present and future) are the two ways a block actually reaches a subject without going through a named Role — both also transcribed directly from pkg/atom/types.go.
How Magistrala services check authorization
Every service that needs an authorization decision — including the Enterprise alarms, reports, and re (Rules Engine) services — asks Atom the same shape of question Magistrala's own Go types describe:
type AuthzRequest struct {
SubjectID string
Action string
ResourceID string
ObjectKind string
ObjectID string
Context map[string]any
}
type AuthzResponse struct {
Allowed bool
Reason string
}The Enterprise services observed use ObjectKind = "resource" with a namespaced ObjectType like resource:rule — consistent with Atom's generic object-kind model above, not a bespoke per-service schema. The publicly-runnable equivalent is the CLI:
magistrala-cli authz check <subject_id> <action> --object-kind <kind> --object-id <id> --token <token>(see the Authz CLI — the only authorization-related CLI command; there is no CLI for managing Roles/Permission Blocks/Direct Policies themselves, which are administered through Atom directly.)
Atom's action set is tenant-configurable rather than a fixed compiled schema the way SpiceDB's was, so this page doesn't maintain a static action catalog table — it would go stale. Use Atom's own Actions and Effective Actions views to see what's actually granted right now.
API
Magistrala API reference for users, workspaces, devices, channels, groups, and messages — Atom's GraphQL API plus the still-current HTTP/MQTT/CoAP/WS message publishing endpoints, with sample requests.
Authentication
Secure user and client access in Magistrala via JWTs, Google OIDC, API keys and mutual TLS (mTLS).