Page Contents


A LoopBack 4 component for authorization support.


Authorization decides if a subject can perform specific action on an object.


Role based

Permission based

Vote based

Key building blocks

  1. Decorate a method to describe:
  • Permission (maps the method to an action on the protected resource)

    • Type of the protected resource (such as customer or order)
    • What action does the method represent (such as changeEmail, createOrder, or cancelOrder)
  • ACL (provides role based rules)

    • allowedRoles
    • deniedRoles
  • Voters (supplies a list of function to vote on the decision)

  1. Intercept a method invocation
  • Build authorization context

    • Subject (who) - from authentication
    • Map principals to roles
    • Inspect the target method for metadata - Permission, ACL, voters
  • Run through voters/enforcers to make decisions

Decision matrix

The final decision is controlled by voting results from authorizers and options for the authorization component.

The following table illustrates the decision matrix with 3 voters and corresponding options.

Vote #1 Vote # 2 Vote #3 Options Final Decision
Deny Deny Deny any Deny
Allow Allow Allow any Allow
Abstain Allow Abstain any Allow
Abstain Deny Abstain any Deny
Deny Allow Abstain {precedence: Deny} Deny
Deny Allow Abstain {precedence: Allow} Allow
Allow Abstain Deny {precedence: Deny} Deny
Allow Abstain Deny {precedence: Allow} Allow
Abstain Abstain Abstain {defaultDecision: Deny} Deny
Abstain Abstain Abstain {defaultDecision: Allow} Allow

The options is described as follows:

export interface AuthorizationOptions {
   * Default decision if all authorizers vote for ABSTAIN
  defaultDecision?: AuthorizationDecision.DENY | AuthorizationDecision.ALLOW;
   * Controls if Allow/Deny vote takes precedence and override other votes
  precedence?: AuthorizationDecision.DENY | AuthorizationDecision.ALLOW;

The authorization component can be configured with options:

const options: AuthorizationOptions = {
  precedence: AuthorizationDecisions.DENY;
  defaultDecision: AuthorizationDecisions.DENY;

const binding = app.component(AuthorizationComponent);


npm install --save @loopback/authorization

Basic use

Start by decorating your controller methods with @authorize to require the request to be authorized.

In this example, we make the user profile available via dependency injection using a key available from @loopback/authorization package.

import {inject} from '@loopback/context';
import {authorize} from '@loopback/authorization';
import {get} from '@loopback/rest';

export class MyController {
  @authorize({allow: ['ADMIN']})
  numOfViews(): number {
    return 100;

Extract common layer(TBD)

@loopback/authentication and @loopback/authorization shares the client information from the request. Therefore we need another module with types/interfaces that describe the client, like principles, userProfile, etc… A draft PR is created for this module: see branch

Since the common module is still in progress, as the first release of @loopback/authorization, we have two choices to inject a user in the interceptor:

  • @loopback/authorization requires @loopback/authentication as a dependency. The interceptor injects the current user using AuthenticationBindings.CURRENT_USER. Then we remove this dependency in the common layer PR, two auth modules will depend on @loopback/security.

    • This is what’s been done in my refactor PR, Principle and UserProfile are still decoupled, I added a convertor function to turn a user profile into a principle.
  • The interceptor injects the user using another key not related to @loopback/authentication.(Which means the code that injects the user stays as it is in Then we unify the user set and injection in the common layer PR: same as the 1st choice, two auth modules will depend on @loopback/security.



run npm test from the root folder.


See all contributors.