Skip to Content

Zuplo is a lightweight, fully managed API management platform designed for developers. It provides a programmable and cost-effective alternative to traditional API management solutions.

Zuplo allows you to add policies, which are modular, executable components that intercept and modify API requests and responses as they flow through the API gateway. They act as "middleware" for your API traffic.

In this blog post, we will demonstrate how you can use Enforcer to create a Policy Decision Point (PDP) and add an AuthZen policy to Zuplo that will call this PDP to authorize requests.

This blog post assumes you have some basic knowledge of the Enforcer product and AuthZen. If not, you can watch Andrew Clymer’s AuthZen video to get an introduction. This blog post also assumes a basic working knowledge of Zuplo.

Creating a Zuplo Todo List API with API Key Authentication

For this blog post, we will require a basic API in Zuplo using their Todo List API example. To follow along, create a new API in Zuplo and select the “Todo List” option.

Creating a Zuplo Zup

We will also need to add API Key authorization. I will not go into too much detail with this, but Zuplo has great documentation as part of their Getting Started tutorial that walks you through adding API Key Authentication.


I followed their tutorial and added the API Key Authentication Policy to all of the endpoints of my Todo List API.

Setting API Authentication Policy

I also created two separate consumers in their API Key Service.

Creating API Service Keys

I can confirm that the API Key Authentication Policy is working by testing one of the API endpoints. When calling the endpoint without an authorization header, Zuplo returns an HTTP 401 (Unauthorized) response.

Test Your API

Using the API key from one of the previously created consumers, the API endpoint returns the list of todos.

Test Your API Success

Create a Basic PDP

With the Zuplo API created, let’s focus on the PDP. I created an empty ASP.NET Core project and installed the Rsk.Enforcer.AuthZen NuGet package.

Then, I updated my startup code by adding the following code:

  1. The call to AddEnforcer adds the various Enforcer services. You can obtain an Enforcer demo license from here
  2. AddPolicyEnforcementPoint adds and configures the Policy Enforcement Point (PEP) for Enforcer.
  3. AddEmbeddedPolicyStore Informs Enforcer that the policies must be loaded as embedded resources and will be prefixed with ZuploEnforcerPdp".Policies (in other words, these embedded resources can be found in the application’s /Policies directory. (We’ll look at the policy below).
  4. Finally, we register the AuthZen middleware by calling the app.UseEnforcerAuthZen();

As mentioned above, I am using the embedded resource policy store. I added an ALFA policy document to the /Policies directory and set its build action as an embedded resource.

 

Global.alfa

For now, the ALFA policy document looks as follows.

I can ensure that everything is hooked up correctly by running the project and sending an empty payload to the evaluation endpoint:

The PDP responds as follows:

The response indicates that the authorization request is not allowed, which is expected since a) our policy document does not contain any rules yet, and b) the request payload did not contain information on which the PDP can base a decision.


Once again, I suggest you watch Andrew Clymer’s AuthZen video to understand how the requests should be made.

Exposing our PDP to the Internet

Before we switch back to Zuplo, I’d like to expose the PDP to the internet. Currently, we can make requests to the evaluation endpoint on localhost; however, once we add the AuthZen Policy to Zuplo, this policy must be able to make requests to the PDP running on my local machine.

I am using ngrok and running the following command:

ngrok http --host-header=rewrite localhost:5217

This will start the ngrok tunnel and indicate the public URL I can use to access my PDP.

ngrok running

In a production environment, your PDP will be hosted on public infrastructure, so this is just needed during development when I want to allow Zuplo to make requests to the PDP running on my development machine.

Add AuthZen Policy in Zuplo

With the PDP in place, let’s add the AuthZen Policy in Zuplo. Navigate to your list of policies, and create a new inbound policy.

 

Creating a Zuplo Policy

Add a new “AuthZen Authorization” policy. You can leave the default configuration, but be sure to update the authorizerHostname with the URL of the PDP - in our case, the public URL generated by ngrok.

Create Policy

Once the policy is created, we can apply it to all the operations in the Todo List API.

Apply To Operations

Next, we can switch to the Route Designer and ensure that the AuthZen policy executes after the API Key policy but before any other policies, such as input validation policies.

