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;
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?
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