Adaptadores de autenticación personalizados
Rebase incluye su propia autenticación — configúrala aquí. Esta página trata del otro caso: un proveedor de identidad que ya utilizas o por el que ya pagas.
Adaptadores de autenticación personalizados
Sección titulada «Adaptadores de autenticación personalizados»Rebase permite el reemplazo completo del sistema de autenticación integrado a través de una arquitectura de autenticación modular (pluggable). Esto desacopla la verificación de autenticación de la base de datos y de las capas REST/WebSocket, permitiendo una integración fluida con proveedores externos como Clerk, Auth0, Firebase Auth o servicios de identidad JWT personalizados.
El contrato AuthAdapter
Sección titulada «El contrato AuthAdapter»Puedes implementar la interfaz AuthAdapter directamente para un control total. La definición de la interfaz es la siguiente:
import { Hono } from "hono";import type { HonoEnv } from "@rebasepro/server";import { AuthenticatedUser, AuthAdapterCapabilities, UserManagementAdapter, UserCreationPrepareResult, UserCreationFinalizeResult } from "@rebasepro/types";
export interface AuthAdapter { /** Unique identifier for this auth adapter (e.g., "clerk", "custom") */ readonly id: string;
/** * Verifies an incoming HTTP request and returns the authenticated user payload. * Called by Hono authentication middleware on every REST endpoint. */ verifyRequest(request: Request): Promise<AuthenticatedUser | null>;
/** * Verifies a raw token string (e.g. for WebSocket connection handshake phase 1). * If omitted, a synthetic request is automatically constructed. */ verifyToken?(token: string): Promise<AuthenticatedUser | null>;
/** Optional user management operations (CRUD) for the panel */ userManagement?: UserManagementAdapter;
/** Optional: Mount adapter-specific custom public routes (e.g. callback paths) */ createAuthRoutes?(): Hono<any, any, any> | undefined;
/** Optional: Mount adapter-specific admin-only routes */ createAdminRoutes?(): Hono<any, any, any> | undefined;
/** Advertise supported capabilities (to customize what the panel shows) */ getCapabilities(): AuthAdapterCapabilities | Promise<AuthAdapterCapabilities>;
/** Lifecycle hooks called during backend start and graceful shutdown */ initialize?(): Promise<void>; destroy?(): Promise<void>;
/** Custom user lifecycle hooks (e.g., hash passwords before collection writes) */ prepareUserCreation?( values: Record<string, unknown>, collectionAuth?: unknown ): Promise<UserCreationPrepareResult>;
finalizeUserCreation?( entity: { id: string; values: Record<string, unknown> }, clearPassword?: string ): Promise<UserCreationFinalizeResult>;
/** Static service key to bypass checks for server-to-server calls */ serviceKey?: string;}El payload del usuario autenticado
Sección titulada «El payload del usuario autenticado»Independientemente del proveedor de autenticación externo elegido, tu adaptador debe resolver las verificaciones de tokens exitosas en un objeto AuthenticatedUser uniforme. El RLS Scope Injector de Rebase mapea estos valores directamente a variables de sesión de PostgreSQL dentro de las transacciones:
export interface AuthenticatedUser { uid: string; // Maps to pg local 'app.user_id' -> rebase.uid() email: string; // User email address displayName?: string | null; // Optional display name photoUrl?: string | null; // Optional avatar URL roles: string[]; // Maps to pg local 'app.user_roles' -> rebase.roles() isAdmin: boolean; // Grants global superuser privileges if true rawToken?: string; // The original token string (for downstream forwarding) claims?: Record<string, any>; // Custom claims/metadata (available in rebase.jwt())}Integración rápida mediante createCustomAuthAdapter
Sección titulada «Integración rápida mediante createCustomAuthAdapter»Para escenarios estándar (como validar JWTs de un servicio de terceros), puedes utilizar la utilidad createCustomAuthAdapter. Esta utilidad gestiona los valores predeterminados de las capacidades e implementa la validación de tokens de WebSocket de forma predeterminada al envolver tu implementación de verifyRequest.
Ejemplo: Integración con Clerk
Sección titulada «Ejemplo: Integración con Clerk»Para conectar un backend de Rebase con Clerk, puedes verificar los tokens JWT de Clerk utilizando el JSON Web Key Set (JWKS) de Clerk:
import { initializeRebaseBackend } from "@rebasepro/server";import { createCustomAuthAdapter } from "@rebasepro/server";import { createRemoteJWKSet, jwtVerify } from "jose";
// Clerk JWKS URLconst CLERK_JWKS_URL = "https://clerk.your-domain.com/.well-known/jwks.json";const JWKS = createRemoteJWKSet(new URL(CLERK_JWKS_URL));
const clerkAuthAdapter = createCustomAuthAdapter({ serviceKey: process.env.REBASE_SERVICE_KEY, verifyRequest: async (request) => { const authHeader = request.headers.get("Authorization"); const token = authHeader?.replace("Bearer ", ""); if (!token) return null;
try { // Verify Clerk JWT token against JWKS const { payload } = await jwtVerify(token, JWKS);
const metadata = payload.metadata as Record<string, unknown> | undefined; const roles = Array.isArray(metadata?.roles) ? metadata.roles as string[] : [];
return { uid: payload.sub!, email: (payload as Record<string, unknown>).email as string || "", displayName: (payload as Record<string, unknown>).name as string || null, roles: roles, isAdmin: roles.includes("admin"), claims: payload as Record<string, unknown> }; } catch (error) { console.error("Clerk token verification failed:", error); return null; // Fail-closed } }, capabilities: { hasBuiltInAuthRoutes: false, // Login is managed by Clerk UI emailPasswordLogin: false, registrationEnabled: false, passwordReset: false, profileUpdate: false, sessionManagement: false }});
const backend = await initializeRebaseBackend({ auth: clerkAuthAdapter, // ...});Ejemplo: Integración con Firebase Auth
Sección titulada «Ejemplo: Integración con Firebase Auth»Para verificar tokens de Firebase Auth utilizando los certificados públicos de Firebase:
import { initializeRebaseBackend } from "@rebasepro/server";import { createCustomAuthAdapter } from "@rebasepro/server";import { createRemoteJWKSet, jwtVerify } from "jose";
const FIREBASE_JWKS_URL = "https://www.googleapis.com/robot/v1/metadata/jwk/securetoken@system.gserviceaccount.com";const JWKS = createRemoteJWKSet(new URL(FIREBASE_JWKS_URL));const FIREBASE_PROJECT_ID = "my-firebase-project-id";
const firebaseAuthAdapter = createCustomAuthAdapter({ serviceKey: process.env.REBASE_SERVICE_KEY, verifyRequest: async (request) => { const authHeader = request.headers.get("Authorization"); const token = authHeader?.replace("Bearer ", ""); if (!token) return null;
try { const { payload } = await jwtVerify(token, JWKS, { issuer: `https://securetoken.google.com/${FIREBASE_PROJECT_ID}`, audience: FIREBASE_PROJECT_ID });
const roles = Array.isArray((payload as Record<string, unknown>).roles) ? (payload as Record<string, unknown>).roles as string[] : [];
return { uid: payload.sub!, email: (payload as Record<string, unknown>).email as string || "", displayName: (payload as Record<string, unknown>).name as string || null, photoUrl: (payload as Record<string, unknown>).picture as string || null, roles: roles, isAdmin: roles.includes("admin"), claims: payload as Record<string, unknown> }; } catch (error) { console.error("Firebase token verification failed:", error); return null; } }});
const backend = await initializeRebaseBackend({ auth: firebaseAuthAdapter, // ...});Montar rutas de autenticación y acciones del panel
Sección titulada «Montar rutas de autenticación y acciones del panel»Si tu proveedor de autenticación personalizado requiere montar endpoints de redirección (como rutas de callback de OAuth o flujos de inicio de sesión SAML), implementa el método createAuthRoutes en tu adaptador:
const myOauthAdapter: AuthAdapter = { id: "custom-oauth", verifyRequest: async (req) => ({ // validate the token, then return the caller uid: "…", email: "user@example.com", roles: [], isAdmin: false }), getCapabilities: () => ({ hasBuiltInAuthRoutes: true, emailPasswordLogin: false, registrationEnabled: false, passwordReset: false, adminPasswordReset: false, sessionManagement: false, profileUpdate: false, emailVerification: false, magicLink: false, anonymousLogin: false, enabledProviders: [] }), createAuthRoutes: () => { const app = new Hono<HonoEnv>();
// Mounted automatically under /api/auth/callback app.get("/callback", async (c) => { const code = c.req.query("code"); // Exchange code for provider tokens and set cookies/redirect return c.redirect("/dashboard"); });
return app; }};Si deseas permitir operaciones CRUD de usuarios directamente dentro del panel, implementa el helper userManagement dentro de las opciones del adaptador, el cual proporciona hooks para listUsers, createUser, updateUser y deleteUser.
Próximos pasos
Sección titulada «Próximos pasos»- Authentication — la configuración del proveedor integrado
- Endpoints and tokens — las rutas que debe satisfacer un adaptador
- Security Rules (RLS) — para qué se utilizan los claims que devuelve un adaptador