ASP.Net Core - do not redirect to auth API error

In my ASP.NET Core project, I got several API controllers that support jwt authorization as follows:

[Route("api/v1/[controller]")] public class MyController : Controller { [HttpGet("[action]")] [Authorize(Policy = MyPolicy)] public JsonResult FetchAll() { } } 

When authorization to access the FetchAll () Fails action, I want HttpStatusCode.Forbidden as an answer. Does Mvc redirect for account / login instead? ReturnUrl = [...]

I tried to capture Redirect-Events and return a Forbidden / Unauthorized cookie override to no avail:

  app.UseIdentity(); var tokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = TokenController.DummyKey, ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(0) }; app.UseJwtBearerAuthentication(new JwtBearerOptions { AutomaticAuthenticate = true, AutomaticChallenge = true, TokenValidationParameters = tokenValidationParameters, }); app.UseCookieAuthentication(new CookieAuthenticationOptions() { AutomaticAuthenticate = false, AutomaticChallenge = false, AuthenticationScheme = "BsCookie", CookieName = "access_token", TicketDataFormat = new CustomJwtDataFormat(SecurityAlgorithms.HmacSha256, tokenValidationParameters), Events = new CookieAuthenticationEvents { OnRedirectToLogin = context => { if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK) context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; else context.Response.Redirect(context.RedirectUri); return Task.FromResult(0); }, OnRedirectToAccessDenied = context => { if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK) context.Response.StatusCode = (int)HttpStatusCode.Forbidden; else context.Response.Redirect(context.RedirectUri); return Task.FromResult(0); } }, }); 

Both events are never triggered, and Visual Studio output indicates that fetchall Fails and Account / Login will be returned instead:

 Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/api/v1/Lehrer/GetAll application/json Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token. Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer. Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null). Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'. Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (). Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden. Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: AuthenticationScheme: Identity.Application was challenged. Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sam.Learning2.Controllers.LehrerController.GetAll (Sam.Learning2) in 49.7114ms Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 121.6106ms 302 Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/Account/Login?ReturnUrl=%2Fapi%2Fv1%2FLehrer%2FGetAll 

I want my APIs to return 401/403 instead of redirecting to Login - how can I achieve this if the above code does not work?

+12
authentication asp.net-core jwt
source share
2 answers

ASP.NET Core 2.x Update

Authorization has changed a bit in ASP.NET Core 2.0. The answer below ist is valid only for ASP.NET Core 1.x. For ASP.NET Core 2.0, refer to this answer and this revocation of GitHub .

ASP.NET Core 1.x

What you seem to have forgotten is that app.UseIdentity() also logs 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 Core Identity ASP.NET sets AutomaticChallange to true for cookie middleware ( ApplicationCookie ) ( see source ). Therefore, redirecting to /Account/Login?ReturnUrl . You will need to disable this option in Identity.

 services.AddIdentity(options => { options.Cookies.ApplicationCookie.AutomaticChallenge = false; }); 

If you really want to have Identity Auth (login to web page) and JWT, you will need to register middlewares based on the URL. So, i.e. app.UseIdentity() is only registered for non-api addresses, and Jwt middleware is only registered for URLs starting with /api .

You can do this with .MapWhen ( docs ).

 app.MapWhen(context => !context.Request.Path.StartsWith("/api"), branch => { branch.UseIdentity(); }); 

Now branch.UseIdentity() will only be used for URLs that do not start with /api , which are usually your MVC views, where redirection to /Account/Login is required.

+16
source share

I just use Barry Dorrans Asp Net Authorization

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 redirecting Mvc to accounting / login? ReturnUrl = [...], and in the API you will get 401 or 403.

+7
source share

All Articles