2

I am working on requirement In which I have check whether our request header contains Authorization header and based on that either call another Server and return 403. Currently I have done it by creating Custom ActionAttribute like this:

 public class ValidateAuthHeaderAttribute: ActionFilterAttribute
{
    private readonly ILogger<ValidateAuthHeaderAttribute> _logger;
    public ValidateAuthHeaderAttribute(ILogger<ValidateAuthHeaderAttribute> logger)
    {
        _logger = logger;
    }
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var httpContext = context.HttpContext;

        if (httpContext.Request.Headers.ContainsKey("Authorization"))
        {
            return;
        }
        var failureResponse = new FailureResponseModel
        {
            Result = false,
            ResultDetails = "Authorization header not present in request",
            Uri = httpContext.Request.Path.ToUriComponent(),
            Timestamp = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
            Error = new Error
            {
                Code = 108,
                Description = "Authorization header not present in request",
                Resolve = "Send Request with authorization header to avoid this error."
            }
        };

        var responseString = JsonConvert.SerializeObject(failureResponse);

        context.Result = new ContentResult
        {
            Content = responseString,
            ContentType = "application/json",
            StatusCode = 403
        };
    }
}

And I am using this Custom Attribute in my Controller/Methods like this.

[TypeFilter(typeof(ValidateAuthHeaderAttribute))]

Now this is working fine, But I was reading about Policy Based Authorization in .Net Core doc. So as it is recommended now to use Policies. I was thinking it is possible to port my code to Custom Policy.

Shabir jan
  • 2,295
  • 2
  • 23
  • 37
  • That looks like an extension to the [question](https://stackoverflow.com/questions/55810466/httpcontext-header/55813238#55813238) I answered earlier. As your scenario is very simple, and you don't have any Authentication/Authorization integration, ActionFilter is sufficed. – Shahzad Hassan Apr 26 '19 at 12:00
  • I'll try to update the code that I uploaded earlier to GitHub to facilitate the solution. – Shahzad Hassan Apr 26 '19 at 12:01
  • Before I proceed to update the code, in my opinion, Custom Authorization Policy implementation would be overkill for your scenario. The fact is that when you have Authorization in place, your AuthHeader will be checked automatically by the `[Authorize]` filter. You can do something like [Authorize(Policy = "MyPolicy")] but it will still check if the AuthHeader is present. If it's a Bearer token, all the claims it carries will be added to the Claims property of the HttpContext.User.Claims. Then you can use the policy to verify that the user has specific claims or user is authenticated etc – Shahzad Hassan Apr 26 '19 at 14:52
  • As you need to utilise the Authorization header to make subsequent class using `HttpClient`, I don't think that utilising Authorization policies will help you in this case. Authorization policies were added to allow more custom kind of Authorization instead of just Role based Authorization – Shahzad Hassan Apr 26 '19 at 14:56

1 Answers1

6

IMO, I would suggest you keep using ValidateAuthHeaderAttribute which is much easier.

If you insist on policy, follow steps below:

  1. Requirement

    public class AuthorizationHeaderRequirement: IAuthorizationRequirement
    {
    }
    public class AuthorizationHeaderHandler : AuthorizationHandler<AuthorizationHeaderRequirement>
    {
        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizationHeaderRequirement requirement)
        {
            // Requires the following import:
            //     using Microsoft.AspNetCore.Mvc.Filters;
            if (context.Resource is AuthorizationFilterContext mvcContext)
            {
                // Examine MVC-specific things like routing data.
                var httpContext = mvcContext.HttpContext;
    
                if (httpContext.Request.Headers.ContainsKey("Authorization"))
                {
                    context.Succeed(requirement);
                    return;
                }
                var failureResponse = new FailureResponseModel
                {
                    Result = false,
                    ResultDetails = "Authorization header not present in request",
                    Uri = httpContext.Request.Path.ToUriComponent(),
                    Timestamp = DateTime.Now.ToString("s", CultureInfo.InvariantCulture),
                    Error = new Error
                    {
                        Code = 108,
                        Description = "Authorization header not present in request",
                        Resolve = "Send Request with authorization header to avoid this error."
                    }
                };
    
                var responseString = JsonConvert.SerializeObject(failureResponse);
                mvcContext.Result = new ContentResult
                {
                    Content = responseString,
                    ContentType = "application/json",
                    StatusCode = 403
                };
    
                await mvcContext.Result.ExecuteResultAsync(mvcContext);
            }
            return;
        }
    }
    
  2. Configure in Startup.cs

    services.AddAuthorization(options =>
    {
        options.AddPolicy("AuthorizationHeaderRequirement", policy =>
            policy.Requirements.Add(new AuthorizationHeaderRequirement()));
    });
    
    services.AddSingleton<IAuthorizationHandler, AuthorizationHeaderHandler>();
    
  3. Controller

    [Authorize(Policy = "AuthorizationHeaderRequirement")]
    public IActionResult Privacy()
    {
        return View();
    }
    
Edward
  • 28,296
  • 11
  • 76
  • 121