Authorization Model¶
DotID’s Authorization Service implements a resource-based access-control
system inspired by AWS IAM.
It acts as a Policy Decision Point (PDP): callers describe who wants to do
what on which resource, and the service returns ALLOW or DENY.
Core Concepts¶
Accounts¶
An Account is the top-level organizational container (tenant). Every
resource FRN includes an account-id segment so that policies can be scoped
per tenant.
Groups¶
A Group collects one or more principals (users or service-account clients). Groups are the “who” axis of the authorization model.
Each member is stored as a GroupMember with:
principalId – the Keycloak subject identifier (
subclaim).principalType –
userorclient.
A principal may belong to multiple groups.
Policy Sets and Policies¶
A PolicySet is a named container that groups related policies.
A Policy holds the actual authorization rules in a JSON document
stored as JSON. See Policy Document Format for the
full schema.
Permissions (the Binding)¶
A Permission is the three-way binding that answers:
“Which policies apply when members of Group G access resources in Account A?”
The answer is the policies inside Policy Set S.
Principal --> GroupMember --> Group
|
Permission
|
Account (resource scope)
|
PolicySet
|
Policy (1..N)
|
Statement[]
The tuple (group_id, account_id, policy_set_id) is unique – duplicate
bindings are rejected with HTTP 409.
Evaluation Algorithm¶
The policy engine implements a classic explicit-deny-wins evaluation model with support for IAM policies, SCPs, resource policies, permission boundaries, and delegated administrator grants. A single authorization check proceeds as follows:
Parse the resource FRN – validates the FRN string; rejects malformed identifiers immediately.
Resource-based policy – if a resource policy exists for the target FRN and explicitly allows/denies the action, return early.
Root user bypass – root users have implicit full access to their own account (like AWS root), no policy attachment needed. If the principal is a root user and the target resource belongs to the same account, return ALLOW with reason
ROOT_USER_BYPASS.Resolve identity-based policies – resolves group memberships via account assignments, IAM managed/inline policies, and permission set policies for the principal.
Explicit Deny (identity) – iterate every statement with
"Effect": "Deny". If any statement matches, return DENY immediately (deny always wins).SCP evaluation – for principals in an organization, evaluate Service Control Policies. If the action is not allowed by any SCP, return DENY.
Explicit Allow (identity) – iterate every statement with
"Effect": "Allow". If a statement matches, proceed to boundary check.Delegated Admin Allow – if no identity policy granted access, check whether the principal qualifies as a delegated administrator:
The principal must be a root user (
userType == "root").The principal’s account must have a delegation for the action’s service namespace (the prefix before the first
:in the action string, e.g.,"audit"from"audit:Event:Read").The namespace must be eligible for delegation (see below).
The target resource must belong to an account within the same organization as the delegation.
Requests targeting the principal’s own account are skipped (root users already have full access on their own account).
Wildcard FRN targets (account segment
*) are allowed.
If all conditions pass, the check returns
matchedStatement: "DelegatedAdminAllow"and proceeds to the permission boundary check.Namespace delegation eligibility
Only operational and observability namespaces may be delegated. Governance and security-critical namespaces are permanently excluded to prevent privilege escalation:
iam– not delegable. A delegate could modify or remove other users’ permissions, including the root user’s own policies.org– not delegable. Organization structure is a management-account-only concern.scp– not delegable. Delegating SCP management would allow weakening security guardrails across the organization.sts– not delegable. Cross-account role assumption is identity infrastructure, not an operational service.audit– delegable. Read-only audit log access for org-wide compliance visibility.quota– delegable. View and manage service quotas across the organization.
Future namespaces follow the same rule: if delegating the namespace could allow the delegate to alter, escalate, or remove permissions for other principals, it must not be delegable.
Permission boundary – if a permission boundary is set for the user, verify the action is within the boundary. If not, return DENY.
Return ALLOW – if a matching allow statement (or delegation grant) survived all checks, return ALLOW.
Default DENY – if no statement matched, return DENY.
Audit logging – every decision (including default denies) is persisted to the audit log.
Statement Matching¶
A statement matches only when all three sub-checks pass:
Action matching
Exact match:
"devices:Read"matches only"devices:Read".Global wildcard:
"*"matches any action.Service prefix wildcard:
"devices:*"matches any action starting with"devices:".
Resource matching
Literal
"*"matches any resource.Otherwise the pattern is parsed as an FRN and matched segment-by-segment using
FrnMatcher(see FRN Specification).
Condition matching
Conditions apply additional constraints based on the request context map.
All operators in a statement must pass (AND logic).
Operator |
Semantics |
|---|---|
|
|
|
|
|
|
|
|
Unknown operators evaluate to false and log a warning.
Condition keys may carry a dotid: prefix (stripped before lookup).
Context keys are tried in both their original form and a
camelCase to snake_case converted form.
Batch Evaluation¶
The batch endpoint loads group memberships and policies once for a principal, then evaluates each check against the pre-loaded data. This is significantly more efficient than issuing individual requests.
Capabilities¶
Capabilities are account-level business qualifications stored on the Account entity in the DotID authorization service. They are distinct from — and evaluated after — the SCP/IAM policy evaluation described above.
The evaluation order is:
Roles, SCPs, and IAM policies are evaluated (steps 1–11 above).
If the result is
ALLOW, the target service checks whether the account holds the required capability for the requested operation.If the capability is absent, the service returns
403 Forbidden("account not qualified — contact platform support").
Capabilities are not part of the policy document format and are not evaluated by the Policy Decision Point. They are checked independently by each service after authorization passes.
Known capabilities:
enroll_things— register new devices in ThingHubapprove_licenses— approve and issue licenses in TrustMintpublish_marketplace— publish products to the Bazaar marketplacemanage_ota_rollouts— create and manage OTA rollouts in OTAForge
Capabilities are granted and revoked by platform admins in SuperCrew. Accounts start with no capabilities. See Access Control Layers for the full three-layer model (Role → SCP → Capability) and how these layers interact.
Related References¶
- FRN Resource Registry
Registry of all FRN resource patterns across all services.
- Managed Policy Sets
Pre-defined, platform-provided policy sets (e.g.
IAMFullAccess,AuditReadOnlyAccess) that can be attached to IAM users and groups.
Cache Invalidation¶
Every mutation (create, update, delete) on any authorization entity
increments a global policy version counter and broadcasts a
policy.changed event over Server-Sent Events (SSE).
Downstream caches should either:
Subscribe to
GET /api/v1/events/streamand invalidate on any received event, orPoll
GET /api/v1/policy-versionperiodically.