What does it accomplish?
MultiAuth is a sample for people who wants to use the same website for internal and external purpose but with either Windows Authentication (internal) or Basic Authentication (external) access.
How does it work?
1. Enable both “Basic Authentication” and “Windows Authentication” for the site (or vdir)
2. During EndRequest in the pipeline, for the 401 response
a. Remove all “WWW-Authenticate” headers (context.Response.Headers.Remove(“WWW-Authenticate”))
b. check the “host” in http header and
i. if host url is internal then add WWW-Authenticate: Negotiate and WWW-Authenticate: NTLM
ii. if host url is external then add WWW-Authenticate: Basic realm=”<host>”
Example URL's
http://computername/multiauth/time.aspx would use “Windows Authentication”
http://computername.domain.com/multiauth/time.aspx would use “Basic Authentication”
Main portion of the code to get this functionality shown below
public void IssueAuthenticationChallenge(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
// Issue authentication challenge according to configuration
// Authorization header starting with TlRMTVNTUA = NTLMSSP
if (context.Response.StatusCode == HttpNotAuthorizedStatusCode)
{
authorizationHeader = context.Request.Headers[HttpAuthorizationHeader];
if (!((authorizationHeader == null) || (authorizationHeader.Equals(String.Empty))))
{
if (authorizationHeader.Contains("Negotiate") || authorizationHeader.Contains("NTLM") || authorizationHeader.Contains("Basic"))
{
//2nd 401 in case of NTLM
context.Response.Headers.Add("MultiAuth", "Second round of 401 so ignore"); //adding comments for easy http debug trace
}
}
else
{
// remove all WWW-Authenticate headers and add only what is required
context.Response.Headers.Remove(HttpWWWAuthenticateHeader);
hostName = context.Request.Headers["host"];
if (hostName.Contains(externalName))
{
//adding comments to debug through http trace
context.Response.Headers.Add("MultiAuth", "Adding Basic, Status:" + context.Response.StatusCode);
context.Response.AddHeader(HttpWWWAuthenticateHeader, "Basic realm =\"" + externalName + "\"");
}
else if (hostName.Contains(internalName))
{
//adding comments to debug through http trace
context.Response.Headers.Add("MultiAuth", "Adding Integrated, Status:" + context.Response.StatusCode);
context.Response.AddHeader(HttpWWWAuthenticateHeader, "Negotiate");
context.Response.AddHeader(HttpWWWAuthenticateHeader, "NTLM");
}
}
}
}
Yea, its that simple to achieve things using IIS7 new integrated pipeline with a mix of managed code 