authzen inbound

Finally, we can test the “Get all todos” endpoint. We’ll get an HTTP status 403 (Forbidden) response, which is expected, as our policy document does not yet contain any rules.

Test Your API Forbidden

Add a read-access Rule

Let’s add a rule to the policy document allowing read access for all users.

However, before we do that, let’s revisit the AuthZen Policy configuration in Zuplo. You will notice that the default policy that was created bound the request method to the action attribute.

 

Edit Policy

If we look at the previously denied request sent from Zuplo to our PDP in the ngrok inspector, we will notice the presence of the action attribute, which contains the HTTP method.

ngrok - POST results

With this in mind, let’s update the ALFA policy document to add a hasReadAccess rule for all users. This rule will allow all requests where the Action (i.e. the HTTP verb) is “GET”.

When we restart the PDP and execute the request to list all todos again, the authorization succeeds, and Zuplo returns the list of todos.

Test Your API - 200 OK

Add a Write Access Rule for Managers

Next, we want to enable managers to have write access. In other words, managers must be able to execute any of the endpoints that use the POST, PATCH, or DELETE HTTP verbs.

For this, we can update the policy document as follows:

  1. We added an IsManager condition to check whether a user is a manager based on their role.
  2. We added a hasWriteAccess rule that permits managers to perform “POST”, “PATCH”, or “DELETE” actions.

Next, we need a way to determine whether a user has the “manager” role. There are two approaches we can take to do this:

  1. We can set the roles in Zuplo using additional user metadata in the API Key Service and attach it to the request made to the PDP.
  2. We can let our PDP resolve the user roles based on the user ID.

I will demonstrate both these approaches.

Attach User Roles via Zuplo

The first thing I am going to do is to add the manager role for one of the users I created earlier. The second user will not have the manager role.

 

Change Consumer

When configuring the AuthZen Policy earlier, we used the default settings to set the user attribute using the special $authzen-prop function. Unfortunately, as indicated in the AuthZen Authorization Policy documentation, this function only works for setting the id and name properties. 

To attach the roles as custom properties to the user attribute, we must do so in code. For this, we can create a custom code inbound policy and use the setAuthorizationContext method to set the user attribute.

The code for this policy attaches the roles from the metadata to the properties of the user attribute.

Next, we need to wire up this policy on all our routes and ensure that it executes before the AuthZen Authorization Policy.

Request Handling

With this configured, we can confirm that the new policy works correctly by making a request with the API key of the user who does not have the manager role.

As expected, we get an HTTP Status 403 (Forbidden).

Test Your API Post Forbidden

If we make the same request with the API key of the user with the manager role, the request succeeds.

Test Your API - POST Success

Resolve User Roles Inside the PDP

The other approach is to assign the correct user roles to each user inside our PDP. For this, we can create a Custom AttributeValueProvider, allowing us to return additional attributes to the PDP.

First, let’s create a record containing the return result, which will be the roles for the subject.

Then, we can add the implementation for the record attribute provider. For this sample, the provider will return a hard-coded set of roles for each user we previously created in the API Key Service in Zuplo. In a production application, this data will most likely come from a database or another data source.

The final bit is to tell Enforcer about the custom Policy Attribute Provider by adding a call to AddPolicyAttributeProvider<T>.

With this in place, we can make a request using the API key of the user who does not have the manager role. As expected, we get an HTTP Status 403 (Forbidden).

Test Your API - POST - Forbidden

Making the same request again, but this time with the API key of the user who has the manager role, the request succeeds.

Test Your API - POST - Created

Conclusion

In this blog post, I demonstrated how to create a PDP with Enforcer and how to enable Zuplo API Gateway to consult the Enforcer PDP using the AuthZen protocol to determine if the API call should be allowed. This separation of concerns enables developers to use their preferred API gateway and Policy Decision Point.

Enforcers' ALFA policy language is the most readable policy language available today, allowing not only developers but also other stakeholders to understand access control.

The source code for the PDP can be found on GitHub

Try Enforcer for Free

Get a 30-day free, fully functional license of Enforcer and use policies to enforce your API gateway rules today.