Mixing Forms and Windows Authentication

CraigBlog

Syndication

A client of mine wants to provide single sign-on (SSO) capabilities in their web application, so that users don't have to type in their domain password when authenticating to the application. The twist? Only some users of the application use SSO: the rest have accounts that exist only in the application database. So we couldn't just flip on “integrated authentication” in IIS and party on. But with the help of Keith Brown, I was able to figure out a pretty nifty solution.

The trick was realizing that if you enable both “anonymous“ and “integrated“ authentication for a particular virtual directory, the browser won't try to authenticate to the web server until it receives a 401 (Unauthorized) back from the web server. But you can issue your own 401 any time you like! So what I did was to just set up Forms authentication as normal, but also provided a checkbox on the login form that said, “Use my network credentials.” Then, in my login form, I did something like this:

public class Login : Page {
  protected
Label ErrorMessageLabel;
  protected
TextBox UsernameTextBox;
  protected
TextBox PasswordTextBox;
  protected
CheckBox CheckBox1;

  public void Page_Load(object
o, EventArgs e) {
    if
(IsPostBack) {
      string authenticatedUser = null
;
      if (CheckBox1.Checked)
// Use their network credentials
     
{
        string
user = Request.ServerVariables["LOGON_USER"];
        if (user.Length == 0)
// They haven't provided credentials yet
       
{
         
Response.StatusCode = 401;
          Response.StatusDescription = "Unauthorized";
          Response.End();
        }
        else
// They have
       
{
         
authenticatedUser = user;
       
}
      }
      else
// Use the username and password they provide
     
{
         if
(IsPasswordOK(UsernameTextBox.Text, PasswordTextBox.Text)) {
          authenticatedUser = UsernameTextBox.Text;
        }
      }
      if (authenticatedUser != null)
// They authenticated successfully
     
{
        // Issue the Forms Auth cookie and send them on their way

        FormsAuthentication.RedirectFromLoginPage(authenticatedUser, false
);
      }
      else
// They didn't
     
{
       
ErrorMessageLabel.Text = "Invalid username or bad password. Please try again.";
     
}
    }
  }
}

What this does is - when the user submits the login - check to see whether they want to authenticate by providing a username and password (normal Forms authentication) or whether they want to authenticate automatically, using their logged-in credentials. Right now, I'm figuring this out by having them explicity check a checkbox, but I do lots of other things. For example, I could have them always enter their username, and then go look in the database to see whether they're supposed to get a SSO login or a normal one. Or I could have them check the checkbox once and remember their settings forever after in a cookie.

Whatever mechanism I decide on, the trick here is that I can force the browser to authenticate by sending back a 401. Then, in subsequent visits, I can check the LOGON_USER server variable to see if the authentication was successful or not. If it is, I'm perfectly welcome to issue them a valid Forms Authentication login, secure in the knowledge that the user has proven knowledge of their password to IIS already.

If the user is using IE, the authentication will happen automatically, using whatever credentials they're logged in to the client machine with. It works in Firefox, too, but they get that little username/password popup dialog box. Oh well - maybe the Firefox people will add auto login in a future release, or someone will write an extension. But failing that, providing SSO only to IE users is good enough for us.


Posted Jul 24 2004, 08:40 AM by craig-andera

Comments

Darrell Norton's Blog wrote Mixing Forms and Windows Authentication
on 07-26-2004 7:25 AM
Mixing Forms and Windows Authentication
Christopher wrote RE: Mixing Forms and Windows Authentication
on 07-27-2004 11:59 AM
That, sir, is completely hardcore. :) Slick.
Craig wrote re: Mixing Forms and Windows Authentication
on 07-27-2004 12:27 PM
I aim to please. ;)
Dimitri Glazkov wrote re: Mixing Forms and Windows Authentication
on 08-18-2004 9:54 AM
Craig,

This is pretty cool -- you could make this even better by using my Credentials Screening solution (http://glazkov.com/blog/archive/2004/06/06/189.aspx). That way, you won't even need to see a login form if your network credentials are valid.

:DG<
Craig wrote re: Mixing Forms and Windows Authentication
on 08-18-2004 10:57 AM
I'm not sure I understand. This is an IE-only solution, and IE already doesn't pop up a dialog box.

In order to never display a login form, you have to catch the second 401 that happens when they provide network credentials that are no good, or fail to provide any to your first challenge. And the problem with that is, the dialog box that pops up for non-IE users pops up after the first challenge, so you'd still have that.

I guess what you'd have to do is to figure out based on the user-agent string which browser they're using, and react accordingly. Assuming they haven't used one of the many available plugins to make it lie to you. :) If you did that, though, you'd be able to skip displaying the form and go straight to the challenge.

All in all, it would be a moderately complicated piece of code.
Dimitri Glazkov wrote re: Mixing Forms and Windows Authentication
on 08-18-2004 11:36 AM
IE doesn't always let you slip through withouth the dialog box. For example, if you are accessing the site that is not in your Local Intranet zone, you will get the dialog box no matter what. Credentials Screening solution I proposed addresses this exact problem. Otherwise, in your solution, even after you check the "use network credentials" checkbox, you will a standard security dialog box unless the site in Local Intranet zone, which may or may not be the case, depending on the configuration of the network.

I agree, it adds complexity, but it also adds completeness :)
Craig wrote re: Mixing Forms and Windows Authentication
on 08-18-2004 11:54 AM
Interesting! I didn't know that about the Intranet Zone!

