User Logon and Authentication
- 5 minutes to read
The Security System supports the following authentication techniques:
When you create a new XAF application, select an appropriate authentication type on the Choose Security page:
To enable authentication in an existing application, refer to the following sections:
Windows Active Directory Authentication
With Active Directory Authentication, Windows checks the user identity, and XAF does not store user passwords in the database. The user name is obtained from the WindowsIdentity object and includes the computer or domain name (for example, COMPUTERNAME\UserName or DOMAINNAME\UserName). You can enable the AuthenticationActiveDirectory.CreateUserAutomatically option to create a new user object automatically when a user logs into the application for the first time.
For testing purposes, the Security System creates a new user object for your Windows account and assigns the administrative role to it when you start the application for the first time in DEBUG
mode with the CreateUserAutomatically
option enabled. In production code, the Security System does not create a new role or assign a role to a newly created user. In this case, you can assign a role manually in the Administrative UI or in the database directly, or specify the SecurityStrategyComplex.NewUserRoleName property. For further customization, you can handle the AuthenticationActiveDirectory.CustomCreateUser event (for example, you can automatically create restricted accounts associated with a specific default role).
Enable Active Directory Authentication
WinForms or ASP.NET Web Forms + .NET Framework
Invoke the Application Designer and drop the SecurityStrategyComplex and AuthenticationActiveDirectory components from the Visual Studio Toolbox to the designer’s Security pane:
WinForms (2-Tier Security) or ASP.NET Core Blazor + .NET 6
Files: ASP.NET Core Blazor - MySolution.Blazor.Server\Startup.cs WinForms - MySolution.Win\Startup.cs
// ...
builder.Security
.UseIntegratedMode(options => {
// ...
// Assign a role with the 'Default' name to new users.
options.NewUserRoleName = "Default";
// ...
})
.AddWindowsAuthentication(options => {
// Enable auto-creation of new users.
options.CreateUserAutomatically();
// Customize new user auto-creation.
options.Events.CustomCreateUser = (e) => {
// ...
};
});
// ...
WinForms (Middle-Tier Security) or Web API + .NET
Files: Middle Tier Server - MySolution.MiddleTier\Startup.cs Web API Service - MySolution.WebApi\Startup.cs
// ...
services.AddXafAspNetCoreSecurity(Configuration, options => {
// Assign a role with the 'Default' name to new users.
options.NewUserRoleName = "Default";
})
.AddAuthenticationActiveDirectory(options => {
// Enable auto-creation of new users.
options.CreateUserAutomatically = true;
// Customize new user auto-creation.
options.Events.CustomCreateUser = (e) => {
// ...
};
});
// ...
Standard Authentication
With Standard Authentication, the Security System uses the internal XAF authentication mechanism and stores user credentials in the application’s database. Users need to input their name and password in the login form before application startup.
Note
You can customize the authentication process and add extra logon parameters. The following help section describes how to do this: Customize Standard Authentication Behavior and Supply Additional Logon Parameters (.NET Applications).
For testing purposes, XAF generates the administrative and non-administrative user objects (Admin and User) with empty passwords. In production code, create users and assign roles to them in the Administrative UI or database directly.
Tip
To protect your applications from brute force attacks, XAF includes user lockout functionality. For more information, refer to the following topic: ISecurityUserLockout.
Enable Standard Authentication
WinForms or ASP.NET Web Forms + .NET Framework
Invoke the Application Designer and drop the SecurityStrategyComplex and AuthenticationActiveDirectory components from the Visual Studio Toolbox to the designer’s Security pane.
WinForms (2-Tier Security) or ASP.NET Core Blazor + .NET 6
Files: ASP.NET Core Blazor - MySolution.Blazor.Server\Startup.cs WinForms - MySolution.Win\Startup.cs
// ...
builder.Security
.UseIntegratedMode(options => {
// ...
})
.AddPasswordAuthentication(options => {
options.IsSupportChangePassword = true;
// ...
});
// ...
WinForms (Middle-Tier Security) or Web API + .NET
Files: Middle Tier Server - MySolution.MiddleTier\Startup.cs Web API Service - MySolution.WebApi\Startup.cs
// ...
services.AddXafAspNetCoreSecurity(Configuration, options => {
//...
})
.AddAuthenticationStandard(options => {
options.IsSupportChangePassword = true;
});
// ...
OAuth2 and Custom Authentication
The following examples demonstrate custom authentication implementations:
- Customize Standard Authentication Behavior and Supply Additional Logon Parameters (.NET Applications)
- Active Directory and OAuth2 Authentication Providers in ASP.NET Core Blazor Applications
- Active Directory and OAuth2 Authentication Providers in WinForms Applications
- OAuth2 Authentication Providers in ASP.NET Web Forms Applications
Authenticate a User in Code (Blazor, Web API Service)
XAF supports API that you can use to access and manage application users as well as authenticate users. This API includes the following services:
- UserManager
- Exposes API required to manage user objects in the database.
- SignInManager
- Exposes API required to sign a user into an application.
The following code snippet demonstrates how to use API that the UserManager
and SignInManager
services expose to sign into a nested scope and execute a controller’s action on a service user’s behalf (user impersonation):
Note
Note that the user impersonation technique demonstrated below is not supported for WinForms applications.
In Blazor applications, the demonstrated technique is not compatible with the static API exposed by the SecuritySystem class. This is because the SecuritySystem
class’s methods always operate on the XAF application instance rather than a scope, so these methods are not affected by impersonation. To avoid faulty behavior in application logic that uses impersonation, ensure that this logic never uses the static API exposed by the SecuritySystem
class.
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.Security;
using DevExpress.Persistent.Base;
// ...
public partial class MyController : ViewController<ListView> {
SimpleAction myAction;
IServiceScopeFactory serviceScopeFactory;
[ActivatorUtilitiesConstructor]
public MyController(IServiceProvider serviceProvider) : this() {
// ...
myAction.Execute += MyAction_Execute;
serviceScopeFactory = serviceProvider.GetRequiredService<IServiceScopeFactory>();
}
// ...
private void MyAction_Execute(object sender, SimpleActionExecuteEventArgs e) {
// ...
// Create a nested service scope whithin which to establish a separate login session.
using (IServiceScope impersonationScope = serviceScopeFactory.CreateScope()) {
// Use the UserManager to obtain the "ServiceUser" user object.
using IObjectSpace nonSecuredObjectSpace = impersonationScope.ServiceProvider
.GetRequiredService<INonSecuredObjectSpaceFactory>().CreateNonSecuredObjectSpace<ApplicationUser>();
ApplicationUser serviceUser = impersonationScope.ServiceProvider
.GetRequiredService<UserManager>().FindUserByName<ApplicationUser>(nonSecuredObjectSpace, "ServiceUser");
// Sign in as "ServiceUser" to the nested scope.
SignInManager signInManager = impersonationScope.ServiceProvider.GetService<SignInManager>();
signInManager.SignIn(serviceUser);
// Obtain an Object Space from the nested scope and use this Object Space
// to manipulate business objects on the "ServiceUser" user's behalf.
using IObjectSpace objectSpace = impersonationScope.ServiceProvider
.GetRequiredService<IObjectSpaceFactory>().CreateObjectSpace<MyActionPerMonth>();
// ...
}
}
}