This should be simple, but I simply cannot figure it out after all my googling. Here's what I want. I have a custom Users table (no roles at the moment) that I'd like to authorize against. For this I'll have to implement a custom Membership Provider which I've already done. My question is though, how do I go about setting a custom IPrincipal to the HttpContext.Current.User? Where should that happen? Let's say I have the following setup:
public class CustomMembershipProvider : MembershipProvider
{
private IUserRepository _repository;
public CustomMembershipProvider(IUserRepository repository)
{
_repository = repository;
}
public override bool ValidateUser(string username, string password)
{
//check user repository
}
//additional methods omitted for brevity
}
I then have a custom user class the implements IPrincipal
and IIdentity
public class CustomUser : IPrincipal
{
public CustomUser(string name, int userId, string additionalInfo)
{
Identity = new CustomIdentity(name, userId, additionalInfo);
}
public IIdentity Identity { get; private set; }
public bool IsInRole(string role)
{
return true;
}
}
public class CustomIdentity : IIdentity
{
public CustomIdentity(string name, int userId, string additionalInfo)
{
Name = name;
UserId = userId;
AdditionalInfo = additionalInfo;
}
public string Name { get; private set; }
public string AuthenticationType
{
get { return "CustomAuth"; }
}
public bool IsAuthenticated
{
get { return !String.IsNullOrEmpty(Name); }
}
public int UserId { get; private set; }
public string AdditionalInfo { get; private set; }
}
So my question is, where is the correct place to set the Context.User to an instance of this custom user? Do I need a custom Authorize Attribute? If so, what would that look like?
I suggest using a custom controller base class for all your controllers
Then, in OnAuthorization
, call
protected override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
// Actual Authentication
HttpContext.User = user;
Thread.CurrentPrincipal = user;
base.OnAuthorization(filterContext);
}
I'm not entirely sure how to invoke the membership provider because I'm doing it manuallt, but I think you have static access to Membership.Provider
to perform the actual object construction.
Do I need a custom Authorize Attribute?
No. Notice the difference of authentication and authorization: authentication establishes the user's identity in your system. Authorization allows or denies a specific request. Hence, AuthorizeAttribute
also has a Roles
parameter to allow an action to be called only by certain users.