In my case, I generally need to provide a basic password protection for simple admin/reporting tools or development environments I want to keep away from prying eyes. The optimal solution for me would be something that I can simply set up in web.config and forget about.
This article will outline the basics of getting something as simple as that set up and how you'd configure your web application once the code is running.
Setting up browser-based authentication involves the following steps:
Code
In setting up our HttpModule, the event that we are most interested in is Application.AuthenticateRequest. We need to setup a handler for it in the HttpModule.Init() method.
Once that's done, we can handle the bulk of the HTTP work that needs to be done. This little bit of code sets up the variables and tests to see if we can even handle this request.
HttpApplication app = (HttpApplication)source;string authStr = app.Request.Headers["Authorization"];/* If there's nothing in the header, then it's an anonymous request */if (authStr == null || authStr.Length == 0) return;/* If the authtype isn't Basic, then assume someone else will handle it. */authStr = authStr.Trim();if (authStr.IndexOf("Basic",0) != 0) return;
Next, we need to interpret the header information which is stored in Base64 for basic authentication.
string encodedCredentials = authStr.Substring(6);byte[] decodedBytes = Convert.FromBase64String(encodedCredentials);string s = new ASCIIEncoding().GetString(decodedBytes);string[] userPass = s.Split(new char[] {":"});string username = userPass[0];string password = userPass[1];
Finally, authenticate the user using the credentials we were presented with and modify the headers to reflect the results. If we are successful, give the current context a Principal based on our credentials in case that information is needed further down the line.
if (AuthenticateUser(app, username, password, out roles)){ string realm = "dieselrover"; app.Context.User = new GenericPrincipal(new GenericIdentity(username, realm), roles);}else{ DenyAccess(app);}
The AuthenticateUser method simply checks the credentials against some settings in the web.config. If you are interested in seeing that, just download the project and browse through it. You can easily override that method with your own if you want a more complicated data store for usernames and passwords, but I would strongly suggest evaluting a more robust solution if you need "real" authentication.
Configuration
Now lets look at how to set this up and get it running. For those of you not interested in how it really works, you can just download the binary, put it in your bin folder, and edit the web.config file.
First, set up the configuration handler:
<configSections> <section name="MonoSite.Authentication"type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </configSections>
Second, configure the authentication settings by setting the username, password, and realm. The realm is used by the client to organize saved passwords.
<MonoSite.Authentication> <add key="username" value="admin" /> <add key="password" value="admin1234" /> <add key="realm" value="dieselrover" /></MonoSite.Authentication>
Third, setup the HttpModule.
<httpModules> <add name="Authentication" type="MonoSite.Http.AuthenticationModule,MonoSite.Http.Authentication" /></httpModules>
Lastly, tell ASP.NET that you want there to be some sort of authentication.
<system.web> <authorization> <deny users="?"/> </authorization></system.web>
If you want to only password protect certain subfolders of your application, you can do that easily by using the location tag.
<location path="admin"> <system.web> <authorization> <deny users="?"/> </authorization> </system.web></location>
Source code and binaries
-
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.