I want to add User authorization and authentication in asp.net mvc project. I am Entity Framework Code First. Now I want to create some default user and default role for it. For this I want to create a Admin Role, but it is preventing me that User and Role Named admin and Admin Exists already. But when I see in my Database Table such as AspNetUSers , Role etc. there I did not find any named Admin. So how can I do this?
If the admin role and users are built in, so where is the password. And also how can I create some other default users and roles each time when my application is running first.
I am using MVC 5 ,not mvc 4. There are difference for both of these two.
Thanks,
Abdus Salam Azad
Since no one ever answered your question, I though I would add some code that shows how to do this from the Seed method on a migration. This code is used to seed an initial user in the database with an admin role. In my case, only the 'admin' user can add new users to the site.
protected override void Seed(PerSoft.Marketing.Website.Models.ApplicationDbContext context)
{
const string defaultRole = "admin";
const string defaultUser = "someUser";
// This check for the role before attempting to add it.
if (!context.Roles.Any(r => r.Name == defaultRole))
{
context.Roles.Add(new IdentityRole(defaultRole));
context.SaveChanges();
}
// This check for the user before adding them.
if (!context.Users.Any(u => u.UserName == defaultUser))
{
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
var user = new ApplicationUser { UserName = defaultUser };
manager.Create(user, "somePassword");
manager.AddToRole(user.Id, defaultRole);
}
else
{
// Just for good measure, this adds the user to the role if they already
// existed and just weren't in the role.
var user = context.Users.Single(u => u.UserName.Equals(defaultUser, StringComparison.CurrentCultureIgnoreCase));
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
manager.AddToRole(user.Id, defaultRole);
}
}
Related
I want to create web portal, where there will be multiple users of 3-4 types. So I have created roles in Startup.cs Like
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
createRolesandUsers();
}
// In this method we will create default User & roles
private void createRolesandUsers()
{
ApplicationDbContext context = new ApplicationDbContext();
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
if (!roleManager.RoleExists("Admin"))
{
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = "Admin";
roleManager.Create(role);
var user = new ApplicationUser();
user.UserName = "1";
user.Email = "a#b.com";
user.ScreenName = "Ra";
user.UserType = "Admin";
string userPWD = "1";
var chkUser = UserManager.Create(user, userPWD);
if (chkUser.Succeeded)
{
var result1 = UserManager.AddToRole(user.Id, "Investor");
}
}
It creates Usertypes and on login page I give radio button to select own type.
Now, suppose there are 4 roles.
Admin
Player
Coach
And suppose 10 people signup to site
2 people as admin
4 people as player
4 people as coach.
Now each one has it's type and user id. And if they log in, they can't access controllers of each other due to Autorize attribute. But my question is, what about 4 players? Will they be ever able to access each others account?
They have same authorize rights and they are authenticate too. How can I prevent users from same type to access each other's account ?
I use " User.Identity.GetUserId() " on each page to get current user and I log all transactions by current id.
I'm working on a ASP.Net MVC 5 app and using ASP.Net identity 2, and need to authorize users based on roles and permissions. roles and permissions is not related to each other. for example, to access "action1" action method,( "admin" role ) or ( combination of "role1" and "permission1" ) must exist for him, but other users that is not in "admin" role or combination of ( "role1" and "permission1") is not true for theirs, don't allow to access that action method.
how i can do this scenario?
do claims based authorization useful in this manner?
or i must implement Permission entity and custom AuthorizeAttribute? if true how?
best regards
Check out the ResourceAuthorize attribute in the Thinktecture.IdentityModel.Owin.ResourceAuthorization.Mvc package.
This attribute authorizes a user based on an action (e.g. read) and a resource (e.g. contact details). You can then base whether or not they are allowed to perform that action on a resource based on a claim (e.g. their presence in a role).
See here for a good example.
Might not be exactly what you are looking for, but you can take inspiration and implement your own authorization attribute using similar logic.
This is custom made Authorize which checks permission from database.
For example you have 3 bools for permission Account,Clients,Configuration
and you want to restrict user based on them.
you can add even two permission on one action, for example you have a method which can be accessed by Account and Client permission than you can add following line
Modify this to use roles with permissions in this, this is the easiest and best way to handle it.
[PermissionBasedAuthorize("Client, Account")]
This method below is which check the bools from database.
public class PermissionBasedAuthorize : AuthorizeAttribute
{
private List<string> screen { get; set; }
public PermissionBasedAuthorize(string ScreenNames)
{
if (!string.IsNullOrEmpty(ScreenNames))
screen = ScreenNames.Split(',').ToList();
}
public override void OnAuthorization(HttpActionContext actionContext)
{
base.OnAuthorization(actionContext);
var UserId = HttpContext.Current.User.Identity.GetUserId();
ApplicationContext db = new ApplicationContext();
var Permissions = db.Permissions.Find(UserId);
if (screen == null || screen.Count() == 0)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
bool IsAllowed = false;
foreach (var item in screen)
foreach (var property in Permissions.GetType().GetProperties())
{
if (property.Name.ToLower().Equals(item.ToLower()))
{
bool Value = (bool)property.GetValue(Permissions, null);
if (Value)
{
IsAllowed = true;
}
break;
}
}
if (!IsAllowed)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
}
}
I implemented a Permission-based extension for Microsoft Identity 2 membership system. But in this extension, permissions and roles are related together. there is a many-to-many relation between them. Also you can have a complex authentication with combination of roles and permissions. I suppose it can help you to do permission based authentication.
You can do permission authentication in two ways:
First approach:
// GET: /Manage/Index
[AuthorizePermission(Name = "Show_Management", Description = "Show the Management Page.")]
public async Task<ActionResult> Index(ManageMessageId? message)
{
//...
}
Second approach:
// GET: /Manage/Users
public async Task<ActionResult> Users()
{
if (await HttpContext.AuthorizePermission(name: "AllUsers_Management", description: "Edit all of the users information."))
{
return View(db.GetAllUsers());
}
else if (await HttpContext.AuthorizePermission(name: "UnConfirmedUsers_Management", description: "Edit unconfirmed users information."))
{
return View(db.GetUnConfirmedUsers());
}
else
{
return View(new List<User>());
}
}
Also it's an open source and free extension and you can access to the repository here.
Here is my problem with my MVC 4 Internet project using Forms Authentication.
Lets say i have hotels and i want the authorized users accessing each under different roles.
So the user logs in. Then from a dropdownlist selects the target Hotel and the application´s security responds accordingly.
I would need something like [Authorize(Roles = "Administrator")] but only in that hotel scope.
My first aproach was inheriting from AuthorizeAttribute and override AuthorizeCore like is shown in this thread
From there I could get the HttpContext.Session["HotelId"] and query a UserRolesInHotel table. That said, I should have my own roles table with a structure similiar to UserId, RoleId, HotelId. So SimpleRolePrivider comes short to this task and i would be forced to create a CustomeRoleProvider. RoleProvider Methods don´t handle extra params as I need like HotelId when adding a new role to a user.
For clarification:
User A logs in with user/password ->OK (SimpleMembershipProvider)
Authenticated User A selects Hotel 1 -> User A is an "Administrator" for Hotel 1.
Authenticated User A change to Hotel 2 -> User A is a "User" in Hotel 2
I can have any number of hotels.
User A -> Hotel 1 -> { "Administrator", "User"}
User A -> Hotel 2 -> { "User" }
User A -> Hotel 3 -> { "Owner" }
User A -> Hotel 4 -> { "Administrator" }
The list of roles is always the same.
I´ve been struggling with this implementation for a couple of days and i couldn´t come up with a pratical solution.
Any thougths would be much appreciated.
Thanks!
This is what I did:
Added a DefaultBuildingId to the user profile.
Then I created a CustomRoleProvider and overrided GetRolesForUser method like this
public override string[] GetRolesForUser(string userName)
{
if (HttpContext.Current.Session != null)
{
var user = _userRepository.GetByName(userName);
if (!user.IsActive)
{
throw new ApplicationException(string.Format("some message {0}", userName));
}
if (HttpContext.Current.Session["BuildingId"] == null)
{
var building = _buildingRepository.Get(user.DefaultBuildingId);
if (building == null)
{
throw new ApplicationException("error message");
}
HttpContext.Current.Session["BuildingId"] = building.BuildingId;
}
int buildingId = Convert.ToInt32(HttpContext.Current.Session["BuildingId"]);
return _userRepository.GetRolesForUserInBuilding(user.UserId, buildingId).ToArray();
}
throw new ApplicationException("error message.");
}
Added a custom AuthorizeAttribute
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
var repo = UnityManager.Resolve<IUserRepository>();
var buildingId = (int)httpContext.Session["BuildingId"];
var userName = httpContext.User.Identity.Name;
var user = repo.GetByName(userName);
var userRolesInBuilding = repo.GetRolesForUserInBuilding(user.UserId, buildingId);
foreach (var role in Roles.Split(','))
{
if (userRolesInBuilding.Contains(role.Trim()))
{
return true;
}
}
return false;
}
And finally this is how to use it at controller or action level.
[BuildingAthorize(Roles = "Administrators")]
I also added a ddl to the layout to let the user change the building and set the new BuildingId overriding the value at the session/db. This way a user can work in different Hotels during the same session and only access areas and functionality he has for that particular hotel.
I have an mvc project with database first entityframework. In Project I have 3 tables.
Users >>> UsersInRoles <<< Roles with many to many relationship.
and my CreateUser codes below;
public bool CreateUser(string email, string password, string birthday,string firstname,string lastname)
{
bool result;
var dogumgunu = Convert.ToDateTime(birthday);
var sifre = FormsAuthentication.HashPasswordForStoringInConfigFile(password, "sha1");
var confirmation = CreateConfirmationToken(email);
try
{
var user = new User
{
UserName = email,
Password = sifre,
UserJoinDate = DateTime.Now,
UserBirthDay = dogumgunu,
UserConfirmationToken = confirmation,
UserID = Guid.NewGuid(),
MemberFirstName = firstname,
MemberLastName = lastname
};
var role = new Role
{
RoleName = "Client"
};
user.Roles.Add(role); //problem is here!!!!!!!!!
_bb.Users.AddObject(user);
_bb.SaveChanges();
result = true;
}
catch (Exception)
{
result = false;
}
return result;
}
In this code I am new user creating. And I am adding a role. But This code include a new Role in Roles table. I dont want to this. I want to just add UsersInRoles table a new user. What is wrong? Thanks for reply.
Swap these two lines:
_bb.Users.AddObject(user);
user.Roles.Add(role);
because AddObject converts the whole object graph to the Added state. If you add the role afterwards, its state will remain Unchanged.
And you should fetch the role from the database first or create a Role object that only has an existing RoleId. (A so called stub entity).
So in stead of new Role you could do
var role = _bb.Roles.Single(r => r.RoleName == "Client");
I have the following code. But there must be a more database efficient way to do this, because, correct me if Im wrong the number of database queries is
(1 + (qty of users with admin role))
With a new MVC 4 project the membership defaults are the tables UserProfile, webpages_Roles and webpages_UsersInRoles. I see lots of built in methods for Roles.Get*. If I want to avoid writing code like what I have below do I need to explicitly create a model for webpages_Roles and webpages_UsersInRoles as well as all the code first properties? Getting just the username from Roles.Get* doesnt suffice, I need the full UserProfile.
FYI the "UserRole" object below is just an enum
public ActionResult Admins()
{
var dbContext = new UsersContext();
var usernames = Roles.GetUsersInRole(UserRole.SiteAdministrator.ToString());
var adminUsers = new List<UserProfile>();
foreach (string username in usernames)
{
var adminUser = dbContext.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == username);
adminUser.Roles.Add(UserRole.SiteAdministrator);
adminUsers.Add(adminUser);
}
return View(adminUsers);
}
Yes, you don't want to do it that way. That's a very inefficient way.
Instead, use the tools as they were designed. For example, something like this:
var usernames = Roles.GetUsersInRole(UserRole.SiteAdministrator.ToString());
var adminUsers = dbContext.UserProfiles
.Where(x => usernames.Contains(x.Username)).ToList();
return View(adminUsers);