views:

237

answers:

4

Hi, i'm starting a project using ASP.NET MVC and i can't figure out what's the best way of handling authorization and roles based on a team_id. Every blog entry or forum post i read always talk about defining a global role("admin", "helpdesk", "editor", etc...) using asp.net membership or creating a CustomAuthorize filter. The problem in my application is that there are no global roles. A user is going to be manager of team1, but cannot edit or view team2 details. So the authorization details are: - A user can view his team planning and his team mates availability, but cannot see other teams - team manager can edit team details, but cannot edit other team's details - A team can have 1 or many managers - A user can be part of 1 or many teams

ATM, i have 3 tables to handle this relation.

teams --> teams_users <-- users
team_id   #team_id        user_id
          #user_id
          isManager?

As last resort, i'm planing on storing user's current team_id and isManager status in session vars when he logs in, and create a CustomAuthorize filter that will check if session team_id is the same as model.team_id. Let me know if there is another way of doing it. Thank you

+1  A: 

I would then have 2 roles - Manager and User Then I would tie in the database just like you specified.

The roles would control what actions each user can perform (user can view info, a manager can edit/create info), then in each action I would do a quick check can the current user. Do this action on the team that would be required (i.e. does the user have access to the team).

Solmead
A: 

I have developed two custom attributes to handle cases like this: RoleOrOwnerAuthorization and RoleOrOwnerAssociatedAuthorization. RoleOrOwner looks to see if the current user of the system is the same as the user id of the data in question. That is, you are authorized to view your own data. RoleOrOwnerAssociated checks to see if there is a row in a join table relating the data to the current user. For example, I may have Groups, GroupLeaders, and Users, where GroupLeaders is a join table linking Groups to Users. To view a Group's data you would need to either be in the ViewGroups role or be a group leader (as evidenced by a row in GroupLeaders with the group's id and your id). I think that this works very well.

tvanfosson
+1  A: 

Finally, i ended up creating a custom route:

/{team_id}/controller/action/{id}

{team_id} is set once the user logs in, then a custom filter verifies that the user belongs to team on top of each controller. Whenever he changes team, the {team_id} is updated. In addition, there is a "isManager" filter to secure specific manager action that will check if the user is manager of the current team. Thank you guys for your answers

JohnK
+1  A: 

I think your solution looks good. If you rely much on ASP.NET roles to do the initial lifting for you, you'll have this problem a lot:

User 1 is a manager for team 1 and a regular user for team 2. ViewSchedule is readonly for users and editable for managers. Code on ViewSchedule:

if (User.IsInRole("manager")) {
    if (isTeamManager(userid)) {}
}
else {}

bool isTeamManager(int userid) {
    return db.IsTeamManager(userid) {
}

If you do this, then when the user is using team 2, he'll miss that block altogether. He is a manager as far as ASP.NET roles are concerned but isn't one for that team. No problem, obviously we can combine the conditionals like this:

if (User.IsInRole("manager") && isTeamManager(userid)) { }
else {}

Oh yeah, and if we're calling isTeamManager() then we're already getting the only info that User.IsInRole("manager") provides so we don't even need that:

if (isTeamManager(userid)) { }
else {}

So now we're not even using roles in our code. I'd just stick with your original idea.

Dinah