I have an ASP.NET Core site that uses cookie authentication for most pages. For those pages, the default server response of providing a 302 redirect for an unauthorized clie
Replace the redirect event handler with one that uses the default behavior only if the path is not an API. In Startup.ConfigureServices
, add this:
services.ConfigureApplicationCookie(options => {
options.Events.OnRedirectToAccessDenied = ReplaceRedirector(HttpStatusCode.Forbidden, options.Events.OnRedirectToAccessDenied);
options.Events.OnRedirectToLogin = ReplaceRedirector(HttpStatusCode.Unauthorized, options.Events.OnRedirectToLogin);
});
Use this helper method to replace the redirect methods:
static Func<RedirectContext<CookieAuthenticationOptions>, Task> ReplaceRedirector(HttpStatusCode statusCode, Func<RedirectContext<CookieAuthenticationOptions>, Task> existingRedirector) =>
context => {
if (context.Request.Path.StartsWithSegments("/api")) {
context.Response.StatusCode = (int)statusCode;
return Task.CompletedTask;
}
return existingRedirector(context);
};
With this in place, the API controller methods can call Unauthorized()
and Forbid()
without causing redirects.
Update: The above is for ASP.NET Core 2. The code for ASP.NET Core 1 is different.
For .net core 2.x here's a fix (based on Edward's answer) :
services.ConfigureApplicationCookie(options =>
{
options.Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = ReplaceRedirector(HttpStatusCode.Forbidden, context => options.Events.RedirectToAccessDenied(context)),
OnRedirectToLogin = ReplaceRedirector(HttpStatusCode.Unauthorized, context => options.Events.RedirectToLogin(context))
};
});
where ReplaceRedirector
:
Func<RedirectContext<CookieAuthenticationOptions>, Task> ReplaceRedirector(HttpStatusCode statusCode, Func<RedirectContext<CookieAuthenticationOptions>, Task> existingRedirector) =>
context =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
context.Response.StatusCode = (int)statusCode;
return Task.CompletedTask;
}
return existingRedirector(context);
};
Other simple way
.AddCookie(options =>
{
options.AccessDeniedPath = "/Home/401";
options.Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = context =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
context.Response.StatusCode = (int)(HttpStatusCode.Unauthorized);
}
return Task.CompletedTask;
},
};
})