Official Plugins (Kuzzle v2.x)
keycloak v1.x
2

About #

Kuzzle Keycloak Plugin #

This is the official Kuzzle Keycloak plugin.

This plugins allows you to connect to Kuzzle using Keycloak

Kuzzle #

Kuzzle is an open-source backend that includes a scalable server, a multiprotocol API, an administration console and a set of plugins that provide advanced functionalities like real-time pub/sub, blazing fast search and geofencing.

Compatibility matrix #

Kuzzle Version Plugin Version
>= 2.17.3 1.x.x

Installation #

To install this plugin on your Kuzzle stack (for each of your Kuzzle nodes), you will first need a Kuzzle Application like so. (see Getting Started)

Once you have it, you will need to:

  • Import the Keycloak plugin,
  • Create a new instance of the plugin
  • And then use it in your application.

You will end up with something like this:

Copied to clipboard!
import { Backend } from 'kuzzle';
import { PluginKeycloak } from 'kuzzle-plugin-keycloak'; // Import the keycloak auth plugin

const app = new Backend('kuzzle');

const pluginKeycloak = new PluginKeycloak(); // Create a new instance of the Keycloak plugin

app.plugin.use(pluginKeycloak); // Add the plugin to your application

app.start()
  .then(() => {
    app.log.info('Application started');
  })
  .catch(console.error);

Configure a Strategy #

You can find sample configuration files for this plugin in the example folder.

Example

Copied to clipboard!
{
  "plugins": {
    "keycloak": {
      "issuerAutoDiscover": true, // Auto discover issuer endpoint metadata
      "issuerConfig": { // See https://github.com/panva/node-openid-client/blob/main/docs/README.md#issuer
        "issuer": "http://localhost:8080/realms/myrealm"
      },
      "clientConfig": { // https://github.com/panva/node-openid-client/blob/main/docs/README.md#class-client
        "client_id": "myclient",
        // The url has the following format: http://<kuzzle host>/_login/<strategy>
        "redirect_uris": ["http://localhost:7512/_login/keycloak"],
        "response_type": "code",
        "token_endpoint_auth_method": "none"
      }
    }
  }
}

You can try your strategy by visiting http://<kuzzle host>/_login/keycloak

Configure multiple keycloak strategies #

Each strategy configured must have a unique name otherwise it might use the configuration of another strategy and cause an undefined behaviour.

By default when creating an instance of PluginKeycloak the strategy name is keycloak, so if you create another instance, the instance will have the same name by default which will create an undefined behaviour.

To avoid this, you can configure the strategy name when you are creating an instance of the PluginKeycloak like so:

Copied to clipboard!
import { Backend } from 'kuzzle';
import { PluginKeycloak } from 'kuzzle-plugin-keycloak'; // Import the keycloak auth plugin

const app = new Backend('kuzzle');

/**
 * Create a new instance of the Keycloak plugin
 * Since no strategyName has been configured the name of the strategy is defaulted to `keycloak`
 */
const pluginKeycloak = new PluginKeycloak();

// Create a new instance of the Keycloak plugin
const pluginKeycloakAdmin = new PluginKeycloak({
  strategyName: 'keycloak-admin' // Set the strategy name to `keycloak-admin`
});

app.plugin.use(pluginKeycloak); // Add the plugin to your application
app.plugin.use(pluginKeycloakAdmin, { name: 'keycloak-admin' }); // Add the plugin to your application and name it keycloak-admin

app.start()
  .then(() => {
    app.log.info('Application started');
  })
  .catch(console.error);

Strategy Config Properties #

issuerAutoDiscover #

Auto discover issuer endpoint metadata. When true you only need to specify the issuer in the issuerConfig

The client will try to retrieve metadata information from the endpoint using the .well-known endpoint if there is one.

For more informations see Issuer.discover.

issuerConfig #

Issuer metadata information, for a list properties see Issuer Metadata.

clientConfig #

Client metadata information, for a list properties see Client Metadata.

User Profile Attribution #

Once a user connects to Kuzzle using the Keycloak strategy, the user will be granted with each profiles based on the Keycloak Roles starting with kuzzleprofile-. Each role entry not starting with kuzzleprofile- will be ignored.

Keycloak Roles starting with kuzzleprofile- should always match Kuzzle profiles.

Import Keycloak user data #

Once a user connects to Kuzzle using the Keycloak strategy, Kuzzle will retrieve informations stored in the ID Token claims which are not OpenID attributes and put them inside the custom data of the Kuzzle user.

The plugin can be configured to include or exclude any attributes that should or should not be retrieved from the ID Token claims and be put inside the custom data of the Kuzzle user.

Include specific attributes inside Kuzzle user data #

Copied to clipboard!
import { Backend } from 'kuzzle';
import { PluginKeycloak } from 'kuzzle-plugin-keycloak'; // Import the keycloak auth plugin

const app = new Backend('kuzzle');

const pluginKeycloak = new PluginKeycloak({
  userdata: {
    mode: 'include',
    // Only include email, first_name and last_name fields inside the Kuzzle user's custom data
    includes: [ 'email', 'first_name', 'last_name' ]
  }
}); // Create a new instance of the Keycloak plugin

app.plugin.use(pluginKeycloak); // Add the plugin to your application

app.start()
  .then(() => {
    app.log.info('Application started');
  })
  .catch(console.error);

Exclude specific attributes from being included inside Kuzzle user data #

Copied to clipboard!
import { Backend } from 'kuzzle';
import { PluginKeycloak } from 'kuzzle-plugin-keycloak'; // Import the keycloak auth plugin

const app = new Backend('kuzzle');

const pluginKeycloak = new PluginKeycloak({
  userdata: {
    mode: 'exclude',
    // Exclude the social_security_number field from being stored inside the Kuzzle user's custom data.
    excludes: [ 'social_security_number' ]
  }
}); // Create a new instance of the Keycloak plugin

app.plugin.use(pluginKeycloak); // Add the plugin to your application

app.start()
  .then(() => {
    app.log.info('Application started');
  })
  .catch(console.error);

Community #