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.
- :octocat: Github
- 🌍 Website
- 📚 Documentation
Compatibility matrix #
Kuzzle Version | Plugin Version |
---|---|
>= 2.17.3 | 1.x.x |
>= 2.42.0 | 2.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:
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
{
"plugins": {
"keycloak": {
"issuer": "https://keycloak/realms/example",
"adminUrl": "https://keycloak/admin/realms/example",
"clientId": "kuzzle-backend",
"clientSecret": "fBw6BYE...zIej5D87C",
"callbackURL": ["http://localhost:3000"]
}
}
}
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:
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);
OpenID Protocol Overview #
Key Components #
- End User: The person trying to access a service
- Relying Party (RP): The application/website requesting authentication
- OpenID Provider (OP): The identity provider that authenticates the user
- ID Token: A JWT (JSON Web Token) containing user information
Flow description #
- User attempts to access a protected resource on the Relying Party
- RP redirects user to the OpenID Provider
- User authenticates with the OP
- OP generates an ID Token and authorization code
- User is redirected back to RP with the tokens
- RP validates the tokens and grants access
User Profile Attribution #
Once a user connects to Kuzzle using one of the provided strategies, the user will be granted with each profiles returned by the ProfileExtractor that is starting with kuzzleprofile-
. Each entry not starting with kuzzleprofile-
will be ignored.
Returned profiles starting with kuzzleprofile-
should always match Kuzzle profiles. As an example if you have a profile named visitor
, the ProfileExtractor should return a list of profiles containing kuzzleprofile-visitor
.
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 #
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 #
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);