Users (OrchardCore.Users)¶
The Users module enables authentication UI and user management.
Features¶
The module contains the following features apart from the base feature:
- Users Change Email: Allows users to change their email address.
- Users Registration: Allows new users to sign up to the site and ask to confirm their email.
- External User Authentication: Enables a way to authenticate users using an external identity provider.
- Reset Password: Allows users to reset their password.
- User Time Zone: Provides a way to set the time zone per user.
- Custom User Settings: See its own documentation page.
- Users Authentication Ticket Store: Stores users authentication tickets on server in memory cache instead of cookies. If distributed cache feature is enabled it will store authentication tickets on distributed cache.
- Two-Factor Authentication Services: Provides Two-factor core services. This feature cannot be manually enabled or disable as it is enabled by dependency on demand.
- Two-Factor Email Method: Allows users to two-factor authenticate using an email.
- Two-Factor Authenticator App Method: Allows users to two-factor authenticate using any Authenticator App.
- User Localization: Allows ability to configure user culture per user from admin UI.
User Display Name Shape¶
The UserDisplayName shape has been introduced to render a user's display name in a consistent and cache-friendly way. This is frequently used in admin content lists.
If you override the affected shapes (see the changes in the relevant pull request), we recommend you make use of UserDisplayName too.
To use this shape:
- Add the
OrchardCore.DisplayManagementpackage to your project if you haven't already. - In
_ViewImports.cshtml, add:
@addTagHelper *, OrchardCore.DisplayManagement
You can then display a user's name like this:
<user-display-name
user-name="@(contentItem.Author)"
display-type="SummaryAdmin"
cache-id="user-display-name-author" />
This ensures user names are rendered consistently while making use of OrchardCore's caching system for performance.
Note
You may add additional HTML attributes, such as title, to show a tooltip for the username badge.
Two-factor Authentication¶
Orchard Core includes the features needed to secure your app with two-factor authentication. To use two-factor authentication, enable "Two-Factor Email Method" and/or "Two-Factor Authenticator App Method". Configure the process from Settings → Security → User Login on the "Two-Factor Authentication" tab.
User Localization¶
The feature adds the ability to configure the culture per user from the admin UI.
This feature adds a RequestCultureProvider to retrieve the current user culture from its claims. This feature will set a new user claim with a CultureClaimType named "culture". It also has a culture option to fall back to other ASP.NET Request Culture Providers by simply setting the user culture to "Use site's culture" which will also be the selected default value.
Time zone select list customization¶
The User Time Zone editor uses the shared ITimeZoneSelectListProvider service for its <select> items. Replace DefaultTimeZoneSelectListProvider if you need different labels, ordering, or filtering for time zone options across Orchard Core.
Custom Paths¶
If you want to specify custom paths to access the authentication related urls, you can change them by using this option in the appsettings.json:
"OrchardCore": {
"OrchardCore_Users": {
"LoginPath": "Login",
"LogoffPath": "Users/LogOff",
"ChangePasswordUrl": "ChangePassword",
"ChangePasswordConfirmationUrl": "ChangePasswordConfirmation",
"ExternalLoginsUrl": "ExternalLogins",
"ExternalLoginsUrl": "ExternalLogins",
"TwoFactorAuthenticationPath": "TwoFactor"
}
}
Audit Trail Integration¶
By enabling the "Users Audit Trail" feature within this module, user events such as user creation, updating, or deletion are logged in Admin > Tools > Audit Trail. By default, the event stores the user's name and ID beyond the common Audit Trail data.
It's also possible to include a partial JSON snapshot of the User object. To prevent storing particularly sensitive data, this functionality is limited out of the box. You have to go to Admin > Settings > Security > User Audit Trail and select which properties or custom user settings should be stored. The following options are available:
- Store: Stores the value of the property as a string.
- ErasingRedactor: Stores an empty string instead of the value. This is to indicate that the property exists for the
Userobject in question. - PartialAsteriskRedactor: Stores the value as a string, but the middle characters are redacted. For example,
SampleUserbecomesS********r. - HmacRedactor: Uses "HMAC SHA-256" to encode the data before storing it, as a hash or fingerprint. This redactor is only available when both
HmacRedactorOptions.KeyandHmacRedactorOptions.KeyIdare configured. For security reasons, these values should be unique per tenant. For the options to be loaded, you need to bind the settings manually.
You can also create your own redactor simply by adding a singleton Redactor service.
Note that when a user is deleted, all User snapshots are cleared out from existing Audit Trail events to comply with regulations about personal information retention.
Documenting Filters in the Admin UI¶
The users admin list (Security → Users) has a Filters dropdown next to the search box. Its Filter syntax entry opens the Available Filters dialog, which lists every filter a user can type into the search box (name:, email:, status:, role:, sort:, …) as a compact grid of cards. Each card shows the filter title, its capability icons, the syntax token, and a short description.
The list works exactly like the content items admin list filters; only the model type differs. There are two independent extension points: the filter logic and the filter card that documents it in the dialog.
Registering the filter logic¶
Implement IUsersAdminListFilterProvider and add your terms to the QueryEngineBuilder<User>:
public sealed class SsnUsersAdminListFilterProvider : IUsersAdminListFilterProvider
{
public void Build(QueryEngineBuilder<User> builder)
{
builder
.WithNamedTerm("ssn", builder => builder
.OneCondition((val, query) =>
query.With<UserProfileIndex>(i => i.Ssn != null && i.Ssn.Contains(val))));
}
}
Register it in your module's Startup:
services.AddScoped<IUsersAdminListFilterProvider, SsnUsersAdminListFilterProvider>();
Registering the filter card¶
Implement a DisplayDriver<UserIndexOptions> and return a View result placed in the Content zone of the Thumbnail display type. The position after Content: controls the order the card appears in.
public sealed class SsnUsersAdminListDisplayDriver : DisplayDriver<UserIndexOptions>
{
public override IDisplayResult Display(UserIndexOptions model, BuildDisplayContext context)
{
return View("UsersAdminFilters_Thumbnail__Ssn", model)
.Location("Thumbnail", "Content:35");
}
}
services.AddDisplayDriver<UserIndexOptions, SsnUsersAdminListDisplayDriver>();
The card template¶
The shape name UsersAdminFilters_Thumbnail__Ssn resolves to a Razor view named UsersAdminFilters-Ssn.Thumbnail.cshtml placed under Views/Items/. Each card is automatically wrapped in a Bootstrap card and laid out in the responsive grid, so the template only supplies the card's inner content: a title with its capability icons on the first line, the filter token below it, and a short description.
@model ShapeViewModel<UserIndexOptions>
@{
var term = Model.Value.FilterResult.FirstOrDefault(x => x.TermName == "ssn");
}
<div class="d-flex justify-content-between align-items-center gap-2">
<h6 class="card-title fw-semibold mb-0">@T["SSN"]</h6>
<span class="text-primary text-nowrap">
<i class="fa-solid fa-sm fa-minus" title="@T["Accepts a single value"]" aria-hidden="true"></i>
</span>
</div>
<div class="mt-1"><code class="small text-nowrap">@(term?.ToString() ?? "ssn:...")</code></div>
<p class="card-text small text-body-secondary mt-1 mb-0">@T["Filters on a user's social security number."]</p>
Use the same capability icons the built-in filters use so the shared legend at the bottom of the dialog stays accurate: fa-check (Default — may be entered with or without the term name), fa-minus (Single — accepts a single value), and fa-bars (Multiple — supports the AND, OR, and NOT operators and groups).
Recipe Configuration¶
User module settings can be configured using the Settings recipe step:
Login Settings¶
{
"steps": [
{
"name": "settings",
"LoginSettings": {
"UseSiteTheme": false,
"DisableLocalLogin": false,
"AllowRememberMe": true,
"UsePersistentAuthenticationCookie": false,
"AllowChangingUsername": false,
"AllowChangingEmail": false,
"AllowChangingPhoneNumber": true
}
}
]
}
| Property | Type | Description |
|---|---|---|
UseSiteTheme |
Boolean | Whether to use the site theme for the login page. |
DisableLocalLogin |
Boolean | Whether to disable local username/password login. |
AllowRememberMe |
Boolean | Whether to show the Remember me option on the login form. Default: true. When disabled, the UsePersistentAuthenticationCookie setting controls all local and external sign-ins. |
UsePersistentAuthenticationCookie |
Boolean | Whether authentication cookies persist across browser sessions. When AllowRememberMe is enabled, this is the default value of the Remember me option. Default: false. |
AllowChangingUsername |
Boolean | Whether to allow users to change their username. |
AllowChangingEmail |
Boolean | Whether to allow users to change their email address. |
AllowChangingPhoneNumber |
Boolean | Whether to allow users to change their phone number. Default: true. |
Registration Settings¶
{
"steps": [
{
"name": "settings",
"RegistrationSettings": {
"UsersMustValidateEmail": true,
"UsersAreModerated": false,
"UseSiteTheme": false
}
}
]
}
| Property | Type | Description |
|---|---|---|
UsersMustValidateEmail |
Boolean | Whether users must validate their email address before activation. |
UsersAreModerated |
Boolean | Whether new user registrations require administrator approval. |
UseSiteTheme |
Boolean | Whether to use the site theme for the registration page. |
Reset Password Settings¶
{
"steps": [
{
"name": "settings",
"ResetPasswordSettings": {
"AllowResetPassword": true,
"UseSiteTheme": false
}
}
]
}
| Property | Type | Description |
|---|---|---|
AllowResetPassword |
Boolean | Whether to allow users to reset their password. |
UseSiteTheme |
Boolean | Whether to use the site theme for the reset password page. |
Change Email Settings¶
{
"steps": [
{
"name": "settings",
"ChangeEmailSettings": {
"AllowChangeEmail": true
}
}
]
}
| Property | Type | Description |
|---|---|---|
AllowChangeEmail |
Boolean | Whether to allow users to change their email address. |
External Authentication Settings¶
{
"steps": [
{
"name": "settings",
"ExternalLoginSettings": {
"UseExternalProviderIfOnlyOneDefined": false,
"UseScriptToSyncProperties": false,
"SyncPropertiesScript": ""
},
"ExternalRegistrationSettings": {
"DisableNewRegistrations": false,
"NoPassword": false,
"NoUsername": false,
"NoEmail": false,
"UseScriptToGenerateUsername": false,
"GenerateUsernameScript": ""
}
}
]
}
Two-Factor Authentication Settings¶
{
"steps": [
{
"name": "settings",
"TwoFactorLoginSettings": {
"RequireTwoFactorAuthentication": false,
"AllowRememberClientTwoFactorAuthentication": true,
"NumberOfRecoveryCodesToGenerate": 5,
"UseSiteTheme": false
},
"RoleLoginSettings": {
"RequireTwoFactorAuthenticationForSpecificRoles": false,
"Roles": [
"Administrator"
]
},
"AuthenticatorAppLoginSettings": {
"UseEmailAsAuthenticatorDisplayName": false,
"TokenLength": 6
},
"EmailAuthenticatorLoginSettings": {
"Subject": "Your verification code",
"Body": "Your code is {{ Code }}"
},
"SmsAuthenticatorLoginSettings": {
"Body": "Your verification code is {{ Code }}"
}
}
]
}
Commands¶
The Users module registers the createUser command, which you can run from a recipe's command step.
createUser /UserName:<username> /Password:<password> /Email:<email> /PhoneNumber:<phonenumber> /Roles:{rolename,rolename,...}
| Switch | Description |
|---|---|
UserName |
The username of the new user. |
Password |
The password of the new user. It has to satisfy the configured password rules. |
Email |
The email address of the new user, which is marked as confirmed on creation. |
PhoneNumber |
The phone number of the new user. Optional. |
Roles |
A comma-separated list of the roles to assign to the user. Optional. |
For example, to create an administrator during setup from a recipe:
{
"name": "command",
"Commands": [
"createUser /UserName:admin /Password:Password1! /Email:admin@example.com /Roles:Administrator"
]
}