Passwords in the Security System
- 3 minutes to read
This topic describes built-in XAF tools for generating and changing user passwords when using the AuthenticationStandard authentication.
Password Encryption
The ApplicationUser class generated by the Template Kit stores passwords as hash codes created using the Rfc2898DeriveBytes class.
Important
If your application uses the legacy SHA-512 password hashing algorithm, update old passwords to the more secure RFC 2898 algorithm. You cannot upgrade to version v25.2 without this update. For details, refer to the following help topic: Update Legacy SHA-512-Hashed User Passwords.
Administrator-Generated Passwords
Administrators can use the ResetPassword Action to generate a password for a particular user. This Action is activated if a user type implements the IAuthenticationStandardUser interface, and the Standard Authentication is applied.
The ResetPasswordController View Controller provides the ResetPassword Action, which is enabled for root Views and located in the RecordEdit Action Container. This Action invokes the following dialog:

The user can change the generated password later.
Note
Changes you made in the Detail View are lost after the ResetPassword Action execution. To save changes when this Action is executed, set the SaveUserObjectOnPasswordChanging property to true.
Change the Password After the First Logon
User objects that implement the IAuthenticationStandardUser interface have the ChangePasswordOnFirstLogon property. If you set this property to true for a particular user, the following dialog displays after this user is logged on:

Since the AuthenticationActiveDirectory authentication type does not expect XAF application passwords to change, this window displays only when Standard Authentication is used.
End-User Password Modifications
When using the Standard Authentication type, end users that have access to the My Details Detail View can change their passwords using the ChangeMyPassword Action. This Action is located in the Edit Action Container and is activated for the My Details Detail View. It invokes the following dialog:

Note
- You can force users to have complex passwords using the approach described in the Non-Persistent Objects Validation topic.
- Changes you made in the Detail View are lost after the ChangeMyPassword Action execution. To save changes when this Action is executed, set the SaveUserObjectOnPasswordChanging property to
true.
Access Passwords in Code
It is impossible to decrypt the stored value to get the original password. To verify or encrypt passwords with a custom algorithm, use one of the following methods:
The static
PasswordCryptographer.VerifyHashedPasswordDelegateandPasswordCryptographer.HashPasswordDelegatemethods.The following code snippet demonstrates how to customize the behavior of these methods:
using DevExpress.Persistent.Base; // ... PasswordCryptographer.VerifyHashedPasswordDelegate = VerifyHashedPassword; PasswordCryptographer.HashPasswordDelegate = HashPassword; // ... static bool VerifyHashedPassword(string saltedPassword, string password) { bool result; // validate password here. return result; } static string HashPassword(string password) { string hash; // create hash here. return hash; }To compare a plain password with a hashed password in a non-XAF .NET app with XPO, use the following code:
using DevExpress.Persistent.Base; using DevExpress.Persistent.BaseImpl.PermissionPolicy; using DevExpress.Xpo; using DevExpress.Xpo.DB; using DevExpress.Xpo.Metadata; using System.Linq; namespace ConsoleApp1 { class Program { static void Main(string[] args) { var dictionary = new ReflectionDictionary(); dictionary.GetDataStoreSchema(typeof(ApplicationUser)); var cs = @"integrated security=SSPI;pooling=false;data source=(localdb)\mssqllocaldb;initial catalog=MainDemo_v20.1"; XpoDefault.DataLayer= XpoDefault.GetDataLayer(cs, AutoCreateOption.None); XpoDefault.Session = null; var session = new UnitOfWork(); var user = session.Query<ApplicationUser>().FirstOrDefault(u => u.UserName == "John"); var saltedPassword = (string)user?.GetMemberValue("StoredPassword"); var areEqual = PasswordCryptographer.VerifyHashedPasswordDelegate(saltedPassword, "test"); } } }The ComparePassword(String) and SetPassword(String) methods. To use these methods, obtain an instance of the target user class that implements the IAuthenticationStandardUser interface. See the example in the following help topic: How to: Implement a Custom Security System User Based on an Existing Business Class.
Validate Password Complexity
For more information, refer to the following topic: Validate Password Complexity.