简体   繁体   中英

Authorization in a layered application

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:

  • fine-grained: you want to create authorization policies that take into account multiple parameters or attributes and possibly relationships between the client (the requestor) and the targeted entity eg a listing in your case.
  • externalized: you want to decouple the business logic from the authorization logic. In your question you complain about how complex the code and the SQL statements are becoming. This is a direct consequence of not clearly separating business logic from authorization logic.

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:

  • an architecture as illustrated below
    • The policy enforcement point (PEP) intercepts your API calls. It protects your API, inspects the messages and sends an authorization request to the policy decision point (PDP).
    • The policy decision point (PDP) evaluates incoming authorization requests from the PEP against a set of authorization policies written in XACML. The PDP eventually reaches a Permit or Deny decision. To reach decisions it may need to look up additional attribute values from databases, web services, LDAP, or files. These are called policy information points in the architecture. XACML架构流程
  • a policy language: the XACML policy language is attribute-based which means it uses attributes to define what can be allowed and what is not. For instance, you could define rules such as:
    • a real estate agent can see all the listings if and only if the listing location == the agent location
    • a real estate agent can edit a listing if and only if he/she owns the listing
    • a real estate agent can close a listing if and only if the listing's item is sold and if and only if the agent is the person that sold the item.
  • a request/response scheme: XACML also defines a way to query the PDP and to get responses back. A PDP can be queried either via single questions or via multiple questions in a single request eg:
    • Can Alice view listing 123? Yes, permit.
    • Can Alice view, edit, or delete listing 123? Permit; Deny; Deny.

With a XACML-based approach, you get to maintain your business logic and your API separate from the authorization logic. This has several benefits:

  1. you can always reimplement the API and keep the same authorization model
  2. you can easily expand your API without having to rewrite the authorization
  3. you can change your authorization logic independently of your code
  4. you can audit your authorization logic more easily
  5. your authorization logic is technology-neutral. It works for REST APIs, web services, databases, and more

I recommend you check out the following resources:

  1. the OASIS XACML website
  2. the ALFA plugin for Eclipse - a free tool to write XACML policies.
  3. The XACML developer community

There are both vendor and open-source implementations of XACML:

  • Axiomatics is a vendor solution that provides both .NET and Java XACML implementations
  • SunXACML is a long-standing open source Java XACML implementation

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM