Skip to content

Latest commit

 

History

History
266 lines (195 loc) · 6.68 KB

access.md

File metadata and controls

266 lines (195 loc) · 6.68 KB

Access authorization

The Authorization is intrinsically linked with the Authentication.

IA3

Directives

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 are authorization:{directive}.

anonymous

Grants access if its value is true and no credentials were provided1.

id

Grants access if resolved Identity matches the value of the URL path segment placeholder named after the directive's value.

Example

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.

role

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.

Dynamic roles

The role directive can be used with a placeholder in the route.

# context.toa.yaml

exposition:
  /:org-id:
    role: app:{org-id}:moderator

rule

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.

Example

# 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.

delegate

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.

Roles

Role values are strings that can be assigned to an Identity and used for matching with values of the role directive.

Hierarchies

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.

Example

# 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.

IA3

The root-level Role Scope system is preserved and cannot be used with the role directives.

See also role management resources.

Policies

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 Directive anonymous: true to both read:list and read:post Policy Scopes. This means that a list of posts and each post can be accessed without authorization.
  • an Attachment post attaches Directive id: user-id to both post:submit and post:edit Policy Scopes. This means that an Identity can submit and edit their own posts.
  • an Attachment post:edit attaches Directive role: app:posts:editor to post:edit Policy Scope. This means that an identity with the role scope app: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.

Nesting

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

  1. Credentials in the request make the response non-cachable.