Friday, June 06, 2008

Mixing Forms and Windows authentication in ASP.NET

In ASP.NET it is easy to set the prefered authentication method in the web.config file.
For external websites this is set mostly to Forms authentication through a own Login.aspx. When you use Windows authentication the authentication is handled by Windows, and you will get a Windows logon window automatically if the authentication failed.
In forms authentication users will be logged in based on, for example credentials which are located in the applications database. With windows authentication users are logged in based on their Windows domain account.
How can you mix those two? 
In this situtation a client wanted to enable Windows authentication for the domain users, and Forms authentication for external users.
You can't do this through the web.config file. Let's first look at methods:

Windows authentication
If you choose Windows authentication you can get the user name with the  server variable LOGON_USER.

string user = Request.ServerVariables["LOGON_USER"];

If the user, is not autorized a IIS 401 security error page will appear. The server variable is then an empty string.

Forms authentication
With forms authentication the user will be redirected to given login page. (Mostly likely login.aspx). In this page you can check the user in you database and authenticate it based on that result.

In the mix
If you mix those two you probably want to match the Windows user with the application users. However first you must setup your application to accept both users.

I found a solution here. Basically it drills down to the following:

1. Set Forms authentication in you web.config

2. Create an extra login page, Winlogin.aspx and let that be the forms login page. (in the web.config)

3. In IIS set security on Winlogin.aspx so, that it won't allow anonymous users.

4. In Winlogin.aspx determine if the user is authenticated based on his windows account. If you have the user you can also (if needed) check if he is in your own database, and if OK, redirect from this page:

FormsAuthentication.RedirectFromLoginPage(UserId, false);

5. If the user is not authenticated, the IIS 401 security error will be shown. You can hower redirect to your own HTML page in IIS, by setting the custom error redirect.

6. In your OwnRedirect401.html redirect to the your 'normal' Login.aspx with for example a META redirect, like this:

<meta http-equiv="refresh" content="0;URL=Login.aspx" />

Note that you must exclude login.aspx as a protected page in you web,config. I.o.w allow anonymous users, other wise you will end up again on your Winlog.aspx.
<location path="login.aspx">
      <allow users="?"/>
Some references:
Above method described in detail (MSDN article)
A alternate approach to the problem


Fahima said...

your site is very nice ...
this is very helpful and attractive.
visit for help help

Anonymous said...

But this triggers login/password popup dialog to appear for external users if they go to winlogin.aspx. How to prevent this? Thanks, m

Anonymous said...

Not work for not domain users

Anonymous said...

for the issue with external users, I guess you will have to check if the user request is coming from intranet or internet, if internet user, redirect it to the form authentication page.

mukesh arora said...

toI'm getting login/password popup dialog to appear for external users if they go to winlogin.aspx. How to prevent this? Thanks, MA

Anonymous said...

For external users, the login Page is what I want. Credentials are verified against database.dbo.table. Some of these users might not even be part of Active Directory. So that's fine. But for internal users, whom are part of Active Directory, I want to bypass login Page amd get username from Active Directory and go directly to process Application. How do I get that userName from Active directory. Everything I've tried comes up empty, unless I'm debugging from localhost. Thanks.

Cindy Dy said...

I am very happy to locate your website. I just wanted to thank you for the time you spent on this great article. I definitely enjoyed reading it and I have you bookmarked to check out new stuff you post.