Skip to content

Improve multi-tenant security #8260

@ricardopieper

Description

@ricardopieper

Describe the feature request

I wish the frontend SDKs were not be able to change their context at will.
Or make it clear in the docs when you cannot use the client SDKs.

Background

Hello, we are studying whether we will adopt Unleash or not in our application.

We have a multi-tenant application, where tenants cannot see the data of another tenant in any way. This includes the feature toggle state.

We use the feature toggles both in our backend and frontend. The backend uses toggles to change the way we do certain things, while in the frontend we use it to conditionally render things. So we don't do anything crazy with it.

Our customers are very sensitive to security breaches (most of them are banking/finance) and we are under constant scrutiny from red teams, both our own and from our customers.

The docs suggest this is the way to segment users by tenant using the SDK:

const unleash = new UnleashClient({
    url: 'https://<your-unleash-instance>/api/frontend',
    clientKey: '<your-client-side-token>',
    appName: 'my-webapp',
});

//...

unleash.setContextField('tenantId', 'SomeTenantId');

In this case, client is in complete control of their own segmentation. We consider it to be a data breach if the user of tenant X can successfully check if another tenant has some feature enabled.

Our in-house feature toggle system today is very bad, but it is secure: the toggle state of one tenant never leaks to another tenant.

One way is to use an unguessable tenant ID but then it becomes more cumbersome to handle things in the UI.

The way I see it, the only way to use Unleash for us is to do the entire thing in our backend, and expose a route that the frontend clients can use to check that a certain feature toggle is enabled.

Am I missing something in the docs that addresses this or should we just do everything in the backend?

Solution suggestions

I didn't think too hard about it, so I don't know if they make sense or not.

Solution 1: Per-Tenant clientKey:

The SDK could be initialized with a different clientKey for each tenant. Using the unleash API, we could associate a client key with certain context properties that cannot be overwritten by the client. The app backend must return an appropriate clientKey for the frontend to initialize the client.

Solution 2: Predefined contexts identified by a key:

A separate unguessable key that you use to initialize the client. In Unleash, you define these keys and their context. Again the app backend is responsible for returning this key.

const unleash = new UnleashClient({
url: 'https:///api/frontend',
clientKey: '',
predefinedContextKey: await getUnleashPredefinedContextKey(), //does a request to the backend app
appName: 'my-webapp',
});

Maybe there are other solutions potentially leveraging Unleash Edge, but I can't think of one ATM.

Metadata

Metadata

Assignees

Type

No type

Projects

Status

For later

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions