Sécuriser une application Spring Boot/Angular avec KeyCloak [Part 1]

yagni.tech code & craft team
9 min readJan 6, 2019

--

Dans cette première partie, nous allons apprendre à installer, configurer et utiliser Keycloak, créer une API REST avec Spring Boot et la sécuriser, nous verrons dans la deuxième partie la création d’un front avec Angular et comment sécuriser l’application entière avec Keycloak.

Keycloak c’est quoi ?
Comme vous pouvez le savoir, la majorité des applications aujourd’hui ont besoin de mettre en place un système d’authentification robuste, pour répondre à ce besoin il existe un paquet de solutions comme OpenAM, WSO2, KeyCloak, donc nous pouvons définir Keycloak comme identity/access manager open source.

Quelques mots sur Keycloak ?

  • Solution open source développée en Java et portée par Redhat.
  • Il propose plusieurs adaptateurs/connecteurs Spring Boot & Spring Security & Tomcat , JavaScript, NodeJS , Android …
  • Prise en charge d’openID Connect (une extension de OAuth 2.0) et SAML 2.0
  • Il offre une API Rest pour la partie administration
  • Il propose une console d’administration pour la gestion centralisée des utilisateurs
  • Il permet la gestion de session / Prise en charge de CORS
  • Une bonne documentation 😃
  • ….

Dans ce tutoriel, nous allons se baser sur le protocole OpenID connect (OIDC), comme j’ai déjà mentionné, OIDC est une extension d’ OAuth 2.0 qui utilise quelques normes de JWT ( JSON WEB Token), ce dernier donne la possibilité de définir un token en format JSON comme suite :

JSON WEB Token

Un Token JWT est simplement constitué de trois parties séparées par un point : header.payload.signature.
Le header indique l’algorithme utilisé dans l’encodage, le payload contient les informations en base64 sur l’utilisateur connecté, l’expiration du token … les champs utilisés sont définis par la spécification registered claims, et enfin la signature c’est l’encodage du header et du payload en utilisant l’algorithme prédéfini dans le header.

Pour mieux connaître JWT n’hésitez pas d’aller sur leur site officiel
=> Donc tout ça pour dire que le token généré par Keycloak est un JWT.

Installation de KeycLoak

Pour une installation en local il suffit de suivre les étapes suivantes :

Pour démarrer Keycloak en local, il suffit de lancer le script standalone.bat situé dans le répertoire bin/

Keycloak est démarré par défaut sur localhost:8080

Pour pouvoir configurer Keycloak, il nous faut un compte admin que nous pouvons créer via la console d’administration comme suit :

Création d’un admin

Cliquez sur Create, une fois vous êtes connectés, la console d’administration doit ressembler à l’image suivante :

La console d’administration

Fonctionnement de KeyCloak

Il est nécessaire de connaître certains concepts et termes clés avant d’essayer d’utiliser Keycloak pour sécuriser vos applications Web et vos services REST

Utilisateurs : Ils sont des entités pouvant se connecter à votre système
Rôles : ils identifient un type ou une catégorie d’utilisateur. Admin, user, …
Groupe : permet de gérer un groupe d’utilisateur
Royaumes (realms): un domaine qui gère un ensemble d’utilisateurs, d’informations d’identification, des rôles et des groupes.
Clients : ils sont des entités pouvant demander à Keycloak d’authentifier un utilisateur ( comme des applications )
Identity token: un token qui fournit des informations d’identité sur l’utilisateur
Access token :
un token pouvant être fourni dans le cadre d’une requête HTTP autorisant l’accès au service invoqué.
Thèmes : Les thèmes et styles CSS à appliquer aux templates Keycloak sur les pages (login, registration, account ..Ect) et les emails.

Pour approfondir le sujet, n’hésitez pas d’aller jeter un œil sur la documentation

Le schéma suivant résume le fonctionnement de Keycloak

Composants Keycloak

