UNPKG

@loopback/authorization

Version:

A LoopBack component for authorization support.

196 lines (181 loc) 4.71 kB
// Copyright IBM Corp. and LoopBack contributors 2018,2020. All Rights Reserved. // Node module: @loopback/authorization // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT import {BindingAddress, InvocationContext} from '@loopback/core'; import {Principal, Role} from '@loopback/security'; /** * Built-in roles */ export const EVERYONE = '$everyone'; export const AUTHENTICATED = '$authenticated'; export const UNAUTHENTICATED = '$unauthenticated'; export const ANONYMOUS = '$anonymous'; /** * Decisions for authorization */ export enum AuthorizationDecision { /** * Access allowed */ ALLOW = 'Allow', /** * Access denied */ DENY = 'Deny', /** * No decision */ ABSTAIN = 'Abstain', } /** * Authorization metadata supplied via `@authorize` decorator */ export interface AuthorizationMetadata { /** * Roles that are allowed access */ allowedRoles?: string[]; /** * Roles that are denied access */ deniedRoles?: string[]; /** * Voters that help make the authorization decision */ voters?: (Authorizer | BindingAddress<Authorizer>)[]; /** * Name of the resource, default to the method name */ resource?: string; /** * Define the access scopes */ scopes?: string[]; /** * A flag to skip authorization */ skip?: boolean; } /** * Request context for authorization */ export interface AuthorizationContext { /** * An array of principals identified for the request - it should come from * authentication */ principals: Principal[]; /** * An array of roles for principals */ roles: Role[]; /** * An array of scopes representing granted permissions - usually come from * access tokens */ scopes: string[]; /** * An name for the target resource to be accessed, such as * `OrderController.prototype.cancelOrder` */ resource: string; /** * Context for the invocation */ invocationContext: InvocationContext; } /** * A function to decide if access to the target should be allowed or denied */ export type Authorizer< T extends AuthorizationMetadata = AuthorizationMetadata, > = /** * @param context: Context information for authorization * @param metadata: Metadata representing requirements for authorization */ ( context: AuthorizationContext, metadata: T, ) => Promise<AuthorizationDecision>; /** * Inspired by https://github.com/casbin/node-casbin */ export interface AuthorizationRequest { /** * The domain (realm/tenant) */ domain?: string; /** * The requestor that wants to access a resource. */ subject: string; /** * The resource that is going to be accessed. */ object: string; /** * The operation that the requestor performs on the resource. */ action: string; } /** * An enforcer of authorization policies */ export interface Enforcer { /** * Extract the request from authorization context * @param authorizationContext */ buildRequest( authorizationContext: AuthorizationContext, ): Promise<AuthorizationRequest>; /** * Decide if the request can be granted access * @param request */ enforce(request: AuthorizationRequest): Promise<AuthorizationDecision>; } /** * The custom error class that describes the error thrown by * the authorization module. * Should be extracted to the common layer shared by authentication * and authorization. */ export class AuthorizationError extends Error { /** * Machine readable code, can be understood by any clients */ code?: string; /** * The status code for HTTP requests */ statusCode?: number; } export interface AuthorizationOptions { /** * Default decision if all authorizers vote for ABSTAIN * If not set, default to `AuthorizationDecision.DENY` */ defaultDecision?: AuthorizationDecision.DENY | AuthorizationDecision.ALLOW; /** * Controls if Allow/Deny vote takes precedence and override other votes. * If not set, default to `AuthorizationDecision.DENY`. * * Once a vote matches the `precedence`, it becomes the final decision. The * rest of votes will be skipped. */ precedence?: AuthorizationDecision.DENY | AuthorizationDecision.ALLOW; /** * Default authorization metadata if a method is not decorated with `@authorize`. * If not set, no authorization will be enforced for those methods that are * not associated with authorization metadata. */ defaultMetadata?: AuthorizationMetadata; /** * Default HTTP status code when the final decision is `AuthorizationDecision.DENY`. * If not set, default to 403 */ defaultStatusCodeForDeny?: number; }