Authentication and Access Control
Authentication and Access Control
ModulaCMS authenticates users through password login, API keys, or OAuth providers, then controls access with role-based permissions.
Log in with a password
Authenticate with email and password. The server creates a session and returns an HTTP-only cookie valid for 24 hours.
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "admin@example.com", "password": "your-password"}'
{
"user_id": "01JMKW8N3QRYZ7T1B5K6F2P4HD",
"email": "admin@example.com",
"username": "admin",
"created_at": "2026-01-15T10:00:00Z"
}
The response includes a Set-Cookie header with the session token. Include this cookie in subsequent requests.
Good to know: The login endpoint is rate-limited to 10 attempts per minute per IP address.
Use an API key
For programmatic access (CI/CD, SDKs, external integrations), create an API key and use it as a Bearer token:
curl http://localhost:8080/api/v1/media \
-H "Authorization: Bearer mcms_01JMKX5V6QNPZ3R8W4T2YH9B0D"
API keys inherit the permissions of the user they belong to. Create them via the tokens endpoint or the built-in admin panel.
Create an API key
curl -X POST http://localhost:8080/api/v1/tokens \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"user_id": "01HXK4N2F8RJZGP6VTQY3MCSW9",
"token_type": "api_key",
"token": "my-generated-token-value",
"issued_at": "2026-01-15T10:00:00Z",
"expires_at": "2027-01-15T10:00:00Z",
"revoked": false
}'
Good to know: Token management permissions (
tokens:read,tokens:create,tokens:delete) are not included in the bootstrap editor or viewer roles. Only admin users can manage tokens by default.
Use OAuth
ModulaCMS supports OAuth 2.0 with Google, GitHub, Azure AD, or any standard OAuth provider. Initiate the flow by redirecting users to /api/v1/auth/oauth/login. After the user authenticates with the provider, ModulaCMS provisions or links the user account, creates a session, and redirects to your configured success URL.
For setup details, see OAuth integration.
Get the current user
Retrieve the authenticated user's profile and role:
curl http://localhost:8080/api/v1/auth/me \
-H "Cookie: session=YOUR_SESSION_COOKIE"
{
"user_id": "01JMKW8N3QRYZ7T1B5K6F2P4HD",
"email": "admin@example.com",
"username": "admin",
"name": "System Administrator",
"role": "01JMKW8N3QRYZ7T1B5K6F2P4HE"
}
Log out
curl -X POST http://localhost:8080/api/v1/auth/logout \
-H "Cookie: session=YOUR_SESSION_COOKIE"
Clears the session cookie and invalidates the session.
Register a user
Register a new user via the public registration endpoint:
curl -X POST http://localhost:8080/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "jdoe",
"name": "Jane Doe",
"email": "jane@example.com",
"password": "secure-password"
}'
ModulaCMS always assigns the viewer role to new users, regardless of any role specified in the request body. Only administrators can change a user's role after registration.
Create and manage users
Admins can create users with any role through the users API:
curl -X POST http://localhost:8080/api/v1/users \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"username": "jdoe",
"name": "Jane Doe",
"email": "jane@example.com",
"password": "secure-password-123",
"role": "editor"
}'
Update a user's role
curl -X PUT http://localhost:8080/api/v1/users/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"user_id": "01HXK4N2F8RJZGP6VTQY3MCSW9",
"username": "jdoe",
"name": "Jane Doe",
"email": "jane@example.com",
"role": "admin"
}'
Get a user's full profile
Retrieve a user with all associated data (OAuth connections, SSH keys, sessions, tokens):
curl "http://localhost:8080/api/v1/users/full/?q=01HXK4N2F8RJZGP6VTQY3MCSW9" \
-H "Authorization: Bearer YOUR_API_KEY"
Delete a user
Delete a user and reassign their content to another user:
curl -X POST http://localhost:8080/api/v1/users/reassign-delete \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"user_id": "01HXK...",
"reassign_to": "01HXK..."
}'
Reset a password
Request a password reset link:
curl -X POST http://localhost:8080/api/v1/auth/request-password-reset \
-H "Content-Type: application/json" \
-d '{"email": "jane@example.com"}'
This always returns HTTP 200 with a generic message to prevent user enumeration. If the email exists and you have configured the email service, ModulaCMS sends a reset link. The reset token expires in 1 hour.
Confirm the reset:
curl -X POST http://localhost:8080/api/v1/auth/confirm-password-reset \
-H "Content-Type: application/json" \
-d '{"token": "a1b2c3d4...", "password": "new-secure-password"}'
Manage sessions
List active sessions to see which devices and IPs have active sessions:
curl http://localhost:8080/api/v1/sessions \
-H "Authorization: Bearer YOUR_API_KEY"
Invalidate a specific session:
curl -X DELETE "http://localhost:8080/api/v1/sessions/?q=01HXK9C3..." \
-H "Authorization: Bearer YOUR_API_KEY"
Roles and permissions
ModulaCMS uses role-based access control (RBAC) to protect every API endpoint. Assign a role to each user, attach permissions to that role, and ModulaCMS enforces permission checks on every request.
Built-in roles
ModulaCMS ships with three system-protected roles created during installation. You cannot delete or rename them.
| Role | Permissions | Description |
|---|---|---|
admin |
All 72 | Full access, bypasses all permission checks |
editor |
36 | Content, media, routes, datatypes, fields, field types (full CRUD) |
viewer |
5 | Read-only access to content, media, routes, and field types |
Admin users bypass permission checks entirely. This is a role-level bypass -- admins are not checked against the permission system at all.
Permission format
Permissions follow the resource:operation format. The resource identifies what is being accessed, and the operation identifies the action.
Examples: content:read, media:create, users:delete, config:update.
HTTP methods map to operations automatically:
| HTTP Method | Operation |
|---|---|
| GET | read |
| POST | create |
| PUT / PATCH | update |
| DELETE | delete |
Create a custom role
Create roles with any combination of permissions:
# Create the role
curl -X POST http://localhost:8080/api/v1/roles \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"label": "contributor"}'
# List available permissions
curl http://localhost:8080/api/v1/permissions \
-H "Authorization: Bearer YOUR_API_KEY"
# Assign permissions to the role
curl -X POST http://localhost:8080/api/v1/role-permissions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"role_id": "01HXK7A1...", "permission_id": "01HXK8B2..."}'
List permissions for a role
curl "http://localhost:8080/api/v1/role-permissions/role/?q=01HXK7A1..." \
-H "Authorization: Bearer YOUR_API_KEY"
Revoke a permission
curl -X DELETE "http://localhost:8080/api/v1/role-permissions/?q=ROLE_PERMISSION_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Good to know: Permission changes take effect within 60 seconds. The permission cache refreshes automatically on a regular interval.
All available permissions
The full set of 72 permissions covers these resources:
| Resource | Operations |
|---|---|
| content | read, create, update, delete, publish, admin |
| datatypes | read, create, update, delete, admin |
| fields | read, create, update, delete, admin |
| media | read, create, update, delete, admin |
| routes | read, create, update, delete, admin |
| users | read, create, update, delete, admin |
| roles | read, create, update, delete, admin |
| permissions | read, create, update, delete, admin |
| sessions | read, delete, admin |
| ssh_keys | read, create, delete, admin |
| config | read, update, admin |
| admin_tree | read, create, update, delete, admin |
| field_types | read, create, update, delete, admin |
| admin_field_types | read, create, update, delete, admin |
| deploy | read, create |
| webhook | create, read, update, delete |
Good to know: All bootstrap permissions are system-protected. You cannot delete or rename them, but you can create additional custom permissions for use with custom roles.
Configure sessions
Configure session behavior in modula.config.json:
| Field | Default | Description |
|---|---|---|
cookie_name |
-- | Name of the session cookie |
cookie_duration |
-- | Session duration |
cookie_secure |
false |
Restrict cookie to HTTPS connections |
cookie_samesite |
"lax" |
SameSite attribute ("lax", "strict", "none") |
ModulaCMS always sets cookies with HttpOnly enabled and Path set to /.
Next steps
- Build a custom admin interface -- create admin screens and manage content via the API
- OAuth integration -- set up Google, GitHub, or Azure AD login