Web Api and where should I contorol Request Header data - asp.net-web-api

In Asp.net Web Api, I want to control, request "access token" key is (which is in request header) valid or not. But I cound't decide where should I implement this kind of control. ActionFilter or controller constructor etc. etc.

How about using a DelegatingHandler? It is part if the Web Api pipeline and executes before Routing and Controller handlers.
A really simple handler for access tokens may look like this. You would implement IsValid as you see fit.
public class ValidateTokenHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var token = request.Headers.Authorization;
if (token == null or !IsValid(token))
{
return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
return await base.SendAsync(request, cancellationToken);
}
}

Related

Bot Framework sending OPTIONS message

Recently, I have been getting 405 response messages logged in Application Insights from the bot framework relating to "OPTIONS" message being sent.
How should my service be responding to these?
Who is making these requests?
Sorry if you saw my previous answer; it was completely off base so I deleted it in shame.
The requests you mention are made by Azure when navigating to WebChat or the Settings tab. To allow the call, you can create a custom bot auth class:
public class CustomBotAuthenticationAttribute : BotAuthentication
{
public override Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (actionContext.Request.Method.Method == "OPTIONS") // allow OPTIONS through, and do not authenticate
return Task.CompletedTask;
return base.OnActionExecutingAsync(actionContext, cancellationToken);
}
}
Then, in the MessagesController:
[CustomBotAuthentication] // Change from [BotAuthentication]
public class MessagesController : ApiController
{
public HttpResponseMessage Options() // handle options
{
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)

Web API - Get RouteData, Action or Controller in DelegationHandler from HttpRequestMessage

I am having a difficulty to get route data, action or controller in DelegatingHandler.
public class LoggingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var routeData = request.GetRouteData();
in this example routeData is always null. Is there any way how to get the context of the Web API controllers and thus actions so I could tell what action the URL is trying to invoke?

Setting Result in the context of ChallengeAsync method in an authentication filter

This question is related to the answer I have provided here. OP's comment got me thinking a bit. I suggested using a class implementing IHttpActionResult like this in the ChallengeAsync method of the authentication filter.
public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
CancellationToken cancellationToken)
{
context.Result = new ResultWithChallenge(context.Result);
return Task.FromResult(0);
}
public class ResultWithChallenge : IHttpActionResult
{
private readonly IHttpActionResult next;
public ResultWithChallenge(IHttpActionResult next)
{
this.next = next;
}
public async Task<HttpResponseMessage> ExecuteAsync(
CancellationToken cancellationToken)
{
var response = await next.ExecuteAsync(cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
response.Headers.WwwAuthenticate.Add(
new AuthenticationHeaderValue("Basic", "realm=localhost"));
}
return response;
}
}
Instead of this, I can simplify the ChallengeAsync like this.
public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
CancellationToken cancellationToken)
{
var result = await context.Result.ExecuteAsync(cancellationToken);
if (result.StatusCode == HttpStatusCode.Unauthorized)
{
result.Headers.WwwAuthenticate.Add(
new AuthenticationHeaderValue("Basic", "realm=localhost"));
}
context.Result = new ResponseMessageResult(result);
}
This saves me from creating a class implementing IHttpActionResult but is this the right way? I get an uneasy feeling that this is somehow bad from a performance standpoint because it feels like I'm converting action result to HttpResponseMessage and back to action result. Any pointers on the need for a separate class here implementing IHttpActionResult like what I suggested will be appreciated as against using the code above.
The intent was to use the first approach rather than the second. For example, see the Basic Authentication sample (also available for MVC), which follows the first approach:
http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/BasicAuthentication/ReadMe.txt
The second approach mostly works. I wouldn't be too concerned about the performance standpoint; either way you're allocating one action result object and one response message object, so I'm not seeing much difference there.
However, there are a couple of reasons I'd recommend the first approach:
The second approach won't work the same way in MVC. Both MVC and Web API have authentication filters, and they basically work the same way. But in MVC, there isn't an equivalent to ResponseMessageResult (the HttpContext is updated as needed, rather than returning a HttpResponseMessage that could be replaced by each caller going up the stack). If you have an MVC implementation of your authentication filter, you'd likely end up doing the first approach there anyway.
It slightly changes the pipeline behavior from what's intended. The code in ChallengeAsync runs earlier than the code in the context.Result that it returns. For example, if the code changed a property on the HttpRequestMessage and that impacted a later filter's ChallengeAsync logic, the behavior could be different than what's intended.
The framework definitely could make it easier to implement the interface; feel free to vote on this work item:
https://aspnetwebstack.codeplex.com/workitem/1456

Authorization Header in request is always null

I have created a Delegated Handler to do some token authentication.
public class SimpleWebTokenHandler: DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Headers.Authorization == null)
{
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
return await base.SendAsync(request, cancellationToken);
}
}
I am not even getting to the token validation part because the Autorization header is always null. However I can see it chrome developer tools it is being sent.
Turns out that the format of the Authorization header has to be something like
<Authorization> <Scheme> <token>="<tokenValue>"
I was missing the quotes.

Adding message handler on the fly

I have four message handlers - MyHandler, MyHandler1, MyHandler2 and MyOtherHandler. I have MyHandler and MyOtherHandler added to the handlers collection, but not MyHandler1 or MyHandler2.
config.MessageHandlers.Add(new MyHandler());
config.MessageHandlers.Add(new MyOtherHandler());
I want MyHandler1 or MyHandler2 to be added to the pipeline on the fly by MyHandler, depending on some condition. I know that MyHandler1 and 2 can be added to the config.MessageHandlers collection and do nothing when their turn comes, when 'some' condition does not apply but that is not what I want. Let's say I have about 100 such handlers and I don't want all of them to run in the pipeline but only when MyHandler thinks it is appropriate.
I cannot manually insert MyHandler1 into the pipeline by setting MyHandler.InnerHandler. The chain is cached globally for all requests and I cannot modify it for something related to a specific request. Here is what I did.
I created a base handler that increases the visibility of SendAsync.
public abstract class MyBaseHandler : DelegatingHandler
{
public Task<HttpResponseMessage> WrapperSendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
return this.SendAsync(request, cancellationToken);
}
}
I derived MyHandler1 and 2 from this base.
public class MyHandler1 : MyBaseHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Use request
var response = await base.SendAsync(request, cancellationToken);
// Use response
return response;
}
}
Now, MyHandler can instantiate MyHandler1 or Myhandler2 based on the condition and sets the InnerHandler to its own InnerHandler and just call and return SendAsync through the wrapper.
public class MyHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// Check condition and choose MyHandler1 or MyHandler2 or just return
// await base.SendAsync(request, cancellationToken);
var h = new MyHandler1();
h.InnerHandler = this.InnerHandler;
return await h.WrapperSendAsync(request, cancellationToken);
// When MyHandler1 and MyHandler2 is no good, I just want
// to do nothing and let the other handlers do their job
// return await base.SendAsync(request, cancellationToken);
}
}
It does work but I'm not sure if I'm breaking something by doing this. Am I overlooking something by taking this approach?
Your approach looks good. I'm pretty sure it should work just fine.

Resources