Redirect to login when unauthorized in ASP.NET Core

C#asp.netasp.net Coreasp.net Identityasp.net Core-Mvc

C# Problem Overview


In the previous ASP.NET MVC, there was an option to redirect to the login action, if the user was not authenticated.

I need the same thing with ASP.NET Core, so I:

  1. created a ASP.NET Core project from the Visual Studio template
  2. added [Authorize] to some arbitrary action
  3. opened the corresponding view in my browser

I don't expect a redirect because I haven't configured it. BUT, it automatically redirects to the login action!

Where/how is this option set?

C# Solutions


Solution 1 - C#

With the current aspnet core version (2.1.0), this has changed, now you can use the extensions:

   services.ConfigureApplicationCookie(options => options.LoginPath = "/login");

or

 services
         .AddAuthentication()
         .AddCookie(options =>
         {
             options.LoginPath = "/login";
             options.LogoutPath = "/logout";
         });

You can see more about migrating in to 2.0 in this article.

Solution 2 - C#

The redirect did not work in my app at all and none of the solutions here fixed it, but using Status Code Pages did:

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

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

app.UseMvc(...        

Solution 3 - C#

You can configure the path using CookieAuthenticationOptions class.

Something like this.

app.UseCookieAuthentication(new CookieAuthenticationOptions {
        LoginPath = new PathString("/Login/"),
        AuthenticationType = "My-Magical-Authentication",
        // etc...
        },
});

Solution 4 - C#

For anyone that's interested it can also be done with the AddIdentity service provider.

services.AddIdentity<User, IdentityRole>(options =>
    {
        options.Cookies.ApplicationCookie.AutomaticAuthenticate = true;
        options.Cookies.ApplicationCookie.AutomaticChallenge = true;
        options.Cookies.ApplicationCookie.LoginPath = "/Auth/Login";
    })
    .AddEntityFrameworkStores<MehandiContext>()
    .AddDefaultTokenProviders();

And as explained here: https://stackoverflow.com/a/41643105/5784635

I attempted this in April 2017 and "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0" doesn't redirect I had to use the 1.0.1 version

Solution 5 - C#

The way that dotnet core scaffolds Cookie Authentication is using the Identity framework. For a fresh project, I recommend going to the command line and doing something like this:

dotnet new mvc -o ExampleProject --auth Individual

You can gain full control of the authentication process by modifying the folowing method in Startup.cs to look like this:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<IdentityUser, IdentityRole>()
        // services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddRazorPagesOptions(options =>
        {
            options.AllowAreas = true;
            options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
            options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
        });

    services.ConfigureApplicationCookie(options =>
    {
        options.LoginPath = $"/Identity/Account/Login";
        options.LogoutPath = $"/Identity/Account/Logout";
        options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
    });

    // using Microsoft.AspNetCore.Identity.UI.Services;
    services.AddSingleton<IEmailSender, EmailSender>();
}

Reference: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-2.2&tabs=visual-studio#full

My personal preference for authentication is the hybrid flow of IdentityServer4, gives you a scope for configuring multiple applications using a single sign on.

Solution 6 - C#

this code block in the startup file works for me in .Net Core 3.1

services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });

Solution 7 - C#

placing should be important in configuration middleware piplines.

app.UseSession();
        app.UseAuthentication();
        app.UseStatusCodePages(context => {
            var response = context.HttpContext.Response;
            if (response.StatusCode == (int)HttpStatusCode.Unauthorized ||
                response.StatusCode == (int)HttpStatusCode.Forbidden)
                response.Redirect("/Login");
            return Task.CompletedTask;
        });
        app.UseClaimsMiddleware();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Login}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });

Solution 8 - C#

The code above works fine for me using Identity Authentication in asp net core 3.1

  1. First you must add the following code to your Startup.cs file
services.ConfigureApplicationCookie(options =>
{
     options.Cookie.Name = ".AspNetCore.Identity.Application";
     options.AccessDeniedPath = "/User/PageNotAllowed";               
});
  1. Create an Action in your Controller responsable for manage the user account (In my case is the User class)
public IActionResult PageNotAllowed()
{
    return View();
}
  1. Final step you just need to create the PageNotAllowed View at your own taste.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongrokkyView Question on Stackoverflow
Solution 1 - C#animalito maquinaView Answer on Stackoverflow
Solution 2 - C#Serj SaganView Answer on Stackoverflow
Solution 3 - C#AnurajView Answer on Stackoverflow
Solution 4 - C#Anton ToshikView Answer on Stackoverflow
Solution 5 - C#Ryan DinesView Answer on Stackoverflow
Solution 6 - C#Jose Rodrigo Moreno CorderoView Answer on Stackoverflow
Solution 7 - C#Muni ChittemView Answer on Stackoverflow
Solution 8 - C#Ricardo Filipe Marinho BrazView Answer on Stackoverflow