Entities — Versola Docs
/docs
Pre-1.00.7.5versola.ioGitHub

Entities

Users, clients and resources — the three actors Versola is built around, and how they relate to tenants, scopes, permissions and roles

Versola is organized around the three actors of OAuth 2.0: the user (the OAuth resource owner) who owns the data, the client that wants to act on their behalf, and the resource that holds the data. Everything else in the admin console (tenants, scopes, permissions and roles) exists to describe how these three are allowed to interact.

The big picture

flowchart TB
    subgraph tenant["🏢 Tenant — configuration boundary"]
        client["📱 Client<br/><i>an application</i><br/>redirect URIs, scopes,<br/>permissions, auth flow"]
        resource["🔌 Resource<br/><i>an upstream API</i><br/>resource URI, audience,<br/>endpoints"]
        scope["🏷️ Scope<br/><i>claims released<br/>to the client</i>"]
        permission["🔑 Permission<br/><i>a set of<br/>resource endpoints</i>"]
        role["👥 Role<br/><i>a set of<br/>permissions</i>"]
    end

    owner["👤 Resource Owner<br/><i>the end user</i><br/>global identity + claims"]

    owner -->|holds roles in| tenant
    owner -->|grants access to| client
    client -->|requests| scope
    client -->|may request| resource
    resource -->|lists allowed clients in| client
    role -->|bundles| permission
    permission -->|unlocks endpoints of| resource
    client -->|carries own| permission

    style owner fill:#166534,stroke:#166534,color:#fff
    style client fill:#155e75,stroke:#e6edf3,color:#fff
    style resource fill:#155e75,stroke:#e6edf3,color:#fff
    style scope fill:#334155,stroke:#e6edf3,color:#fff
    style permission fill:#92400e,stroke:#92400e,color:#fff
    style role fill:#92400e,stroke:#92400e,color:#fff
EntityWhat it isWhere it lives
UserAn end user with an identity and claims (the OAuth resource owner)auth (global, not tenant-scoped)
ClientAn application requesting tokenscentral, inside a tenant
ResourceAn upstream API protected by edgecentral, inside a tenant
TenantThe namespace owning everything belowcentral
ScopeClaims a client may receive about the usercentral, inside a tenant
PermissionA named set of resource endpointscentral, inside a tenant
RoleA named set of permissions, assigned to userscentral, inside a tenant

Tenant — the configuration boundary

A tenant is the namespace that owns clients, resources, scopes, permissions and roles. Two tenants can each have a web-app client with no interference. A tenant may be bound to an edge deployment, and every client and resource inside it inherits that binding.

Users are deliberately not tenant-scoped: one person has one identity across the whole platform. What is tenant-scoped is their roles: a user can be an administrator in one tenant and an ordinary user in another.

Create entities in dependency order. Each step links to its guide.

  1. Tenant. Choose the security profile now: it cannot be changed later.
  2. Scopes, if your clients need their own bundles of claims.
  3. Client. A resource’s audience lists clients, so they must exist first.
  4. Resource, with its endpoints and audience.
  5. Permissions, each mapped to resource endpoints.
  6. Roles, each a set of permissions. Then open a service client again and give it the permissions it needs.
  7. Users, assigned to roles per tenant.

How a request flows through them

sequenceDiagram
    participant Owner as 👤 Resource Owner
    participant Client as 📱 Client
    participant Auth as auth
    participant Edge as edge
    participant Resource as 🔌 Resource

    Owner->>Client: Uses the application
    Client->>Auth: /authorize (scope, resource)
    Auth->>Auth: Authenticate the owner<br/>(auth flow of this client)
    Auth->>Auth: Check requested resources:<br/>client must be in resource.audience
    Auth-->>Client: Access token (aud = resource URIs)

    Client->>Edge: GET /resources/{resourceId}/orders<br/>+ access token
    Edge->>Edge: Verify signature, aud, expiry
    Edge->>Edge: Match method + path → endpoint
    Edge->>Edge: Permission check<br/>(owner roles or client permissions)
    Edge->>Edge: Evaluate allow (CEL),<br/>step-up, max age
    Edge->>Resource: Proxy request<br/>+ injected headers/query/body
    Resource-->>Edge: Response
    Edge-->>Client: Response

The two authorization gates are worth calling out separately:

  1. At token issuance (auth): the requested resource values are checked against the registry: the resource must exist in the client’s tenant, and the client must be listed in its audience. Only then does the resource URI land in the token’s aud claim.
  2. At request time (edge): the token’s aud must cover the resource, the matched endpoint must be reachable through the caller’s roles (or, for client_credentials, the client’s own permissions), and the endpoint’s allow expression must return true.

When a change takes effect

ChangeEffect
Edit which endpoints a permission maps to, or which permissions a role or client holdsedge applies it after its next configuration refresh (configuration-cache-refresh-interval). The new rules apply to tokens that were already issued
Remove a role from a userThe token’s roles claim is fixed when the token is issued. The change reaches the user’s next issued or refreshed access token. Until then the old token still carries the role
Revoke a token, a refresh chain or a sessionedge refuses the token once it has received the revocation event

Removing a role does not revoke tokens that were already issued. They keep the role until they expire.