Cross Application Authentication (part 2 – The Server)
with Native .NET Forms Authentication
In the first of this series, I explained my troubleshooting process for justifying having two ASP.NET forms authentication applications. We would need one for 1.x apps and one for 2.x apps. We came to the conclusion that the application setup and design was straight forward, but would not work without getting our systems administrator hat out and getting up to our elbows in IIS. In this part of the series we will explain what needs to be done in IIS and your application configuration files to get you up and running with a cross application native ASP.NET forms authentication application.
Before we get down to it, I must acknowledge that this is the basic setup. It will work on a single IIS host. If you are clustering or load balancing this could be a good starting place. So lets get to it.
There are plenty of documents out there on how to setup IIS and ASP.NET forms authentication. Lets skim over the high points of these documents. Then I will explain the shortcomings.
The first thing you will be told to do is modify your application’s web.config so that it knows where to send users for authentication. Something like this:
Remember our app was called myTestApp (at /testap/) and the authentication application was called myAuth (at /myauth/). The authentication token we were sharing was “.MYAUTH”. Now that we have myTestApp configured for authentication, we need to tell it who needs authenticated. For simplicity’s sake lets just deny everyone who is not authenticated like this:
<deny users="?" />
The “?” means everyone who is not authenticated. This is in contrast with “*” which means everyone. So if this authorization block is in the root web.config for the application it will protect the whole application from unauthenticated users unless in a subfolder with another web.config as was demonstrated Part 1 of this series.
Now that your application needing protected is configured you need to make sure your authentication application is sending signals on the same channel. What do I mean by that? The configuration specified above is expecting a token named “.MYAUTH” to come across from the authentication application. So you need to tell it to use this name since the default is “.ASPXAUTH”. Specifying a unique name is paramount to having more than one authentication application running at the same time in a cross application design.
Now that the application knows what it is doing IIS needs to know that the application will be taking care of it’s own authentication. How we accomplish this my navigating to the Directory Security tab under the properties of the directory your application in the IIS MMC. It can be found after clicking the ‘Edit’ button under “Anonymous access and authentication control”. “Anonymous access” needs to be enabled, and “Integrated Windows authentication” needs to be disabled, as well as “Basic authentication”.
Show Stopper Caveat
Now this is where most tutorials and documentation will leave you. ‘Have a nice day.’ So why doesn’t the one we just setup work? This after following numerous tutorials and reading numerous articles. Many of them with titles like “Forms Authentication Explained” and “Exposed: ASP.NET 2.0 Forms Authentication Secrets”. I was just waiting to find one that had a free offer to attend some motivational seminar. So we were back to the same problem.
It seemed like .NET wasn’t allowing the application to read the cookie, like it was isolating the applications. So I took a look at my code, everything seemed ok and then I noticed my call to RedirectFromLoginPage() and remembered one of the defaults values for the ‘forms’ element. It was called enableCrossAppRedirects. By default it was set to false “to indicate that forms authentication does not support automatic processing of tickets that are passed between applications on the query string or as part of a form POST”.
Was that my problem? It still didn’t work, so was it part of the puzzle? Not directly, but if the profile for a users browser indicated it was not capable of using cookies it could later cause problems.
At this point I needed to ruminate on everything I hand done. Like an old cliché I decided that I needed to come at it from a different angle. Turn it upside down and think about the box. So maybe it is the desired default to prevent a token from passing to another application. So I set out to find out how to prevent this from happening. I found a MSDN article all about protecting forms authentication.
I started combing through the data. In the section talking about methods of encryption I noted an option that contained the phrase “IsolateApps”. The article stated that IsolateApps should be “set to true to ensure a malicious Web application in a shared hosting scenario cannot compromise the authentication mechanism for other applications”. Well that is just silly, I would never pay for hosting that I didn’t own the base domain and thus was only a subdirectory. But I see the obscure possibility. So then how do you set it to “false”. This seemed to be the missing key. I guess if it is not set it would be assumed to be false.
This article stated that the machine.config.comments contains all the defaults for the machine.config. I did not find this line in the .comments file. Fortunately this article linked to an article dealing specifically with the MachineKey element and where to put it.
I added the following line to my machine.config:
A test, and it was working. My application could see that it was authenticated and how. It could also retrieve the username. There were however no roles associated with my user, which are central to the way some of my apps operate. So now it is time to get coding. The next article will cover the basics of forms authentication on the side of the programmer.