User Management
This guide covers user management, authentication flows, and password management in TentoCMS.
Overview
TentoCMS uses a global user model with per-project role assignments. Users exist at the system level and can be granted access to one or more projects (grouped under organisations), each with a specific role.
Key Concepts
- Global Users: Users are created once and can access multiple projects
- Project Access: Each user-project relationship includes a role assignment
- Session-Based Auth: Sessions stored in D1 for strong consistency
- Role Hierarchy:
editor<publisher<developer<admin
User Roles & Permissions
| Role | Permissions |
|---|---|
| Editor | Create/edit drafts, upload media, preview content, clone content |
| Publisher | Editor + publish, unpublish, schedule, revert versions |
| Developer | Publisher + manage page types, components, collections, webhooks |
| Admin | Full access including user management, project settings, audit logs, and live (production) API keys |
User Invitation Flow
For Administrators
- Navigate to Settings > Users
- Click Invite User
- Enter the user's email and name
- Select a role for this project
- If you have admin access to multiple projects: Select which projects to add the user to
- Click Create User
Multi-Project Invitation
If you are an admin in multiple projects, the invite form will show a project selection section. This allows you to:
- Add a new or existing user to multiple projects at once
- Assign the same role across all selected projects
- For new users: only one setup link is generated (they set one password for all projects)
Note: Users have a single global password that works across all projects they belong to.
New User
If the email doesn't exist in the system:
- A new user record is created
- A password setup token is generated (valid for 1 hour)
- A modal displays the setup URL and shows which projects the user was added to
Important: Copy the setup URL and share it with the user manually. Email notifications are not yet implemented.
Existing User
If the email already exists:
- The user is added to your project(s) with the specified role
- No password setup is needed (they use their existing password)
- A toast notification confirms the addition
For New Users
- Receive the setup URL from your administrator
- Visit the URL (e.g.,
https://admin.example.com/auth/setup-password?token=xxx) - Enter and confirm your new password
- Click Set Password
- Navigate to the login page and sign in
Password Requirements
Following NIST SP 800-63B guidelines, TentoCMS uses a length-based password policy:
- Minimum 12 characters
- No composition rules (uppercase, numbers, symbols not required)
- All characters allowed including spaces (for passphrases)
This approach provides better security than complexity rules because:
- Length provides more entropy than forced character classes
- Complexity rules lead to predictable patterns ("Password1!")
- Passphrases like "correct horse battery staple" are both secure and memorable
Password Recovery
User-Initiated (Forgot Password)
- Go to the login page
- Click Forgot password?
- Enter your email address
- Click Send Reset Link
- Check your email for the reset link (or contact admin for the link)
- Visit the reset link
- Enter and confirm your new password
- Sign in with your new password
Note: The system always shows a success message to prevent email enumeration attacks. If you don't receive an email, contact your administrator.
Admin-Initiated (Reset Password)
Administrators can reset a user's password:
- Navigate to Settings > Users
- Click on the user's name to view details
- In the Account section, click Reset Password
- A modal displays the new setup URL
- Share the URL with the user
Important: This invalidates the user's current password immediately. They must use the new setup link to regain access.
Multi-Project Login
There's no dedicated organisation/project selection page. When a user with access to multiple organisations or projects logs in, TentoCMS automatically picks the first available organisation and, within it, the first available project, then takes them straight to the dashboard.
Login Flow
- Enter email and password at
/login - The app auto-selects the user's first available organisation and project
- Redirected directly to the dashboard for that org/project
To work in a different organisation or project, switch after logging in (see below).
Switching Organisations & Projects
Users with access to multiple organisations or projects can switch without re-authenticating:
- Click the scope switcher card at the top of the sidebar (shows the current organisation and project)
- Select a different organisation or project from the dropdown
- You're taken to the new organisation/project context — no full page reload is needed
Note: Your role may differ between projects.
Session Management
Session Details
- Storage: D1 database (for strong consistency)
- Duration: 7 days
- Refresh: Automatic sliding window (refreshed when < 1 day remaining)
- Cookie: HTTP-only, secure, and
SameSite=Strictwhen aCOOKIE_DOMAINis configured (production's custom domain) orSameSite=Nonewhen it isn't (e.g. staging's*.workers.dev/*.pages.devorigins, which are cross-site relative to each other)
Why D1 Instead of KV?
Cloudflare KV has eventual consistency (up to 60 seconds propagation). This causes race conditions where:
- User logs in (session written to KV in region A)
- User immediately navigates (request hits region B)
- Session doesn't exist yet in region B → user appears logged out
D1 provides strong consistency required for authentication.
API Keys
API keys authenticate requests to the Public REST API. They are managed in the admin UI under Settings → API Keys.
Creating an API key
- Sign in with an admin account (creating live/production keys requires the admin role).
- Go to Settings → API Keys and click Create API Key.
- Give the key a name, choose its access level, and optionally set an expiry date.
- Copy the key immediately — the full key is shown only once and cannot be retrieved later.
Key types & access levels
| Type / level | Prefix | Access | Who can create |
|---|---|---|---|
| Production, public | tento_pk_ | Read-only (safe for client-side use) | Admin |
| Production, secret | tento_sk_ | Read + write (server-side only; requires at least one permission) | Admin |
| Preview | preview_ | Fetch draft content in preview mode | Publisher or higher |
Store keys as environment variables — never commit them to version control. For rate limits and error codes, see Limits & Errors.
API Endpoints
Note: The paths below still use
tenantin their route names (/switch-tenant,/admin/tenant-users) — this is legacy naming from before the organisation/project model landed and hasn't been renamed. Functionally, they operate on the current project.
Public Endpoints (No Auth Required)
| Endpoint | Method | Description |
|---|---|---|
/api/v1/auth/login | POST | Authenticate with email/password |
/api/v1/auth/setup-password | POST | Set password with setup token |
/api/v1/auth/forgot-password | POST | Request password reset |
/api/v1/auth/reset-password | POST | Reset password with token |
Authenticated Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/auth/me | GET | Get current user and organisation/project context |
/api/v1/auth/logout | POST | End session |
/api/v1/auth/switch-tenant | POST | Switch active project |
/api/v1/auth/password | POST | Change password (requires current password) |
Admin Endpoints (Admin Role Required)
| Endpoint | Method | Description |
|---|---|---|
/api/v1/admin/tenant-users | GET | List users in the current project |
/api/v1/admin/tenant-users/:id | GET | Get user details |
/api/v1/admin/tenant-users/admin-tenants | GET | Get projects where current user is admin |
/api/v1/admin/tenant-users/invite | POST | Invite user to current project |
/api/v1/admin/tenant-users/invite-multi | POST | Invite user to multiple projects |
/api/v1/admin/tenant-users/:id | PUT | Update user role |
/api/v1/admin/tenant-users/:id | DELETE | Remove user from project |
/api/v1/admin/tenant-users/:id/reset-password | POST | Generate password reset token |
Security Considerations
Password Security
- Hashing: PBKDF2-SHA256 at the maximum iteration count the Cloudflare Workers platform allows
- Salt: 128-bit random salt per password
- Verification: Timing-safe comparison to prevent timing attacks
Rate Limiting
- Login attempts: 3 per IP and 5 per email per 30 minutes, with exponential lockout (5 min → 15 min → 1 hour → 24 hours) on repeated failures
- Exceeded limit: Returns 429 (
RATE_LIMITED) with aretryAftervalue (seconds) in the error body - API rate limits: see Limits & Errors
Token Security
- Setup/Reset tokens: 32 random bytes, hex-encoded to a 64-character string
- Expiry: 1 hour
- Single use: Cleared after successful password set
Troubleshooting
"Invalid or expired setup link"
The password setup token has expired or already been used.
Solution: Ask your administrator to generate a new password reset link.
"This link is missing required information"
The URL is incomplete or the token parameter is missing.
Solution: Ensure you're using the complete URL provided by your administrator.
User appears logged out after login
This can happen if there's a cookie issue or session problem.
Solutions:
- Clear browser cookies and try again
- Ensure cookies are enabled
- Try a different browser
Cannot access certain pages
Your role may not have permission for that feature.
Solution: Contact your administrator to request appropriate role assignment.
Future Enhancements
The following features are planned for future releases:
- Email notifications: Automatic sending of invitation and reset emails
- OAuth/SSO: Google, GitHub, SAML authentication
- Self-service password reset: Email-based recovery without admin intervention
- User activity logging: Last login tracking, session history
- Bulk user import: CSV upload for multiple users

