pac4j enseña a proteger rutas de Spark Java con OIDC sin escribir el filtro
spark-pac4j entrega un SecurityFilter, una CallbackRoute y una LogoutRoute listos para enganchar a las rutas de Spark Java; el mismo Config vale para Keycloak, Entra ID u Okta.

Proteger un puñado de rutas en una aplicación Spark Java con OpenID Connect no obliga a escribir el filtro de sesión a mano. La biblioteca spark-pac4j aporta tres piezas ya resueltas —SecurityFilter, CallbackRoute y LogoutRoute— que se enganchan a las rutas de Spark y delegan la autenticación en cualquier proveedor OIDC: Keycloak, Google, Microsoft Entra ID u Okta, entre otros. El ejemplo arranca con Spark 2.9 y Java 17 sobre un proyecto Maven.
Qué se añade al proyecto
Al pom.xml hay que sumar tres dependencias: spark-core 2.9.4, spark-pac4j 6.0.2 y pac4j-oidc 6.5.8. La primera conecta pac4j con el framework y la segunda implementa el protocolo. Conviene tener presente que spark-pac4j v6 apunta a pac4j v6 y a Spark v2.9, que es un framework javax.servlet, así que la integración arrastra el módulo pac4j-javaee correspondiente. Hay una aplicación de ejemplo más completa en el repositorio de demostración.
La configuración no tiene nada específico de Spark, y ahí está la gracia. Se construye un Config con un OidcClient sobre una OidcConfiguration donde se fijan discoveryURI, clientId y secret. Ese mismo objeto sirve igual en Spring Boot o en Javalin: pac4j es un motor de seguridad agnóstico de framework y el módulo de integración solo lo enchufa a las rutas. La URL de callback, con ?client_name=OidcClient que añade pac4j por su cuenta, es la que hay que registrar en el proveedor. Un aviso: el ejemplo activa setAllowUnsignedIdTokens(true) porque el servidor de demostración público emite ID tokens sin firmar. Con un proveedor propio esa línea se borra.
Antes del filtro y después del login
En Spark todo se registra con los métodos estáticos de la clase Spark. Un before("/protected", new SecurityFilter(config, "OidcClient")) intercepta la petición antes de la ruta. Si el usuario es anónimo, lo redirige al proveedor y detiene la petición; si ya tiene sesión, la ruta se ejecuta. El segundo argumento nombra el cliente y se le pueden añadir autorizadores y matchers para afinar el control de acceso, por ejemplo exigir un rol concreto. Antes de arrancar hay que llamar a FrameworkAdapter.applyDefaultSettingsIfUndefined(config) para que la configuración herede los valores por defecto de Spark: contexto web, sesión y acciones HTTP.
CallbackRoute recibe el código de autorización, lo canjea por access token e ID token, valida el ID token, guarda el perfil en la sesión y devuelve al usuario a la URL que había pedido. Su tercer argumento activa la renovación de sesión, que sirve para frenar ataques de fijación de sesión. La ruta se registra en GET y en POST: el segundo es para el modo form_post, mientras que el flujo code por defecto vuelve por GET. Para salir, LogoutRoute con setDestroySession(true) cierra la sesión local y, según cómo se configure, también la del proveedor.
Para quien mantenga una aplicación web pequeña o una API en Spark, el interés está en que la parte de OIDC no hay que reimplementarla ni adaptarla al framework: las versiones encajan con pac4j v6 y el mismo Config se reutiliza en otras integraciones. Lo que toca verificar en cada caso es el proveedor. Los detalles de discovery, firma de tokens y logout central cambian entre Keycloak, Entra ID y Okta, y son los que suelen dar guerra al pasar de la demo a producción.

