We have an IAuthorizationFilter
and we can use it to authorize requests.
But there is one problem with it. I have to support multiple authorization filters, e.g.:
BearerTokenAuthorizationFilter
ApiKeyAuthorizationFilter
I would get behavior like this:
Firstly, BearerTokenAuthorizationFilter
checks if authorization header starts with Bearer
. If not, then if another authorization filter is applicable for current action, then let's run this another authorization filter. If there's no, then return an "HTTP 401 Unauthorized" error.
And the same with ApiKeyAuthorizationFilter
. At the start, it checks if authorization header starts with Basic
. If not, checks if another authorization filter exists and if yes then run it. Otherwise, return "HTTP 401 Unauthorized" error.
And to prevent infinite loop we need somehow store information that specific authorization filter was already performed.
It's easy to do in AuthenticationHandler
. We can return AuthenticateResult.NoResult()
when specific AuthenticationHandler
is not applicable to handle this requests and another will run. If all were performed, then return 401 Unauthorized.
So I would have similar mechanism as exists for AuthenticationHandler
(AuthenticateResult.NoResult()
). How can I achieve this using AuthorizationFilter
?
I think for your requirement,there should be three filters
Scheme Filter
-Check if the auth scheme is correct ,if not correct,return fail
BearerTokenAuthorizationFilter
-if the scheme is "Bearer",If yes then check the claims from the string ,return fail if claims are not correct
ApiKeyAuthorizationFilter
-if the scheme is "Basic",If yes then check the user /Password from the string return fail if user /Password are not correct
I tried as below:
public class SchemeFilter : IAuthorizationFilter
{
private readonly string[] Schemes = new string[] { "Bearer", "Basic"};
private bool exist { get; set; }=false;
public void OnAuthorization(AuthorizationFilterContext context)
{
if (context.HttpContext.Request.Headers.ContainsKey("Authorization"))
{
var str = context.HttpContext.Request.Headers["Authorization"].ToString();
foreach (var scheme in Schemes)
{
exist=str.StartsWith(scheme);
if (exist)
{
break;
}
}
}
if (!exist)
{
context.Result = new UnauthorizedResult();
}
}
}
public class BasicFilter : IAuthorizationFilter
{
private readonly string Scheme = "Basic";
public void OnAuthorization(AuthorizationFilterContext context)
{
var check=context.HttpContext.Request.Headers.TryGetValue("Authorization", out var value);
if ( value[0].StartsWith(Scheme))
{
var basicstr = value[0];
//modify the logical here yourself
if (basicstr != "Basic expectedbasicstr")
{
context.Result = new UnauthorizedResult();
}
}
}
}
public class BearerFilter : IAuthorizationFilter
{
private readonly string Scheme = "Bearer";
public void OnAuthorization(AuthorizationFilterContext context)
{
var check = context.HttpContext.Request.Headers.TryGetValue("Authorization", out var value);
if ( value[0].StartsWith(Scheme))
{
var bearerstr = value[0];
//modify the logical here yourself
if (bearerstr != "Bearer expectedbearerstr")
{
context.Result = new UnauthorizedResult();
}
}
}
}