I have created a custom authentication and authorisation for my users.The problem I am facing is how to get mvc to check that role from inside my users table matches the [Authorize(Role)] on my controller so as to set httpauthorised to true.Below is my customauthorise class.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Controller.TempData["ErrorDetails"] = "You must be logged in to access this page";
filterContext.Result = new RedirectResult("~/User/Login");
return;
}
if (filterContext.HttpContext.Request.IsAuthenticated)
{
using (var db = new GManagerDBEntities())
{
var authorizedRoles = (from u in db.Users
where u.Username == filterContext.HttpContext.User.Identity.Name
select u.Role).FirstOrDefault();
Roles = String.IsNullOrEmpty(Roles) ? authorizedRoles.ToString() : Roles;
}
}
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Controller.TempData["ErrorDetails"] = "You do nat have necessary rights to access this page";
filterContext.Result = new RedirectResult("~/User/Login");
return;
}
}
public CustomAuthorizeAttribute(params object[] roles)
{
if (roles.Any(r => r.GetType().BaseType != typeof(Enum)))
throw new ArgumentException("roles");
this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));
}
}
below is my controller with decoration
[CustomAuthorize(Role.Administrator)]
[HttpGet]
public ActionResult CreateEmployees()
{
return View();
}
and my enum for role
public enum Role
{
Administrator = 1,
UserWithPrivileges = 2,
User = 3,
}
and model
public class UserModel
{
public int UserID { get; set; }
[Required]
[Display(Name="Username:")]
public string Username { get; set; }
[Required]
public string Password { get; set; }
public int Role { get; set; }
}
see pastie for clear view pastie
links I have viewed in trying to solve this among others but I cant seem to piece it togetherMVC 3 Authorize custom roles http://forums.asp.net/p/1573254/3948388.aspx
Customized authorization attribute in MVC 4 with Roles
Create the following database data tables. Open Visual Studio 2015 or an editor of your choice and create a new project. Choose "web application" project and give an appropriate name to your project. Select "empty" template, check on the MVC box, and click OK.
For role-based authorization, the customer is responsible for providing the user ID, any optional attributes, and all mandatory user attributes necessary to define the user to Payment Feature Services. The customer must also define the roles that are assigned to the user.
using the link shared by @VikasRana http://www.codeproject.com/Articles/578374/AplusBeginner-splusTutorialplusonplusCustomplusF
I got rid of my enum Role and my method
public CustomAuthorizeAttribute(params object[] roles)
{ ...}
I then changed Role in my model to be a string e.g. User.Role="Admin" instead of int. In my onAuthorization method I changed it to:
` public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Controller.TempData["ErrorDetails"] = "You must be logged in to access this page";
filterContext.Result = new RedirectResult("~/User/Login");
return;
}
if (filterContext.Result is HttpUnauthorizedResult)
{
filterContext.Controller.TempData["ErrorDetails"] = "You don't have access rights to this page";
filterContext.Result = new RedirectResult("~/User/Login");
return;
}
}
and in my global.asax added this.
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (FormsAuthentication.CookiesSupported == true && Request.IsAuthenticated== true)
{
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
try
{
//let us take out the username now
string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
string roles = string.Empty;
using (GManagerDBEntities db = new GManagerDBEntities())
{
User user = db.Users.SingleOrDefault(u => u.Username == username);
roles = user.Role;
}
//let us extract the roles from our own custom cookie
//Let us set the Pricipal with our user specific details
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
new System.Security.Principal.GenericIdentity(username, "Forms"), roles.Split(';'));
}
catch (Exception)
{
//something went wrong
}
}
}
}
Above method is not ideal though.It gets run for every simple page request about 3 times or more.
So here is solution 2:better solution Implement a custom role provider since we are already using custom role implementation.Simply follow this linkhttp://techbrij.com/custom-roleprovider-authorization-asp-net-mvc
Thanks Gotalove for this method in Global.asax. Here is some more help for anyone trying to do a custom Forms Authentication (FormsAuthentication, FormsAuthenticationTicket) using entity framework.
Login Controller SetAuthTicket
protected void GetRoles(int UserID)
{
var db = new ResearchSurveysEntities();
string[] getRoles = { };
try
{
var query =
from p in db.UserProfiles
join i in db.webpages_UsersInRoles on p.UserId equals i.UserId
join r in db.webpages_Roles on i.RoleId equals r.RoleId
where p.UserId == UserID
select new { p.UserId, r.RoleName };
if (query.Count() > 0)
{
List<string> gRoles = new List<string>();
foreach (var item in query)
{
gRoles.Add(item.RoleName);
}
getRoles = gRoles.ToArray();
}
roles = String.Join("|", getRoles);
}
catch (Exception ex)
{
WebUtilities wu = new WebUtilities();
wu.NotifyWebmaster(ex.ToString(), "Get roles for AdminUserID: " + UserID.ToString(), string.Empty, "Login Error");
}
finally
{
db.Dispose();
}
}
WebConfig
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
Global.asax (From above example)
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null || authCookie.Value == "")
return;
FormsAuthenticationTicket authTicket;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
// retrieve roles from UserData
string[] roles = authTicket.UserData.Split('|');
if (Context.User != null)
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With