In response to my blog post Using Forms Authentication with Windows Authentication ("Mixed Mode"), I'm often asked how I made this work.  I used two time-honored development methods to do so:

  1. Copied someone else's idea (thanks, Paul!)
  2. Cheat

For the most part, when people ask about making it “work”, they really want a fine-tuning of a couple of features, mainly getting rid of a Windows login box as the request is bounced around to the different login pages.  Ignoring the login may work for you and I, but that login tends to stop ordinary users dead in their tracks.  If one of these ordinary users happens to be a boss-level, you're going to hear about it.

In a nutshell, here's what I did:

  1. Set IIS to “allow anonymous” only.  No other authentication is enabled at the website level.
  2. Set application to Forms Authentication in the web.config, and the forms login is webform.aspx weblogin.aspx.
  3. Created winlogin.aspx, and set authentication on this page only to be Windows Integrated.  If you right-click on My Computer, then choose Manage, and drill down to your site, you can right-click on the individual file and change the authentication for this file only.  Remember to remove “allow anonymous”.
  4. This is where I cheat.  In the page_load() for weblogin.aspx, I check the client's IP address using a regular expression.  If your network is set up properly, all of your internal users are coming from a reserved block of IP addresses, maybe 10.nnn.nnn.nnn, or 172.nnn.nnn.nnn.  These are also the only users who will be able to authenticate using Windows authentication.  If the client's IP address passes the RegEx test, the client is redirected to winlogin.aspx.  If not, the client stays at weblogin.aspx.
  5. For external users, they login using weblogin.aspx.  If they are authenticated, they receive a FormsAuthentication ticket, and they are redirected to their original destination page.  Users who authenticate via FormsAuthentication are not redirected to winlogin.aspx after they log in.
  6. When internal users are bounced to winlogin.aspx, IIS automatically examines their credentials due to the setting on this individual page.  If the credentials are correct, winlogin.aspx reads the user's network identity, cross-references it with the database used for Forms Authentication, and if the user is allowed access to the application, the user's roles and user ID/name/number are used.  Winlogin.aspx then creates a standard FormsAuthentication ticket using this information, and redirects the user to whatever page they were trying to access.  Since the user now has a FormsAuthentication ticket, they can access the application without further authentication.
  7. If their credentials are not correct, the user is presented with the Windows login screen.  If they present a valid login, they are processed as above.  Otherwise, they are denied access to the application.

My two recommendations for trying this are:

  1. Make sure you understand Paul's article, and watch your authentciation settings at the application level, and in the case of winlogin.aspx, at the page level.
  2. Yes, you need to have every user in a single data store.  This is key to determining if a user has access to the application, and determining their application roles.