I have been trying to prevent the redirect when I return an NotAuthorized IActionResult from a Controller, but regardless of my attempts, NotAuthorized gets translated to a Redirect.
I have tried what is mentioned here (same issue, using older beta framework, I use 1.0.0-rc1-final). I do not have the Notifications namespace (has been removed in rc1-final).
This is my Login Controller:
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return Ok(model);
}
if (result.IsLockedOut)
{
return new HttpStatusCodeResult((int)HttpStatusCode.Forbidden);
}
else
{
return HttpUnauthorized();
}
}
return HttpUnauthorized();
}
In Startup.cs I have tried variations over this:
services.Configure<CookieAuthenticationOptions>(o =>
{
o.LoginPath = PathString.Empty;
o.ReturnUrlParameter = PathString.Empty;
o.AutomaticChallenge = false;
});
Everytime a login fails (please ignore that the password is returned on Ok) and should result in an empty 401 page, I get a redirection to /Account/Login instead. What is the trick here?
The solution is not to configure CookieAuthenticationOptions directly, but do it via IdentityOptions like this:
services.Configure<IdentityOptions>(o =>
{
o.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = ctx =>
{
if (ctx.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
return Task.FromResult<object>(null);
}
ctx.Response.Redirect(ctx.RedirectUri);
return Task.FromResult<object>(null);
}
};
});
Taken from here ( Shawn Wildermuth --> ASP.NET 5 Identity and REST APIs --> Comment of "Mehdi Hanafi") and tested the API with Postman
config.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = ctx =>
{
if (ctx.Request.Path.StartsWithSegments("/api") &&
ctx.Response.StatusCode == 200)
{
ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
return Task.FromResult<object>(null);
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
return Task.FromResult<object>(null);
}
}
};
from Identity 2.0, you'd need to add:
using Microsoft.AspNetCore.Authentication.Cookies;
and in ConfigureServices:
services.ConfigureApplicationCookie(options =>
{
options.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = (x =>
{
if (x.Request.Path.StartsWithSegments("/api") && x.Response.StatusCode == 200)
x.Response.StatusCode = 401;
return Task.CompletedTask;
}),
OnRedirectToAccessDenied = (x =>
{
if (x.Request.Path.StartsWithSegments("/api") && x.Response.StatusCode == 200)
x.Response.StatusCode = 403;
return Task.CompletedTask;
})
};
});
the segments check should of course be adjusted to your routes.
If you have some pages for which the redirect is desired and other URLs that should not have a redirect, see this question for a solution that uses the default redirect logic only for non-API URLs:
来源:https://stackoverflow.com/questions/34770886/mvc6-unauthorized-results-in-redirect-instead