Page Contents

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:

src/controllers/who-am-i.controller.ts

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';
  }
}

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.