Testable authentication handler for web API
Basically you need somehow confirm that 


StatusCode == HttpStatusCode.Unauthorized  
ReasonPhrase == someDefinedConstant  


If you only Assert the first, you can't be sure that the logic is flawless. If you only test the second you can't be sure that StatusCode == HttpStatusCode.Unauthorized.  

But again, proper unit tests should fail exactly for one reason.  

As others had this problem also, Omer Rauchwerger has created a NUnit addin which can be found here: http://rauchy.net/oapt/

Comments  

Comments should be used to describe why something is done. The code itself should describe what is done.
So comments like // Check for API key should be removed and the code following should be extracted to a separate method.  

timestamp validation  

As the message will be "Timestamp is required" for a failed validation, I guess that you need to check if at least one key is found. There it is better to use Any() over Count().  

Style  

You should be consistent in your coding style. Here you one time use if (!condition) and another time you use if (condition == false).  

Refactoring  

Extracted validation methods  

private bool ContainsApiKey(HttpRequestMessage request)
{
    return request.Headers.Contains(AuthConfig.ApiKeyHeader);
}

private bool ContainsTimeStamp(HttpRequestMessage request)
{
    return request.GetQueryNameValuePairs().Any(k =&gt; k.Key.ToLower() == "timestamp");
}

private bool ContainsSignature(HttpRequestMessage request)
{
    return (request.Headers.Authorization != null &amp;&amp; request.Headers.Authorization.Scheme == AuthConfig.AuthenticationScheme);
}

private UserDTO GetUser(HttpRequestMessage request)
{
    string apikey = request.Headers.GetValues(AuthConfig.ApiKeyHeader).First();
    return  _userRepo.GetUserAuthInfo(apikey);
}

private bool IsValidUser(UserDTO user)
{
    return user != null;
}

private bool IsValidSignature(UserDTO user, HttpRequestMessage request)
{
    string signature = _signatureCalculator.GetSignature(user.Secret, request.RequestUri.OriginalString);
    return  request.Headers.Authorization.Parameter == signature
}


and the cleaned up former method  

protected override Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{

    if (!ContainsApiKey(request))
    {
        return SendResponseText(SecurityHandler.AuthError.ApiKeyMissing);
    }

    if (!ContainsTimeStamp(request))
    {
        return SendResponseText(SecurityHandler.AuthError.TimeStampMissing);
    }

    if (!IsValidTimestamp(request))
    {
        return SendResponseText(SecurityHandler.AuthError.TimeStampInvalid);
    }

    if (!ContainsSignature(request))
    {
        return SendResponseText(SecurityHandler.AuthError.SignatureMissing);
    }

    UserDTO user = GetUser(request);
    if (!IsValidUser(user))
    {
        return SendResponseText(SecurityHandler.AuthError.ApiKeyInvalid);
    }

    if (!IsValidSignature(user,request))
    {
        return SendResponseText(SecurityHandler.AuthError.SignatureInvalid);
    }

    return base.SendAsync(request, cancellationToken);
}