Authentication Decorator
Syntax:
- single strategy:
@authenticate(strategyName)
- multiple strategies:
@authenticate(strategyName1, strategyName2)
- single strategy with options:
@authenticate({ strategy: strategyName, options: {option1: 'value1', option2: 'value2'} })
- multiple strategies with options:
@authenticate({ strategy: strategyName1, options: {option1: 'value1'} }, { strategy: strategyName2, options: {option2: 'value2'} })
To mark a controller method as needing an authenticated user, the decorator requires one or more strategies.
Method Level Decorator
Here’s an example using ‘BasicStrategy’: to authenticate user in function
whoAmI
:
import {inject} from '@loopback/core';
import {securityId, SecurityBindings, UserProfile} from '@loopback/security';
import {authenticate} from '@loopback/authentication';
import {get} from '@loopback/rest';
export class WhoAmIController {
constructor(@inject(SecurityBindings.USER) private user: UserProfile) {}
@authenticate('BasicStrategy')
@get('/whoami')
whoAmI(): string {
return this.user[securityId];
}
}
Class Level Decorator
To configure a default authentication for all methods within a class,
@authenticate
can also be applied at the class level. In the code below,
whoAmI
is protected with BasicStrategy
even though there is no
@authenticate
is present for the method itself. The configuration is inherited
from the class. The hello
method does not require authentication as it’s
skipped by @authenticate.skip
.
@authenticate('BasicStrategy')
export class WhoAmIController {
constructor(@inject(SecurityBindings.USER) private user: UserProfile) {}
@get('/whoami')
whoAmI(): string {
return this.user[securityId];
}
@authenticate.skip()
@get('/hello')
hello(): string {
return 'Hello';
}
}
Note: If only some of the controller methods are decorated with the @authenticate decorator, then the injection decorator for SecurityBindings.USER in the controller’s constructor must be specified as @inject(SecurityBindings.USER, {optional:true}) to avoid a binding error when an unauthenticated endpoint is accessed. Alternatively, do not inject SecurityBindings.USER in the controller constructor, but in the controller methods which are actually decorated with the @authenticate decorator. See Method Injection, Constructor Injection and Optional Dependencies for details.
For more information on authentication with LoopBack, visit here.
Multiple Strategies
@authenticate()
can takes in more than one strategy. For example:
import {inject} from '@loopback/core';
import {securityId, SecurityBindings, UserProfile} from '@loopback/security';
import {authenticate} from '@loopback/authentication';
import {get} from '@loopback/rest';
export class WhoAmIController {
constructor(@inject(SecurityBindings.USER) private user: UserProfile) {}
@authenticate('BasicStrategy', 'JWTStrategy')
@get('/whoami')
whoAmI(): string {
return this.user[securityId];
}
}
The logic on how the strategies are executed is similar to how passport.js does it:
- The authentication strategies will be executed in the provided order.
- If at least one authentication strategy succeeds, the request will be further processed without throwing an error.
- Once a strategy succeeds or redirects, all subsequent strategies will not be evaluated.
- If all strategies fail, an error will be thrown with the error message of the first provided strategy.
Note: It is not feasible to use multiple strategies that redirect (e.g. OAuth login redirects) since the first redirect will halt the execution chain.