Managing Umbraco users involves creating accounts for Backoffice access, assigning user groups, configuring permissions, and securely removing access. This guide covers the complete lifecycle of Umbraco user management with .NET-specific security practices.
Prerequisites
Before managing Umbraco users:
- Administrator Access - Admin or higher access to Umbraco Backoffice
- User Group Understanding - Review Umbraco User Groups
- Security Policy - Documented approval process for granting access
- Umbraco Version - This guide covers Umbraco 10+ (.NET 6+) and Umbraco 8 (.NET Framework)
Understanding Umbraco User Types
Backoffice Users
- Access Umbraco CMS admin interface (
/umbraco) - Manage content, media, and settings
- Cannot access front-end member areas
- Stored in
umbracoUserdatabase table
Members
- Front-end website users
- Access protected content areas
- Use separate authentication system
- Stored in
cmsMemberdatabase table
Note: This guide focuses on Backoffice users. For member management, see Umbraco Members documentation.
Adding New Backoffice Users
Step 1: Navigate to Users Section
- Log in to Umbraco Backoffice (
https://yourdomain.com/umbraco) - Click Users in left sidebar
- Click Create button (top-right)
- Select User
Step 2: Enter User Details
Required Fields:
- Name - Full name (e.g., "John Smith")
- Email - Valid email address (must be unique)
- Username - Login username (auto-generated from email or custom)
- User Group - Select one or more groups:
- Administrators
- Editors
- Writers
- Translators
- Sensitive Data (custom groups)
Optional Fields:
- Language - Backoffice interface language
- Start Nodes - Limit content tree access (for editors)
- Culture - Regional settings
Step 3: Configure User Group Assignment
Select appropriate user groups:
Administrators - Full access to all sections
Editors - Content, Media, and limited Settings
Writers - Content creation only (no publish)
Translators - Multi-language content management
Best Practice: Use principle of least privilege. Grant minimal access needed.
Step 4: Set Start Nodes (Optional)
Limit content tree visibility:
- Scroll to Start Nodes section
- Click Choose under Content
- Select node(s) to limit access
- User can only see content under selected nodes
Example: Regional editor should only access /en/regions/north-america/
Step 5: Save and Send Invitation
- Click Save button
- Umbraco generates invitation email
- Email contains:
Email Template:
Subject: You've been invited to Umbraco
You've been invited to access the Umbraco CMS for [Site Name].
Username: [email]
Setup your password: [link]
This invitation expires in 72 hours.
Step 6: User Accepts Invitation
User actions:
- Click invitation link
- Redirected to Umbraco password setup page
- Enter new password (requirements):
- Minimum 10 characters (default)
- At least 1 uppercase letter
- At least 1 lowercase letter
- At least 1 number
- At least 1 special character
- Click Set Password
- Redirected to Backoffice login
- Log in with email and new password
Adding Users Programmatically
Via Umbraco Services (Umbraco 10+)
using Umbraco.Cms.Core.Models.Membership;
using Umbraco.Cms.Core.Services;
namespace YourProject.Services
{
public class UserManagementService
{
private readonly IUserService _userService;
private readonly IUserGroupService _userGroupService;
public UserManagementService(
IUserService userService,
IUserGroupService userGroupService)
{
_userService = userService;
_userGroupService = userGroupService;
}
public IUser CreateUser(string email, string name, string userGroupAlias)
{
// Get user group
var userGroup = _userGroupService.GetUserGroupByAlias(userGroupAlias);
if (userGroup == null)
throw new Exception($"User group '{userGroupAlias}' not found");
// Create user
var user = _userService.CreateUserWithIdentity(
username: email,
email: email,
passwordValue: null, // Will be set via invitation
memberTypeAlias: null
);
user.Name = name;
user.Language = "en-US";
// Add to user group
user.AddGroup(userGroup.ToReadOnlyGroup());
// Save user
_userService.Save(user);
// Send invitation email
_userService.SendUserInvite(user);
return user;
}
}
}
Via Umbraco API (Umbraco 8)
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
public class UserManager
{
private readonly IUserService _userService;
public UserManager(IUserService userService)
{
_userService = userService;
}
public IUser AddBackofficeUser(string email, string name, string userGroup)
{
var user = _userService.CreateUserWithIdentity(email, email);
user.Name = name;
user.Language = "en-US";
// Add to user group
var group = _userService.GetUserGroupByAlias(userGroup);
if (group != null)
{
user.AddGroup(group.ToReadOnlyGroup());
}
_userService.Save(user);
return user;
}
}
Managing Existing Users
Update User Details
- Navigate to Users section
- Find and click user to edit
- Modify fields:
- Name
- Email (triggers new verification)
- User Groups
- Language
- Start Nodes
- Click Save
Change User Group
Via Backoffice:
- Click user to edit
- Scroll to User Groups section
- Check/uncheck groups
- Click Save
Changes take effect immediately - user may need to log out and back in.
Disable User (Suspend Access)
Umbraco 10+:
- Click user to edit
- Toggle Disabled switch to ON
- Click Save
User cannot log in but account data is preserved.
Programmatically:
public void DisableUser(int userId)
{
var user = _userService.GetUserById(userId);
if (user != null)
{
user.IsApproved = false;
_userService.Save(user);
}
}
Reset User Password
Via Backoffice:
- Navigate to Users
- Click user to edit
- Scroll to Password section
- Click Send password reset email
- User receives email with reset link
Programmatically:
public void SendPasswordReset(string email)
{
var user = _userService.GetByEmail(email);
if (user != null)
{
var token = _userService.GeneratePasswordResetToken(user, 24); // 24 hours
// Send email with token
}
}
Removing Backoffice Users
Step 1: Pre-Removal Checklist
Before removing user:
- Content ownership transferred to remaining staff
- Scheduled content releases reassigned
- User notified of access removal (if appropriate)
- Document templates updated if user-specific
- Webhooks or integrations verified
- API keys/tokens revoked if user had access
- Audit trail reviewed for recent changes
Step 2: Transfer Content Ownership
Content created by user should be reassigned:
public void TransferContent(int fromUserId, int toUserId)
{
var contentService = Services.ContentService;
var fromUser = _userService.GetUserById(fromUserId);
var toUser = _userService.GetUserById(toUserId);
if (fromUser == null || toUser == null) return;
// Get all content by user
var content = contentService.GetPagedDescendants(
-1,
0,
int.MaxValue,
out long totalRecords,
filter: $"creator={fromUserId}"
);
foreach (var item in content)
{
item.WriterId = toUserId;
contentService.Save(item, toUserId);
}
}
Step 3: Remove User from Umbraco
Via Backoffice:
- Navigate to Users section
- Right-click user to remove
- Click Delete
- Confirm deletion in dialog
- User is permanently removed
Immediate Effects:
- User cannot log in to Backoffice
- User removed from user lists
- Content ownership preserved (not deleted)
- Audit logs remain
What is NOT Deleted:
- Content created by user
- Media uploaded by user
- Forms submitted via user account
- Audit history
Step 4: Programmatically Remove User
public void RemoveUser(int userId)
{
var user = _userService.GetUserById(userId);
if (user != null)
{
// Optionally transfer content first
// TransferContent(userId, replacementUserId);
// Delete user
_userService.Delete(user, true); // true = permanent deletion
// Log removal
_logger.LogInformation($"Removed user: {user.Email}");
}
}
Step 5: Post-Removal Actions
Verify removal:
- User no longer appears in Users section
- Login with user credentials fails
- Content ownership transferred successfully
Clean up:
- Remove from any external systems (e.g., help desk)
- Update team documentation
- Revoke access to related services (FTP, database, etc.)
Bulk User Management
Import Users from CSV
Create bulk import service:
using CsvHelper;
using System.Globalization;
public class BulkUserImporter
{
private readonly IUserService _userService;
private readonly IUserGroupService _userGroupService;
public BulkUserImporter(IUserService userService, IUserGroupService userGroupService)
{
_userService = userService;
_userGroupService = userGroupService;
}
public void ImportFromCsv(string filePath)
{
using var reader = new StreamReader(filePath);
using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
var records = csv.GetRecords<UserImportModel>();
foreach (var record in records)
{
try
{
var user = _userService.CreateUserWithIdentity(
record.Email,
record.Email
);
user.Name = record.Name;
user.Language = record.Language ?? "en-US";
// Add to user group
var group = _userGroupService.GetUserGroupByAlias(record.UserGroup);
if (group != null)
{
user.AddGroup(group.ToReadOnlyGroup());
}
_userService.Save(user);
_userService.SendUserInvite(user);
Console.WriteLine($"Created user: {record.Email}");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to create {record.Email}: {ex.Message}");
}
}
}
}
public class UserImportModel
{
public string Email { get; set; }
public string Name { get; set; }
public string UserGroup { get; set; }
public string Language { get; set; }
}
CSV Format:
Email,Name,UserGroup,Language
john@example.com,John Smith,Editors,en-US
jane@example.com,Jane Doe,Writers,en-US
Bulk Remove Inactive Users
public void RemoveInactiveUsers(int inactiveDays)
{
var users = _userService.GetAll(0, int.MaxValue, out long total);
var cutoffDate = DateTime.Now.AddDays(-inactiveDays);
foreach (var user in users)
{
var lastLogin = user.LastLoginDate;
if (lastLogin < cutoffDate)
{
_logger.LogInformation($"Removing inactive user: {user.Email} (last login: {lastLogin})");
_userService.Delete(user, true);
}
}
}
Security Best Practices
Regular User Audits
Monthly Review:
public class UserAuditReport
{
public void GenerateReport()
{
var users = _userService.GetAll(0, int.MaxValue, out long total);
var report = new StringBuilder();
report.AppendLine("Umbraco User Audit Report");
report.AppendLine($"Generated: {DateTime.Now}");
report.AppendLine();
foreach (var user in users)
{
report.AppendLine($"User: {user.Name} ({user.Email})");
report.AppendLine($"Groups: {string.Join(", ", user.Groups.Select(g => g.Name))}");
report.AppendLine($"Last Login: {user.LastLoginDate}");
report.AppendLine($"Failed Login Attempts: {user.FailedPasswordAttempts}");
report.AppendLine();
}
// Send report via email or save to file
}
}
Two-Factor Authentication
Enable 2FA for administrators:
- Navigate to User profile (top-right)
- Click Edit
- Scroll to Two-Factor Authentication
- Click Enable
- Scan QR code with authenticator app
- Enter verification code
- Save backup codes securely
Enforce 2FA for user groups:
// Custom middleware to enforce 2FA
public class TwoFactorAuthMiddleware
{
public async Task InvokeAsync(HttpContext context)
{
if (context.User.Identity?.IsAuthenticated == true)
{
var user = await _userManager.GetUserAsync(context.User);
if (user != null && !user.TwoFactorEnabled)
{
// Redirect to 2FA setup
context.Response.Redirect("/umbraco/backoffice/setup-2fa");
return;
}
}
await _next(context);
}
}
Password Policies
Configure in appsettings.json:
{
"Umbraco": {
"CMS": {
"Security": {
"UserPassword": {
"RequiredLength": 10,
"RequireNonLetterOrDigit": true,
"RequireDigit": true,
"RequireLowercase": true,
"RequireUppercase": true,
"MaxFailedAccessAttemptsBeforeLockout": 5
}
}
}
}
}
Common Issues
Invitation Email Not Received
Solutions:
- Check spam/junk folder
- Verify SMTP configuration in
appsettings.json - Test email sending:
public async Task TestEmail(string toEmail)
{
var emailSender = Services.EmailSender;
await emailSender.SendAsync(
new EmailMessage(
toEmail,
"Test Email",
"This is a test email from Umbraco",
isBodyHtml: false
),
emailType: "Test"
);
}
- Check Umbraco logs:
App_Data/Logs/
Cannot Delete User (Admin)
Cause: Must be at least one Administrator Solution: Promote another user to Administrator first, then delete
User Locked Out
Cause: Too many failed login attempts Solution:
public void UnlockUser(string email)
{
var user = _userService.GetByEmail(email);
if (user != null)
{
user.FailedPasswordAttempts = 0;
user.IsLockedOut = false;
_userService.Save(user);
}
}
Next Steps
- Umbraco User Groups and Permissions - Configure access levels
- User Management Overview - Governance and best practices
- Umbraco Integrations - Configure tracking and tools