Patrones de Implementación BFF
Patrones de Implementación BFF
Section titled “Patrones de Implementación BFF”Este documento materializa el Token Handler Pattern (presentado en los Diagramas de Secuencia) en implementaciones tangibles dentro de un ecosistema Quarkus + Apache Camel.
1. Agente OAuth2 (SSO Handshake)
Section titled “1. Agente OAuth2 (SSO Handshake)”Corresponde al diagrama 02_sso_handshake_sequence.puml.
El “OAuth2 Agent” es responsable de gobernar el flujo de redirecciones Seguras con el Identity Provider (IdP).
Controlador: JAX-RS WebResource
Section titled “Controlador: JAX-RS WebResource”Dos simples interfaces @Path gestionan el punto de entrada y salida:
@Path("/bff/auth")public class OAuth2AgentResource {
@GET @Path("/login") public Response initiateLogin() { // Genera el desafío PKCE // Redirige al URL de Autorización del IdP (HTTP 302) return Response.status(302).location(idpUrl).build(); }
@GET @Path("/callback") public Response handleCallback(@QueryParam("code") String code) { // Valida el Authorization Code y extrae el Payload // Delega el Exchange a una Ruta Camel si se requiere orquestación (seda:exchange-token)
String sessionId = UUID.randomUUID().toString(); // Construcción Estricta de la Cookie NewCookie sessionCookie = new NewCookie.Builder("session_id") .value(sessionId) .path("/") .secure(true) // Requiere HTTPS .httpOnly(true) // Bloquea lectura desde JavaScript en el SPA .sameSite(NewCookie.SameSite.LAX) // Protección CSRF base .build();
return Response.status(302).cookie(sessionCookie).location(spaUrl).build(); }}Encriptación y Estado (Session Store)
Section titled “Encriptación y Estado (Session Store)”Los tokens crudos jamás deben llegar (o “sangrar”) hacia el frontend. Siguiendo el rigor del estándar:
- El
OAuth2Agentextrae elaccess_tokenyrefresh_tokendel IdP. - Una clave simétrica interna (gestionada vía GCP Secret Manager o Vault) encripta este payload empleando algoritmo
AES-GCM. - El paquete encriptado se vuelca en la Caché Distribuida (ej. Firestore / Cloud SQL) y se asocia al string aleatorio
sessionId. - El
sessionIdviaja transparentemente e inyectado al navegador como cabeceraSet-Cookie(HttpOnly; Secure).
2. OAuth2 Proxy / API Proxy (Intercepción de Peticiones)
Section titled “2. OAuth2 Proxy / API Proxy (Intercepción de Peticiones)”Corresponde al diagrama 03_bff_token_handling_sequence.puml.
El interceptor (Proxy) captura las peticiones nativas en JSON del Frontend, les inyecta el verdadero token re-hidratado y las lanza contra el Servidor de Recursos (Salesforce API).
Constructo Fundamental: Filtros REST y Clientes Declarativos
Section titled “Constructo Fundamental: Filtros REST y Clientes Declarativos”Debido a que el cometido central del BFF es ser un túnel de paso directo (leer cookie, desencriptar subyacente, re-enviar), el uso de los componentes ContainerRequestFilter y RestClient de JAX-RS resulta ser extremadamente más rápido y purista arquitectónicamente que embutir cada petición a través de un enrutador completo de Apache Camel.
// 1. Filtro Pre-Matching para interceptar tráfico SPA hacia APIs@Provider@PreMatchingpublic class SessionDecryptionFilter implements ContainerRequestFilter {
@Override public void filter(ContainerRequestContext ctx) { // 1. Extraer la cookie "session_id" Cookie sessionCookie = ctx.getCookies().get("session_id"); if (sessionCookie == null) throw new UnauthorizedException();
// 2. Recuperar el paquete cifrado de la Caché Distribuida y desencriptarlo String plainAccessToken = decryptToken(cacheStore.get(sessionCookie.getValue()));
// 3. Mutar la petición inyectando explícitamente el Bearer Token ctx.getHeaders().putSingle("Authorization", "Bearer " + plainAccessToken); }}
// 2. Cliente REST Declarativo encapsulando la API subyacente@RegisterRestClient(configKey = "backend-api")public interface BackendProxyClient {
@GET @Path("/{path: .*}") Response forwardRequest(@PathParam("path") String path, @HeaderParam("Authorization") String token);}Rol Secundario: Apache Camel
Section titled “Rol Secundario: Apache Camel”Si un endpoint en concreto requiere coordinación o coreografía (ej: consultar a 3 bases de datos, cruzar un CSV y enriquecer el JSON de salida), solo en esa circunstancia entra en juego Apache Camel. Para todo el proxying CRUD natural, los filtros JAX-RS mantienen un pipeline performante y completamente estandarizado.