ASP.Net Core - no redirect on API auth error

后端 未结 3 1737
余生分开走
余生分开走 2021-02-12 19:57

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
         


        
相关标签:
3条回答
  • 2021-02-12 20:30

    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.

    0 讨论(0)
  • 2021-02-12 20:37

    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.

    0 讨论(0)
  • Update ASP.NET Core 2.x

    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.

    ASP.NET Core 1.x

    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.

    0 讨论(0)
提交回复
热议问题