Strategies

Plugins can add new authentication strategies to Kuzzle.
For example, our official OAUTH2 Authentication plugin adds OAUTH2 support to Kuzzle.

All authentication strategies supported by Passport.js can be integrated to Kuzzle.


Registering authentication strategies

Passport.js provides a wide range of authentication strategies.
Custom authentication strategies can also be implemented by subclassing the abstract Passport Strategy class.

To register strategies to Kuzzle, a authenticators object property must be exposed by the plugin, for instance:

this.authenticators = {
  Local: require('passport-local'),
  Oauth2: require('passport-oauth2')
};

Credentials security

User credentials are very sensitive data, and these must be properly isolated to prevent security vulnerabilities.
To do so, Kuzzle guarantees that it never interprets, modifies, or stores credentials information.

Instead, Kuzzle:

  • provides a global user unique identifier (referred from now on as the user's kuid), giving the possibility to a user to authenticate with multiple strategies
  • entrusts implemented strategies with credentials protection, validation, verification and storage

Managing credentials

There are two ways of interfacing credentials management:

  • statically, by exposing a strategies object
  • dynamically, by using the dedicated strategy accessors

Whether strategies are added statically or dynamically, the strategies object must expose the following properties:

Arguments Type Description
config
object
Authentication strategy configuration
methods
object
List of exposed methods

config

The config part of the strategies object can contain the following properties:

Arguments Type Description
authenticator
string
One of the exposed authenticators name
constructor
object

Deprecated since v1.4.0

(use the authenticator property instead)
The constructor of the Passport.js strategy. Does not support dynamic strategy registration
authenticateOptions
object
(optional) Additional options to be provided to the Passport's authenticate method
fields
string[]
(optional) The list of accepted field names by the strategy credentials.
The list is informative only, meant to be used by the getAllCredentialFields and the getCredentialFields API methods
strategyOptions
object
(optional) Options provided to the Passport.js strategy constructor

methods

The methods part of the strategies object can contain the following properties:

Arguments Type Description
create
string
The name of the exposed create function
delete
string
The name of the exposed delete function
exists
string
The name of the exposed exists function
update
string
The name of the exposed update function
validate
string
The name of the exposed validate function
verify
string
The name of the exposed verify function
afterRegister
string
(optional) The name of the exposed afterRegister function
getById
string
(optional) The name of the exposed getById function
getInfo
string
(optional) The name of the exposed getInfo function

Even though each strategy must declare its own set of properties, the same strategy method can be used by multiple strategies.


create

The create function adds credentials to a user.

For security reasons, plugins are entirely responsible of how credentials are managed, storage included: Kuzzle does not read, modify, or store credentials.

If needed, Kuzzle exposes a secure and isolated storage space for each plugin. It can be accessed using the Repository constructor.

Arguments

create(request, credentials, kuid, strategy)

Arguments Type Description
request
Request
API request asking for the credentials creation
credentials
object
New credentials to create, already validated by this strategy's validate function
kuid
string
User's kuid
strategy
string
Authentication strategy used by these credentials

Returned value

The create function must return a promise, resolving to an object. The content of that object depends on this authentication strategy; usually a feedback about the created credentials is expected. That object can be left empty.

The object resolved by the promise is directly forwarded to the originating user. For security reasons, it must only contain non sensitive information.

delete

The delete function deletes a user's credentials.

Arguments

delete(request, kuid, strategy)

Arguments Type Description
request
Request
API request asking for the credentials deletion
kuid
string
User's kuid
strategy
string
Authentication strategy name

Returned value

The delete function must return a promise. The resolved value is not used.


exists

The exists function checks whether a user is known to the authentication strategy.

Arguments

exists(request, kuid, strategy)

Arguments Type Description
request
Request
Source API request
kuid
string
User's kuid
strategy
string
Authentication strategy name

Returned value

The exists function must return a promise, resolving to a boolean representing the result of the user existence check.


update

The update function updates a user's credentials.

Arguments

update(request, credentials, kuid, strategy)

Arguments Type Description
request
Request
Source API request
credentials
object
Updated credentials.
Those are already validated by this strategy's validate function
kuid
string
User's kuid
strategy
string
Authentication strategy name

Returned value

The update function must return a promise, resolving to an object. The content of that object depends on this authentication strategy; usually a feedback about the updated credentials is expected. That object can be left empty.

The object resolved by the promise is directly forwarded to the originating user. For security reasons, it must only contain non sensitive information.

validate

The validate function verifies that credentials are well-formed.

Arguments

validate(request, credentials, kuid, strategy, isUpdate)

Arguments Type Description
request
Request
Source API request
credentials
object
Credentials to validate
kuid
string
User's kuid
strategy
string
Authentication strategy name
isUpdate
boolean
Tells whether the request is a credentials update. In the case of an update, the credentials object may only contain changes to be applied, instead of a complete credentials description

Returned value

The function validate must return a promise. The resolved value, if there is one, is ignored.


verify

The verify function authenticates a user.

The number of arguments taken by the verify function depends on the authentication strategy.
For instance, a local authentication strategy requires that the verify function validates both a user name and a password, so these two arguments will have to be provided to the verify function.

Arguments

verify(payload, ...)

Arguments Type Description
payload
object
Login request made to passport
...
*
Additional arguments; depends on the authentication strategy

payload

The payload object has the following properties:


Properties Type Description
original
Request
Source API login request
query
object
Direct link to original.input.args, containing the optional request arguments
body
object
Direct link to original.input.body, containing the request body content

Returned value

The verify function must return a promise, resolving to an object with the following properties:


Properties Type Description
kuid
string
If the authentication succeeds, this property must be set to the user's kuid. Otherwise, this must be set to null
message
string
If kuid is set to null (authentication failed), this optional property can be set with a rejection reason
A failed authentication is not an error. The returned promise should only be rejected if an actual error occurs.

(optional) afterRegister

The afterRegister function is called when the Passport.js strategy is instantiated by Kuzzle.

Arguments

afterRegister(strategyInstance)

Arguments Type Description
strategyInstance
object
The Passport.js strategy instance

(optional) getById

The getById function returns credentials information using the authentication strategy's user identifier (which may not be the kuid).

If this function is not implemented, an empty object is returned by Kuzzle instead.

The returned information can be forwarded to users. For security reasons, it must only contain non sensitive information.

Arguments

getById(request, id, strategy)

Arguments Type Description
request
Request
The API request asking for credentials information
id
string
Strategy's user identifier
strategy
string
Authentication strategy name

Returned value

The getById function must return a promise, resolving to an object containing credentials information. It can be left empty.


(optional) getInfo

The getInfo function returns information about a user's credentials.

If this function is not implemented, an empty object is returned by Kuzzle instead.

The returned information can be forwarded to users. For security reasons, it must only contain non sensitive information.

Arguments

getInfo(request, kuid, strategy)

Arguments Type Description
request
Request
The API request asking for credentials information
kuid
string
User's kuid
strategy
string
Authentication strategy name

Returned value

The getInfo function must return a promise, resolving to an object containing credentials information. It can be left empty.


Example

module.exports = class AuthenticationPlugin {
  constructor() {}

  /**
    Required plugin initialization function
    (see the "Plugin prerequisites" section)
   */
  init (customConfig, context) {
    this.authenticators = {
      StrategyConstructor: require('some-passport-strategy')
    };

    this.strategies = {
      '<strategy name>': {
        config: {
          // Must be declared in this.authenticators
          authenticator: 'StrategyConstructor',

          // The list of fields that have to be provided in the credentials
          fields: ['login', 'password']
        },
        methods: {
          create: 'create',
          delete: 'delete',
          exists: 'exists',
          update: 'update',
          validate: 'validate',
          verify: 'verify'
        }
      }
    };
  }

  /**
   * Stores the provided credentials 
   * Must keep a link between the persisted credentials
   * and the kuid
   */
  create (request, credentials, kuid) {
    // store credentials
    return Promise.resolve({/* non sensitive credentials info */});
  }

  /**
   * Removes the user's stored credentials from
   * the plugin persistence layer
   */
  delete (request, kuid) {
    // remove credentials
    return Promise.resolve();
  }

  /**
   * Checks if user's credentials exist in the persistence layer
   */
  exists (request, kuid) {
    // check credentials existence
    return Promise.resolve(/* boolean value */);
  }

  /**
   * Updates the user's credentials information in the
   * persistence layer
   *
   * @param {KuzzleRequest} request
   * @param {object} credentials
   * @param {string} kuid
   * @returns {Promise<object>}
   */
  update (request, credentials, kuid) {
    // update credentials
    return Promise.resolve(/* non sensitive credentials info */);
  }

  /**
   * Validates credentials against the strategy rules 
   * (required fields, password strength, username uniqueness, ...)
   */
  validate (request, credentials, kuid, strategy, isUpdate) {
    // validate credentials
    return Promise.resolve(/* true|false */);
  }

  /**
   * Returns an object with the authenticated user id if successful,
   * and a reason if the authentication fails
   */
  verify (request, ...credentials) {
    const kuid = /* authentification */;

    if (kuid) {
      return Promise.resolve({kuid});
    }

    return Promise.resolve({
      kuid: null,
      message: 'Login failed - You shall not pass! Reason: ...'
    });
  }
}