Maintenant, nous allons mettre tout ça en pratique en essayant de sécuriser une application Spring Boot. Nous allons commencer par créer un projet Spring Boot de type web pour mettre en place une API Rest de gestion de produits

Les dépendances Maven

Pour sécuriser une application Spring Boot avec Keycloak, nous aurions besoin des deux dépendances, le starter spring boot et l’adapter keycloak

<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>${keycloak.version}</version>
</dependency>

<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-adapter</artifactId>
<version>${keycloak.version}</version>
</dependency>

Une classe model ‘Produit’

package fr.tuto.keycloak.app.modele;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@AllArgsConstructor
public class Product {

private String id;
private String reference;
private double price;


}

Remarque : les annotations @Setter @Getter proviennent de la libraire lombok qui permet de générer les getters et les setters à la compilation.

Un contrôleur qui propose une unique ressource ‘/products’ qui permet de récupérer la liste des produits

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class ProductController {

@Autowired
private ProductService productService;

@RequestMapping("/products")
public List<Product> getProducts() {
return productService.getProducts();
}


}

Un service de produit qui nous construit une liste de produits

package fr.tuto.keycloak.app.services;

import fr.tuto.keycloak.app.modele.Product;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ProductService {


public List<Product> getProducts(){
return List.of(
new Product("id1","XXABC",120.00),
new Product("id2","XXZER",130.00),
new Product("id3","XXRFR",110.00),
new Product("id4","XXTER",140.00)
);
}
}

Remarque : List.of est une nouveauté de Java 1.9, si vous utilisez une version antérieure, vous pouvez passer par Arrays.asList() pour construire votre liste.

Un petit index.html permettant d’accéder à la resource /products.

<!DOCTYPE html>
<html>
<head>
<title>My Products App</title>
</head>
<body>
<h1>KeyCloak Test</h1>
<a href="/products">My products</a></body>
</html>

Un Runner classique Spring Boot

package com.softeam.keycloak.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class KeycloakAppApplication {

public static void main(String[] args) {

SpringApplication.run(KeycloakAppApplication.class, args);
}
}

Remarque : il ne faut pas oublier de modifier le port pour que l’application tourne sur un autre port que le 8080 car Keycloak tourne par défaut sur le même port ou faire le contraire et modifier le fichier de configuration Keycloak sur \standalone\configuration\standalone.xml

<socket-binding name=”http” port=”${jboss.http.port:8080}”/>

Configuration Keycloak

Création d’un domaine/realm Keycloak

Configuration d’un realm

Dans ma configuration, j’ai choisi l’option User registration, Forgot password et Login with email, vous pouvez sélectionner les options les plus convenables pour votre application.

Ajout d’un rôle

Nous avons au moins un rôle pour l’associer à nos utilisateurs.

Ajout d’un rôle

Ajout d’un client

Comme j’ai déjà précisé, un client correspond à la ressource qui va demander l’authentification à Keycloak, donc finalement l’Api REST de produits que nous avons déjà créé.

Ajout d’un nouveau client

Configuration du client

client settings

Mapping user to role

Pour associer un utilisateur à un rôle, il est nécessaire de passer par le bloc ‘Role Mappings’ de la vue user.

Côté application Spring BOOT

Après avoir ajouté l’adapter Keycloak pour Spring Boot et le démarreur Keycloak Spring Boot comme dépendances , il reste qu’à fournir une configuration supplémentaire via Spring Boot (application.properties).
En général, une configuration Keycloak doit se faire via la mise à disposition d’un fichier keycloak.json , dans le cas de Spring Boot, nous passerons directement par applications.properties

keycloak.auth-server-url=http://localhost:8080/auth
keycloak.realm=spring-boot
keycloak.public-client=true
keycloak.resource=products-app

Ensuite, au lieu de passer par le web.xml pour configurer la partie sécurité, il suffit d’ajouter les properties suivantes dans applications.properties et c’est Spring qui va assigner login-method à Keycloak et il va configurer les contraintes de sécurité au moment du démarrage de l’application.

