Subject

All you need to know about defining and using the subject in Kilpi.


The subject represents the current user as well as any of their authorization-related data, such as permissions and memberships.

The current user is provided using the getSubject adapter to allow getting the subject from any system or authentication provider.

Defining a getSubject adapter

Implement your getSubject adapter by passing it to createKilpi. It should call your authentication system or provider and return any value that represents the current subject or e.g. null if there is no authenticated subject.

export const Kilpi = createKilpi({
async getSubject() {
const user = await myAuthenticationProvider.getCurrentUser();
if (!user) return null;
return { id: user.id, name: user.name };
},
// ...
});

The subject’s type is automatically inferred by your policies.


Passing a context argument

Commonly, your getSubject may require additional context (e.g. the current request).

export const Kilpi = createKilpi({
async getSubject(ctx?: Request) {
if (!ctx) return null;
const user = await myAuthenticationProvider.getCurrentUser(ctx);
if (!user) return null;
return { id: user.id, name: user.name };
},
// ...
});

You can then pass this ctx object when authorizing using the authorize() API.

await Kilpi.some.policy().authorize({ ctx: request });

Additional data

Very commonly, your subject has other authorization-related properties not received directly from your authentication provider. These include e.g. permissions, roles, and memberships. It is often practical and efficient to include them in your getSubject instead of fetching in policies.

export const Kilpi = createKilpi({
async getSubject(ctx?: Request) {
const user = await myAuthenticationProvider.getCurrentUser(ctx);
if (!user) return null;
const memberships = await db.listMembershipsForUser(user);
return { ...user, memberships };
},
// ...
});

Accessing the subject

To access the subject, you can get it from the result of authorize() when the decision is granted (or when using .assert()) or by using the Kilpi.$getSubject() utility.

const subject = await Kilpi.$getSubject();

Performance considerations and caching / deduping

Kilpi calls getSubject for you on every single authorize() call. Especially, if your getSubject is an expensive or slow function, you should consider caching it for each request (deduplicating).

This can be done in multiple ways, and some plugins (such as ReactServerPlugin) even automatically cache the subject for each request.