Wednesday, March 02, 2005

Enterprise Library authentication

Doug Rohrer, one of Avanade guys who worked on the Enterprise Library, has posted a fantastic End to End Enterprise Library project which incorporates the EL into ASP.NET and Winforms applications.

Using Collin Collier's wonderful Copy Source As HTML makes blogging the code much easier.

Looking at Doug's work, we run into the common pattern of writing a base page class which all asp.net pages inherit. Then he overrides the OnInit function to kickstart authentication.

I've been using an ASP.NET Http Module to trap OnAuthenticate, but this is an interesting approach. Here's Dougs BasePage class:

using System;

using Microsoft.Practices.EnterpriseLibrary.Security;

using SecCache = Microsoft.Practices.EnterpriseLibrary.Security.Cache;

using Microsoft.Practices.EnterpriseLibrary.Configuration;

using System.Web.Security;

using System.Security.Principal;

using EntLibCommonCSharp;

 

 

namespace EntLibWebCSharp

{

    /// <summary>

    /// Summary description for BasePage.

    /// </summary>

    public class BasePage: System.Web.UI.Page

    {

 

        #region Private Variables

 

        private IAuthenticationProvider _authenProvider;

        private IAuthorizationProvider _authorProvider;

        private IRolesProvider _rolesProvider;

        private ISecurityCacheProvider _secCacheProvider;

        private IPrincipal _principal;

        private EntLibCommonCSharp.AppConfigData _config;

 

        #endregion

 

        #region Public Properties

 

        /// <summary>

        /// An Enterprize Library Authentication Provider instance. 

        /// Used to determine if a user's credentials are valid.

        /// </summary>

        internal IAuthenticationProvider AuthenProvider {

            get {

                if (null==_authenProvider) {

                    _authenProvider = AuthenticationFactory.GetAuthenticationProvider();

                }

                return _authenProvider;

            }

        }

 

        /// <summary>

        /// An Enterprize Library Authorization Provider instance. 

        /// Used to determine if a user is permitted to perform a certain action.

        /// </summary>

        internal IAuthorizationProvider AuthorProvider {

            get {

                if (null==_authorProvider) {

                    _authorProvider = AuthorizationFactory.GetAuthorizationProvider();

                }

                return _authorProvider;

            }

        }

 

        /// <summary>

        /// An Enterprize Library Roles Provider instance. 

        /// Used to retrieve a principal object given an identity.

        /// </summary>

        internal IRolesProvider RolesProvider {

            get {

                if (null==_rolesProvider) {

                    _rolesProvider = RolesFactory.GetRolesProvider();

                }

                return _rolesProvider;

            }

        }

 

        /// <summary>

        /// An Enterprize Library Security Cache Provider instance.

        /// Used to store and retrieve a principal object given a security token.

        /// </summary>

        internal ISecurityCacheProvider SecCacheProvider {

            get {

                if (null==_secCacheProvider) {

                    _secCacheProvider = SecurityCacheFactory.GetSecurityCacheProvider();

                }

                return _secCacheProvider;

            }

        }

 

        /// <summary>

        /// The current principal

        /// </summary>

        internal IPrincipal Principal {

            get {

                return _principal;

            }

        }

 

        /// <summary>

        /// Provides easy access to configuration data in the application config file.

        /// </summary>

        internal AppConfigData Config {

            get {

                if (null==_config) {

                    _config = (AppConfigData)ConfigurationManager.GetConfiguration(AppConfigManager.SectionName);

                }

                return _config;

            }

        }

 

        /// <summary>

        /// Sets the principal for this page request.

        /// </summary>

        /// <param name="principal">The principal to use for the rest of the request.</param>

        internal void SetPrincipal(IPrincipal principal) {

            _principal = principal;

        }

 

 

        #endregion

 

        public BasePage()

        {

            // No constructor necessary

        }

 

 

        /// <summary>

        /// Fires at the beginning of the page lifecycle.  Overriden here to retrieve principal data from the

        /// Enterprise Library Security Cache provider or, if unable, to redirect to he login page.

        /// The Login.aspx page will add the appropriate token via the ASP.NET forms authentication cookie

        /// if the user successfully logs in.

        /// </summary>

        /// <param name="e"></param>

        protected override void OnInit(EventArgs e) {

            base.OnInit(e);

            // Make sure to skip this step if you're already on the login page

            if (ResolveUrl("~/Login.aspx")!=Request.Url.AbsolutePath) {

                try {

                    // Load the principal from the FormsAuthentication ticket information.

                    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt((string)Request.Cookies[FormsAuthentication.FormsCookieName].Value);

                    GuidToken token = new GuidToken(new System.Guid(ticket.UserData));

                    IPrincipal principal = SecCacheProvider.GetPrincipal(token);

                    if (null==principal) {

                        Response.Redirect("~/Login.aspx");

                    } else {

                        SetPrincipal(principal);

                    }

                } catch (Exception) {

                    // If we have any issues, redirect to Login

                    Response.Redirect(ResolveUrl("~/Login.aspx"));

                }

            }

        }

 

 

    }

}



Cool stuff!