The Request Builder feature in recent versions of Fiddler includes a number of enhancements, including the ability to follow HTTP redirections, and to automatically authenticate (using the current user's credentials) to servers that demand authentication using the NTLM or Negotiate (NTLM/Negotiate) challenge-response protocols. Following redirections is simple enough, but properly constructing a response to a server's Negotiate authentication request entails some very complicated code. The problem is that while .NET can automatically add credentials to HTTPWebRequest objects, there's no trivial way to calculate the challenge-response string when you're using a socket directly (as Fiddler does).

Fortunately, a (now-defunct) blog post from "Jeff" suggested a hack that works rather well—use Reflection to grab internal fields (including the challenge-response string) from a dummy WebRequest object. While using Reflection to grab internal fields is inherently fragile (e.g. subject to breakage in updated versions of the framework) this particular trick appears to work reliably in both .NETv2 and .NETv4 frameworks.

Each Fiddler session keeps a dummy WebRequest variable which is not initialized by default.

private WebRequest __WebRequestForAuth = null;

If, however, the server returns a WWW-Authenticate header demanding NTLM or Negotiate, and the Session Flag x-Builder-AutoAuth is present on the session, then the object will be initialized, with the current session's URL:

if (null == __WebRequestForAuth) 
{   
    __WebRequestForAuth = HttpWebRequest.Create(this.fullUrl);
}

Then, we use Reflection to get the Authorization String we'll be adding to the request

try                
{                    
#region Use-Reflection-Magic-To-Tweak-Internals                    
    Type tWebReq = __WebRequestForAuth.GetType();
    tWebReq.InvokeMember("Async", BindingFlags.Default 
| BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetProperty, null, __WebRequestForAuth, new object[] { false });

    object objServerAuthState = tWebReq.InvokeMember("ServerAuthenticationState", BindingFlags.Default | BindingFlags.NonPublic | 
     BindingFlags.Instance | BindingFlags.GetProperty, null, __WebRequestForAuth, new object[0]);                    
    
    if (objServerAuthState == null) throw new ApplicationException("Auth state is null");

    Type tAuthState = objServerAuthState.GetType(); 
    tAuthState.InvokeMember("ChallengedUri", BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null, objServerAuthState, new object[] { new Uri(this.fullUrl)});                    
#endregion Use-Reflection-Magic-To-Tweak-Internals

    string sAuthString = (bIsProxyAuth) ? oResponse["Proxy-Authenticate"] : oResponse["WWW-Authenticate"];

    // Next line uses default creds for current user. You could manually specify like so = new NetworkCredential("user", "pass", "domain") :
    ICredentials oCreds = CredentialCache.DefaultCredentials;  // This may throw, due to clock skew, etc.                    
    Authorization auth = AuthenticationManager.Authenticate(sAuthString, __WebRequestForAuth, oCreds);
    if (null == auth) throw new Exception("AuthenticationManager.Authenticate returned null.");                     
    string sAuth = auth.Message;

    // Create the new session that we'll resend with credentials
    nextSession = new Session(oRequest.pipeClient, oResponse.pipeServer);
    if (!auth.Complete)
    {
        nextSession.__WebRequestForAuth = __WebRequestForAuth;
    }
    __WebRequestForAuth = null;

    // Set the headers and body for the new session, using the 
    // Challenge-Response that we Reflected out of the Framework
    nextSession.requestBodyBytes = this.requestBodyBytes;
    nextSession.oRequest.headers = (HTTPRequestHeaders)this.oRequest.headers.Clone();
    nextSession.oRequest.headers[bIsProxyAuth ? "Proxy-Authorization" : "Authorization"] = sAuth;
catch (Exception eX) { FiddlerApplication.DoNotifyUser("Automatic authentication was unsuccessful.\n\n" + eX.Message, "Automatic Authentication failed"); }

That's all there is to it.

-Eric