3

I'm trying to achieve the following scenario's for my intranet site that i'm developing:

  • When a user which is logged on a PC in the same domain as the website and connected to the same network as the website, accesses the intranet site, (s)he will be logged in automatically (windows authentication)
  • When the same user with the same PC is logged in on the same domain as the website but on a other network, for example home network, as the website, (s)he will be logged in automatically (windows authentication)
  • When the same user opens the website from his/her home PC which is not part of the domain and network, (s)he will be redirected to the forms authentication login page and is able to login with his/her AD credentials (Forms authentication with AD Membership)
  • When a other user which doesn't have a AD account and is not on a PC which is part of the domain, (s)he will be redirected to the forms authentication login page and is able to login with his/her SQL user scredentials (Forms authentication with SQL membership)

I almost have this working except for 1 important step. The code i have right now is this:

Global.asax

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        // we only want 302 redirects if they are for login purposes
        if (this.Response.StatusCode == 302 && this.Response.RedirectLocation.Contains("/WinLogin"))
        {
            if (Request.UserHostAddress.StartsWith("10.1.34") || Request.UserHostAddress.StartsWith("10.1.35"))
            {
                this.Response.StatusCode = 401;
                // note that the following line is .NET 4.5 or later only
                // otherwise you have to suppress the return URL etc manually!
                this.Response.SuppressFormsAuthenticationRedirect = true;
            }
        }
    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        if (Request.IsAuthenticated && HttpContext.Current.User.Identity is WindowsIdentity)
        {
            // note that we will be stripping the domain from the username as forms authentication doesn't capture this anyway

            // create a temp cookie for this request only (not set in response)
            var tempCookie = FormsAuthentication.GetAuthCookie(Regex.Replace(HttpContext.Current.User.Identity.Name, ".*\\\\(.*)", "$1", RegexOptions.None), false);

            // set the user based on this temporary cookie - just for this request
            // we grab the roles from the identity we are replacing so that none are lost
            HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(FormsAuthentication.Decrypt(tempCookie.Value)), (HttpContext.Current.User.Identity as WindowsIdentity).Groups.Select(group => group.Value).ToArray());

            // now set the forms cookie
            FormsAuthentication.SetAuthCookie(HttpContext.Current.User.Identity.Name, false);
        }
    }

WinLogin.aspx:

var membershipProvider1 = Membership.Providers["MyAdMembershipProvider"];
var membershipProvider2 = Membership.Providers["MySqlMembershipProvider"];
if (membershipProvider1.ValidateUser(TextBox1.Text, TextBox2.Text) || membershipProvider2.ValidateUser(TextBox1.Text, TextBox2.Text))
{
    // set the forms auth cookie
    FormsAuthentication.SetAuthCookie(TextBox1.Text, false);

    // reset request.isauthenticated
    var authCookie = System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        if (authTicket != null && !authTicket.Expired)
        {
            var roles = authTicket.UserData.Split(',');
            System.Web.HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
        }
    }

    FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, false);
}

Web.config

<authentication mode="Forms">
  <forms name=".ASPXFORMSDEMO" loginUrl="WinLogin.aspx" />
</authentication>
<authorization>
  <deny users="?"  />
  <allow users="*"   />
</authorization>

<location path="/WinLogin.Aspx">
  <system.web>
    <authorization>
      <allow users="?"/>
    </authorization>
  </system.web>
</location>

Settings in IIS

Website root level

  • Anonymous Authentication Enabled
  • Forms authentication Enabled
  • Windows authentication Enabled

WebLogin.aspx level

  • Anonymouse Authentication Enabled
  • Forms authentication Enabled
  • Windows authentication Disabled

All my scenarios work except the part where i define if i can use windows authentication or not. With the setup i have right now, only PC's within my local network will continue using windows authentication. Whenever i go with my pc outside the network, i'll get the forms authentication login screen.

Does anyone have a suggestion how i can determine if windows authentication should be used or not. I've been on the track on using the current users logged in user name and check for it's domain and use that, but i can't seem to get that as of the IIS settings of the website.

Thanks in advance!

Pim Dröge
  • 85
  • 1
  • 10
  • The article i've used to get to this solution is located at http://world.episerver.com/blogs/Dan-Matthews/Dates/2014/8/Mixing-Forms-and-Windows-Authentication/ – Pim Dröge Dec 09 '15 at 14:29
  • It's not enough to simply check their domain and username. If that was all you needed, some hacker could create a domain with the same name as yours, and a username matching a user and then have free access. – mason Dec 09 '15 at 14:30

0 Answers0