Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Basic Authentication middleware in ASP.NET Core 1.1

I am attempting to configure Basic Authentication on an MVC service in an ASP.NET Core 1.1 application. I would like to indicate a service requires Basic Authentincation by adding an attribute on the service action (rather than allowing basic auth application wide). After doing some reading it seems like the appropriate way to do this is using a Middleware Filter.

The most comprehensive guide I have found on Middleware filters is here

The above post indcates that I need to create a Pipeline class as follows

public class MyPipeline  
{
    public void Configure(IApplicationBuilder applicationBuilder) 
    {
        var options = // any additional configuration

        //I changed this to use the "UseMiddleware"
        applicationBuilder.UseMiddleware<AuthenticationMiddleware>(options);
    }
}

I also need a middleware class. I have modified and example from here

public class AuthenticationMiddleware
{
    private readonly RequestDelegate _next;

    public AuthenticationMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        string authHeader = context.Request.Headers["Authorization"];
        if (authHeader != null && authHeader.StartsWith("Basic"))
        {
            //Extract credentials
            string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
            Encoding encoding = Encoding.GetEncoding("iso-8859-1");
            string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));

                int seperatorIndex = usernamePassword.IndexOf(':');

                var username = usernamePassword.Substring(0, seperatorIndex);
                var password = usernamePassword.Substring(seperatorIndex + 1);

                //Here is the tricky bit
                DBAuth authenticator = new DBAuth(ConnectionString);


                if(authenticator.IsAuthorized(username, password))
                {
                    await _next.Invoke(context);
                }
                else
                {
                    context.Response.StatusCode = 401; //Unauthorized
                    return;
                }
            }
            else
            {
                // no authorization header
                context.Response.StatusCode = 401; //Unauthorized
                return;
            }
        }
    }
}

Question: How do I pass the connection string to the AuthenticationMiddleware class so I can check the username and password against a database? I really want to do it via injection rather than using the Configuration.GetConnectionString() inside the Middleware class.

From the pipeline sample code it seems like options can be passed to the middleware class but I am not sure how to modify the AuthenticationMiddleware class to accept the options or what class options actually is

PS: I know Basic Authentication is bad, but this is the requirement I have been given

like image 698
MLE Avatar asked Jan 13 '17 21:01

MLE


1 Answers

You should be able to do it by modifying your Invoke method from

public async Task Invoke(HttpContext context)

to

public async Task Invoke(HttpContext context, AppDbContext dbContext)

or alternatively

public async Task Invoke(HttpContext context)
{
    var dbContext = context.RequestServices.GetService<AppDbContext>();
}

and just normally reigster your AppDbContext in your application's Startup.cs

public ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppDbContext>(config => 
    {
        config.UseXxx(...);
    });
}
like image 51
Tseng Avatar answered Oct 12 '22 16:10

Tseng