How to redirect to log in page on 401 using JWT authorization in ASP.NET Core

Viewed 9505

I have this JWT authorization configuration in my Startup.cs:

services.AddAuthentication(opts =>
{
    opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(opts =>
{
    opts.RequireHttpsMetadata = false;
    opts.SaveToken = true;
    opts.TokenValidationParameters = new TokenValidationParameters()
    {
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("my_secret_key")),
        ValidIssuer = "iss",
        ValidAudience = "aud",
        ValidateIssuerSigningKey = true,
        ValidateLifetime = true
    };
});

My HomeController has [Authorize] attribute. So upon access to Home/Index, I get a 401 response and I am presented with a blank page. I want to redirect to my Account/LogIn page but I am not sure how to do it.

I read that this shouldn't automatically redirect because it won't make sense to API calls if they are not authorized and then you redirect them, so what is the proper way on how I would get them to the login page on 401.

Please bear in mind that in this project, I have both Web API and Action methods with [Authorize] attributes so I need to redirect only when it is an action method.

3 Answers

Thanks for your suggestion... after spending a good time on google i could find your post and that worked for me. You raised a very good point because it does not make sense for app API calls.

However, I have a situation where the Actions called from the app has a specific notation route (/api/[Controller]/[Action]) which makes me possible to distinguish if my controller has been called by Browser or App.

app.UseStatusCodePages(async context =>
{            
    var request = context.HttpContext.Request;
    var response = context.HttpContext.Response;
    var path = request.Path.Value ?? "";

    if (response.StatusCode == (int)HttpStatusCode.Unauthorized && path.StartsWith("/api", StringComparison.InvariantCultureIgnoreCase))
    {
        response.Redirect("~/Account/Login");
    }
});

This works for both Razor Pages and MVC Views as follows: response.Redirect("/Login"); for Razor Pages. response.Redirect("/Home/Login"); for MVC Views. In order for this to work, the Authorize filter has to be added to the Controller. The code block also has to be added between app.UseAuthentication(); and app.UseAuthorization(); methods.

app.UseStatusCodePages(async context =>
            {
                var response = context.HttpContext.Response;

                if (response.StatusCode == (int)HttpStatusCode.Unauthorized ||
                    response.StatusCode == (int)HttpStatusCode.Forbidden)
                    response.Redirect("/Home/Login");
            });
Related