ASP.NET MVC - How to Show Unauthorized Error on Login Page

ASP.NET MVC - How to show unauthorized error on login page?

You can look for the ?ReturnUrl= querystring value, or you can create your own authorization filter & set a field in TempData indicating the reason.

Here is a simple custom filter that will do the trick:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{

// NOTE: This is not thread safe, it is much better to store this
// value in HttpContext.Items. See Ben Cull's answer below for an example.
private bool _isAuthorized;

protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
_isAuthorized = base.AuthorizeCore(httpContext);
return _isAuthorized;
}

public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);

if(!_isAuthorized)
{
filterContext.Controller.TempData.Add("RedirectReason", "Unauthorized");
}
}
}

Then in your view, you can do something like this:

@if(TempData["RedirectReason"] == "Unauthorized")
{
<b>You don't have permission to access that area</b>
}

(Though I'd recommend a better approach than these magic strings, but you get the point)

MVC 4 Unauthorized access error page

How about an exception filter?

 [HandleError(Exception = typeof(UnauthorizedAccessException), View = "MyErrorPage")]
public class MyController { }

I can't test this at the moment, if this doesn't work let me know and I'll create a custom filter for this purpose.

UPDATE

Since you've created your own custom attribute, you would pass information to your view from your attribute via TempData:

 public void OnAuthorization(AuthorizationContext filterContext)
{
//Note you could assign a complex type here, let's just assign a string
filterContext.Controller.TempData["ErrorDetails"] = "Here are my details";

// Redirect to an "Unauthorized" controller
filterContext.HttpContext.Response.Redirect(urlHelper.Action("Index", "Unauthorized"), true);

Redirect Unauthorized Page Access in MVC to Custom View

With following change it is working

public class CustomAuthorize : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//filterContext.Result = new HttpUnauthorizedResult(); // Try this but i'm not sure
filterContext.Result = new RedirectResult("~/Home/Unauthorized");
}

public override void OnAuthorization(AuthorizationContext filterContext)
{
if (this.AuthorizeCore(filterContext.HttpContext))
{
base.OnAuthorization(filterContext);
}
else
{
this.HandleUnauthorizedRequest(filterContext);
}
}

}

And then applying on Controller or Action as below:

[CustomAuthorize(Roles = "Admin")]

With above approach I need to revisit all the controller/actions and change the Authorized attribute! Also some testing will be needed.

I am still not sure why Web.Config route not working as same has been explained in MVC Documentation. May be something has changed in MVC 4!

asp.net mvc 401 Unauthorized error after redirect

So after a full day of investigation I started to doubt that reason may be in the Authorize Attribute or global filters and began thinking that maybe IIS somehow returns 401 on the redirect requests. But some of other actions with RedirectToAction were found by me and they worked. Besides versions hosted on another IIS had the same problem

Then I started to wonder if there is any Authorization configuration in the MVC project other then default and searched through the project "authorize" which didn't give any unexpected results

But then an idea came up to me to search through all the solution the "redirect" phrase and I finally found the root of the issue...

Sample Image

So on the Application_EndRequest the StatusCode is set to 401 and the error returned for the wrong type of the request

I guess searching for "401" would also help and if the constants were named they would have been found earlier

Getting 401 Unauthorized with MVC Pages while Identity Razor pages work as expected

This has been answered here: https://stackoverflow.com/a/62090053/3317709

It turned out that using IdentityServer extension methods add a policy scheme such that only /Identity pages have cookie authentication. The rest default to JWT.

We can customize this by adding our own policy like so:

builder.Services.AddAuthentication()
.AddIdentityServerJwt()
.AddPolicyScheme("ApplicationDefinedAuthentication", null, options =>
{
options.ForwardDefaultSelector = (context) =>
{
if (context.Request.Path.StartsWithSegments(new PathString("/Identity"), StringComparison.OrdinalIgnoreCase) ||
context.Request.Path.StartsWithSegments(new PathString("/demo"), StringComparison.OrdinalIgnoreCase))
return IdentityConstants.ApplicationScheme;
else
return IdentityServerJwtConstants.IdentityServerJwtBearerScheme;
};
});

// Use own policy scheme instead of default policy scheme that was set in method AddIdentityServerJwt
builder.Services.Configure<AuthenticationOptions>(options => options.DefaultScheme = "ApplicationDefinedAuthentication");

Getting some 401 - Unauthorized exception when going to my ASP.NET MVC website

Check web.config settings for system.web/authorization; you should either not have that element at all, or it should only contain <allow users="*"/>.MVC is using its own logic (AuthorizeAttribute) to determine what an anon user may access (or not). Web.config settings should not collide with this.

Check if anonymous authentication is enabled within IIS for that website. Besides that one, Forms Authentication needs to also be enabled, and all other auth modes (if they are installed) should be disabled.

If not login then redirect to Login with AuthorizeWebForm attribute

I got solution. I just put below code to my web.config. the session was already checked in custom error class. if session is null, then it is redirecting to login page.

<authentication mode="Forms"> 
<forms name=".SomeLoginCookie" loginUrl="~/Account/Login" timeout="2880" protection="All" enableCrossAppRedirects="true" />
</authentication>

How can I show Authenticated but UNAUTHORIZED users an unauthorized page MVC 3?

Your solution is similar to mine except that I did this:

  1. Create a custom exception, UnauthorizedDataAccessException.

  2. Create a custom exception filter (so that it could log the invalid access attempt).

  3. Register my custom exception attribute as a global filter in App_start.

  4. Create a marker interface, ISecureOwner and added it to my entity.

  5. Add a secure 'Load' extension method to my repository, which throws the exception if the current user is not the owner of the entity that was loaded. For this to work, entity has to implement ISecureOwner that returns the id of the user that saved the entity.

Note that this just shows a pattern: the details of how you implement GetSecureUser and what you use to retrieve data will vary. However, although this pattern is okay for a small app, it is a bit of hack, since that kind of security should be implemented deep down at the data level, using ownership groups in the database, which is another question :)

    public class UnauthorizedDataAccessException : Exception
{
// constructors
}

public class UnauthorizedDataAccessAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.Exception.GetType() == Typeof(UnauthorizedDataAccessException))
{
// log error
filterContext.ExceptionHandled = true;
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Error", action = "UnauthorizedDataAccess" }));
}
else
{
base.OnException(filterContext);
}
}

// marker interface for entity and extension method
public interface ISecureOwner
{
Guid OwnerId { get; }
}

// extension method
public static T SecureFindOne<T>(this IRepository repository, Guid id) where T : class, ISecureOwner, new()
{
var user = GetSecureUser();
T entity = repository.FindOne<T>(id);

if (entity.OwnerId != user.GuidDatabaseId)
{
throw new UnauthorizedDataAccessException(string.Format("User id '{0}' attempted to access entity type {1}, id {2} but was not the owner. The real owner id is {3}.", user.GuidDatabaseId, typeof(T).Name, id, entity.OwnerId));
}

return entity;
}

// Register in global.asax
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
var filter = new UnauthorizedDataAccessAttribute { ExceptionType = typeof(UnauthorizedDataAccessException) };
filters.Add(filter);
filters.Add(new HandleErrorAttribute());
}

// Usage:
var ownedThing = myRepository.SecureFindOne<myEntity>(id))


Related Topics



Leave a reply



Submit