Thanks for explaining. :)
Dimitri Glazkov wrote re: Mixing Forms and Windows Authentication
on 08-19-2004 6:01 AM
Not a problem. Now I can go tell people for a week that I taught Craig Andera something :)
Craig wrote re: Mixing Forms and Windows Authentication
on 08-19-2004 6:29 AM
Heh. I think you need some new goals: finding something I don't know is too easy. :)
Dimitri Glazkov wrote Better Credentials Screening
on 10-04-2004 6:36 AM
Support Guy wrote re: Mixing Forms and Windows Authentication
on 06-07-2005 9:26 AM
Interestingly enough, I just read this blog: http://ackbarr.xoops.org/archives/2005/03/31/integrated-windows-authentication-in-firefox/
Getting Windows Authentication working in Firefox
If you have control of the browser settings (it's in user.js in Firefox) you can make it a default setting.
This is a pretty old blog so this may not be relevant info anymore.
Just trying to help out.
Craig wrote re: Mixing Forms and Windows Authentication
on 06-07-2005 9:34 AM
Interesting - I'll have to check that out. I don't think it helps my client, but it might help *me*, which is more important. :)

Thanks!
Dimitri Glazkov wrote Better Credentials Screening
on 07-05-2005 6:27 AM
B³: Beto Borbolla Blog wrote Windows &amp; Forms Authentication
on 07-18-2005 2:31 PM
Interesante tip de como proveer un proceso de autentificación integrada tanto para usuarios que puedes...
CraigBlog wrote Mixing Forms and Windows Authentication in ASP.NET 2.0
on 06-19-2006 10:06 AM
JTower wrote re: Mixing Forms and Windows Authentication
on 10-20-2006 7:27 AM
Brilliant work! Thanks for posting this, Craig. It was exactly what I was looking for.
Doug wrote re: Mixing Forms and Windows Authentication
on 09-17-2007 7:14 AM
Craig or Dimitri,
Do you still have the code for the credentialing screening available? Looks like the link above no longer exists and I would like to look closer at Dimitri's code.

Thanks in advance.
Doug
Doug wrote re: Mixing Forms and Windows Authentication
on 09-17-2007 7:15 AM
I'm trying to use the above (which is awesome) and avoid the login pop-up but rather gather the user context since they have already logged into the domain.
Craig wrote re: Mixing Forms and Windows Authentication
on 09-17-2007 7:47 AM
Which link are you talking about that no longer exists?
SBM wrote re: Mixing Forms and Windows Authentication
on 08-07-2008 8:09 AM

How can i access to the Default page directly when i am in INTRANET.I'm tryung to eliminate the check box:

INTRANET ----> Page Default

INTERNET ------> login page ---OK----> Page Default

craig-andera wrote re: Mixing Forms and Windows Authentication
on 08-07-2008 8:29 AM

You could try an approach like this one:

glazkov.com/.../credentials-screening

SBM wrote re: Mixing Forms and Windows Authentication
on 08-07-2008 8:55 AM

yes it's true,BUT

For internet Access i want to have my personel login page where i test the validity of username and login by my self.that's mean

Internet ----> "MY login Forms page and not Windows login" ----function IsPasswordOK(string,string) return true--> Page Default.

I think that IIS have some impact to do it.

Thank you craig-andera!

craig-andera wrote re: Mixing Forms and Windows Authentication
on 08-07-2008 9:32 AM

Looks like the xmlhttprequest object supports username and password authentication. So write some javascript that attempts to retrieve a page with your username and password. If it works, the username and password are authentic.

SBM wrote re: Mixing Forms and Windows Authentication
on 08-07-2008 9:41 AM

:)

think you craig

but exactly i need  a solution for this constraint:

if the user is from my local network and Domain he should access to the site (Default page) directly.

if the user is from internet or another Domain he access to my login.aspx page and he write user/password ;than i have a test throw an SQL table if  the user/password are valid so access to Default.aspx.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?