Skip to content
Authorization

Authorization

Authorization is the process of deciding what an authenticated identity is allowed to do. In Roled, it answers the question: “What are you allowed to do?”

Authentication vs. Authorization

Authorization always comes after authentication. You must first prove who you are before Roled decides what you can access.

AuthenticationAuthorization
QuestionWho are you?What are you allowed to do?
MechanismOAuth 2.0 flow → JWTPermission middleware
ResultAccess token200 OK or 403 Forbidden
WhenOnce per sessionOn every request

How Authorization Works in Roled

Every incoming request to a protected endpoint goes through the same process:

    flowchart TD
    A["Incoming request with Bearer JWT"] --> B["Validate JWT"]
    B --> C["Identify: user or client?"]
    C --> D{User token?}
    D -- Yes --> E["Find user's permissions from the role"]
    D -- No --> G["Find client's direct permissions"]
    E --> H["Build permission set"]
    G --> H
    H --> I{Required permission\nin set?}
    I -- Yes --> J["Allow request"]
    I -- No --> K["403 Forbidden"]
  

This identical process applies to both users and machine clients — the difference is only in where permissions come from.

Where Permissions Come From

For Users (via Roles)

A user’s permissions come from their assigned role. Each role has a set of permissions:

    graph LR
    User["User: Alice Smith"] --> Role["Role: Store Manager"]
    Role --> P1["products:create"]
    Role --> P2["products:update"]
    Role --> P3["orders:read"]
  

When Alice makes a request, Roled:

  1. Finds Alice’s role from the database.
  2. Loads all permissions for that role.
  3. Checks whether the required permission is in the list.

For Clients (Direct Permissions)

A client’s permissions are assigned directly, without going through a role:

    graph LR
    C["Client: Backend Service"] --> P1["users:read"]
    C --> P2["users:create"]
    C --> P3["users:update"]
    C --> P4["roles:read"]
  

When the backend service makes a request, Roled loads its directly-assigned permissions and checks them.

OAuth Scopes

In traditional OAuth 2.0 setups, applications request specific scopes during authentication to specify required permissions (e.g., read:users, write:posts).

Roled takes a streamlined approach: user and client permissions are deliberately managed and assigned by project administrators rather than requested dynamically by applications.

Instead of requiring applications to request individual scopes at login, Roled automatically evaluates access based on the roles and permissions assigned to the user or client. Project administrators define exactly who can perform which actions, while applications simply authenticate and let Roled enforce access control.

This has several advantages:

  • Simpler for developers — no need to understand or declare scopes.
  • Centrally managed — administrators change permissions without touching application code.
  • Consistent model — the same authorization logic applies to both users and machine clients.
  • Instant effect — permission changes take effect immediately without requiring token reissuance.

Checking Authorization in Your Application

Your application can use the /api/v1/tokens/current endpoint to check what the current user or client is allowed to do:

curl --request GET \
  --url https://auth.roled.id/api/v1/tokens/current \
  --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJo...'

This returns the identity’s project, role, and full list of effective permissions — useful for building UI permission guards or pre-flight checks in your application.

{
  "success": true,
  "data": {
    "id": "2JTsCIYytiCinRkhtWVN2q",
    "issued_at": "2026-07-29T10:00:00Z",
    "expires_at": "2026-07-29T11:00:00Z",
    "project": {
      "id": "2JUSLUee46xG6iEwG8JwPc",
      "name": "Business App",
      "description": "App for managing business operations",
      "logo_url": "https://example.com/logo.png"
    },
    "client": {
      "id": "2JRYkzSeBV89itqcU9mraF",
      "name": "Main Client"
    },
    "user": {
      "id": "2JRtk7i2aEFKpsKTNx6YWR",
      "display_name": "Alice Smith",
      "email": "alice.smith@example.com",
      "external_user_id": "921f28239dcd",
      "avatar_url": "https://example.com/profiles/alice-smith.jpg"
    },
    "role": {
      "id": "2JRtjyxfZudzaJkFczgoUY",
      "code": "store-manager",
      "name": "Store Manager",
      "description": "Manages store operations including products, orders, and staff"
    },
    "permissions": [
      "products:create",
      "products:read",
      "products:update",
      "products:delete",
      "orders:read",
      "orders:update",
      "users:read"
    ]
  }
}

Design Principles

Roled’s authorization model is built around a few clear principles:

  1. Server-side resolution — permissions are always resolved from the database, never trusted from the JWT payload.
  2. Instant effect — changing a role’s permissions or a client’s permissions takes effect immediately on the next request.
  3. Uniform model — the same permission resolution logic applies to users and clients.
  4. Admin-controlled — the project administrator defines access rules, not individual applications.

Key Points

  • Authorization answers “What are you allowed to do?” — it happens after authentication.
  • Users get permissions through their role; clients have permissions assigned directly.
  • Permissions are resolved server-side on every request — never from the JWT.
  • Permission changes take effect immediately without token reissuance.
  • Roled does not use OAuth scopes — permissions are centrally defined by administrators.
  • The 403 Forbidden response is returned when a permission is missing.