Reputation: 21
I am trying to build security architecture in OData WebAPI service. The idea is to make decoupled architecture, security layer should be loosely coupled with WebAPI controllers, meaning when I update WebAPI controllers, I don't need to update security layer, I just need to supply rules to security layer somehow. I would like if I can make security checks to be done in only one layer, security layer and not to include business layer for more complex checks. I was reading about proposed solutions and most of them are basically similar, I should use tokens from token provider for authentication and roles from role provider for authorization. Authorization is done by flagging WebAPI controller methods with Authorize attribute. For example I have CompaniesController:
public class CompaniesController : ODataController
{
//code omitted
[Authorize("Admin,CompanyAdmin")]
public IQueryable<User> GetUsers()
{
//code for querying users from database...
}
}
This code would allow only clients with role Admin and/or CompanyAdmin to call method Companies(id)/GetUsers where id is unique key of Company. The exposed resourse is collection of users belonging to company with that id. I agree this approach is good architecture, but this doesn't solve next problem: I want to have security rule that will allow CompanyAdmin to get users only from Company that it is administered by that CompanyAdmin. This gives me trouble to decide how to achieve this and should this be "job" of security layer or business layer.
Add CompanyAdmin identification as a claim in token and check that value against id in request URL (ex. /Companies(2)/GetUsers), if it matches return users, otherwise return status code 401 Unauthorized. Check is performed in attribute class derived from Authorize attribute - ex. [AdvancedAuthorize("Admin,CompanyAdmin{identification}")] identification in brackets means that for CompanyAdmin security layer needs to compare identification value from token to id value from URL
Get CompanyAdmin identification from token, same as 1. approach or get identification from database, from Authorizations table where we have records with authorizations for each user and check if id from URL matches. Business layer method is called from WebAPI controller and I would supply id from URL as parameter in business layer method.
Which approach is better? Or maybe some other approach is better than both?
Upvotes: 0
Views: 512
Reputation: 907
The exposed resource in this case would be a collection of users.
GET /companies/{company-id}/users
Personally, I would go with your second option because it seems easier to implement.
Otherwise, some business logic would be needed in a custom authorization filter to determine that the company for which the 'users' sub-resource is requested is administered by the authenticated user.
Upvotes: 1