Here's how I suggest solving your problem:
Create your own interface that implements System.Security.Principal , where you can place any methods that you need:
public interface ICustomPrincipal : IPrincipal { bool IsInClient(string client); }
Implement this interface:
public class CustomPrincipal : ICustomPrincipal { private readonly IPrincipal _principal; public CustomPrincipal(IPrincipal principal) { _principal = principal; } public IIdentity Identity { get { return _principal.Identity; } } public bool IsInRole(string role) { return _principal.IsInRole(role); } public bool IsInClient(string client) { return _principal.Identity.IsAuthenticated && GetClientsForUser(_principal.Identity.Name).Contains(client); } private IEnumerable<string> GetClientsForUser(string username) { using (var db = new YourContext()) { var user = db.Users.SingleOrDefault(x => x.Name == username); return user != null ? user.Clients.Select(x => x.Name).ToArray() : new string[0]; } } }
In Global.asax.cs, assign your user principle in the context of the request user (and, if necessary, to the executable stream if you plan to use it later). I suggest using the Application_PostAuthenticateRequest event not the Application_AuthenticateRequest for this purpose, otherwise your main one will be overridden (at least ASP.NET MVC 4):
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) { Context.User = Thread.CurrentPrincipal = new CustomPrincipal(User); }
Then, in order to be able to use the User property from the HttpContext in the controller, without changing it to ICustomPrincipal each time, define the base controller where you will override the default User property:
public class BaseController : Controller { protected virtual new ICustomPrincipal User { get { return (ICustomPrincipal)base.User; } } }
Now let other controllers inherit from it:
public class HomeController : BaseController { public ActionResult Index() { var x = User.IsInClient(name);
If you use the Razor View Engine , and you would like to be able to use your method in a very similar way:
@User.IsInClient(name)
you need to override the type of WebViewPage :
public abstract class BaseViewPage : WebViewPage { public virtual new ICustomPrincipal User { get { return (ICustomPrincipal)base.User; } } } public abstract class BaseViewPage<TModel> : WebViewPage<TModel> { public virtual new ICustomPrincipal User { get { return (ICustomPrincipal)base.User; } } }
and tell Razor to reflect your changes by changing the appropriate section of the Views \ Web.config file:
<system.web.webPages.razor> ... <pages pageBaseType="YourNamespace.BaseViewPage">