# Configuring Logto API Resources and Scopes for Authorization

> Learn to configure Logto API resources and scopes for robust OAuth 2.0 authorization. Define protected APIs and granular permissions for your applications.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: how-to-guide
- Published: 2026-07-04

---

**Logto implements OAuth 2.0 / OpenID Connect authorization by separating API resources from scopes, allowing you to define protected APIs as resources and granular permissions as scopes, then assign specific scope whitelists to applications that clients request during the authorization flow.**

Logto is an open-source identity and access management platform that follows the OAuth 2.0 and OpenID Connect standards. Configuring Logto API resources and scopes for authorization involves defining protected APIs as **resources**, creating granular **scopes** for those resources, and linking allowed scopes to **applications** so that access tokens carry only the permissions granted by the user. This architecture, implemented in the `logto-io/logto` repository, enables fine-grained access control across distributed services.

## Understanding the Resource and Scope Architecture

Logto models authorization through three interconnected entities: resources, scopes, and applications. This separation allows you to reuse scope names across multiple APIs while maintaining distinct permission boundaries.

### Resource Definition

In [`packages/schemas/src/types/resource.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/resource.ts), a **resource** represents a protected API endpoint. Each resource stores an identifier, name, description, and an array of associated scopes. The resource acts as the top-level container for permissions, allowing you to group related scopes under a single API entity.

### Scope Model

Individual scopes are defined in [`packages/schemas/src/types/scope.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/scope.ts) as first-class entities containing `id`, `name`, `description`, and `resourceId` fields. The file exports `scopeResponseGuard` for runtime validation, ensuring that scope data conforms to the expected schema before persistence. Scopes are simple strings (such as `read:user` or `write:order`) that represent specific operations a client can perform against the resource.

### Application Linkage

Applications (OAuth clients) store their permitted scopes in the `scopes` field, as defined in [`packages/schemas/src/types/application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/application.ts). This field acts as a whitelist that determines which scopes the client is allowed to request during the authorization flow. When a user authenticates, Logto validates that the requested scopes are a subset of the application's stored scopes.

## How Logto Evaluates Authorization Scopes

The authorization flow in Logto evaluates scopes through a four-stage filtering process:

1. **Application-level whitelist** – The client can only request scopes explicitly listed in the application's `scopes` field.
2. **Tenant-level configuration** – Global tenant settings enable or disable specific scopes (such as `Roles` or `Organizations`); disabled scopes are filtered out before the consent page renders.
3. **Consent page** – The user interface displays the intersection of requested scopes and available scopes, allowing the user to approve or deny each permission individually.
4. **Token issuance** – The final access token contains a space-separated `scope` claim listing only the approved scopes, which the resource server validates against required permissions.

## Configuring Resources via the Management API

Administrators manage resources and scopes through Logto's Management API. The API payloads mirror the schema definitions found in the source code, ensuring type safety between the backend and client requests.

### Creating a New Resource with Scopes

Use the `POST /api/resources` endpoint to create a resource and define its scopes in a single request:

```http
POST https://<logto-host>/api/resources
Content-Type: application/json
Authorization: Bearer <admin-access-token>

{
  "name": "Orders API",
  "description": "Access to order data",
  "scopes": [
    { "name": "order:read",  "description": "Read order information" },
    { "name": "order:write", "description": "Create or modify orders" }
  ]
}

```

The scopes array in the request body corresponds to the `Scope` type defined in [`packages/schemas/src/types/scope.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/scope.ts).

### Adding Scopes to Existing Resources

To append scopes to an existing resource without recreating it, target the resource-specific scopes endpoint:

```http
POST https://<logto-host>/api/resources/123456/scopes
Content-Type: application/json
Authorization: Bearer <admin-access-token>

{
  "name": "order:delete",
  "description": "Delete an order"
}

```

This endpoint creates a new scope entity and associates it with the resource identified by `123456`.

