Im making a website with an API, the API needs validation so the user only gets his own data. I have written the following middleware to validate the login.
public class ApiAuthenticationMiddleware
{
private readonly RequestDelegate _next;
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
public ApiAuthenticationMiddleware(RequestDelegate next,
SignInManager<ApplicationUser> signInManager,
UserManager<ApplicationUser> usermanager)
{
_next = next;
_signInManager = signInManager;
_userManager = usermanager;
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Query.ContainsKey("password") || !context.Request.Query.ContainsKey("email"))
{
context.Response.StatusCode = 401; //UnAuthorized
await context.Response.WriteAsync("Invalid User Key");
return;
}
var email = context.Request.Query["email"];
var password = context.Request.Query["password"];
var result = await _signInManager.PasswordSignInAsync(email, password, false, lockoutOnFailure: false);
if (result.Succeeded)
{
await _next.Invoke(context);
}
else if (//some more checks)
context.Response.StatusCode = 401; //UnAuthorized
await context.Response.WriteAsync("Invalid User Key");
return;
}
}
}
What I want is that a blank page or an error message like "Invalid User Key" is shown if the user has no valid login. However what happens at the moment is the home page is returned (because my middleware is called before usemvc and the return statement skips the controller request done by usemvc).
My relevant code in the configure method in startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseIdentity();
app.UseWhen(x => (x.Request.Path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase)),
builder =>
{
builder.UseMiddleware<ApiAuthenticationMiddleware>();
});
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
How can I make my middleware return a blank page with status code?
Update
After trying alot of things I found that when I remove:
context.Response.StatusCode = 401; //UnAuthorized
It works as expected, the user gets the message given in:
await context.Response.WriteAsync("Invalid User Key");
Howerver I dont want the user to get a 200 statuscode on login fail but a 401 statuscode. But when using the statuscode line the user is redirected. So how can I send the statuscode without redirection?
Try to use .Clear() before setting the StatusCode .
context.Response.Clear();
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await context.Response.WriteAsync("Unauthorized");
I have a hunch that app.UseIdentity()
has default behavoir that when a 403/401 occurs, it will intercept the response and initiate a redirect. Try commenting it out and see if it works.
Alternate solution see: https://stackoverflow.com/a/43456151/3948882
Last comment: I strongly encourage not passing credentials for each request. I recommend using prebuilt auth providers and implement as your middleware. The Authorize
attribute should be sufficient for requests made and can do what you are looking for. If you do want to return something special, you can override the response with middleware like the app.UseIdentity()
middleware might be with redirecting.
You should also set ContentType. Something like this:
context.Response.ContentType = "text/plain";
context.Response.StatusCode = 401; //UnAuthorized
await context.Response.WriteAsync("Invalid User Key");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With