@loopback/docs
Version:
Documentation for LoopBack 4
167 lines (117 loc) • 5.17 kB
Markdown
# @loopback/authorization
A LoopBack 4 component for authorization support.
## Overview
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)
2. 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:
```ts
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:
```ts
const options: AuthorizationOptions = {
precedence: AuthorizationDecisions.DENY;
defaultDecision: AuthorizationDecisions.DENY;
}
const binding = app.component(AuthorizationComponent);
app.configure(binding.key).to(options);
```
## Installation
```shell
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.
```ts
import {inject} from '@loopback/context';
import {authorize} from '@loopback/authorization';
import {get} from '@loopback/rest';
export class MyController {
@authorize({allow: ['ADMIN']})
@get('/number-of-views')
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
https://github.com/strongloop/loopback-next/tree/security/packages/security
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 https://github.com/strongloop/loopback-next/pull/1205_). 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`.
## Related resources
## Contributions
- [Guidelines](https://github.com/strongloop/loopback-next/blob/master/docs/CONTRIBUTING.md)
- [Join the team](https://github.com/strongloop/loopback-next/issues/110)
## Tests
run `npm test` from the root folder.
## Contributors
See
[all contributors](https://github.com/strongloop/loopback-next/graphs/contributors).
## License
MIT