# API Scopes

API scopes are token-level access restrictions that sit on top of role-based permissions. They control which parts of the API a token can access, independent of the user's role.

For role-based permissions, see [Roles & Permissions](roles-and-permissions.md). For the RBAC model, see [Authorization Concepts](../concepts.md).

## How Scopes Work

Scopes are included in OIDC tokens and follow the format `resource-group:access-type`. Each API endpoint is associated with one or more required scopes.

When a request arrives, the PDP checks:

1. Does the token have at least one of the endpoint's required scopes?
2. Does the principal have the required role permissions in the workspace?

Both must pass. This is the **two-layer authorization** model.

## Available Scopes

### Per-API Scopes

Each API has a read and write scope. A token with an API-specific scope can only access that API's endpoints.

| API | Read Scope | Write Scope | Endpoints |
|------|-----------|-------------|------|
| Audit | `audit:read` | `audit:write` | `/apis/audit/` |
| Auth | `auth:read` | `auth:write` | `/apis/auth/` |
| Data Designer | `data-designer:read` | `data-designer:write` | `/apis/data-designer/` |
| Entities | `entities:read` | `entities:write` | `/apis/entities/` (internal — see note) |
| Evaluation | `evaluation:read` | `evaluation:write` | `/apis/evaluation/` |
| Files | `files:read` | `files:write` | `/apis/files/` |
| Guardrails | `guardrails:read` | `guardrails:write` | `/apis/guardrails/` |
| Inference | `inference:read` | `inference:write` | `/apis/inference-gateway/` |
| Jobs | `jobs:read` | `jobs:write` | `/apis/jobs/` |
| Models | `models:read` | `models:write` | `/apis/models/` |
| Safe Synthesizer | `safe-synthesizer:read` | `safe-synthesizer:write` | `/apis/safe-synthesizer/` |
| Secrets | `secrets:read` | `secrets:write` | `/apis/secrets/` |

!!! note
    The `entities:read` and `entities:write` scopes are for internal service-to-service usage. The generic entities API is not accessible to regular users — only PlatformAdmin and service principals can access it. Users interact with entities through feature-specific APIs (Models, Evaluation, etc.) which use their own scopes.

### Platform Scopes

The `platform:*` scopes act as catch-alls that grant access to **all** APIs:

| Scope | Description |
|-------|-------------|
| `platform:read` | Read access to all platform APIs |
| `platform:write` | Write access to all platform APIs |

Each endpoint in the authorization policy lists both its API-specific scope and the corresponding `platform:*` scope. A token needs at least one of the listed scopes to pass the scope check.

### Requesting Scopes

The CLI requests `platform:read platform:write` by default, granting full access. You can restrict a token to specific areas:

```bash
# Full access (default)
nemo auth login

# Read-only access to everything
nemo auth login --scope "platform:read"

# Only evaluation and models access
nemo auth login --scope "evaluation:read evaluation:write models:read models:write"
```

## Two-Layer Authorization

For a request to succeed, it must satisfy **both** requirements:

1. **Token scope check**: The API token must have at least one of the endpoint's required scopes
2. **Permission check**: The principal must have the required permissions through role grants in the workspace

### Examples

| User Role | Token Scopes | Request | Result |
|-----------|-------------|---------|--------|
| Editor | `platform:read platform:write` | Create model | ✓ Allowed |
| Editor | `platform:read` only | Create model | ✗ Denied by scope check |
| Viewer | `platform:read platform:write` | Create model | ✗ Denied by role check |
| Viewer | `platform:read` | List models | ✓ Allowed |

This enables least-privilege tokens: an Editor can create a read-only token (`platform:read`) for monitoring scripts that should never modify resources.

## IdP Configuration

Scopes must be registered in your IdP as custom API scopes. The CLI requests them during the OAuth flow, and the IdP includes granted scopes in the access token.

If your IdP prefixes scopes (e.g., Azure AD uses `api://client-id/platform:read`), configure `scope_prefix` in the {{platform_name}} OIDC settings so the platform strips the prefix before authorization:

```yaml
auth:
 oidc:
 scope_prefix: "api://your-client-id/"
```

If you use per-API scopes, each scope (e.g., `api://nmp/models:read`) must be exposed individually in the IdP app registration.

## Scope Checking Behavior

The PDP distinguishes between OIDC standard scopes and platform scopes:

- **No scopes in token**: Scope checking is skipped (backward compatible)
- **Only OIDC scopes** (`openid`, `profile`, `email`): Treated as no platform scopes — checking skipped
- **Platform scopes present** (contain `:`): At least one required scope must match
- **PlatformAdmin**: Bypasses scope checking entirely

## When to Restrict Scopes

- **CI/CD tokens** that should only read: `platform:read`
- **Monitoring scripts** that should never modify resources: `platform:read`
- **Evaluation-only pipelines**: `evaluation:read evaluation:write models:read`
- **Data ingestion scripts**: `files:read files:write`
- **Shared service accounts**: limit blast radius by restricting to only the areas needed

## Related

- [Roles & Permissions](roles-and-permissions.md) — Role-based permission model.
- [Using Authentication](../authentication/using-authentication.md) — Log in, requesting scopes, and token management.
- [OIDC Setup](../authentication/oidc.md) — Configuring scope prefix and default scopes.
- [Security Model](../security-model.md) — Trust boundaries and two-layer authorization.
