Login

How do I create a custom authentication module?

Versions: 4.70, FAQ number: 96, Old FAQ number: 977

Q: How do I create a custom authentication module?

A:  Create an authentication module and add the module to EPiServer's chain of authentication providers, see sample code below.

Note that you can only capture a login when using forms authentication. If Windows authentication is used, the user authentication is handled automatically by EPiServer behind the scenes. As a consequence, there is no need to run Login.aspx when using Windows authentication. Login.aspx is only run when forms authentication is used.

Here is how you create your own authentication module:

First, create your Authentication module

public class SampleAuthenticationProvider
{
  public static void SampleAuthentication(
     object sender, AuthenticationEventArgs e)
  {
   if (e.IsHandled)
    return;

   bool authenticationSuccess = false;

   // TODO Validate e.Username, e.Password against your
   // user database

   if (!authenticationSuccess)
    return;

   // Create an IPrincipal with the users roles and return it. This
   // step is what signals "Authentication Success" to EPiServer.
   // TODO Determine actual roles for user

   IPrincipal user = new GenericPrincipal(
             new GenericIdentity(e.Username),
             new string[] { "WebEditors" });

   e.Principal = user;
  }
}

Second, add the module to EPiServer's chain of authentication providers

Add your provider to the chain of authentication providers, by adding the following code to the Application_Start event handler:

AuthenticationProvider.AddAuthenticationModule( new AuthenticationEventHandler( SampleAuthenticationProvider.SampleAuthentication ));

The AuthenticationProvider class is located in the EPiServer.Security namespace.

Alternative authentication provider

The code below is an alternative version of an authentication provider. The main difference is that this provider will always try to authenticate the user, regardless of whether another provider has already handled the login or not. If the user has been authenticated by another provider, the existing authentication is removed from the cache and replaced by our authentication.

// Example of an "overriding" authentication provider, i e even if a provider
// earlier in the chain has authenticated this user we want to do our
// own authentication and override the earlier auth.
public class AlternativeAuthenticationProvider
{
  public static void AlternativeAuthentication(
                        object sender, AuthenticationEventArgs e)
  {
    // Has this user already been authenticated?
    if ( e.Principal != null )
    {
      // Check if we have a cached principal that we authenticated
      if (e.Principal.Identity.AuthenticationType == 
                       "My Authentication Scheme")
      {
        // Do not re-authenticate the principal 
        return;
      }
    }

    // Do our own authentication
    MyAuthentication auth = new MyAuthentication();

    if ( auth.Authenticate(e.Username, e.Password) )
    {
      IIdentity ident =
        new GenericIdentity( e.Username, "My Authentication Scheme" );

      // Check if this user has already been authenticated by some
      // other authentication provider.
      if (e.IsHandled)
      {
        // Remove it from the user cache
        UnifiedPrincipal.RemoveFromCache( ident );
      }

      // A successful authentication - create a new principal
      // that is returned to EPiServer

      e.Principal = new GenericPrincipal( ident, auth.Roles );
    }
  }
}

Single sign-on from EPiServer

If you want to write a single sign-on application where EPiServer handles the user logon against an external system using the same user name and password, here is how:

public class OtherSystemAuthenticationProvider
{
  public static void OtherSystemAuthentication(
    object sender, AuthenticationEventArgs e)
  {
    // Handle login to the external system
    // User name and password are accessed from e.Username and e.Password
    //
    // NOTE: this authentication provider will be called for each page request
    // (and redirect), so write your code to handle this. If the user has
    // already been logged into the other system, just bail out.
 
    
     Pseudocode:
    
     if (_loggedIntoOtherSystem)
       return;
    
     .. logon user into other system..

     _loggedIntoOtherSystem = true;
    
  }
}

And add your provider:

protected void Application_Start(Object sender, EventArgs e)
{
  AuthenticationProvider.AddAuthenticationModule(
     new AuthenticationEventHandler
       ( OtherSystemAuthenticationProvider.OtherSystemAuthentication ));
}

EPiTrace logger