keycloak.security-constraints[0].authRoles[0]=manager
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/products/*

Finalement , je vais modifier le fichier index.html pour ajouter la possibilité de se déconnecter et de gérer son compte Keycloak via notre application web.
En règle générale, pour déconnecter un utilisateur Keycloak, il faut passer par une URL qui ressemble à la suivante :
http://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri
Tandis que pour la gestion de son compte, il faut passer par l’Url suivant :
http://auth-server/auth/realms/{realm-name}/account/

Keycloak fournit un client par défaut nommé “Account” qui permet la gestion d’un compte utilisateur

Notre index.html ressemblera désormais à :

<!DOCTYPE html>
<html>
<head>
<title>My awesome landing page</title>
</head>
<body>
<h1>KeyCloak Test</h1>
<a href="/products">My products</a>
<footer>
<a href=http://localhost:8080/auth/realms/spring-boot/account/ >Gérer mon compte</a>
</footer>
</body>
</html>

Récapitulatif

Résultat

En arrivant sur http://localhost:8081/products, Keycloak va nous proposer de s’authentifier via sa page de login par défaut

Il faut utiliser l’utilisateur que nous avons déjà créé pour se connecter , une fois la connexion est aboutie nous aurions le résultat suivant :

Modifier le thème de la page de login
Toutes les pages fournies par Keycloak comme la page de login, la page d’inscription et la page de gestion de comptes sont modifiables, nous pouvons mettre en place le style CSS qui convient à nos applications, c’est ce que nous allons essayer d’appliquer sur la page de login.

Pour modifier le thème Keycloak, il faut passer par Realm Settings / Thèmes comme suit :

Keycloak propose la liste des thèmes disponibles pour toutes les pages, ainsi que les emails ( eh oui nous pouvons aussi créer nos propres templates de mails 😜)

Par défaut Keycloak propose deux thèmes :

Nous allons voir comment peut-on créer notre propre thème et ainsi le déployer sur Keycloak et l’appliquer à notre domaine/realm.

Let’s go ✌️

Il est recommandé de copier et de modifier un thème existant.
Pour pouvoir modifier le thème et voir les modifications sans redémarrer le serveur Keycloak, vous devez modifier le fichier “standalone.xml” sur votre serveur Keycloak afin de désactiver la mise en cache.

<theme>
<staticMaxAge>-1</staticMaxAge>
<cacheThemes>false</cacheThemes>
<cacheTemplates>false</cacheTemplates>
...
</theme>

Cette manipulation ne doit pas se faire en production car ça peut engendrer des grands problèmes de performance.

Nous commençons par dupliquer le théme ‘keycloak’ en allant sur \themes 👇

J’ai renommé le dossier en ‘product-app’

Nous pouvons vérifier dans la configuration si Keycloak propose déjà notre nouveau thème products-app 👇

Ajout d’un nouveau thème

Maintenant il faut faire appel à vos compétences en CSS pour créer un style propre pour la page de login et comme j’ai des compétences très modestes en CSS, nous allons faire un exemple très simple.

Pour faire ceci il faut aller sur products-app/login/resources/*

Je vais modifier l’image du fond par exemple :

.login-pf body {
background: url(“../img/img.jpg”) no-repeat center center fixed;
background-size: cover;
}

Je vais également apporter quelques modifications au look des zones de texte et aux boutons, vous pouvez vous amusez en modifiant le fichier styles.css ( n’oubliez pas de nettoyer en cas de duplication 🙏).

Résultat

C’est moche, je sais 👊 le but était uniquement de montrer comment personnaliser les pages Keycloak en créant vos propres thèmes, après à vous de jouer 😄

Le code est disponible sous GitHub.

--

--

yagni.tech code & craft team
yagni.tech code & craft team

Written by yagni.tech code & craft team

Digital Factory , we Build & Run Amazing Apps

Responses (5)