---
title: Registration and authentication
related:
  - https://docs.kentico.com/documentation/business-users/members.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

Registration and authentication are two critical components of web application security.

Registration is the process by which a user creates an account on a web application. This process typically involves collecting information from the user, such as their name, email address, and a chosen password. The purpose of registration is to allow the web application to keep track of each user's account and provide them with personalized services and content.

Authentication, on the other hand, is the process of verifying a user's identity when they sign in to the web application. This involves checking the user's credentials, such as their username and password, against the information stored in the application's database. The purpose of authentication is to ensure that only authorized users can access designated parts of the web application and its resources (for example, [secured pages](https://docs.kentico.com/documentation/business-users/website-content/secure-pages.md) or [content items](https://docs.kentico.com/documentation/business-users/content-hub/content-items.md#secure-content-items)).

Together, registration and authentication provide several benefits for web application users and administrators. By registering, users can access personalized services and content, save preferences and settings, and track their activity in the application.

## Configure registration and authentication

Xperience uses a customized implementation of [ASP.NET Identity](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity) (Identity) to manage registration and authentication. Identity is included as part of the .NET framework and can be added to the application and configured as part of the startup pipeline in **Program.cs**.

```csharp title="Program.cs - add Identity to the application"
using System;

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Identity;

using Kentico.Web.Mvc;
using Kentico.Membership;

// ...

// Adds and configures ASP.NET Identity for the application
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
    // Ensures that disabled member accounts cannot sign in
    options.SignIn.RequireConfirmedAccount = true;
    // Ensures unique emails for registered accounts
    options.User.RequireUniqueEmail = true;

    options.Password.RequireDigit = false;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequiredLength = 4;
    options.Password.RequireUppercase = false;
    options.Password.RequireLowercase = false;
})
    .AddUserStore<ApplicationUserStore<ApplicationUser>>()
    .AddRoleStore<ApplicationRoleStore<ApplicationRole>>()
    .AddUserManager<UserManager<ApplicationUser>>()
    .AddRoleManager<RoleManager<ApplicationRole>>()
    .AddSignInManager<SignInManager<ApplicationUser>>();
```

In the code snippet above, `ApplicationUser` is Xperience's implementation of the Identity [user object](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.identityuser). This object is then mapped to `MemberInfo` which is persisted in the Xperience database – registered visitors are referred to as members in the system. For more information about the data flow and behavior, see [Xperience ASP.NET Identity architecture](#xperience-asp.net-identity-architecture).

If we break down the registration:

