Skip to main content

General rules

It is crucial to be able to define good, unambiguous parameters for access query. Thanks for them Access Control might be as granular as you need and properly do its job without a lot of maintenance.

It is impossible to define all kind of principals, actions and subjects within a single package. Therefore, you should be creating as many options to define access query elements as needed.


The elements of Access Query must contain as many details as you need to perform checks on a policy level or policy must be able to retrieve that information

For example, based on the tutorial it is impossible to define access control policies based on IP address of the request. There is no such information in the query and Access Control Policy is not able to retrieve it somehow.

In order to achieve that you must inject that information to Principal somehow.

Let's redefine our principal then

// this needs to be obtained from a request somehow
export interface PrincipalMeta {
ipAddress: string;

export interface Principal {
wrapped: 'logged-in' | _Principal.Anonymous;
meta: PrincipalMeta

The way of obtaining principal also changes

function getWrappedPrincipalFromRequest(req: express.Request): Principal {
if (req.headers.authorization === 'itsme') {
return 'logged-in';
return _Principal.Anonymous.INSTANCE;

function getPrincipalFromRequest(req: express.Request) {
return {
wrapped: getWrappedPrincipalFromRequest(req),
meta: {
ipAddress: req.header('x-forwarded-for') || req.socket.remoteAddress

Example policy

.registerPolicy(({action, subject, principal}) => {
// anonymous user from private IP address class can read articles
if (_Principal.Anonymous.isType(principal.wrapped) && principal.meta.ipAddress.startsWith('10.0.0.')) {
return action === 'read' && subject === 'article';

The same rule applies to subject. If you need tenancy control you might need to include that information