xaf-security
XAF: Security System
Overview
XAF Security System provides role-based access control (RBAC) via SecurityStrategyComplex. It controls:
- Authentication — who can log in
- Authorization — what they can see and do (type/object/member level)
- ORM-level filtering: queries auto-modified so users only retrieve permitted records
- UI: navigation items, editors, actions hidden/disabled based on permissions
Setup in Program.cs (ASP.NET Core Blazor)
builder.Services.AddXaf(builder.Configuration, b => {
b.UseApplication<MyBlazorApplication>();
b.AddObjectSpaceProviders(providers => {
providers.UseEntityFramework(ef => {
ef.DefaultDatabaseConnection("Default", p => p.UseDbContext<MyDbContext>());
});
});
b.Security
.UseIntegratedMode(options => {
options.RoleType = typeof(PermissionPolicyRole);
options.UserType = typeof(ApplicationUser);
})
.AddPasswordAuthentication(options => {
options.IsSupportChangePassword = true;
});
});
WinForms:
winApplication.Security = new SecurityStrategyComplex(
typeof(ApplicationUser),
typeof(PermissionPolicyRole),
new AuthenticationStandard());
Authentication Types
| Type | Method | Use Case |
|---|---|---|
| Username + Password | AddPasswordAuthentication |
Standard apps |
| Windows / AD | AddWindowsAuthentication |
Internal enterprise, SSO |
| OAuth2 / Entra ID | AddOAuth2Authentication (v24.2+) |
Cloud SaaS, Azure AD |
| Mixed | Combine multiple .Add*() calls |
Local + external providers |
Active Directory
b.Security
.UseIntegratedMode(options => {
options.RoleType = typeof(PermissionPolicyRole);
options.UserType = typeof(ApplicationUser);
options.NewUserRoleName = "Default";
})
.AddWindowsAuthentication(options => {
options.CreateUserAutomatically();
});
OAuth2 / Entra ID (v24.2+)
b.Security
.UseIntegratedMode(options => {
options.RoleType = typeof(PermissionPolicyRole);
options.UserType = typeof(ApplicationUser);
})
.AddPasswordAuthentication()
.AddOAuth2Authentication(options => {
options.Providers.AddMicrosoftAccount(entra => {
entra.ClientId = builder.Configuration["AzureAd:ClientId"]!;
entra.ClientSecret = builder.Configuration["AzureAd:ClientSecret"]!;
entra.TenantId = builder.Configuration["AzureAd:TenantId"]!;
});
options.CreateUserAutomatically();
});
v24.2: OAuth2 preview. v25.1: stabilized API, Google/GitHub providers added.
Permission Model
| Type | Scope | Criteria |
|---|---|---|
TypePermission |
Entire entity class | No |
ObjectPermission |
Specific records | Yes (criteria string/lambda) |
MemberPermission |
Individual property | Yes (combined with object criteria) |
SecurityOperations Constants
SecurityOperations.Read // "Read"
SecurityOperations.Write // "Write"
SecurityOperations.Create // "Create"
SecurityOperations.Delete // "Delete"
SecurityOperations.Navigate // "Navigate"
SecurityOperations.FullAccess // "Create;Read;Write;Delete;Navigate"
SecurityOperations.CRUDAccess // "Create;Read;Write;Delete"
SecurityOperations.ReadOnlyAccess // "Read;Navigate"
SecurityOperations.ReadWriteAccess // "Read;Write"
PermissionSettingHelper — Key Methods
using DevExpress.ExpressApp.Security;
// Type-level
role.AddTypePermission<Order>(SecurityOperations.Read, SecurityPermissionState.Allow);
role.AddTypePermission(typeof(Order), SecurityOperations.FullAccess, SecurityPermissionState.Allow);
// Object-level with criteria string
role.AddObjectPermission<Order>(
SecurityOperations.ReadWriteAccess,
"[AssignedTo.UserName] = CurrentUserId()",
SecurityPermissionState.Allow);
// Object-level with lambda
role.AddObjectPermissionFromLambda<Order>(
SecurityOperations.ReadWriteAccess,
o => o.Status == OrderStatus.Draft,
SecurityPermissionState.Allow);
// Member-level: deny write on specific field
role.AddMemberPermission<Employee>(
SecurityOperations.Write,
nameof(Employee.Salary),
null, // null = all records
SecurityPermissionState.Deny);
Programmatic Role Setup (Updater.cs)
public override void UpdateDatabaseAfterUpdateSchema() {
base.UpdateDatabaseAfterUpdateSchema();
// Admin Role
var adminRole = ObjectSpace.FirstOrDefault<PermissionPolicyRole>(r => r.Name == "Administrators");
if (adminRole == null) {
adminRole = ObjectSpace.CreateObject<PermissionPolicyRole>();
adminRole.Name = "Administrators";
adminRole.IsAdministrative = true; // bypasses ALL permission checks
}
// Users Role (deny-all + specific grants)
var userRole = ObjectSpace.FirstOrDefault<PermissionPolicyRole>(r => r.Name == "Users");
if (userRole == null) {
userRole = ObjectSpace.CreateObject<PermissionPolicyRole>();
userRole.Name = "Users";
userRole.PermissionPolicy = SecurityPermissionPolicy.DenyAllByDefault;
userRole.AddTypePermission<Order>(SecurityOperations.ReadOnlyAccess, SecurityPermissionState.Allow);
userRole.AddObjectPermission<Order>(
SecurityOperations.Write,
"[Owner.UserName] = CurrentUserId()",
SecurityPermissionState.Allow);
}
// Admin User
var adminUser = ObjectSpace.FirstOrDefault<ApplicationUser>(u => u.UserName == "Admin");
if (adminUser == null) {
adminUser = ObjectSpace.CreateObject<ApplicationUser>();
adminUser.UserName = "Admin";
adminUser.SetPassword("");
adminUser.Roles.Add(adminRole);
}
ObjectSpace.CommitChanges();
}
Permission Policies
| Policy | Behavior |
|---|---|
AllowAllByDefault |
Grants all unless explicitly denied |
DenyAllByDefault |
Denies all unless explicitly allowed (production recommended) |
ReadOnlyAllByDefault |
Allows Read/Navigate; denies CUD unless granted |
Checking Permissions in Code
Dependency Injection (recommended)
public class MyService {
readonly ISecurityStrategyBase _security;
public MyService(ISecurityStrategyBase security) => _security = security;
public bool CanCreateOrder() =>
_security.IsGranted(new PermissionRequest(typeof(Order), SecurityOperations.Create));
}
Shorthand Extensions
using DevExpress.ExpressApp.Security;
bool canRead = security.CanRead(typeof(Order));
bool canCreate = security.CanCreate(typeof(Order));
bool canWrite = security.CanWrite(typeof(Order));
bool canDelete = security.CanDelete(typeof(Order));
In Controllers
protected override void OnActivated() {
base.OnActivated();
var security = Application.ServiceProvider.GetRequiredService<ISecurityStrategyBase>();
if (!security.CanCreate(typeof(Order)))
NewAction.Active["Permission"] = false;
}
Custom Security Objects
// EF Core custom user
[DefaultClassOptions]
public class ApplicationUser : PermissionPolicyUser, ISecurityUserWithLoginInfo {
public ApplicationUser(DbContext objectSpace) : base(objectSpace) { }
public virtual string? Department { get; set; }
public virtual DateTime? LastLoginDate { get; set; }
IEnumerable<ISecurityUserLoginInfo> ISecurityUserWithLoginInfo.LoginProviderInfos
=> LoginProviderInfos.OfType<ISecurityUserLoginInfo>();
public virtual IList<ApplicationUserLoginInfo> LoginProviderInfos { get; set; }
= new List<ApplicationUserLoginInfo>();
}
// Register:
b.Security.UseIntegratedMode(options => {
options.UserType = typeof(ApplicationUser);
options.RoleType = typeof(ExtendedRole); // optionally custom role
});
Object-Level Security
XAF rewrites ORM queries automatically — no extra filtering needed:
// Returns only permitted records automatically
var myOrders = objectSpace.GetObjects<Order>();
- EF Core: additional WHERE clauses injected via secured DbContext
- XPO: criteria applied at session/unit-of-work level
Web API Integration
b.Security
.UseIntegratedMode(options => { ... })
.AddPasswordAuthentication();
builder.Services.AddAuthentication()
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters {
ValidIssuer = config["Jwt:Issuer"],
ValidAudience = config["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(config["Jwt:Key"]!))
};
});
Token endpoint: POST /api/Authentication/Authenticate
{ "userName": "Admin", "password": "" }
Use as: Authorization: Bearer <token>
All OData endpoints automatically apply XAF security.
Common Patterns
// Deny-all + grant specific
role.PermissionPolicy = SecurityPermissionPolicy.DenyAllByDefault;
role.AddTypePermission<Order>(SecurityOperations.ReadOnlyAccess, SecurityPermissionState.Allow);
// Admin bypass
adminRole.IsAdministrative = true;
// Per-user row-level security
role.AddObjectPermission<Task>(
SecurityOperations.ReadWriteAccess,
"[AssignedUser.UserName] = CurrentUserId()",
SecurityPermissionState.Allow);
Source Links
- Security System Overview: https://docs.devexpress.com/eXpressAppFramework/113480/data-security-and-safety/security-system/security-system-overview
- Authentication: https://docs.devexpress.com/eXpressAppFramework/113504/data-security-and-safety/security-system/authentication
- OAuth2: https://docs.devexpress.com/eXpressAppFramework/403188/data-security-and-safety/security-system/authentication/oauth2-authentication
- Role-Based Access Control: https://docs.devexpress.com/eXpressAppFramework/113558/data-security-and-safety/security-system/role-based-access-control
- PermissionSettingHelper: https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Security.PermissionSettingHelper._methods
- SecurityOperations: https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Security.SecurityOperations._members
- IsGrantedExtensions: https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Security.IsGrantedExtensions
- GitHub Examples: https://github.com/DevExpress-Examples/XAF_Security_E4908
More from kashiash/xaf-skills
xaf
DevExpress XAF (eXpressApp Framework) master index. Use this skill first when working with any XAF topic to find the right sub-skill. Covers Blazor and WinForms, EF Core and XPO, versions v24.2 and v25.1. Sub-skills: xaf-xpo-models, xaf-ef-models, xaf-controllers, xaf-editors, xaf-custom-editors, xaf-nonpersistent, xaf-security, xaf-multi-tenant, xaf-web-api, xaf-validation, xaf-reports, xaf-dashboards, xaf-office, xaf-blazor-ui, xaf-winforms-ui, xaf-conditional-appearance, xaf-deployment, xaf-memory-leaks.
13xaf-winforms-ui
XAF WinForms UI platform - WinApplication setup, Ribbon vs Standard toolbar, WinForms-specific editors (XtraGrid, DevExpress controls), Detail View layout customization via Layout Manager, custom WinForms controls embedded in XAF views, background workers for thread-safe UI updates, splash screen customization, WinForms navigation (NavigationFrame), printing/preview in WinForms, ClickOnce/MSI deployment. Use when building or customizing XAF WinForms applications.
10xaf-blazor-ui
XAF Blazor UI platform - BlazorApplication setup in Program.cs, AddXaf/AddXafBlazor services, InvokeAsync thread safety (critical for Blazor Server), async controller actions pattern, Blazor-specific editors, embedding custom Razor components as ViewItems using IComponentContentHolder, JavaScript interop via IJSRuntime, Detail View layout customization (tabs/groups), programmatic navigation, error handling with UserFriendlyException, SignalR configuration. Use when building or customizing XAF Blazor Server applications.
10xaf-office
XAF Office/Document Management Modules - FileAttachmentsModule with IFileData/FileAttachment patterns (XPO and EF Core), SpreadsheetModule for Excel editing with ISpreadsheetValueStorage, RichTextModule for Word-like editing with IRichTextDocumentProvider and mail merge, PdfViewerModule for PDF display, platform differences (Blazor vs WinForms), programmatic document manipulation. Use when adding file attachments, spreadsheet editing, rich text editing, or PDF viewing to DevExpress XAF applications.
9xaf-reports
XAF Reports Module (XtraReports v2) - ReportsModuleV2 setup for Blazor and WinForms, report storage (DB/filesystem/custom IReportStorageWebExtension), creating predefined reports in code (PredefinedReportsUpdater), data sources (CollectionDataSource/EntityServerModeSource), report parameters, programmatic export (PDF/Excel/Word), in-app designer, PrintAction, security permissions for report design vs view. Use when working with DevExpress XtraReports integration in XAF.
9xaf-editors
XAF built-in property editors and list editors - editor type mapping by data type, EditorAliases constants, [EditorAlias] attribute, [ModelDefault] for DisplayFormat/EditMask, ObjectPropertyEditor for inline sub-forms, list editor types (GridListEditor, DxGridListEditor, TreeListEditor, ChartListEditor), GridListEditor WinForms customization, DxGridListEditor Blazor customization, IModelListView/IModelColumn properties. Use when working with built-in XAF editors or customizing grid/list views.
8