### Assigning Scopes to Applications

Before a client can request scopes, you must update the application configuration to whitelist those permissions:

```http
PATCH https://<logto-host>/api/applications/abcdef
Content-Type: application/json
Authorization: Bearer <admin-access-token>

{
  "scopes": [
    "order:read",
    "order:write"
  ]
}

```

This modification updates the application's `scopes` field in [`packages/schemas/src/types/application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/application.ts), enabling the authorization server to validate future requests.

## Requesting and Validating Scopes in the OAuth Flow

After configuration, the runtime flow handles scope validation according to the logic in [`packages/toolkit/core-kit/src/openid.ts`](https://github.com/logto-io/logto/blob/main/packages/toolkit/core-kit/src/openid.ts).

### Authorization Request

Clients initiate the flow by requesting specific scopes via the `scope` query parameter:

```text
GET https://<logto-host>/oidc/auth
?client_id=abcdef
&redirect_uri=https%3A%2F%2Fmyapp.com%2Fcallback
&response_type=code
&scope=order:read%20order:write
&state=xyz

```

Logto parses this parameter, validates the scopes against the application whitelist and tenant configuration, and stores the authorized set in the interaction session.

### Token Validation in Protected Endpoints

Resource servers must verify that incoming access tokens contain the required scope. A Node.js implementation using the Logto SDK appears as follows:

```js
import { verifyAccessToken } from '@logto/node';

app.get('/orders/:id', async (req, res) => {
  const token = await verifyAccessToken(req.headers.authorization);
  if (!token.scope.includes('order:read')) {
    return res.status(403).json({ error: 'Insufficient scope' });
  }
  // ... fetch and return order data
});

```

The `scope` claim in the token is a space-separated string of granted permissions, matching the format defined in the OAuth 2.0 specification.

## Summary

- **Resources** represent protected APIs and contain arrays of scopes, defined in [`packages/schemas/src/types/resource.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/resource.ts).
- **Scopes** are first-class entities with `name`, `description`, and `resourceId` fields, validated by `scopeResponseGuard` in [`packages/schemas/src/types/scope.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/scope.ts).
- **Applications** whitelist allowed scopes in their configuration, stored in the `scopes` field per [`packages/schemas/src/types/application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/application.ts).
- The **Management API** provides endpoints to create resources (`POST /api/resources`), add scopes (`POST /api/resources/:id/scopes`), and configure applications (`PATCH /api/applications/:id`).
- The **authorization flow** validates requested scopes against application whitelists and tenant settings before issuing tokens containing space-separated scope claims.

## Frequently Asked Questions

### What is the difference between a resource and a scope in Logto?

A **resource** represents the protected API itself (such as "Orders API"), while a **scope** represents a specific permission within that API (such as "read orders" or "write orders"). Resources act as containers that group related scopes together, allowing you to manage permissions at both the API level and the individual operation level.

### How do I restrict which scopes an application can request?

Update the application's `scopes` field via the Management API (`PATCH /api/applications/:id`) to include only the specific scope names you want to allow. Logto validates every authorization request against this whitelist, rejecting any request for scopes not explicitly listed in the application configuration.

### Can I reuse scope names across different API resources?

Yes. Because scopes are linked to resources via the `resourceId` field, you can define identical scope names (such as `read:data`) on multiple resources. This allows consistent naming conventions across services while maintaining distinct permission boundaries, as the resource identifier distinguishes which API the scope belongs to.

### How does Logto handle OpenID Connect standard scopes?

Logto recognizes standard OIDC scopes (such as `profile`, `email`, and `openid`) through the logic in [`packages/toolkit/core-kit/src/openid.ts`](https://github.com/logto-io/logto/blob/main/packages/toolkit/core-kit/src/openid.ts). These scopes map to specific claims in the ID token and can be toggled at the tenant level. Custom scopes defined for your API resources work alongside these standard scopes in the same authorization request.