6

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

1 Answer 1

3

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(...);
    });
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.