Reputation: 3761
For the purpose of downloading files I need to use a GET: /API/File/ID?bearerToken=XYZ... method.
I've created a DelegatingHandler to add my token to the AuthorizationHeader, but it appears the token validation may be done before this point...
All of the tokens at current at added by Angular adding the token to the HTTP header before the request.
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
GlobalFilters.Add(config);
app.UseWebApi(config);
config.MessageHandlers.Insert(0, new QueryStringBearerToken());
}
..
public class QueryStringBearerToken : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var bearerToken = request.GetQueryNameValuePairs().
Where(kvp => kvp.Key == "bearertoken")
.Select(kvp => kvp.Value)
.FirstOrDefault();
//QueryString exists and Header doesn't
if (!string.IsNullOrWhiteSpace(bearerToken) && !request.Headers.Any(x=>x.Key == "Authorization"))
{
request.Headers.Add("Authorization", "Bearer " + bearerToken);
}
return base.SendAsync(request, cancellationToken);
}
}
Upvotes: 2
Views: 3838
Reputation: 27187
I presume you are using Katana's Bearer middleware? (judging by your call to ConfigureAuth
?)
If so, the Katana middleware will indeed run before the Web API handlers and reject your request before it even gets a chance to be processed by the handler.
Instead of creating a handler you should move your functionality to Katana middleware.
Here's an example:
public class QueryBearerMiddleware : OwinMiddleware
{
public QueryBearerMiddleware(OwinMiddleware next)
: base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
string bearerToken = null;
if (context.Request.QueryString.HasValue)
{
var queryPairs = context.Request.QueryString.ToUriComponent()
.Substring(1)
.Split(new [] {'&'}, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Split('=')).ToDictionary(x => x[0], x => x[1]);
if (queryPairs.ContainsKey("bearertoken"))
{
bearerToken = queryPairs["bearertoken"];
}
}
//QueryString exists and Header doesn't
if (!string.IsNullOrWhiteSpace(bearerToken) && context.Request.Headers.All(x => x.Key != "Authorization"))
{
context.Request.Headers.Add("Authorization", new [] { "Bearer " + bearerToken });
}
await Next.Invoke(context);
}
}
You should register this middleware to run before the Bearer middlware.
Somewhere in your ConfigureAuth
you should have a call to app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
. This new middleware we just created, should be registered before, i.e:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use(typeof(QueryBearerMiddleware));
var config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
GlobalFilters.Add(config);
app.UseWebApi(config);
}
}
Upvotes: 2