Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I validate Request.Headers["Authorization"] for all controller at a single place?

[HttpGet]
public IActionResult Get()
{
    string token = Request.Headers["Authorization"];
    // Validate token.
}

[HttpPost]
public IActionResult Post(int id)
{
    string token = Request.Headers["Authorization"];
    // Validate token.
}

How can I validate Request.Headers["Authorization"] for all controller at a single place?

like image 982
Felipe Deveza Avatar asked Aug 03 '17 21:08

Felipe Deveza


3 Answers

You can create and use custom middleware where you can check header and validate if it should be passed to controller or not.

To achive that create middleware class and regiester it in Startup.cs as below:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConnectionManager conn, ILoggerFactory loggerFactory)
{
    app.UseMiddleware<YourMidllewareClass>();
}

Create Invoke method in middleware class. This method will get called before each request jump into any of your contoller.

public async Task Invoke(HttpContext context)
{
    string token = context.Request.Headers["Authorization"];

    //do the checking
    if (token == null)
    {
        context.Response.StatusCode = 401; 
        await context.Response.WriteAsync("Access denied!");
        return;
    }

    //pass request further if correct
    await _next(context);
}

As far as I rember you must regiester your middleware before UseMvc() method to make sure your Invoke() will be called before Mvc pipeline.

like image 170
miechooy Avatar answered Oct 22 '22 17:10

miechooy


For ASP.NET Core 2.0, some things have changed and you can also use an AuthenticationHandler.
Good documentation to get you started is at https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x.

An example of custom authentication I'm using in my current project:

Startup.ConfigureServices:

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = "Custom Scheme";
            options.DefaultChallengeScheme = "Custom Scheme";
        }).AddCustomAuth(o => { });

Startup.Configure:

        app.UseAuthentication();

And finally:

internal class CustomAuthenticationHandler : 
    AuthenticationHandler<CustomAuthenticationOptions>
{
    public CustomAuthenticationHandler(IOptionsMonitor<CustomAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : 
        base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        try
        {
            // Your auth code here
            // Followed by something like this:
                return AuthenticateResult.Success(
                    new AuthenticationTicket(
                        new ClaimsPrincipal(
                            new ClaimsIdentity(
                                new List<Claim>() { new Claim(ClaimTypes.Sid, Id.ToString()) },
                                Scheme.Name)),
                        Scheme.Name));
        }        
        catch
        {
            return AuthenticateResult.Fail("Error message.");
        }
    }
}

This way, all calls to your controllers will go through the authentication middleware, and you can ignore it, if necessary, by using the [AllowAnonymous] attribute on the controller.

like image 40
Matheus Lacerda Avatar answered Oct 22 '22 15:10

Matheus Lacerda


Or you could use Attributes on the class or method to validate and check the header elements. Depends on the need.

  1. Middleware
  2. Authentication Handler (similar to middleware)
  3. Custom Attributes on the Class or Method.
like image 1
John Reynolds Avatar answered Oct 22 '22 15:10

John Reynolds