Here is how you should set the Thread.CurrentPrincipal
. Add a message handler like this to your Web API project and add the handler in the Register
method of WebApiConfig.cs
like so: config.MessageHandlers.Add(new MyTestHandler());
.
public class MyTestHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var local = request.Properties["MS_IsLocal"] as Lazy<bool>;
bool isLocal = local != null && local.Value;
if (isLocal)
{
if (request.Headers.GetValues("X-Testing").First().Equals("true"))
{
var dummyPrincipal = new GenericPrincipal(
new GenericIdentity("dummy", "dummy"),
new[] { "myrole1" });
Thread.CurrentPrincipal = dummyPrincipal;
if (HttpContext.Current != null)
HttpContext.Current.User = dummyPrincipal;
}
}
return await base.SendAsync(request, cancellationToken);
}
}
This handler sets an authenticated principal to make all your [Authorize]
happy. There is an element of risk with this approach. Only for testing, you should plug this handler into the Web API pipeline. If you plug this handler in to the pipeline (intentional or otherwise) in your production code, it basically defeats your authentication mechanism. To mitigate the risk to some extent (hoping API is not accessed locally), I check to ensure the access is local and that there is a header X-Testing
with a value of true
.
From RestSharp, add the custom header.
var request = new RestRequest(...);
request.AddHeader("X-Testing", "true");
BTW, for integration testing, I'd much rather use in-memory hosting, instead of web-hosting. That way, Web API runs in the same testing project and you can do whatever you want with it, without the fear of breaking something in production. For more info on in-memory hosting, see this and this.