Providing Developer API Access for your SaaS Product Users

Here’s how we used AWS Cognito’s authorizer to enable users to have developer API access restricted to their user data using Client Id/Secret

By Aditya Bhowsingka, Sr. Software Engineer at Ignite Solutions

We are building a SaaS product where users may request API access to our product’s services. This would enable users who want to build custom capabilities to access and leverage our APIs via an authenticated, authorized, and controlled access mechanism.

This requirement is not uncommon. Many services, such as Spotify, or Trello, or Digital Ocean (among many others) allow API based access for developers to build custom services.

Our product needed to enable the following capability:

We needed:

To understand these requirements in technical terms, we first need to understand our tech stack. We are using the following services

Cognito provides a User Pool to manage users. Users logging in via a UI would be authenticated by Cognito and all requests to the API would now have a bearer token. The bearer token contains the Cognito username or the user’s email. Our code thereby authorizes the call to operate only within that user scope.

The AWS API gateway allows access to authenticated APIs via the use of app client id/secret. However, these id/secret pairs only determine whether a call to the API passes through to the code or results in an Unauthorized or Forbidden HTTP error. Cognito does not enable any way to link an app to a Cognito user. Hence, no user-level information is associated with successful calls using the client id/secret. Thus, any additional authorization such as access to a specific user scope by our code is directly not possible when using these API keys.

So, what we needed to do is to programmatically allow the creation, update, delete, and query of a two-way mapping of users and client id. Given a client id, we need to determine which user this client id authorizes. Similarly, given a Cognito Username, we need to create, obtain, reset the client id/secret associated with that user.

Usually, such a use-case would require writing a custom Lambda authorizer. But can also be done using AWS Cognito Authorizer as outlined below.

A mapping database

We start by creating a database mapping a three-way database mapping in our codebase. Conceptually it is a simple table (let’s call it ID_Mapping_Table) with the following schema and indexes on each of the fields

ID_Mapping_Table

This table has 3 fields:

When users are added/provisioned in our system, we ensure that their Internal User_id and their Cognito Username are stored in this table.

API Methods

To support app client id/secret, we provide the following API endpoints:

Decorator

We have a Python decorator that is associated with all authenticated calls. The decorator performs the following tasks:

With this approach, we have enabled user-based access control via direct authenticated use of app client ids and secrets.

Originally published at https://www.ignitesol.com on July 27, 2020.

--

--

Our thoughts and practices on design, technology, culture. We help startups design and build their technology. https://ignitesol.com.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ignite Solutions

Our thoughts and practices on design, technology, culture. We help startups design and build their technology. https://ignitesol.com.