Skip to content

Commit 757ee16

Browse files
committed
feat(authorization): add authorize.skip to skip authorization
1 parent 8d21834 commit 757ee16

File tree

5 files changed

+42
-1
lines changed

5 files changed

+42
-1
lines changed

packages/authorization/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,27 @@ export class MyController {
118118
}
119119
```
120120

121+
Please note that `@authorize` can also be applied at class level for all methods
122+
within the class. In the code below, `numOfViews` is protected with
123+
`BasicStrategy` (inherited from the class level) while `hello` does not require
124+
authorization (skipped by `@authorize.skip`).
125+
126+
```ts
127+
@authorize({allow: ['ADMIN']})
128+
export class MyController {
129+
@get('/number-of-views')
130+
numOfViews(): number {
131+
return 100;
132+
}
133+
134+
@authorize.skip()
135+
@get('/hello')
136+
hello(): string {
137+
return 'Hello';
138+
}
139+
}
140+
```
141+
121142
## Extract common layer(TBD)
122143

123144
`@loopback/authentication` and `@loopback/authorization` shares the client

packages/authorization/src/__tests__/unit/authorize-decorator.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ describe('Authentication', () => {
155155
});
156156
});
157157

158+
it('can skip authorization with a flag', () => {
159+
class TestClass {
160+
@authorize.skip()
161+
getSecret() {}
162+
}
163+
164+
const metaData = getAuthorizationMetadata(TestClass, 'getSecret');
165+
expect(metaData).to.eql({skip: true});
166+
});
167+
158168
it('can stack decorators to target method', () => {
159169
class TestClass {
160170
@authorize.allow('a1', 'a2')

packages/authorization/src/authorize-interceptor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class AuthorizationInterceptor implements Provider<Interceptor> {
6868
debug('No authorization metadata is found for %s', description);
6969
}
7070
metadata = metadata || this.options.defaultMetadata;
71-
if (!metadata) {
71+
if (!metadata || (metadata && metadata.skip)) {
7272
debug('Authorization is skipped for %s', description);
7373
const result = await next();
7474
return result;

packages/authorization/src/decorators/authorize.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ export class AuthorizeMethodDecoratorFactory extends MethodDecoratorFactory<
8888
return list;
8989
}
9090
}
91+
9192
/**
9293
* Decorator `@authorize` to mark methods that require authorization
9394
*
@@ -191,6 +192,11 @@ export namespace authorize {
191192
* Deny unauthenticated users
192193
*/
193194
export const denyUnauthenticated = () => deny(UNAUTHENTICATED);
195+
196+
/**
197+
* Skip authorization
198+
*/
199+
export const skip = () => authorize({skip: true});
194200
}
195201

196202
/**

packages/authorization/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ export interface AuthorizationMetadata {
5858
* Define the access scopes
5959
*/
6060
scopes?: string[];
61+
/**
62+
* A flag to skip authorization
63+
*/
64+
skip?: boolean;
6165
}
6266

6367
/**

0 commit comments

Comments
 (0)