EPiServer CMS 5 - Mixed authentication

Vote:
 

I want to use "Mixed authentication" in an EPiServer solution.

I have searched information about "Mixed authentication in asp.net"

This was my starting point: http://msdn.microsoft.com/en-us/library/ms972958.aspx

I have looked at the "System.Web.Security.WindowsAuthenticationModule" and the "EPiServer.Security.WindowsMembershipProvider".

I have come up to a solution that works. But I want to know if I miss something from a security perspective?

I have two login pages: "FormsLogin.aspx" and "WindowsLogin.aspx"

Authentication is set to "Forms" in web.config

I have a custom section in web.config: <mixedAuthentication enabled="True" windowsLoginUrl="~/Util_/WindowsLogin.aspx" />

Mixed authentication is only true if Authentication.Mode == AuthenticationMode.Forms && MixedAuthentication.Enabled == true (This is what AuthenticationSettings.IsMixedAuthentication checks in the code I'm sending)

In the Page_Init event on my FormsLogin.aspx I check several things:
* if mixed authentication is set
* if the user is not allready authenticated
* if the users ip is in a certain range (Request.UserHostAddress)
* if the users browser is IE

If this all is true I redirect to the WindowsLogin.aspx, which is set to "Windows Integrated Authentication" in IIS and no anonymous access. In WindowsLogin.aspx I call "ValidateWindowsUser", the code I'm sending. Ohterwhise I use FormsLogin.aspx as normal.

I have built an extension to "EPiServer.Security.WindowsMembershipProvider" and its here I want to know if I miss something from a security point of view.

using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Web;
using EPiServer.DataAccess;
using EPiServer.Security;
using MyCompany.Web.Security;

namespace MyCompany.EPiServer.Security.Extensions
{
    public static class WindowsMembershipProviderExtensions
    {
        public static Boolean ValidateWindowsUser(this WindowsMembershipProvider windowsMembershipProvider, out String userName)
        {
            Boolean isValidWindowsUser = false;
            IServiceProvider serviceProvider = null;
            HttpWorkerRequest workerRequest = null;
            String logonUser = null;
            String authenticationType = null;
            List<String> windowsIdentityGroupList = null;
            String tempGroupName = null;           

            userName = null;

            if (HttpContext.Current != null)
            {
                if (AuthenticationSettings.IsMixedAuthentication)
                {
                    serviceProvider = (IServiceProvider)HttpContext.Current;
                    workerRequest = (HttpWorkerRequest)serviceProvider.GetService(typeof(HttpWorkerRequest));

                    logonUser = workerRequest.GetServerVariable("LOGON_USER");
                    authenticationType = workerRequest.GetServerVariable("AUTH_TYPE");

                    if (!String.IsNullOrEmpty(logonUser) && !String.IsNullOrEmpty(authenticationType))
                    {
                        using (WindowsIdentity windowsIdentity = new WindowsIdentity(workerRequest.GetUserToken(), authenticationType, WindowsAccountType.Normal, true))
                        {
                            windowsIdentityGroupList = new List<string>();                               

                            for (int i = 0; i < windowsIdentity.Groups.Count; i++)
                            {
                                try
                                {
                                    tempGroupName = windowsIdentity.Groups[i].Translate(typeof(NTAccount)).Value;
                                }
                                catch
                                {
                                    continue;
                                }

                                if (windowsMembershipProvider.DeletePrefix != null)
                                {
                                    foreach (String prefix in windowsMembershipProvider.DeletePrefix)
                                    {
                                        if (tempGroupName.StartsWith(prefix, StringComparison.InvariantCulture))
                                        {
                                            tempGroupName = tempGroupName.Substring(prefix.Length);
                                            break;
                                        }
                                    }
                                }

                                windowsIdentityGroupList.Add(tempGroupName);
                            }

                            userName = windowsIdentity.Name;
                        }

                        new WindowsProviderDB().SynchronizeGroups(userName, windowsIdentityGroupList.ToArray());

                        isValidWindowsUser = true;
                    }
                }
            }

            return isValidWindowsUser;
        }
    }
}

If "ValidateWindowsUser" returns true I use the out parameter "userName" and set "FormsAuthentication.SetAuthCookie(userName, false)" and then I redirect to "ReturnUrl".

So my question is:
The code in my method "ValidateWindowsUser", is it secure? Should I do it different? Or is my idea not possible at all? Do I have to release the userToken handle?

Regards Hans

#20741
Jun 10, 2008 14:05
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.