Core
Guides v2.x
2

Authentication Strategy #

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.


Exposing authenticators #

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

There are two ways of registering new strategies:

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

ArgumentsTypeDescription
config
object
Authentication strategy configuration
methods
object
List of exposed methods

Statically register strategies #

Plugins can declare a strategies object which contains the authentication strategies to register.
This object will be interpreted by Kuzzle only once, immediately after this plugin's init function has resolved.
Each key of this object is the name of the strategy to register and the value is the strategy object containing config and methods properties.

For example, to register a strategy named local with the Local authenticator:

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

this.strategies = {
  local: {
    config: {
      authenticator: 'Local'
    },
    // these methods must be exposed by the plugin 
    methods: {
      create: 'create',
      delete: 'delete',
      exists: 'exists',
      getById: 'getById',
      getInfo: 'getInfo',
      search: 'search',
      update: 'update',
      validate: 'validate',
      verify: 'verify'
    }
  }
}

Dynamically register strategies #

Strategies can be register at runtime with the PluginStrategy.add method.

Strategies added dynamically in the plugin's init method are added to the static strategies object and loaded by Kuzzle after the plugin initialization.

config #

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

ArgumentsTypeDescription
authenticator
string
One of the exposed authenticators name
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

Strategy Methods #

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

ArgumentsTypeDescription
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
search
string
(optional) The name of the exposed search 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);

ArgumentsTypeDescription
requestKuzzleRequestAPI 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);

ArgumentsTypeDescription
requestKuzzleRequestAPI 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);

ArgumentsTypeDescription
requestKuzzleRequestSource 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);

ArgumentsTypeDescription
requestKuzzleRequestSource 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);

ArgumentsTypeDescription
requestKuzzleRequestSource 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, ...)

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

payload #

The payload object has the following properties:


PropertiesTypeDescription
originalKuzzleRequestSource 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:


PropertiesTypeDescription
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);

ArgumentsTypeDescription
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);

ArgumentsTypeDescription
requestKuzzleRequestThe 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);

ArgumentsTypeDescription
requestKuzzleRequestThe 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.


Given a credentials related search query, returns matched users' kuid.

If this function is not implemented, a missing_optional_method error occurs.

Beware of which properties are searchable. It would be unsafe to let the password be a search criteria, isn't it?

Arguments #

search(searchBody, options);

ArgumentsTypeDescription
searchBodyElasticSearch Query DSLA query concerning the authentication strategy credentials
options{ from?: number, size?: number }Search options useful for paginations

Returned value #

The search function must return a promise, resolving to an search result with the following properties:

  • hits: Array of matched users. Each hit has the following properties:
    • kuid: Users unique identifier
    • ...: Non sensitive credentials specific to this authentication strategy
  • total: Total of matched users.

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


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: ...'
    });
  }
}