The Authorization is intrinsically linked with the Authentication.
The Authorization is implemented as a set of RTD Directives.
Directives are executed in a predetermined order until one of them grants access to a resource. If none of the directives grants access, then the Authorization interrupts request processing and responds with an authorization error.
The Authorization directive provider is named
authorization
, so the full names of the directives areauthorization:{directive}
.
Grants access if its value is true
and no credentials were provided1.
Grants access if resolved Identity matches the value of the URL path segment placeholder named after the directive's value.
Given the Route declaration and corresponding HTTP request:
# context.toa.yaml
exposition:
/users/:user-id:
id: "user-id"
GET /users/87480f2bd88048518c529d7957475ecd/
Authorization: ...
For this request access will be granted if the resolved Identity value
is 87480f2bd88048518c529d7957475ecd
.
Grants access if resolved Identity has a role matching the directive's value or one of its values.
# context.toa.yaml
exposition:
/code:
role: [developer, reviewer]
Access will be granted if the resolved Identity has a role that matches developer
or reviewer
.
Read Roles section for more details.
The role
directive can be used with a placeholder in the route.
# context.toa.yaml
exposition:
/:org-id:
role: app:{org-id}:moderator
The Rule is a collection of authorization directives. It allows access only if all the specified
directives grant access. The value of the rule
directive can be a single Rule or a list of Rules.
# context.toa.yaml
exposition:
/commits/:user-id:
rule:
id: user-id
role: developer
Access will be granted if an Identity matches a user-id
placeholder and has a Role of developer
.
Embeds the value of the current Identity into the request body as a property named after the value of the directive value, and grants access. The request body must be an object.
⚠️
The intended use case for this directive is audit. Using it to pass Identity to the application logic is strongly discouraged.
Role values are strings that can be assigned to an Identity and used for matching with values of
the role
directive.
Role values are alphanumeric tokens separated by a colon (:
).
Each token defines a Role Scope, forming a hierarchy.
A Role matches the value of the rule
directive if that Role has the specified Scope in a
directive.
# context.toa.yaml
/exposition:
/commits/:user-id:
role: developer:senior
The example above defines a role
directive with the specified developer:senior
Role Scope.
This directive matches the roles developer:senior
and developer
,
but it does not match the Role developer:senior:javascript
.
In other words, the Identity must have a specified or more general Role.
The root-level Role Scope
system
is preserved and cannot be used with therole
directives.
See also role management resources.
Component Resource branches cannot have authorization directives.
Instead, they must declare Authorization Policies using policy
directive to
be attached in the Context to a Resource Tree as a set of Authorization Directives
using attachment
directive.
This restriction provides a separation of concerns, allowing components to be reused in different Contexts with varying access rules.
# manifest.toa.yaml
name: posts
exposition:
/:user-id:
GET:
endpoint: observe
policy: read:list
POST:
endpoint: transit
policy: post:submit
/:post-id:
GET:
endpoint: observe
policy: read:post
PUT:
endpoint: assign
policy: post:edit
# context.toa.yaml
exposition:
/posts:
attachment:
read:
anonymous: true
post:
id: user-id
post:edit:
role: app:posts:editor
Policy values as well as Role values define hierarchical Policy Scopes.
In the example above:
- an Attachment
read
attaches Directiveanonymous: true
to bothread:list
andread:post
Policy Scopes. This means that a list of posts and each post can be accessed without authorization. - an Attachment
post
attaches Directiveid: user-id
to bothpost:submit
andpost:edit
Policy Scopes. This means that an Identity can submit and edit their own posts. - an Attachment
post:edit
attaches Directiverole: app:posts:editor
topost:edit
Policy Scope. This means that an identity with the role scopeapp:posts:editor
can edit posts by any author, in addition to the fact that the author themselves can do this thanks to the previous Attachment.
Policies are namespace-scoped, meaning they can be attached to any Route under the
corresponding /{namespace}
prefix.
Attachment is applied to the node where it is declared, as well as its nested nodes. Directives of the Attachment are applied to the node where the attached Policies are declared, as well as their nested nodes.
Here's an example of how this works:
# manifest.toa.yaml
name: posts
exposition:
/:user-id:
GET:
endpoint: observe
policy: read
/:user-id/:post-id:
GET:
endpoint: observe
policy: read
# context.toa.yaml
exposition:
/posts:
/:user-id:
attachment:
read:
anonymous: true
/:user-id/:post-id:
attachment:
read:
role: reader
In the example above, the same Policy read
is attached to two Routes with different Directives.
The following example demonstrates the attachment of the read
Policy to both Routes with the same
Directive:
# context.toa.yaml
exposition:
/posts:
attachment:
read:
anonymous: true
Footnotes
-
Credentials in the request make the response non-cachable. ↩