I am working on a pretty simple project that is mostly made up of getters and searches and access to certain data is limited depending on the user. I want to use this opportunity to do some best practices when it comes to security, authorization in this case.
The application is activated once at which time a token is generated and used for future requests.
My application has a web api for the endpoint which sits on top of a set of services which sits on top a set of repo's which sits on top of a sql server db. All the controllers do is forward the request down to the service layer.
Here is an example controller:
[ApiAuthorize]
[RoutePrefix("api/Catalogue")]
public class CatalogueController : ApiController
{
private ICatalogueService _catalogueService;
public CatalogueController(ICatalogueService catalogueService)
{
_catalogueService = catalogueService;
}
[HttpGet]
[Route("GetCatalogues")]
public IHttpActionResult GetCatalogues(string branchEan)
{
var catalogues = _catalogueService.GetCatalogues(new GetCataloguesRequest()
{
BranchEan = branchEan
});
return Ok(catalogues);
}
}
My custom authorization attribute checks the token and if valid pulls the user details out from the token and creates a generic principle which is then available in my controllers.
To me the web api is just a way to expose my business\\service layer and authorization should be done lower down in my service layer but I can't think of a clean way to get that information down to that layer. In the above example, the service layer will need to check if the user (from the token) has access to that particular branch which means the service layer will need to know who is making the request. The two solutions I can think of is:
1) I am using a request\\response pattern for my service layer so I could create an abstract base class called 'Request' as an example which could store all the user details and each request object to the service layer could inherit from this therefore providing user details to my service layer.
public abstract class Request
{
public Request(string username)
{
this.Username = username;
}
public string Username { get; private set; }
}
public class GetCataloguesRequest : Request
{
public GetCataloguesRequest(string username) : base(username)
{
}
}
2) To define an interface, for example ISecurity, which is then injected into my service layer but this would require the layers above my service layer to implement the interface.
I read here - Placing authorization into the service layer rather than Web API layer - to create an authorization layer but I am not sure of the technical implementation of this.
Any ideas?
What you are looking for is fine-grained, externalized authorization:
There is a model called attribute-based access control (ABAC) that defines an approach to fine-grained externalized authorization. NIST, the National Institute of Standards and Technology, has produced a report on ABAC which you can read online.
OASIS, the organization for the advancement of structured information standards, has defined a standard called XACML (eXtensible Access Control Markup Language) to implement ABAC.
XACML brings you:
With a XACML-based approach, you get to maintain your business logic and your API separate from the authorization logic. This has several benefits:
I recommend you check out the following resources:
There are both vendor and open-source implementations of XACML:
HTH, David.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.