---
title: Handling custom administration authentication
related:
  - https://docs.kentico.com/13/managing-users/user-registration-and-authentication.md
  - https://docs.kentico.com/13/custom-development/handling-global-events.md
  - https://docs.kentico.com/13/custom-development/handling-global-events/reference-global-system-events.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).

You can use [global events](https://docs.kentico.com/13/custom-development/handling-global-events.md) to integrate external user databases, and modify the authentication or authorization process for the **Xperience administration interface**. See the **SecurityEvents** section of the [global event reference](https://docs.kentico.com/13/custom-development/handling-global-events/reference-global-system-events.md) to learn more about the available options.

To set up custom authentication, implement a handler for the **SecurityEvents.Authentication.Execute** event. You can access the authentication data through the event handler's **AuthenticationEventArgs** parameter, which provides the following properties:

- **UserInfo User** – an object representing the user attempting to sign in. The object is the result of the system's standard authentication check. If the default authentication failed, the User property is _null_.
- **string UserName** – contains the username entered during the sign-in attempt.
- **string Password** – contains the password entered during the sign-in attempt.

Once you complete the external authentication process in the handler's code, assign a matching _UserInfo_ object to the _AuthenticationEventArgs_ parameter's **User** property. If the authentication fails, set the property to _null_.

## Example

The following example demonstrates how to integrate external administration authentication by handling security events:

1. Open your Xperience administration solution in Visual Studio.
2. Create a [custom module class](https://docs.kentico.com/13/custom-development/creating-custom-modules/initializing-modules-to-run-custom-code.md).
   - Add the class into a custom assembly (_Class Library_ project) within the solution.
3. Override the module's **OnInit** method and assign a handler to the **SecurityEvents.Authentication.Execute** event:

   ```csharp

   using System.Data;
   using System.Linq;
   using System.Web;

   using CMS;
   using CMS.DataEngine;
   using CMS.Membership;

   // Registers the custom module into the system
   [assembly: RegisterModule(typeof(CustomAuthenticationModule))]

   public class CustomAuthenticationModule : Module
   {
       // Module class constructor, the system registers the module under the name "CustomAuthentication"
       public CustomAuthenticationModule()
           : base("CustomAuthentication")
       {
       }

       // Contains initialization code that is executed when the application starts
       protected override void OnInit()
       {
           base.OnInit();

           // Assigns a handler to the SecurityEvents.Authenticate.Execute event
           // This event occurs when users attempt to sign in to the administration interface
           SecurityEvents.Authenticate.Execute += OnAuthentication;
       }
   }

   ```
4. Define the handler method within the module class:

   ```csharp

   private void OnAuthentication(object sender, AuthenticationEventArgs e)
   {
       // Checks if the user was authenticated by the default system. Only continues if authentication failed.
       if (e.User == null)
       {
           // Object representing the external user
           UserInfo externalUser = null;

           // Gets the credentials entered during the authentication
           string username = SqlHelper.EscapeQuotes(e.UserName);
           string password = SqlHelper.EscapeQuotes(e.Password);

           // Path to an XML database file
           string xmlPath = HttpContext.Current.Server.MapPath("\~/userdatabase.xml");

           // Reads data from the external database
           DataSet userData = new DataSet();
           userData.ReadXml(xmlPath);

           // Authenticates against the external database
           DataRow[] rows = userData.Tables[0].Select("UserName = '" + username + "' AND Password='" + password + "'");                
           if (rows.Count() > 0)       
           {
               // Creates a user record if external authentication is successful
               externalUser = new UserInfo()
               {
                   IsExternal = true,
                   UserName = e.UserName,
                   FullName = "ExternalUser Fullname",
                   Enabled = true
               };
           }

           // Passes the object representing the user (or null if external authentication failed)
           e.User = externalUser;
       }
   }

   ```
5. Save the class and Rebuild the solution.

The system now performs authentication according to user data from the external source if default authentication fails.

> **Tip:** We recommend importing all external roles into the **CMS\_Role** table of the Xperience database. You can then configure the appropriate permissions for these roles, and fully use the built-in security model together with external users.
>
> If you need to implement custom security logic, create handlers for the available [SecurityEvents](https://docs.kentico.com/13/custom-development/handling-global-events/reference-global-system-events.md#securityevents). You can programmatically check if a user belongs to a role by calling the **IsInRole(string roleName, string siteName)** method for **UserInfo** objects.
