Pular para o conteúdo

Adaptadores de autenticação personalizados

O Rebase inclui sua própria autenticação — configure-a aqui. Esta página trata do outro caso: um provedor de identidade que você já utiliza ou pelo qual já paga.

O Rebase permite a substituição completa do sistema de autenticação integrado por meio de uma arquitetura de autenticação plugável. Isso desacopla a verificação de autenticação do banco de dados e das camadas REST/WebSocket, permitindo uma integração perfeita com provedores externos como Clerk, Auth0, Firebase Auth ou serviços de identidade JWT personalizados.

Você pode implementar a interface AuthAdapter diretamente para obter controle total. A definição da interface é a seguinte:

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;
}

Independentemente do provedor de autenticação externo escolhido, seu adaptador deve resolver verificações de token bem-sucedidas em um objeto AuthenticatedUser uniforme. O Rebase RLS Scope Injector mapeia esses valores diretamente para variáveis de sessão do PostgreSQL dentro de transações:

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())
}

Para cenários padrão (como a validação de JWTs de um serviço de terceiros), você pode usar o utilitário createCustomAuthAdapter. Esse utilitário lida com os padrões de capacidades e implementa a validação de token de WebSocket pronta para uso, encapsulando sua implementação de verifyRequest.

Para conectar um backend Rebase ao Clerk, você pode verificar tokens JWT do Clerk usando o JSON Web Key Set (JWKS) do Clerk:

import { initializeRebaseBackend } from "@rebasepro/server";
import { createCustomAuthAdapter } from "@rebasepro/server";
import { createRemoteJWKSet, jwtVerify } from "jose";
// Clerk JWKS URL
const 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,
// ...
});

Para verificar tokens do Firebase Auth usando os certificados públicos do 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,
// ...
});

Montando rotas de autenticação e ações do painel

Seção intitulada “Montando rotas de autenticação e ações do painel”

Se o seu provedor de autenticação personalizado exigir a montagem de endpoints de redirecionamento (como rotas de callback OAuth ou fluxos de login SAML), implemente o método createAuthRoutes no seu 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;
}
};

Se você deseja permitir operações CRUD de usuário diretamente no painel, implemente o helper userManagement nas opções do adaptador, que fornece hooks para listUsers, createUser, updateUser e deleteUser.