---
title: Handling custom external authentication
related:
  - https://docs.kentico.com/k9/managing-users/user-registration-and-authentication.md
  - https://docs.kentico.com/k9/custom-development/handling-global-events.md
  - https://docs.kentico.com/k9/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/k9/custom-development/handling-global-events.md) to integrate external user databases, and modify the authentication or authorization process. See the **SecurityEvents** section of the [global event reference](https://docs.kentico.com/k9/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 log 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 login attempt.
- **string Password** - contains the password entered during the login 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 failed, set the property to _null_.

### Example

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

1. [Assign a handler](https://docs.kentico.com/k9/custom-development/handling-global-events.md) to the **SecurityEvents.Authentication.Execute** event. The example uses a custom class in the App\_Code folder:

   ```csharp

   using System.Data;

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

   [AuthenticationHandler]
   public partial class CMSModuleLoader
   {
       /// <summary>
       /// Custom attribute class.
       /// </summary>
       private class AuthenticationHandler : CMSLoaderAttribute
       {
           /// <summary>
           /// Called automatically when the application starts
           /// </summary>
           public override void Init()
           {
               // Assigns a handler to the SecurityEvents.Authenticate.Execute event
               // This event occurs when users attempt to log in on the website
               SecurityEvents.Authenticate.Execute += OnAuthentication;
           }
       }
   }

   ```
2. Define the handler method (inside the custom **CMSLoaderAttribute** 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;
       }
   }

   ```
3. Save the class.

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 Kentico 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/k9/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.
