skip to Main Content

I want only admins to have access to this controller and its actions, so I’ve written this code:

[Authorize(Roles = Helper.AdminRole)]
public class AdminController : Controller
{
    public IActionResult AdminPanel()
    {
        return View();
    }
    //other actions only available to admins
}

If the user is not logged in and he’s not in the specified role I get a 404 Not Found page and this in the URL:

…./AccessDenied?ReturnUrl=%2FAdmin%2FAdminPanel

How can I make a custom error page for this scenario where the user is asked to log in so he can confirm his role, and when he does log in successfully AND he is in the right role to be redirected to where he wanted to go, but if his role is invalid to be redirected elsewhere/ shown a custom error page?

2

Answers


  1. Take cookie authentication as an example, you just need to configure it like this in program.cs(.Net 6):

    builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(x =>
        {
            //When user doesn't login and he access to an action with [Authorize],
            //He will redirect to the loginPath
            
            x.LoginPath = "/{controller}/{action}";
    
            //When user has loged in but the role is not the specified role,
            //He will redicet to the AccessDeniedPath,
            //Then you can custom your own error page in this path.
    
            x.AccessDeniedPath = "/{controller}/{action}";
        });
    
    Login or Signup to reply.
  2. Your error was caused due to lack of Loginpath settings,not wrong role or password.(So the error code was 404 not 401)

    You could see the test Result:enter image description here

    If you want to custom error page,you could read the official document:
    https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-5.0

    I tried with the codes below:

    ErrorResult class:

     public class ErrorResult
        {
            public bool Success { get; set; } = true;
            public string Msg { get; set; } = "";
            public string Type { get; set; } = "";
            public object Data { get; set; } = "";
            public object DataExt { get; set; } = "";
        }
    

    ErrorHandlingMiddleware:

    public class ErrorHandlingMiddleware
        {
            private readonly RequestDelegate next;
    
            public ErrorHandlingMiddleware(RequestDelegate next)
            {
                this.next = next;
            }
    
            public async Task Invoke(HttpContext context)
            {
                try
                {
                    await next(context);
                }
                catch (Exception ex)
                {
                    var statusCode = context.Response.StatusCode;
                    if (ex is ArgumentException)
                    {
                        statusCode = 200;
                    }
                    await HandleExceptionAsync(context, statusCode, ex.Message);
                }
                finally
                {
                    var statusCode = context.Response.StatusCode;
                    var msg = "";
                    if (statusCode == 401)
                    {
                        
                        msg = "unauthorize";
    
                    }
                    else if (statusCode == 404)
                    {
                        msg = "NotFound";
                    }
                    else if (statusCode == 400)
                    {
                        msg = "BadRequest";
                    }
                    else if (statusCode != 200)
                    {
                        msg = "Unkonwn";
                    }
                    if (!string.IsNullOrWhiteSpace(msg))
                    {
                        await HandleExceptionAsync(context, statusCode, msg);
                    }
                }
            }
            
            private static Task HandleExceptionAsync(HttpContext context, int statusCode, string msg)
            {
                var result = JsonConvert.SerializeObject(new ErrorResult() { Success = false, Msg = msg, Type = statusCode.ToString() });
                context.Response.ContentType = "application/json;charset=utf-8";
                return context.Response.WriteAsync(result);
            }
        }
        
        public static class ErrorHandlingExtensions
        {
            public static IApplicationBuilder UseErrorHandling(this IApplicationBuilder builder)
            {
                return builder.UseMiddleware<ErrorHandlingMiddleware>();
            }
        }
    

    in startup class:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    .....
    app.UseErrorHandling();
    ....
    }
    

    The Result:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search