Cervantes est l’implémentation MicroProfile JWT 2.1 de l’écosystème Vidocq. Elle valide les bearer tokens JWT signés (et optionnellement chiffrés) en s’appuyant exclusivement sur java.security, parse le JSON via Champollion, lit sa configuration via Ravel, expose le principal JsonWebToken en CDI via Vauban, et applique @RolesAllowed sur les endpoints JAX-RS via Cassini. Objectif : conformance 100 % au TCK MicroProfile JWT 2.1 (atteint, 206 / 206 à M6), zéro lib tierce de crypto ou JWT, JPMS strict, prête pour jlink.

Origine du nom

Miguel de Cervantes (1547-1616), écrivain espagnol. Auteur de L’ingénieux hidalgo Don Quichotte de la Manche (1605 / 1615), première grande œuvre de la littérature moderne. Voir la fiche Wikipédia.

Don Quichotte n’est pas adoubé : il se proclame chevalier errant et porte sur lui les preuves de son rang — armoiries peintes sur l’écu, lettres patentes recopiées, récit héraldique récité à chaque rencontre. Le récit picaresque marche à ce procédé : chaque interlocuteur reçoit la revendication, l’examine, la tient pour vraie ou pour folie. Cervantes a inventé la fiction du porteur d’identité signée — un personnage qui se trimballe avec ses preuves et qui exige que le monde les vérifie.

Le JWT est exactement ça : un jeton porteur qui présente une identité signée à chaque requête HTTP, et que chaque service vérifie localement, sans contacter une autorité centrale. Cervantes le runtime ne se contente pas — contrairement aux moulins de La Manche — de tenir pour vraies les revendications du porteur : il vérifie réellement la signature, l’émetteur, l’audience, l’expiration, et n’accorde un rôle qu’après contrôle.

Cervantes, l’auteur Cervantes, le runtime JWT

Don Quichotte porte ses lettres patentes

Chaque requête porte son Authorization: Bearer ey…

Vérification locale, sans roi à consulter

Validation locale via clé publique (offline, pas d’appel à l’émetteur)

Récit héraldique : nom, blason, lignée

Claims : iss, sub, aud, groups, roles

Sceau du donateur

Signature numérique (RS256, ES256, …)

Lettres datées et expirables

exp, nbf, iat avec tolérance de clock-skew

Lignée prouvée par chaîne de témoins

Chaîne de confiance via JWK Set publié à l'`iss`

Adoubement contesté par le curé et le barbier

401 si la signature falsifie, 403 si le rôle manque

En un coup d’œil

Spec implémentée

https://microprofile.io/specifications/microprofile-jwt-auth/

Dépôt

https://codeberg.org/Vidocq/cervantes

Java

25 (LTS)

Modules JPMS

io.vidocq.cervantes.api, io.vidocq.cervantes.core, io.vidocq.cervantes.cdi.vauban, io.vidocq.cervantes.jaxrs, org.eclipse.microprofile.jwt (repackaging)

Packages publics

io.vidocq.cervantes.api. (SPI stable), io.vidocq.cervantes.cdi. (intégration CDI), io.vidocq.cervantes.jaxrs.* (intégration JAX-RS)

Dépendances runtime

microprofile-jwt-auth-api 2.1, jakarta.json-api (via Champollion), jakarta.enterprise.cdi-api 4.1, jakarta.ws.rs-api 4.0, jakarta.annotation-api 3.0, io.vidocq.ravel:ravel-mp-config-api

Crypto

java.security (Signature, KeyFactory), javax.crypto (JWE) — aucune lib tierce

Prête pour jlink

✅ — chaque sous-module a son module-info.java, aucun Automatic-Module-Name

TCK MP JWT 2.1

206 / 206 (100 %) — voir état détaillé

Trois traits identitaires

  1. Zéro lib tierce de crypto ou de JWT. Pas de Nimbus, pas de jose4j, pas de Bouncy Castle, pas de Auth0 java-jwt, pas de SmallRye JWT. Toute la vérification de signature (RS256/384/512, ES256/384/512, transcodage JOSE R‖S ⇄ DER pour ECDSA) passe par java.security.Signature. Le déchiffrement JWE (RSA-OAEP, A256GCM) passe par javax.crypto. Le parsing JSON passe par Champollion (JSON-P 2.1).

  2. @RolesAllowed natif, sans réécrire Cassini. L’intégration JAX-RS pose un SecurityContext adossé au JsonWebToken validé, et applique @RolesAllowed / @PermitAll / @DenyAll via un DynamicFeature. Précédence méthode > classe. 401 si signature invalide, 403 si rôle manquant — uniquement avec l’API JAX-RS standard, aucun patch d’implémentation.

  3. JPMS strict, virtual-thread-friendly, AOT-friendly. Chaque artefact a son module-info.java. io.vidocq.cervantes.internal.* n’est jamais exporté. Aucun setAccessible(true) en production, aucun Proxy dynamique. Le fetch JWKS utilise java.net.http.HttpClient, sans synchronized autour de l’I/O. Compatible GraalVM native-image / Leyden CDS.

Positionnement dans l’écosystème

Diagram

Cervantes consomme l’écosystème de bas en haut : Chappe sert les requêtes, Cassini héberge le filtre d’auth et le DynamicFeature @RolesAllowed, Vauban déclenche la BCE qui synthétise les beans @Claim, Ravel résout les clés mp.jwt.*, Champollion parse le payload JSON du token. Cervantes ajoute la couche d’identité signée — sans rien réécrire ailleurs.

Ressources rapides

  • Démarrage rapide — premier endpoint protégé en moins de cinq minutes.

  • Concepts — JWT, claims standards et MP, signature, JWK Set, rotation.

  • Cas d’usage@RolesAllowed, @Claim, JWKS, JWE, cookies, refresh.

  • Référence — artefacts, annotations, clés mp.jwt.*, algorithmes.

  • Fonctionnement interne — moteur pur, filtre d’auth, cache JWKS, threading.

  • TCK — exécution, statut 206 / 206, exclusions.

  • Migration — depuis SmallRye JWT.

Suivant : Démarrage rapide.