Access Management
Guide to managing Roles, Permissions, and Website Tokens in SveltyCMS.
On this page
SveltyCMS provides a robust Role-Based Access Control (RBAC) system combined with granular permissions to secure your content and sensitive settings.
The Access Management dashboard is located at /config/access-management. The page is admin-only: the load function hard-gates on isAdmin (the config:accessManagement permission alone does not grant entry).
👥 Roles & Permissions
Users are assigned a Role, and Roles are assigned Permissions. This allows you to manage access for groups of users efficiently (e.g., “Editors”, “Authors”, “Admins”).
Admin Role
The Admin role is special. A role with the isAdmin: true flag has all permissions enabled automatically. You cannot modify individual permissions for an Admin role.
Creating & Managing Roles
- Navigate to Config > Access Management.
- Click Create New Role.
- Enter a Role Name (e.g., “Content Editor”) and optional Description.
- Toggle Is Admin if you want this role to have unrestricted access.
Permission Matrix
For non-admin roles, you must explicitly grant permissions. The system organizes permissions into logical groups:
1. Collection Permissions
Control access to specific content types.
- read (
collection:read): View entries in the collection. - create / update (
collection:write): Add and edit entries. - delete (
collection:delete): Remove entries. - collection definitions (
collections:write): Create and modify collection schemas. The create/update/delete definition verbs are aliases of this grant.
There is no separate publish permission in the current catalog. Publishing is a status transition on an entry that still requires collection:write plus the server-side workflow and required-field gates.
2. System Permissions
Control access to core system features:
-
User Management: Create, edit, or delete users (
user:create,user:read,user:write,user:delete,user:manage). -
Configuration: Access system settings, logs, and server info (
config:read,config:write,config:settings,config:audit,config:systemHealth). -
Content Management: Read/write/export/import/sync content (
content:read,content:write,content:export,content:import,content:sync). -
Media Management: Upload and manage files in the Media Library (
media:read,media:write,media:delete).- Admins: Can view, edit, and delete all media files in the system.
- Other Roles: The media list is owner-filtered when the UI passes the user, but the API routes authorize by permission and tenant scope — a role holding
media:writecan mutate another user’s asset by ID. Treat media grants as tenant-wide unless you add a custom ownership gate.
-
Webhooks Management: Configure and secure external HTTP triggers (
config:webhooks). -
API Access: Grant specific endpoint families (
api:graphql,api:collections,api:media,api:website-tokens, …). The catalog uses endpoint names; there is no blanketapi:read/api:writepair.
Changes to permissions take effect immediately for new requests, but users may need to refresh their session (logout/login) for UI elements to update fully.
🧭 Row-Level Access Rules (ACCESS_RULES)
Endpoint RBAC answers whether a role may read a collection. ACCESS_RULES answers which rows — as a query constraint, so pagination, keyset cursors, COUNT(*) and streaming all reflect the caller’s real view instead of filtering after the page was computed.
Configure it in config/private.ts (or the private system settings):
ACCESS_RULES: {
posts: {
editor: { read: { authorId: "$user._id" } },
reviewer: { read: { status: ["draft", "review"] } },
regional: { read: { tenantId: "$tenant.id", status: "published" } },
},
}
| Value | Meaning |
|---|---|
"published" / 42 / true |
Literal equality. |
["draft", "review"] |
Translated to $in. |
"$user._id" |
The authenticated user’s id. |
"$user.role" |
The authenticated user’s role. |
"$tenant.id" |
The resolved tenant id (global when tenancy is off). |
Semantics
- The rule is merged as the left side of
$and, so a caller-supplied filter can never widen the scope. - Admins, system callers, and roles without an entry are unrestricted (backward compatible; no rule = no cost beyond a memoized lookup).
- Point reads, list reads, streaming exports,
count/total, single updates/deletes and bulk updates/deletes all enforce the same rule. A hidden row returns404on mutation, so existence is not revealed. - Only top-level fields are supported. Rules are declarative so they can be indexed; there is no expression language.
- The config is memoized for 60 seconds and invalidated immediately when settings are saved.
Pair a rule with an index on the constrained field (e.g. authorId) — the fragment is merged into the normal query, so the existing index plans apply unchanged.
🔑 Website Tokens
Website Tokens are persistent API keys designed for machine-to-machine communication. They are ideal for:
- Connecting your frontend website (Next.js, SvelteKit, etc.) to the CMS.
- Running automated build scripts.
- Third-party integrations.
Website Tokens vs. User Tokens
| Feature | Website Token | User Token |
|---|---|---|
| Purpose | Server-side integration | User authentication (Login) |
| Expiration | Permanent (until revoked) | Temporary (Session-based) |
| Permissions | Scoped to specific actions | Inherits User’s Role |
| Creation | Manually generated in Admin | Generated via Login API |
Managing Website Tokens
-
Generate Token:
- Enter a descriptive name (e.g., “Production Website”).
- Click Generate.
- Copy the token immediately. For security, it is shown only once.
-
Usage:
- Include the token in the
Authorizationheader of your API requests:Authorization: Bearer <your_token>
- Include the token in the
-
Revocation:
- Click Delete next to a token to immediately invalidate it. All applications using that token will lose access.
Permissions for Tokens
You can now assign Granular Permissions to Website Tokens. By default a token is created with an empty permission list — it is fail-closed and can access nothing until you grant permissions (e.g. collection:read, media:read). Administrators explicitly choose the grants during creation.
Token Expiration
For enhanced security, Website Tokens can have an expiration date:
- 30 Days (Short-term)
- 90 Days (Standard rotation)
- 1 Year (Long-term integration)
- Custom Date
- Never (Use with caution)
Tokens nearing expiration (less than 7 days) are highlighted in the management table. Expired tokens are automatically rejected by the API.
🛡️ Enterprise SSO & OIDC Identity Providers
SveltyCMS includes native Single Sign-On (SSO) support for OpenID Connect (OIDC) and SAML 2.0. OIDC providers are configured from Config > Access Management (Tab 4: SSO & OIDC). SAML 2.0 is configured separately through the /api/auth/saml/* endpoints (see the Authentication API Reference); it is not rendered in Tab 4.
Pre-Configured Provider Presets
The SSO configuration panel provides 1-click presets for popular enterprise identity providers:
- Google Workspace:
https://accounts.google.com - Microsoft Entra ID (Azure AD):
https://login.microsoftonline.com/{tenantId}/v2.0 - Okta:
https://{yourOktaDomain}.okta.com - Auth0:
https://{yourDomain}.auth0.com - Keycloak:
https://{keycloakDomain}/realms/{realm} - Generic OIDC: Any standard OpenID Connect compliant identity provider.
Automated OIDC Discovery
When specifying an issuer URL, clicking Verify Discovery automatically queries the identity provider’s /.well-known/openid-configuration document and configures:
- Authorization Endpoint
- Token Endpoint
- JWKS URI (for RS256/ES256 cryptographic signature validation)
- End Session Endpoint (for RP-Initiated federated logout)
RFC 7636 PKCE Hardening
All OIDC login transactions strictly implement RFC 7636 PKCE (Proof Key for Code Exchange) using the S256 SHA-256 method:
- SveltyCMS generates a cryptographically random 32-byte
code_verifier. - Computes the base64url-encoded SHA-256
code_challenge. - Stores the verifier in a secure, short-lived HttpOnly cookie (
oidc_login_state). - Sends the
code_challengeandcode_challenge_method=S256to the authorization server. - Exchanges the authorization code along with the verifier, immunizing against authorization code injection or interception attacks.
Just-In-Time (JIT) Auto-Provisioning
When enabled, users logging in via SSO for the first time are automatically provisioned in SveltyCMS without requiring pre-registration or manual administrative invites.
- Default Role: Newly provisioned accounts are assigned a configurable default role (e.g.
viewerorauthor). - Claim-to-Role Mapping: Define fine-grained mapping rules based on JWT claims (e.g.
groups,roles, ordepartment):groups: CMS-Admins$\to$admingroups: Content-Editors$\to$editorgroups: Contributors$\to$author
- Role Sync on Login: When toggled, the user’s role is automatically updated on subsequent logins if group memberships change in the corporate directory.
Credential Protection
SSO provider settings are persisted in encrypted system preferences. Client secrets are never returned to client applications in plaintext (•••••••• masking) and are verified through RBAC-gated endpoints requiring administrator privileges.