AWS API Gateway

Overview

One of the possible implementation methods for gating access to features in backend applications can be achieved by deploying an Amazon API Gateway that controls all the incoming traffic to your application. In this tutorial, we'll implement a slim authorizer lambda that leverages Stigg's SDK for feature gating.

Example

Lets take the Example project and consider that its backend servers are behind HTTP API. As part of this example we will implement a Lambda authorizer for HTTP APIs for feature gating.

Mapping REST endpoints to Stigg features

The first step is to define which Stigg feature protects the REST endpoints. In our example, there are 3 features that protects the following REST endpoints:

Stigg featureStigg feature typeProtected REST endpoints
feature-collaboratorsFluctuatingPOST /api/collaborators/
DELETE /api/collaborators/:email
POST /api/collaborators/add-seats
feature-todosFluctuatingGET /api/todos/
POST /api/todos/
PUT /api/todos/:id
DELETE /api/todos/:id
feature-update-todoBooleanPUT /api/todos/:id

Note that PUT /api/todos/:id is protected by 2 different features.

Let's translate this table into code, for simplicity we will focus on PUT /api/todos/:id route only, since it's protected by 2 entitlements.

The rest of the routes will be included in the full source code attached at the end of the article

We will add the features definitions along with their fallback:

const STIGG_FEATURE_TODOS = {
    id: 'feature-todos',
    fallback: {
        hasAccess: true,
        usageLimit: 5,
    },
};

const STIGG_FEATURE_UPDATE_TODO = {
    id: 'feature-update-todo',
    fallback: {
        hasAccess: true,
    },
};

Then add the route definition:

const routes = [
  // ...
  {
    method: 'PUT',
    path: '/api/todos/:id',
    entitlements: [{ feature: STIGG_FEATURE_TODOS }, { feature: STIGG_FEATURE_UPDATE_TODO }],
  },
  // ...
];

Implementing the authorizer lambda

Next, lets compose a simple lambda handler:

exports.handler = async (event, context) => {
    // fetch requested resource from API Gateway authorizer event
    const { method, path } = event?.requestContext?.http;
    const { authorization } = event?.headers;

    // check gating in Stigg for resource
    const isAuthorized = await checkRouteEntitlements(method, path, authorization);

    context.succeed({ isAuthorized });
};

Next, lets implement the checkRouteEntitlements function:

async function checkRouteEntitlements(method, path, authorization) {
    if (!method || !path || !authorization) {
        console.warn('Missing request parameters');
        return false;
    }

    const customerId = findStiggCustomerId(authorization);
    const route = routes.find((route) => route.method === method && isPathMatch(path, route.path));

    if (!route) {
        console.warn(`Missing configuration for route '${method} ${path}'`);
        return false;
    }

    let isAuthorized = true;

    // checking that customer has access to all required entitlements.
    // note that subsequent checks are evaluated in-memory for the same customer
    for (const entitlementToCheck of route.entitlements) {
        const entitlement = await checkEntitlement(customerId, entitlementToCheck);
        console.debug(`Entitlement response for '${entitlementToCheck.feature.id}'`, entitlement);

        isAuthorized = isAuthorized && entitlement.hasAccess;
    }

    console.info(`Route '${method} ${path}' response for '${customerId}' - ${isAuthorized}`);
    return isAuthorized;
}

The implementation of the inner functions was omitted for simplicity, and will be included in the full source code attached at the end of the article

The high-level steps of the authorizer logic:

  • Validate input arguments.
  • Find stigg customer ID (extract it from the authorization header / DB).
  • Find the route definition of the requested route.
  • Iterate over all requested route entitlements and check them agains Stigg.

Source code

For your convenience, we prepared a sample project demonstrate Stigg integration with API Gateway. It's provisioned by Terraform, so it can be easily spin up to check it out.

You can find the source code of an example for API gateway integration in GitHubπŸ‘‡