In my ASP.NET Core project I got a few API-Controllers with jwt-authorization like this:
[Route(\"api/v1/[controller]\")]
public class MyController : Controller
Microsoft's web api stack is set up to do this out-of-the-box. The solution is at the client end.
Add this header to the client request:
'X-Requested-With': 'XMLHttpRequest'
Web api looks for that header. When present it returns a 401 if the request is unauthenticated. When the header is absent it returns the redirect to the login page.
See this https://github.com/aspnet/Security/issues/1394#issuecomment-326445124
I think you only need the more complex code in the cookie events if you cannot modify the client.
I just use Barry Dorrans Asp Net Authorization Workshop
in ConfigureServices
I just add services.AddAuthorization();
.
and in Configure
add this code:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "Cookie",
LoginPath = new PathString("/Account/Login/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true,
Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = (ctx) =>
{
if (ctx.Request.Path.StartsWithSegments("/api") && ctx.Response.StatusCode == 200)
{
ctx.Response.StatusCode = 401;
}
else
ctx.Response.Redirect(ctx.RedirectUri);
return Task.CompletedTask;
},
OnRedirectToAccessDenied = (ctx) =>
{
if (ctx.Request.Path.StartsWithSegments("/api") && ctx.Response.StatusCode == 200)
{
ctx.Response.StatusCode = 403;
}
else
{
ctx.Response.Redirect(ctx.RedirectUri);
}
return Task.CompletedTask;
}
}
}
In Mvc reroute to Account/Login?ReturnUrl=[...] and in API you will get 401 or 403.
The authorization changed a little in ASP.NET Core 2.0. The answer below ist just valid for ASP.NET Core 1.x. For ASP.NET Core 2.0 refer to this answer and this GitHub annoucement.
What you seems to have forgotten is that app.UseIdentity()
also registers the cookie middleware.
var options = app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value;
app.UseCookieAuthentication(options.Cookies.ExternalCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorRememberMeCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorUserIdCookie);
app.UseCookieAuthentication(options.Cookies.ApplicationCookie);
and the ASP.NET Core Identity sets the AutomaticChallange
to true
for cookie (ApplicationCookie
) middleware (see source). Hence the redirect to /Account/Login?ReturnUrl
. You will need do disable this option in Identity.
services.AddIdentity(options =>
{
options.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
If you really want have Identity's Auth (login to web page) and JWT, you'd need to register the middlewares based on the url. So i.e. app.UseIdentity()
is only registered for non-api urls and Jwt middleware is only registered for urls starting with /api
.
You can do that with .MapWhen
(docs).
app.MapWhen(context => !context.Request.Path.StartsWith("/api"), branch =>
{
branch.UseIdentity();
});
Now branch.UseIdentity()
will only be used, for URLs which don't start with /api
, which usually are your MVC views where the redirect to /Account/Login
is desired.