Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining Forms Authentication and Basic Authentication

I have some core ASP code that I want to expose both by secure web pages (using Forms Authentication) and via web services (using Basic Authentication).

The solution that I've come up with seems to work, but am I missing anything here?

First, the whole site runs under HTTPS.

Site is set to use Forms authentication in web.config

<authentication mode="Forms">
  <forms loginUrl="~/Login.aspx" timeout="2880"/>
</authentication>
<authorization>
  <deny users="?"/>
</authorization>

Then I override the AuthenticateRequest in Global.asax, to trigger Basic Authentication on the web service pages:

void Application_AuthenticateRequest(object sender, EventArgs e)
{
    //check if requesting the web service - this is the only page
    //that should accept Basic Authentication
    HttpApplication app = (HttpApplication)sender;
    if (app.Context.Request.Path.StartsWith("/Service/MyService.asmx"))
    {

        if (HttpContext.Current.User != null)
        {
            Logger.Debug("Web service requested by user " + HttpContext.Current.User.Identity.Name);
        }
        else
        {
            Logger.Debug("Null user - use basic auth");

            HttpContext ctx = HttpContext.Current;

            bool authenticated = false;

            // look for authorization header
            string authHeader = ctx.Request.Headers["Authorization"];

            if (authHeader != null && authHeader.StartsWith("Basic"))
            {
                // extract credentials from header
                string[] credentials = extractCredentials(authHeader);

                // because i'm still using the Forms provider, this should
                // validate in the same way as a forms login
                if (Membership.ValidateUser(credentials[0], credentials[1]))
                {
                    // create principal - could also get roles for user
                    GenericIdentity id = new GenericIdentity(credentials[0], "CustomBasic");
                    GenericPrincipal p = new GenericPrincipal(id, null);
                    ctx.User = p;

                    authenticated = true;
                }
            }

            // emit the authenticate header to trigger client authentication
            if (authenticated == false)
            {
                ctx.Response.StatusCode = 401;
                ctx.Response.AddHeader(
                    "WWW-Authenticate",
                    "Basic realm=\"localhost\"");
                ctx.Response.Flush();
                ctx.Response.Close();

                return;
            }
        }
    }            
}

private string[] extractCredentials(string authHeader)
{
    // strip out the "basic"
    string encodedUserPass = authHeader.Substring(6).Trim();

    // that's the right encoding
    Encoding encoding = Encoding.GetEncoding("iso-8859-1");
    string userPass = encoding.GetString(Convert.FromBase64String(encodedUserPass));
    int separator = userPass.IndexOf(':');

    string[] credentials = new string[2];
    credentials[0] = userPass.Substring(0, separator);
    credentials[1] = userPass.Substring(separator + 1);

    return credentials;
}
like image 819
steve cook Avatar asked May 30 '13 07:05

steve cook


People also ask

What is the difference between basic and form based authentication?

Unlike Form-Based Authentication, Basic Authentication DO NOT use cookies, hence there is no concept of a session or logging out a user, which means each request has to carry that header in order to be authenticated. Form-Based Authentication in the other hand is not formalized by any RFC.

What is the difference between Basic Authentication and Windows authentication?

Difference between Basic Authentication and Windows authentication. Windows authentication authenticates the user by validating the credentials against the user account in a Windows domain. Basic authentication verifies the credentials that are provided in a form against the user account that is stored in a database.

Can you explain Windows Forms and Passport authentication?

Passport authentication relies on a centralized service provided by Microsoft. Passport authentication identifies a user with using his or her e-mail address and a password and a single Passport account can be used with many different Web sites.

What is Basic Authentication method?

Basic Authentication is a method for an HTTP user agent (e.g., a web browser) to provide a username and password when making a request. When employing Basic Authentication, users include an encoded string in the Authorization header of each request they make.


1 Answers

.Net 4.5 has a new Response property: SuppressFormsAuthenticationRedirect. When set to true it prevents redirecting a 401 response to the login page of the website. You can use the following code snippet in your global.asax.cs to enable Basic Authentication for e.g. the /HealthCheck folder.

  /// <summary>
  /// Authenticates the application request.
  /// Basic authentication is used for requests that start with "/HealthCheck".
  /// IIS Authentication settings for the HealthCheck folder:
  /// - Windows Authentication: disabled.
  /// - Basic Authentication: enabled.
  /// </summary>
  /// <param name="sender">The source of the event.</param>
  /// <param name="e">A <see cref="System.EventArgs"/> that contains the event data.</param>
  protected void Application_AuthenticateRequest(object sender, EventArgs e)
  {
     var application = (HttpApplication)sender;
     if (application.Context.Request.Path.StartsWith("/HealthCheck", StringComparison.OrdinalIgnoreCase))
     {
        if (HttpContext.Current.User == null)
        {
           var context = HttpContext.Current;
           context.Response.SuppressFormsAuthenticationRedirect = true;
        }
     }
  }
like image 146
user1646217 Avatar answered Oct 29 '22 09:10

user1646217