Per-Customer Access Control using Indent API

7 months ago
Written by
Fouad Matin
@fouadmatin

Per-Customer Access Control is essentially a way of ensuring the principle of least privilege (PoLP) in the context of employee access to customer data.

It's the practice of limiting access rights for users to the bare minimum permissions they need to perform their work.

Imagine a bank where employees can only access the accounts relevant to their role. A teller can manage cash transactions but can't authorize a loan - they simply don't have the "key" to that information.

The same principle applies to customer data in a digital environment. An employee in the sales team shouldn't have access to sensitive personal customer information that is unnecessary for them to perform sales tasks. Least privilege access reduces the risk of internal data breaches and prevents the misuse of privileged data.

More importantly, it helps maintain customer trust, as it ensures their data isn't exposed unnecessarily.

While it may seem like more administrative effort, the efficiency and safety paybacks can be substantial. Consider it the ultimate spring clean - getting rid of access that is no longer needed while being fundamentally aware of who has access to what data!

Per-customer access architecture

Here's how managing per-customer access with Indent works:

  1. List customers from our database
  2. Create a resource for each customer in Indent
  3. Provision when a user is granted or revoked access to a customer
  4. Create a petition to request access to a customer

There's a few different options for how provisioning can work:

  • Group-based: create a group or role in your identity provider for each customer and add users to the group (CustomerAccess_123)
  • Attribute-based: add a customer attribute to each user in your identity provider that can be used to filter customer access (assigned_customers=[123])
  • Webhook-based: create a webhook that is called when a user is granted or revoked access to a customer

We're going to use a custom webhook because it's the most flexible and we can use our existing production access control system rather than a side door.

The webhook will be called once access is granted. After the access time period expires, the webhook will be called again with the access/revoke event and access will be cleaned up. That's it!

Upload customers as Indent resources

First, we'll upload our customers as Indent resources. We'll use the Indent API to create a new resource for each customer.

npm install @indent/api

Next, we'll need to list our customers from our database. We'll use the following query to list all customers:

select id, name, plan from customers;

We can write a script using @indent/api to bulk upload them:

import { IndentAPI } from '@indent/api'
import sql from './sql' // or some SQL client
const indent = new IndentAPI({
spaceName: process.env.INDENT_SPACE,
apiToken: process.env.INDENT_API_TOKEN
})
async function upload() {
const customers = await sql`select id, name, plan from customers;`
await indent.resource.bulkUpdate({
resources: customers.map(c => ({
kind: 'customer',
id: c.id,
displayName: c.name,
labels: { plan: c.plan }
}))
})
}
upload()

These resources will now show up in the Indent API:

> await indent.resource.list()
[{ kind: 'customer', displayName: 'AcmeCorp', ... }, ...]

Next we'll need to handle when access is granted and revoked.

Grant access on a per-customer basis

We'll need to create a webhook in Indent that will be called when a user is granted or revoked access to a customer.

Follow these steps to do that:

  1. Create a webhook in the Indent dashboard
  2. Copy the webhook secret and add to environment as INDENT_WEBHOOK_SECRET

Next we'll need to create a webhook handler that will be called when a user is granted or revoked access to a customer.

We'll use the Indent Webhook SDK to verify the webhook signature and handle the event:

import { verify } from '@indent/webhook'
import { Request, Response } from 'express'
import { Event as AuditEvent } from '@indent/types' // for TypeScript
export default async function(req: Request, res: Response) {
try {
const body = await json(req)
await verify({
secret: process.env.INDENT_WEBHOOK_SECRET,
headers: req.headers,
body: req.body
})
const { events } = body
await Promise.all(
events.map((auditEvent: AuditEvent) => {
let { actor, event, resources } = auditEvent
switch (event) {
case 'access/grant':
return grantPermission(auditEvent)
case 'access/revoke':
return revokePermission(auditEvent)
default:
return Promise.resolve()
}
})
)
res.send(200, '{}')
} catch (err) {
res.send(
200,
JSON.stringify({ error: { message: err.message, stack: err.stack } })
)
}
}
async function grantPermission({ event, actor, resources }: AuditEvent) {
// TODO: Grant permission
/*
* {
* "event": "access/grant",
* "actor": { "email": "[email protected]" },
* "resources": [ grantedUser, grantedResource ]
* }
*/
}
async function revokePermission({ event, actor, resources }: AuditEvent) {
// TODO: Revoke permission
/*
* {
* "event": "access/revoke",
* "actor": { "email": "[email protected]" },
* "resources": [ revokedUser, revokedResource ]
* }
*/
}

Once this webhook is deployed and configured in Indent, we can start granting and revoking access to customers.

Request approval via Indent API

You can also request approval on behalf of your team via the Indent API. This is useful if your team uses an internal admin panel or a tool system like Retool. Use the API to create petitions like this:

import { IndentAPI } from '@indent/api'
const indent = new IndentAPI({
spaceName: process.env.INDENT_SPACE,
apiToken: process.env.INDENT_API_TOKEN
})
const petition = await indent.petition.create({
actor: { kind: 'support-agent', email: '[email protected]' },
resources: [{ kind: 'customer', id: '123' }]
reason: 'to debug BUG-482',
})
// retry checking the petition until approved or timeout
await indent.petition.waitFor({ petitionName: petition.name })

Next steps

This is just the beginning. There's a lot more you can do with Indent to manage temporary access to customers:

  1. Auto approvals for on-call teams or assigned support agents
  2. Geo-restrictions for access based on security and compliance
  3. Grant least privilege roles per customer (e.g. admin vs readonly)

Ready to start managing per-customer access control?

Check out Indent and get a demo

Try Indent for free.