I'm developing a custom middleware for authenticating clients that invokes an API.
I use an attribute to define if an Action requires authentication, but I can't figure out how to get a reference to the requested Controller and Action inside the Invoke method.
Below is my code so far
AuthenticateClient.cs:
public class AuthenticateClient
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private readonly GenericUnitOfWork _worker;
public AuthenticateClient(RequestDelegate next, ApiDbContext db, IHttpContextAccessor httpContext, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<Utility.LCLog.Settings> settings)
{
_next = next;
_logger = loggerFactory.CreateLogger(settings.Value.ApplicationName);
_worker = new GenericUnitOfWork(new AppHelper(httpContext, db, env));
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Headers.Keys.Contains("ClientAuth"))
{
_logger.LogWarning("ClientAuth missing in request", new string[] { "Host: " + context.Request.Host, "IP: " + context.Request.HttpContext.Connection.RemoteIpAddress });
context.Response.StatusCode = 400;
await context.Response.WriteAsync("ClientAuth missing from request header values");
return;
}
else
{
string[] tmp = context.Request.Headers["ClientAuth"].ToString().Split("/");
if (tmp.Length != 2)
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("The format of the ClientAuth value is wrong");
return;
}
else
{
Client client;
string key, pass;
key = tmp[0];
pass = tmp[1];
client = await _worker.GetRepo<Client>().SingleOrDefault(clnt => clnt.Active && clnt.Key.Equals(key) && clnt.Password.Equals(pass));
if (client == null)
{
_logger.LogWarning("Client authentication failed", new string[] { "Key: " + key, "Password: " + pass, "Host: " + context.Request.Host, "IP: " + context.Request.HttpContext.Connection.RemoteIpAddress });
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Authentication failed");
return;
}
}
}
await _next.Invoke(context);
}
}
ClientAuthenticationAttribute.cs:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ClientAuthenticationAttribute : Attribute
{
private readonly bool _authRequired;
public ClientAuthenticationAttribute(bool authRequired = true)
{
_authRequired = authRequired;
}
public bool AuthRequired { get { return _authRequired; } }
}