Rectangle 27 0

asp.net How to create a CustomPrincipal globally (with and without AuthorizeAttribute)?


public ActionResult Foo()
{
    var user = (MyPrincipal)User;

    // work with the custom properties that apply only
    // to anonymous users

    ...
}

[MyAuthorize]
public ActionResult Bar()
{
    var user = (MyPrincipal)User;

    // here you can work with all the properties
    // because we know that the custom authorization
    // attribute set them and the global filter set the other properties

    ...
}
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new GlobalIdentityInjector());
    }
}
public class GlobalIdentityInjector : ActionFilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var identity = filterContext.HttpContext.User.Identity;

        // do some stuff here and assign a custom principal:
        var principal = new MyPrincipal(identity, null);
        // here you can assign some custom property that every user 
        // (even the non-authenticated have)

        // set the custom principal
        filterContext.HttpContext.User = principal;
    }
}
public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }

        // we know that at this stage we have our custom
        // principal injected by the global action filter
        var myPrincipal = (MyPrincipal)httpContext.User;

        // do some additional work here to enrich this custom principal
        // by setting some other properties that apply only to
        // authenticated users

        return true;

    }
}
public class MyPrincipal : GenericPrincipal
{
    public MyPrincipal(IIdentity identity, string[] roles): base(identity, roles)
    {
    }

    ... some custom properties and stuff
}

Almost a year later and this saved me immensely. Thanks a lot Darin.

And now you could have a custom authorization attribute which will be applied only to certain controller actions that require authentication:

Excellent, detailed answer Darin. If only to glean more MVC architecture information from you, could you speak to why you would choose a global action filter vs the other choices?

The first of your suggestions is out of question because it involves using sessions. Personally I never use sessions. Application_AuthenticateRequest is not MVCish. The third and fourth I don't like because of the base controller. And the last one - IHttpModule I don't like because not MVCish. So I choose a global action filter - it doesn't require implementing a base controller (which developers might forget to derive from) and it is universally applied to ALL requests and it is quite common way to implement such functionality in ASP.NET MVC applications.

The global filter will be registered in ~/App_Start/FilterConfig.cs so that it is guaranteed that it will apply to all actions:

You could use a global action filter. Let's suppose that you have a custom principal:

and then you could have 2 types of actions:

then you could write a global authorization action filter (but which doesn't derive from the base AuthorizeAttribute to avoid global authentication, it just implements the IAuthorizationFilter interface to ensure that it runs before any other filters):

Note