Make Web API authentication return 401 instead of redirect to login page

前端 未结 6 1129
孤城傲影
孤城傲影 2021-01-04 00:58

I have Web API with OWIN Authentication in Web MVC. I\'m using in Web.Config for my Web MVC so it\'s redirecting to login page.



        
相关标签:
6条回答
  • 2021-01-04 01:15

    In .NET Core I have solved it like this, Startup.cs:

        public void ConfigureServices(IServiceCollection services)
        {
                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.Cookie.SameSite = SameSiteMode.Strict;
                    options.Cookie.Name = "AuthCookie";
                    options.Events.OnRedirectToAccessDenied = UnAuthorizedResponse;
                    options.Events.OnRedirectToLogin = UnAuthorizedResponse;
                })
        ....
        }
    
        internal static Task UnAuthorizedResponse(RedirectContext<CookieAuthenticationOptions> context)
        {
            context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
            return Task.CompletedTask;
        }
    
    0 讨论(0)
  • 2021-01-04 01:15

    I struggled with this issue and I came up with a way to only do the redirect if I didn't find the token that I use in the header for my custom manual authorization of my WebApi. This is my setup (notice the Provider object and OnApplyRedirect action)

        app.UseCookieAuthentication(new CookieAuthenticationOptions
       {
         AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
         LoginPath = new PathString("/Account/Login"),
         ExpireTimeSpan = TimeSpan.FromMinutes(30),
         Provider =  new CookieAuthenticationProvider
          {
            OnApplyRedirect = (ctx) => {
                var token = HttpContext.Current.Request.Headers.Get("X-User-Token");
                if (token == null) ctx.Response.Redirect(ctx.RedirectUri);
             }
          }
       });  
    
    0 讨论(0)
  • 2021-01-04 01:16

    This is what worked for me.

    Creating a custom attribute:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class NoRedirectAuthorizeAttribute : AuthorizeAttribute
    {        
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
        }
    }
    

    Using the attribute in your controller:

        [HttpDelete]
        [NoRedirectAuthorizeAttribute(Roles = "Admin")]
        [Route("api/v3/thingstodelete/{id=id}")]
        public IHttpActionResult DeleteThingToDelete(Guid id)
        {
          //delete code
        }
    

    Here are just overriding the HandleUnauthorizedRequest method of the AuthorizeAttribute. So, instead of sending a redirect (304) to the login page, we send Forbidden(403) HTTP status code.

    0 讨论(0)
  • 2021-01-04 01:22

    I needed to configure the StatusCodePage middleware to avoid redirection

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...
        app.UseStatusCodePages();
        ...
    }
    
    0 讨论(0)
  • 2021-01-04 01:23

    In order to change the way IIS behaves based on a convention defined by URL, you want to branch your OWIN pipeline. You can do this by using IApplicationBuilder.Map. Assuming a static config:

    public void Configure(IApplicationBuilder app)
    {
        ...
        app.Map("/api", HandleWebApiRequests);
        ...
    }
    
    private static void HandleWebApiRequests(IApplicationBuilder app)
    {
        app.UseWebApi(config);
    }
    

    The Map method branches the pipeline to the HandleWebApiRequests method based on an URL that begins with "/api".

    This should cause 401 errors to behave like they are supposed to and simply return 401 with no redirect.

    0 讨论(0)
  • 2021-01-04 01:35

    Create a custom AuthorizeAttribute:

    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized");
        }
    }
    

    If you in the future skip the web.config stuff and use owin to setup your authentication, you could in your Startup.cs do:

    var provider = new CookieAuthenticationProvider();
    var originalHandler = provider.OnApplyRedirect;
    provider.OnApplyRedirect = context =>
    {
        if (!context.Request.Uri.LocalPath.StartsWith(VirtualPathUtility.ToAbsolute("~/api")))
        {
            context.RedirectUri = new Uri(context.RedirectUri).PathAndQuery;
            originalHandler.Invoke(context);
        }
    };
    
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        CookieName = FormsAuthentication.FormsCookieName,
        LoginPath = new PathString("/Account/LogOn"),
        ExpireTimeSpan = TimeSpan.FromMinutes(240),
        Provider = provider
    });
    
    0 讨论(0)
提交回复
热议问题