Nous allons aujourd’hui nous attarder sur comment sécuriser une api Node.js avec Keycloak. Dans ce tutoriel, vous découvrirez comment créer votre propre API avec Node.js. Nous utiliserons le framework Express pour la construction de notre API (et quelques autres outils)
FICHE TECHNIQUE
Keycloak : 7.0.0.Final
Node : 10.15.3.RELEASE
Express : 4.17.1
Pré-requis
- Git (pour récupérer les sources du projet)
- Node & NPM
- Keycloak installé (en local ou démarré via Docker) et paramétré
- Connaissance de base en Javascript
Cas concret
Imaginons que nous devions créer une API pour une application permettant de gérer plusieurs types d’utilisateurs. Cette application offre donc la possibilité de créer des groupes au sein desquels les utilisateurs auront différents droits.
L’utilisateur non inscrit n’accédera qu’à une partie de notre API L’utilisateur inscrit accédera à une partie supplémentaire de l’API et enfin l’administrateur lui aura l’accès à toute l’API.
Nous avons deux types de droits : USER et ADMIN.
Notre API disposera donc de 3 niveaux : les routes pour les personnes non inscrites, les routes pour les utilisateurs inscrits ( USER ) et enfin les routes pour les administrateurs ( ADMIN )
Les sources du projet sont disponibles ici
Mise en oeuvre
Etape 1 – initialisation de notre projet Node.js
Notre API Node.js suivra les standards ES6. La mise en place de Babel sera donc nécessaire.
Pour cette premiére étape nous allons créer un nouveau dossier pour notre API. Pour cela rendons-nous dans notre terminal :
mkdir api-keycloak && cd api-keycloak
Après cela nous pouvons initialiser notre projet avec :
npm init
Une série d’information sur notre projet nous sera demandé afin de générer un fichier package.json
:
{ "name": "api-keycloak", "version": "1.0.0", "description": "how to securise a Node API with Keycloak", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "christophe PARMENTIER", "license": "ISC" }
Nous avons défini le point d’entrée de notre API "main":"index.js"
à la racine de notre projet. Nous allons donc créer un fichier index.js
:
touch index.js
Nous pouvons dès à présent ouvrir notre éditeur favori.
Etape 2 – Installation des modules requis
Cette étape consiste à installer les modules javascript ( dependencies et devDependencies ) nécessaire à la création de notre API.
Voici la liste des dependencies :
- express : un micro-framework pour Node.js qui facilitera la création de notre API.
- body-parser : qui nous permettra de manipuler les requêtes que nous effectuerons.
Allons-y :
npm install --save express body-parser
À ce niveau notre package.json
ressemble à ceci :
{ "name": "api-keycloak", "version": "1.0.0", "description": "how to securise a Node API with Keycloak", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "christophe PARMENTIER", "license": "ISC", "dependencies": { "body-parser": "^1.19.0", "express": "^4.17.1" } }
Maintenant la liste des devDependencies :
- babel-cli : permet de compiler des fichiers avec une ligne de commande
- babel-preset-es2015 : ce qui nous permettra d’écrire notre API en ES6 !
npm install save-dev babel-cli babel-preset-es2015
Notre package.json
:
{ "name": "api-keycloak", "version": "1.0.0", "description": "how to securise a Node API with Keycloak", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "christophe PARMENTIER", "license": "ISC", "dependencies": { "body-parser": "^1.19.0", "express": "^4.17.1" }, "devDependencies": { "babel-cli": "^6.26.0", "babel-preset-es2015": "^6.24.1" } }
Préparer notre projet à ES6.
- À la racine de notre projet, créons un nouveau fichier de configuration Babel qui permettra à notre API de gérer l’ES6 :
touch .babelrc
- Ouvrons ce fichier et insérons ce code :
{ "presets": ["es2015"] }
- Dans notre
package.json
, ajoutons un nouveau script :
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "babel-node --presets es2015 index.js" },
Notre projet est prêt a être implémenté en ES6 !
Etape 3 – Création de notre server Node.js et de notre premiere route
Après tous ces préparatifs, entrons dans le vif du sujet : la création de notre serveur qui permettra de partager l’API.
- Ajoutons le contenu suivant au fichier
index.js
:
// Nous importons Express dans notre application import express from 'express'; // Notre Application utilisera express grace à cette ligne const app = express(); // Voici notre 1ere route app.get('/', function(req, res) { res.send('Welcome to home page'); }); // Si tout se passe bien notre application écoutera sur le port 3000 app.listen(3000, err => { if (err) { console.error(err); } { console.log(`APP Listen to port : 3000`); } });
Ces quelques lignes nous serviront à lancer notre serveur et afficher notre première page ! Pour cela dans notre terminal, faisons un : npm start
Notre console indique que notre APP est lancée et elle écoute sur le PORT 3000 : APP Listen to port : 3000
Lançons notre navigateur préféré et rendons-nous sur http://localhost:3000/
Ce dernier doit normalement afficher : Welcome to home page
C’est encore loin de ressembler à une API mais c’est un bon début !
Etape 4 – Mettre en place notre API
Maintenant créons nos 3 routes. Nous pouvons enlever la 1ere route que nous avons écrit à l’étape 4 :
app.get('/', function(req, res) { res.send('Welcome to home page'); });
- Importons body-parser :
import bodyParser from 'body-parser';
- et autorisons notre application à utiliser body-parser :
app.use(bodyParser.json());
- Créons la première route publique pour notre API (toutes nos routes commenceront par
/api/
) :
app.get('/api/unsecured', function(req, res) { res.json({ message: 'This is an unsecured endpoint payload' }); });
Notre fichier index.js
à ce stade du tutoriel :
import express from 'express'; import bodyParser from 'body-parser'; const app = express(); app.use(bodyParser.json()); app.get('/api/unsecured', function(req, res) { res.json({ message: 'This is an unsecured endpoint payload' }); }); app.listen(3000, err => { if (err) { console.error(err); } { console.log(`APP Listen to port : 3000`); } });
Après avoir éteint et relancé notre serveur avec npm start
la route /api/public
retournera donc une res ( réponse ) au format JSON avec un message, qui est : voila notre route public
.
Nous savons comment créer une route, voila maintenant les deux autres routes :
app.get('/api/user', function(req, res) { res.json({ message: 'This is an USER endpoint payload' }); }); app.get('/api/admin', function(req, res) { res.json({ message: 'voila notre route admin' }); });
Notre fichierindex.js
:
import express from 'express'; import bodyParser from 'body-parser'; const app = express(); app.use(bodyParser.json()); app.get('/api/unsecured', function(req, res) { res.json({ message: 'This is an unsecured endpoint payload' }); }); app.get('/api/user', function(req, res) { res.json({ message: 'This is an USER endpoint payload' }); }); app.get('/api/admin', function(req, res) { res.json({ message: 'This is an ADMIN endpoint payload' }); }); app.listen(3000, err => { if (err) { console.error(err); } { console.log(`APP Listen to port : 3000`); } });
Nos routes ne sont, pour le moment, pas protégées et tout le monde peut y accéder. c’est le moment de mettre en place Keycloak.
Etape 5 – Mise en place de Keycloak
Nous allons avoir besoin de deux nouvelles dependencies :
- express-session : permet de gérer les sessions avec Express
- keycloak-connect : permet de gérer la connection Keycloack avec Node.js
Allons-y :
npm install express-session keycloak-connect
Nos dépendances installées, il est temps de mettre en place tout cela, dans notre fichier index.js
:
import express from 'express'; import bodyParser from 'body-parser'; // 1 import session from 'express-session'; import Keycloak from 'keycloak-connect'; const app = express(); app.use(bodyParser.json()); // 2 const memoryStore = new session.MemoryStore(); app.use( session({ secret: 'secretKey', resave: false, saveUninitialized: true, store: memoryStore }) ); // 3 const keycloak = new Keycloak({ store: memoryStore }); app.use( keycloak.middleware({ logout: '/logout', admin: '/' }) ); app.get('/api/unsecured', function(req, res) { res.json({ message: 'This is an unsecured endpoint payload' }); }); // 4 app.get('/api/user', keycloak.protect('realm:user'), function(req, res) { res.json({ message: 'This is an USER endpoint payload' }); }); app.get('/api/admin', keycloak.protect('realm:admin'), function(req, res) { res.json({ message: 'This is an ADMIN endpoint payload' }); }); app.listen(3000, err => { if (err) { console.error(err); } { console.log(`APP Listen to port : 3000`); } });
Explications du code :
- Nous commençons par importer
express-session
etkeycloak-connect
- Déclarer un nouvelle instance de
session.MemoryStore()
et mise en place du middlewaresession
dans notre application :app.use( session({ secret: 'secretKey', resave: false, saveUninitialized: true, store: memoryStore }) );
- Déclarer un nouvelle instance de
keycloak-connect
avec le store précédemment instancié. Nous autorisons notre application à utiliser le middleware Keycloak et enfin nous déclarons avec le middleware Keycloak une route /logout qui nous permettra de nous déconnecter. - Nous utilisons
keycloak.protect()
pour définir les droits de chaque utilisateur sur nos routes.
À ce moment si vous décidez de redémarrer votre serveur, vous risquez de tomber sur une erreur de ce type :
Error: ENOENT: no such file or directory, open ‘\*/api-keycloak/keycloak.json’
keycloak-connect
fonctionne avec un fichier keycloak.json
que nous devons générer à partir de l’administration de notre Keycloak.
Etape 6 – Créer notre ‘keycloak.json’
Vous pouvez vous référer à nos articles pour l‘installation de Keycloak et le paramétrage d’un domaine Keycloak. Ici nous utiliserons Keycloak en local
La configuration du domaine est disponible à la racine du projet.
- Sur la console d’administration de Keycloak, créons notre nouveau realm nommé API-KEYCLOAK
- Allons dans le menu Clients et créons un nouveau client :
Attention de bien mettre le Valid Redirect URIs sur http://localhost:3000/* et de mettre l’Access Type sur bearer-only.
- Ensuite rendons-nous dans l’onglet Installation et sélectionnons
Keycloak OIDC JSON
:
- Créons un fichier
keycloak.json
à la racine de notre projet pour y copier le snippet issu de l’administration Keycloak :
{ "realm": "API-KEYCLOAK", "bearer-only": true, "auth-server-url": "http://localhost:8080/auth", "ssl-required": "external", "resource": "api-nodejs", "confidential-port": 0 }
Maintenant nous pouvons lancer notre serveur sans crainte d’avoir une erreur.
À ce niveau assurez-vous d’avoir un utilisateur USER et un utilisateur ADMIN (pour rappel … notre guide complet)
Etape 7 – Tester la sécurité de votre API
La sécurité est en place, il serait maintenant interessant de tester que ce que nous venons de mettre en place est fonctionnel. Vous rappelez vous du client Keycloak api-nodejs que nous avons créé ? il est temps de s’en servir en tant que client de notre API.
Pour tester rapidement les accès, nous allons utiliser le flow Resource Owner Password Credentials de OAuth, comme décrit dans la documentation Keycloak.
Si vous utilisez Postman, la collection est disponible à la racine du projet.
- Pour une demande de token d’utilisation lié à l’utilisateur « user-ineat »
curl -X POST \ http://localhost:8080/auth/realms/API-KEYCLOAK/protocol/openid-connect/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'username=user_ineat&password=password&grant_type=password&client_id=api-nodejs'
N’oubliez pas de changer votre client_id ainsi que votre username et password.
- Pour une demande de token d’utilisation lié à l’utilisateur « admin-ineat »
curl -X POST \ http://localhost:8080/auth/realms/API-KEYCLOAK/protocol/openid-connect/token \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'username=admin_ineat&password=password&grant_type=password&client_id=api-nodejs'
N’oubliez pas de changer votre client_id ainsi que votre username et password.
La réponse de Keycloak devrait ressembler à ce payload :
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxb1FqVFJScWVmWFZzaFJvQURLWkNRRTBaZ2ZWQzVnUk10NENxNEdBSVA0In0.eyJqdGkiOiJiMzg3MzFiYy00NTkzLTRmNzItOGMzNC1lMWRlOWM5MTg5ZTQiLCJleHAiOjE1NzE2NzA2MTIsIm5iZiI6MCwiaWF0IjoxNTcxNjcwMzEyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvQVBJLUtFWUNMT0FLIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjNhZWM1ZmRjLTU2YjctNDBmZS04OTAwLTBmYTA4YmVkNzdmZCIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwaS1ub2RlanMiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI2YjIzYzFkZi02NDUwLTRmY2EtODNmOC1iNmRkNWYwMjhlMWMiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJVU0VSIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyX2luZWF0IiwiZW1haWwiOiJ1c2VyX2luZWF0QGluZWF0LWNvbnNlaWwuZnIifQ.FE2Vq_GpH622-zlLQ2ucsu-YuEzuIkoiK9OyQNzfNuqiG7WPZuEQFW1b1a9X_Urg5HPo0htZ0bNh4V5pQ4G1vwyn3djf24by1RBh4W1x4FPk8M5zW3Uw7SZDi4ffUw8qH_HyS2KiYm1_BHVJuIAySgSdj1XcQNPQMR-gyKpZzwDNJB9FEbZJdXJbVLuyZ_deM_xGCrs9Pi5KbezIInCQSg5uzM78-yEq2-jrP-KtCqtyZUbRsZfeStZf0jGVZNz7kqI9EfG-RSiqeDSvKC1b4X8MYKXZOy9Y53w9FoCxXfQiXgDrWJIvpNY2gsIo874ks0QpPSM8EmpAV232ra6jEQ", "expires_in": 300, "refresh_expires_in": 1800, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2MGY2NzgyNC00NDU2LTQ1YTEtOTM5MC1kNGZlZGEwYmE0OWEifQ.eyJqdGkiOiJiMjFjYzg3Yy05ZjU3LTQ1MTUtOGQyOC0xYmUwNzJlMDI0YzkiLCJleHAiOjE1NzE2NzIxMTIsIm5iZiI6MCwiaWF0IjoxNTcxNjcwMzEyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvQVBJLUtFWUNMT0FLIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL0FQSS1LRVlDTE9BSyIsInN1YiI6IjNhZWM1ZmRjLTU2YjctNDBmZS04OTAwLTBmYTA4YmVkNzdmZCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJhcGktbm9kZWpzIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiNmIyM2MxZGYtNjQ1MC00ZmNhLTgzZjgtYjZkZDVmMDI4ZTFjIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJVU0VSIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIn0.kv5SwclYn2vOF78bpXhNkFdNmUOduwBhs-2_qg-Lmuk", "token_type": "bearer", "not-before-policy": 0, "session_state": "6b23c1df-6450-4fca-83f8-b6dd5f028e1c", "scope": "email profile" }
C’est l’access_token renvoyé par Keycloak que vous devez utiliser lors de l’appel à l’api. Il correspond au fameux bearer attendu dans le header Authorization.
Vous pouvez décoder le contenu d’un token JWT sur le site officiel de la spec (via le decoder) … ce qui parait alors plus clair :
Essayez à présent de contacter chacun des endpoints avec votre bearer user. Seul le endpoint /api/admin devrait vous renvoyer un code HTTP 403 :
curl -X GET \ http://localhost:3000/api/admin \ -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxb1FqVFJScWVmWFZzaFJvQURLWkNRRTBaZ2ZWQzVnUk10NENxNEdBSVA0In0.eyJqdGkiOiJiMzg3MzFiYy00NTkzLTRmNzItOGMzNC1lMWRlOWM5MTg5ZTQiLCJleHAiOjE1NzE2NzA2MTIsIm5iZiI6MCwiaWF0IjoxNTcxNjcwMzEyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvQVBJLUtFWUNMT0FLIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjNhZWM1ZmRjLTU2YjctNDBmZS04OTAwLTBmYTA4YmVkNzdmZCIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwaS1ub2RlanMiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI2YjIzYzFkZi02NDUwLTRmY2EtODNmOC1iNmRkNWYwMjhlMWMiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJVU0VSIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyX2luZWF0IiwiZW1haWwiOiJ1c2VyX2luZWF0QGluZWF0LWNvbnNlaWwuZnIifQ.FE2Vq_GpH622-zlLQ2ucsu-YuEzuIkoiK9OyQNzfNuqiG7WPZuEQFW1b1a9X_Urg5HPo0htZ0bNh4V5pQ4G1vwyn3djf24by1RBh4W1x4FPk8M5zW3Uw7SZDi4ffUw8qH_HyS2KiYm1_BHVJuIAySgSdj1XcQNPQMR-gyKpZzwDNJB9FEbZJdXJbVLuyZ_deM_xGCrs9Pi5KbezIInCQSg5uzM78-yEq2-jrP-KtCqtyZUbRsZfeStZf0jGVZNz7kqI9EfG-RSiqeDSvKC1b4X8MYKXZOy9Y53w9FoCxXfQiXgDrWJIvpNY2gsIo874ks0QpPSM8EmpAV232ra6jEQ' \ -H 'Content-Type: application/x-www-form-urlencoded' \
Access denied
A contrario, si un profil USER tente de contacter /api/user :
curl -X GET \ http://localhost:3000/api/user \ -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxb1FqVFJScWVmWFZzaFJvQURLWkNRRTBaZ2ZWQzVnUk10NENxNEdBSVA0In0.eyJqdGkiOiJiZmNkMTZiNS04Y2ZiLTRmYWMtODUxMi1jMDUxMjZiMjE1ZGMiLCJleHAiOjE1NzE2NzE5MzIsIm5iZiI6MCwiaWF0IjoxNTcxNjcxNjMyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvQVBJLUtFWUNMT0FLIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjNhZWM1ZmRjLTU2YjctNDBmZS04OTAwLTBmYTA4YmVkNzdmZCIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFwaS1ub2RlanMiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiJlYTY0ZmVkOS0zZTU2LTQwNzUtYThmNC0wMDFlM2NhNTY2OTciLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJVU0VSIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ1c2VyX2luZWF0IiwiZW1haWwiOiJ1c2VyX2luZWF0QGluZWF0LWNvbnNlaWwuZnIifQ.wuHxfZVWcJL-KvrKqo6UiUpYs_0CCCuAwHmvuk62BVsl8bEdjwIHFvPdSOh7UYJNUyBnGbWVBC7bSrVp6_C6amjscAA68tZFqtN4I2wbV2XdrblmVBiNq2gU_8WfhlSSt7rocKn3ePWrXhZyUwDTWkKpEMg6w9fTxhktiXkQZpAveUUwtSp7ROpKUFCEpAogFnDPXTDHw52KOgLlyvyxsGhhY-hkNJSHN8CKExR3l5RYMdUc9lcM1DyWvDXJLU5RYDsM6zk6ZFu8h5O_rjqq5mV4OCkNUQQe7dZnD5LpJvJqC0jB5L8uYrOuKY0msLEeSX7Bii1-5vR9NbISWc0zTg' \ -H 'Content-Type: application/x-www-form-urlencoded' \
Nous avons bien un code HTTP 200 :
Conclusion
Nous voila maintenant avec une API Node.js sécurisée à deux niveaux. l’application peut-être améliorée, par exemple :
- Ajouter
nodemon
pour éviter de couper et redémarrer votre serveur à chaque fois qu’une modification sera effectuée. - Mieux découper votre projet (découper son fichier `index.j s` pour créer des dossiers et fichiers ( pour les routes, middleware, etc… ) pour plus de lisibilité.
- Mettre en place une base de donnée (par exemple MongoDB avec Mongoose).
Il y a une infinité d’améliorations mais grace à ce poste vous devriez avoir les bases pour commencer un projet d’api sécurisée avec Node.js et Keycloak.
Source du projet : https://github.com/ineat/node-keycloak-tutorials
Série d’articles Keycloak
- Partie 1 – Securisez vos apis spring avec Keycloak – installation de keycloak.
- Partie 2 – Securisez vos apis spring avec Keycloak – parametrage d’un domaine Keycloak
- Partie 3 – Securisez vos apis spring avec Keycloak – utilisation des connecteurs spring de Keycloak
- Partie 4 – Securisez vos apis spring avec Keycloak – utilisation du connecteur Keycloak-js avec Angular 6
- Partie 5 : Securisez vos apis spring avec Keycloak – Mise en place d’une authentification mutli-domaines
- Partie 6 : Vous le consultez actuellement