Reputation: 11
I have created an asp.net odata web api project that uses an entity framework database. This is nothing special, many tutorials take this approach. I have secured this api with users and roles so only administrators can actually save something using the web api.
My next step would be to make some information only accessible for specific roles. If I, for example, would have an entity Employee with a Salary property. Then how would I restrict (read) access to this property only to Administrators?
Edit
I'll try to specify my question. Given the following controller:
public class EmployeeController : ApiController
{
public IQueryable<Employee> Get()
{
return _Db.Employees;
}
}
Now I'm able to write odata querys aqainst this e.g http://api.com/employee?$select=FirstName,LastName,Salary&$orderby=Salary
If I don't want certain people (or roles) to order by salary I can implement an OrderByQueryValidator. But how can I completely hide the Salary property for normal users while still allowing administrators to select it?
So, given the controller above, I want the administrators to be able execute both these:
http://api.com/employee?$select=FirstName,LastName,Salary&$orderby=Salary
http://api.com/employee?$select=FirstName,LastName&$orderby=FirstName
while normal users will only be able execute this:
http://api.com/employee?$select=FirstName,LastName&$orderby=FirstName
and get an error when trying to select the Salary property.
Upvotes: 1
Views: 1031
Reputation: 223
Creating custom authorization is always an interesting part of projects. The most flexible/cleanest way I have implemented it was with aspects. We used PostSharp, and we simply created a RequirePermission attribute, that could be applied to any methods. The attribute had a parameter that contained the permission, that was required to execute the method. For example: RequirePermission(Permission="ReadSalary"). You can decide it in the attribute what to do when the user doesn't have the required permission. Either throw an exception, or simply skip method execution.
You could reach the same behaviour without aspects, but you will probably write more code, and I find it much cleaner to be solved with aspects.
A quicker and easier way might be to have different ViewModels for different roles, but I would only advice to use something like this if you are sure to keep the number of roles (like admin and user) low. The you could have a EmployeeSummary and an EmployeeDetails view model, and simple give back the right one based on the current user's role.
Upvotes: 0
Reputation: 2009
Use a ViewModel approach. Instead of giving the Employee object, creating a new class named EmployeeViewModel and create the properties you would like to share. I recommend also creating a static method to create a ViewModel from the Model and vice-versa.
Upvotes: 1