- `ApplicationUserStore` is the Xperience-specific implementation of the Identity `UserStore`. It persists data in the Xperience database and ensures conversion between `ApplicationUser` and `MemberInfo`.
- `ApplicationRole` and `ApplicationRoleStore` provide Xperience's ASP.NET Identity role implementation. `ApplicationRole` represents a member role, mapped to `MemberRoleInfo` in the Xperience database. If your project needs additional role fields, you can replace it with an [extended role type](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/member-roles.md#extend-applicationrole). See [Member roles](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/member-roles.md) for details on role management and assignment.
- `RoleManager` – the standard ASP.NET Identity role manager, used to create, update, delete, and query member roles.
- The `RequireConfirmedAccount` option works together with the `ApplicationUser.Enabled` property to ensure that only enabled accounts can sign in to the system. See [Remarks - ApplicationUser.Enabled](#applicationuser.enabled) and [Remarks - Disabling member accounts](#disabling-member-accounts) for more information.
- The `RequireUniqueEmail` option ensures members cannot register an additional account using an email already in the system, which is a requirement of Xperience's Identity implementation.

With Identity configured, add the required `UseAuthentication` and `UseAuthorization` middleware. **Make sure to call the middleware in the provided order.**

```csharp title="Program.cs - add required middleware"
app.UseStaticFiles();

app.UseCookiePolicy();

app.UseAuthentication();

app.UseKentico();

app.UseAuthorization();
```

Identity is now configured for the application. Continue by implementing your desired registration and authentication flows.

## Registration and authentication flows

> **Info:** **[Forms authentication](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/forms-authentication.md)**
>
> Forms authentication is a type of registration and authentication mechanism that uses HTML forms to collect user credentials (such as a username and password). When a visitor attempts to sign in, the collected data is matched againsted the database. This registration method enables a highly customized experience, as it allows for great flexibility when designing the authentication flow.

> **Info:** **[External authentication](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/external-authentication.md)**
>
> External authentication is a process of authenticating visitors to a web application using an external identity provider, such as Google, Facebook, or Twitter. Its purpose is to provide a more convenient and secure way for visitors to access the application, as it allows them to use their existing social media accounts to sign in. This flow also reduces the burden of managing user authentication and security for application developers, as they can rely on the security measures implemented by the external identity provider.

## Management and customization

> **Info:** **[Add fields to member objects](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/add-fields-to-member-objects.md)**
>
> Xperience provides the option to extend `MemberInfo` objects (visitors who register an account in the system) with additional fields. The default object that represents members in Xperience is by default equipped with only the most essential fields required for authentication using ASP.NET Identity. Most projects will likely want to collect a broader set of member data, which is enabled by this extension mechanism.

> **Info:** **[Member roles](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/member-roles.md)**
>
> Xperience integrates with ASP.NET Identity's role management system. You can create and manage member roles, assign them to members, and use the standard `[Authorize(Roles = "...")]` attribute to restrict access to controllers and actions.

> **Info:** **[Manage members in the system](https://docs.kentico.com/documentation/business-users/members.md)**
>
> The system provides a management interface for member objects via the **Members** application. Alternatively, to work with members using the API, use Xperience's ORM framework as described on [Database table API](https://docs.kentico.com/documentation/developers-and-admins/api/database-table-api.md). Members are represented by the `MemberInfo` class.

## Retrieve the currently authenticated member

When implementing restricted sections of the application, you might sometimes need to access the details of the currently authenticated member, such as their email. This data is stored in the `ApplicationUser` object and retrieved via the `UserManager` class.

Identity by default requires the user's name to be populated (ensured by [IUserValidator\<TUser>](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.iuservalidator-1) called as part of the data validation process). To retrieve the current user, you can use `userManager.FindByNameAsync`. The name of the user associated with the current request is stored in `HttpContext.User.Identity.Name`.

Alternatively, if you ensure that all registration flows in your application populate the member's email, you can use `userManager.FindByEmailAsync`.

As a second alternative, you can also use the member's ID, which is guaranteed to exist as it gets assigned by the system when the member account is created.

```csharp title="Retrieve the current authenticated member using their ID"
using System.Security.Claims;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;

using Kentico.Membership;

// Gets instances of required services using dependency injection
public class MemberRetrievalComponent(IHttpContextAccessor httpContextAccessor, UserManager<ApplicationUser> userManager)
{
    public async Task RetrieveCurrentMember()
    {
        // Gets the currently authenticated member account using their ID
        ApplicationUser? currentMember = await userManager.
                        FindByIdAsync(httpContextAccessor.HttpContext?.User.
                            FindFirstValue(userManager.Options.ClaimsIdentity.UserIdClaimType) ?? string.Empty);

        // Custom logic...
    }
}
```

## Authentication and authorization responses

Xperience [pages](https://docs.kentico.com/documentation/business-users/website-content/secure-pages.md) and [content items](https://docs.kentico.com/documentation/business-users/content-hub/content-items.md#secure-content-items) can be hidden behind authentication and authorization access restrictions. When a visitor requests restricted content, the system distinguishes between two scenarios:

- **Not authenticated (HTTP 401)** – the visitor is not signed in. ASP.NET Identity issues a challenge that redirects the visitor to the sign-in page. Defaults to `/Account/Login`.
- **Forbidden (HTTP 403)** – the visitor is signed in but does not belong to any of the required member roles. The system redirects the visitor to the access denied page. Defaults to `/Account/AccessDenied`.

To set custom redirect paths, configure ASP.NET Identity cookie authentication. Set `LoginPath` for unauthenticated redirects and `AccessDeniedPath` for missing role redirects:

```csharp title="Program.cs - Configure authentication redirects"
using using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

// ...

builder.Services.ConfigureApplicationCookie(options =>
{
    // Redirects unauthenticated visitors to the sign-in page
    options.LoginPath = new PathString("/account/signin");

    // Redirects authenticated visitors without the required member role to the access denied page
    options.AccessDeniedPath = new PathString("/account/access-denied");
});
```

## Xperience ASP.NET Identity architecture

> **Info:** The types described in this section belong to two namespaces: `Kentico.Membership` for the ASP.NET Identity layer (`ApplicationUser`, `ApplicationRole`, `ApplicationRoleStore`) and `CMS.Membership` for the Xperience database layer (`MemberInfo`, `MemberExternalLoginInfo`, `MemberRoleInfo`).

Xperience applications implement authentication using [ASP.NET Identity](https://learn.microsoft.com/en-us/aspnet/identity/overview/getting-started/introduction-to-aspnet-identity). The implementation uses the `ApplicationUser` type derived from `IdentityUser` to represent members – accounts registered in the system by site visitors. When saving member data to the database (`CreateAsync` or `UpdateAsync` methods on `UserManager`), Xperience maps data from `ApplicationUser` to `MemberInfo` objects. `MemberInfo` objects are connected to the system's [ORM framework](https://docs.kentico.com/documentation/developers-and-admins/api/database-table-api.md), which is used to persist the data to the database.

Conversely, when retrieving member data from the database (`UserManager.FindBy*` methods), the member is first retrieved as `MemberInfo` and then converted to `ApplicationUser`. The transfer of data between objects from both sides of the flow is handled by the `MapFromMemberInfo` and `MapToMemberInfo` methods on `ApplicationUser`. This mapping can be customized – see [Add fields to member objects](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/add-fields-to-member-objects.md).

Accounts from [external authentication providers](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/external-authentication.md) such as Google, Facebook, etc. are stored using `MemberExternalLoginInfo` objects in the `CMS_MemberExternalLogin` database table. Each member account can have up to `N` associated external credentials, where `N` corresponds to the number of external providers supported by your implementation. Accounts that rely exclusively on authentication via an external provider have their `MemberInfo.MemberIsExternal` property set to `1`.

Identity roles are managed through `ApplicationRole` and `ApplicationRoleStore`. `ApplicationRole` is derived from `IdentityRole` and maps to `MemberRoleInfo` objects in the Xperience database, following the same bidirectional mapping pattern as `ApplicationUser` and `MemberInfo`. If you need to store additional role data, you can replace `ApplicationRole` with an extended role class. `ApplicationRoleStore` implements `IRoleStore` and persists role data through the Xperience ORM framework. For detailed information about member roles and content access control, see [Member roles](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/member-roles.md).

The following diagram summarizes the described behavior and data flow.

![Xperience ASP.NET Identity architecture and data flow](https://docs.kentico.com/docsassets/documentation/registration-and-authentication/identity-architecture.drawio.svg "Xperience ASP.NET Identity architecture and data flow")

## Remarks

### ApplicationUser.Enabled

When creating member accounts in the system, you **must** set their `ApplicationUser.Enabled` property. The enabled status is also controlled via the **Members** application –> **Disable/Enable** action, which toggles the state for the corresponding account.

Based on this property, the system determines whether the account can sign in. To avoid introducing additional Xperience-specific implementations to the Identity logic, the check that prevents disabled accounts from signing in is combined with the `IdentityOptions.SignInOptions.RequireConfirmedAccount` Identity setting (which is typically used with [account email confirmation](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/forms-authentication.md) flows).

```csharp title="Program.cs - Identity configuration"
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

using Kentico.Membership;

// ...

builder.Services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
    // ...
    options.SignIn.RequireConfirmedAccount = true;
})
```

For this reason, enabling this option is **required** for the _Enabled_ status to work correctly.

When using [forms authentication](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/forms-authentication.md) together with email confirmation, `ApplicationUserStore` (the Xperience-specific implementation of the [UserStore](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.entityframeworkcore.userstore) class) sets the `Enabled` property to `true` when the email verification step is successful (`ApplicationUserStore.SetEmailConfirmedAsync` called as part of `UserManager.ConfirmEmailAsync`). The property is not handled automatically at any other point.

### Disabling member accounts

When you disable a member account using the **Disable** action in the **Members** application, the account is not blocked immediately. Disabled accounts can remain active for up to 30 minutes before the system forces the member to re-authenticate. Keep this in mind when disabling accounts that require urgent access revocation – developers can reduce this interval as described below.

Every time the `ApplicationUser.Enabled` property changes, the system generates a new value for the account's [SecurityStamp](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.identityuser-1.securitystamp). The security stamp value is also stored in the client's authentication cookie and compared against the value on the server. If a mismatch is detected (the `Enabled` status changed, a password change occurred, etc.), the client is forced to re-authenticate.

The security stamp comparison is done by [ISecurityStampValidator](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.isecuritystampvalidator) at a set interval, 30 minutes by default. To immediately block access for disabled accounts, change the revalidation interval via `SecurityStampValidatorOptions`.

```csharp title="Program.cs"
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;

// ...

// Sets the validation interval to zero - the authentication cookie stored on the client is checked on every request
// If the validation fails - the security stamp is different than the one stored on the client - 
// the client's authentication cookie (e.g., AspNetCore.Identity.Application) is cleared, forcing reauthentication
builder.Services.Configure<SecurityStampValidatorOptions>(options => options.ValidationInterval = TimeSpan.Zero);
```

### Registration activity logging

The system automatically logs the _Member registration_ [activity](https://docs.kentico.com/documentation/business-users/digital-marketing/contact-activities.md) whenever a member becomes active (enabled). This occurs when saving member data to the database in the following scenarios:

- When a new member is added via `UserManager.CreateAsync` with `ApplicationUser.Enabled` set to true.
- Whenever a member is updated to become active. For example, via `UserManager.ConfirmEmailAsync` when using [email confirmation](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/forms-authentication.md#email-confirmation) for new members, or manually via `UserManager.UpdateAsync`.

Keep this in mind if you plan to set up [automation processes](https://docs.kentico.com/documentation/business-users/digital-marketing/automation.md) with the _Registration_ trigger. The process will only start once the member account is active, not necessarily when the registration form is submitted by the user. Additionally, such processes may also start when reactivating existing member accounts that were previously disabled. However, this only occurs if the reactivation is performed using the ASP.NET Identity API (`UserManager`), not if the member is enabled in the [administration UI](https://docs.kentico.com/documentation/business-users/members.md).

### Page preview mode

[Preview mode](https://docs.kentico.com/documentation/business-users/website-content.md#preview) in Xperience enables editors to view the latest version of pages before they are published. Preview mode works automatically for all [content types](https://docs.kentico.com/documentation/developers-and-admins/development/content-types.md) for pages that are included in routing.

Preview URLs for pages are used in the following scenarios in website channel applications:

- When viewing pages in **Preview** mode in the administration.
- When editing pages via [Page Builder](https://docs.kentico.com/documentation/developers-and-admins/development/builders/page-builder.md).

The preview URLs the system generates for pages consist of virtual context, which is additional information, such as a hash for validating the URL against the client's authentication cookie, context about the current [website channel](https://docs.kentico.com/documentation/developers-and-admins/configuration/website-channel-management.md), view mode (e.g., Read-only), etc. The live site application validates and processes the preview URL and displays the page using the conventional [routing process](https://docs.kentico.com/documentation/developers-and-admins/development/routing.md).

To share a preview of a page externally, users can create a [shareable preview URL](https://docs.kentico.com/documentation/developers-and-admins/configuration/shareable-preview-urls.md). This URL address is different from the one used for the internal preview. Shareable preview URLs are also handled through the regular [routing process](https://docs.kentico.com/documentation/developers-and-admins/development/routing.md).

> **Tip:** **IVirtualContextDecorationArbiter**
>
> You can implement the `IVirtualContextDecorationArbiter` interface to control whether links in previewed content should consist of virtual context. Note that you can't change the actual preview URLs or use the interface to disable authentication of previewed content.
>
> ```csharp title="Example"
> using System;
>
> using CMS;
> using Kentico.Content.Web.Mvc;
>
> [assembly: RegisterImplementation(typeof(IVirtualContextDecorationArbiter), typeof(CustomVirtualContextDecorationArbiter))]
>
> public class CustomVirtualContextDecorationArbiter : IVirtualContextDecorationArbiter
> {
>     private const string ARTICLES_PREFIX = "~/articles/";
>
>     public virtual bool PathRequiresDecoration(string path)
>     {
>         // Do not decorate scripts or article pages
>         return !(path.StartsWith(ARTICLES_PREFIX, StringComparison.OrdinalIgnoreCase));
>     }
> }
> ```

#### MVC authorization flows and preview mode

The preview mode functionality runs on a dedicated internal authentication scheme. As a result, pages [secured behind authorization](https://learn.microsoft.com/en-us/aspnet/core/security/authorization/simple) that checks for a specific authentication scheme are not previewable. This also applies to [shareable preview](https://docs.kentico.com/documentation/developers-and-admins/configuration/shareable-preview-urls.md).

```csharp title="Not previewable authorization configuration"
// Pages served by this controller are not previewable due to the explicit authentication scheme requirement
[Authorize(AuthenticationSchemes = "SomeAuthenticationScheme")]
public class MyController : Controller
```

[Member role-based authorization](https://docs.kentico.com/documentation/developers-and-admins/development/registration-and-authentication/member-roles.md) checks are bypassed when previewing content in the administration or via [shareable preview URLs](https://docs.kentico.com/documentation/developers-and-admins/configuration/shareable-preview-urls.md). This allows editors to review secured content without member-role restrictions.
