16
votes

This should be much simpler than it has proven to be!

I have an ASP.Net web app which uses FORMS authentication to secure part of the site (i.e. the member login area).

Now I simply want to put a traditional/simple browser password popup (directory security) across the whole site because we are testing it and don't want anyone to stumble across the site and see the unfinished version etc!

This used to be super simple in older IIS versions.

I have "installed basic authentication" (as IIS7 doesn't come out of the box with this now). But when I enable it, it tells me that I can't have that enabled at the same time as any redirect based authentication (which is what my FORMS authentication uses).

So that's just stupid.

There has to be a super simple way to simply put a cheap popup password across the whole site without impacting on the other authentication method that you have setup inside web.config for the actual application.

Many thanks..

UPDATES IP access restrictions are no good for a couple of reasons: - My IP is dynamic and therefore constantly changing. - I don't want to bother anyone that needs to see the site by asking them to bring up a console on their machine and work out their IP address or check their router etc. Many of them are non-technical business users and it will take them an hour to work out their IP address. - Both basic auth and windows auth don't allow the underlying forms authentication to remain in place underneath.

What we seem to have here is a massive case of Microsoft trying to over-engineer things and as a result a super simple age-old requirements is no longer possible or easily achieveable. This has to be possible somehow... ANYONE???

3

3 Answers

5
votes

I am running into the same issue. I will be putting up a beta site limited to a preview group. The website uses forms authentication but some people from the preview group will have website accounts and others will not. Irrespective everyone will need to authenticate at root to gain access to the preview.

So far the only thing I have working exactly the way I want it is Helicon Ape. I am running the trial and so far so good.

Standard .htaccess file in root.

AuthUserFile c:\fakepath\.htpasswd
AuthType Basic
AuthName "SITE SECURITY"
Require valid-user

User .htpasswd to add a username and password: username:encryptedpassword.

3
votes

What you describe is a limitation of default ASP.NET, it is only built to run one authentication module at a time. The solution is to build your own IHttpModule that does your custom authentication, and if successful, pass the request to ASP.NET which continue to use Forms.

The following is a basic implementation of such module. It will return a 401 Unauthorized and ask the user to login to the realm WOPR. It will then accept the password Joshua, ignoring the username specified.

Compile this as a separate assembly and add it to your web.config, in the system.web/httpModules and system.webServer/modules sections. No other modification of your web application is required.

using System;
using System.Text;
using System.Web;

namespace Research {
    public class AuthenticationModule : IHttpModule {
        public void Init(HttpApplication app) {
            app.BeginRequest += (sender, e) => {
                if (!Authenticate(app.Context)) {
                    app.Context.Response.Status = "401 Unauthorized";
                    app.Context.Response.StatusCode = 401;
                    app.Context.Response.AddHeader("WWW-Authenticate", "Basic realm=WOPR");

                    app.Response.ClearContent();
                    app.Context.Response.End();
                }
            };
        }

        public void Dispose() {
        }

        public static Boolean Authenticate(HttpContext context) {
            var authHeader = context.Request.Headers.Get("Authorization");
            if (String.IsNullOrEmpty(authHeader))
                return false;

            if (!authHeader.StartsWith("Basic "))
                return false;

            var base64Credentials = authHeader.Substring(6);
            var binaryCredentials = Convert.FromBase64String(base64Credentials);
            var asciiCredentials = Encoding.ASCII.GetString(binaryCredentials);
            if (!asciiCredentials.Contains(":"))
                return false;

            var credentials = asciiCredentials.Split(new[] { ':' }, 2);
            return credentials[1] == "Joshua";
        }
    }
}
2
votes

There is a simple solution for you since you want to use FORMS authentication...

  1. Add this section to your web.config under the main header. Do not merge it -- just copy paste it as one block. The location tag will isolate these rules from the rest of the web.config and allow its easy removal later.

     <location allowOverride="false">
                 <system.web>
                     <authentication mode="Forms">
                         <forms loginUrl="frontdoor.aspx" name=".ASPXFORMSAUTH">
                         </forms>
                     </authentication>
                     <authorization>
                         <deny users="?" />
                     </authorization>
                 </system.web>
             </location>
    
  2. Create a page called "frontdoor.aspx". Get the contents of that aspx page from this link: http://msdn.microsoft.com/en-us/library/xdt4thhy.aspx (scroll down to where it says: "To create the logon page")

  3. ALL DONE! This will lock your entire site and allow you to specify the username and password (I call this process "locking the front door") for the front door independently from the rest of the site. The front door credentials are specified in the front door file itself (not very secure but good enough for what you (we) need) in this conditional:

    [Line 6:]

    If ((UserEmail.Text = "TheSharedFrontDoorLogonName") And (UserPass.Text = "AndItsPassword")) Then
    

Modify the conditional to suit your needs and then e-mail your clients/business-types the credentials to the front door.