Los SDKs de Admin de Firebase Data Connect te permiten llamar a tus consultas y mutaciones desde entornos de confianza, como Cloud Functions, backends personalizados o tu propia estación de trabajo. De la misma manera en que generas SDKs para tus apps cliente, puedes generar un SDK de administrador personalizado en paralelo mientras diseñas los esquemas, las consultas y las mutaciones que implementas en tu servicio de Data Connect. Luego, integra los métodos de este SDK en la lógica de backend o en las secuencias de comandos de administración.
Como mencionamos en otro lugar, es importante tener en cuenta que los clientes no envían las consultas ni las mutaciones de Data Connect en el momento de la solicitud. En cambio, cuando se implementan, las operaciones de Data Connect se almacenan en el servidor como Cloud Functions. Esto significa que, cada vez que implementes cambios en tus consultas y mutaciones, también deberás volver a generar los SDKs de administrador y volver a implementar los servicios que dependan de ellos.
Antes de comenzar
- Obtén más información para diseñar esquemas, consultas y mutaciones de Data Connect. En un flujo de trabajo típico, los desarrollarás en paralelo con el código de tu aplicación, incluidos los servicios que usan SDKs de Admin.
- Instala Firebase CLI.
- Incluye el SDK de Admin para Node.js como una dependencia donde planees llamar a los SDKs de Admin generados.
Genera SDKs de Admin
Después de crear tus esquemas, consultas y mutaciones de Data Connect, puedes generar un SDK de administrador correspondiente:
Abre o crea un archivo
connector.yamly agrega una definiciónadminNodeSdk:connectorId: default generate: adminNodeSdk: outputDir: ../../dataconnect-generated/admin-generated package: "@dataconnect/admin-generated" packageJsonDir: ../..El archivo
connector.yamlsuele encontrarse en el mismo directorio que los archivos GraphQL (.gql) que contienen las definiciones de tus consultas y mutaciones. Si ya generaste SDKs de cliente, este archivo ya se creó.Genera el SDK.
Si tienes instalada la extensión Data Connect de VS Code, siempre mantendrá actualizados los SDKs generados.
De lo contrario, usa Firebase CLI:
firebase dataconnect:sdk:generateO bien, para volver a generar automáticamente los SDKs cuando actualices tus archivos
gql, haz lo siguiente:firebase dataconnect:sdk:generate --watch
Ejecuta operaciones desde un SDK de Admin
El SDK de Admin generado contiene interfaces y funciones que se corresponden con tus definiciones de gql, que puedes usar para realizar operaciones en tu base de datos. Por ejemplo, supongamos que generaste un SDK para una base de datos de canciones, junto con una consulta, getSongs:
import { initializeApp } from "firebase-admin/app";
import { getSongs } from "@dataconnect/admin-generated";
const adminApp = initializeApp();
const songs = await getSongs(
{ limit: 4 },
{ impersonate: { unauthenticated: true } }
);
O bien, para especificar la configuración de un conector, haz lo siguiente:
import { initializeApp } from "firebase-admin/app";
import { getDataConnect } from "firebase-admin/data-connect";
import {
connectorConfig,
getSongs,
} from "@dataconnect/admin-generated";
const adminApp = initializeApp();
const adminDc = getDataConnect(connectorConfig);
const songs = await getSongs(
adminDc,
{ limit: 4 },
{ impersonate: { unauthenticated: true } }
);
Suplantación de la identidad de un usuario no autenticado
Los SDKs de Admin están diseñados para ejecutarse desde entornos confiables y, por lo tanto, tienen acceso sin restricciones a tus bases de datos.
Cuando ejecutes operaciones públicas con el SDK de Admin, debes evitar hacerlo con privilegios de administrador completos (siguiendo el principio de privilegio mínimo). En su lugar, debes ejecutar la operación como un usuario suplantado (consulta la siguiente sección) o como un usuario no autenticado suplantado.
Los usuarios no autenticados solo pueden ejecutar operaciones marcadas como PUBLIC.
En el ejemplo anterior, la consulta getSongs se ejecuta como un usuario no autenticado.
Suplantación de la identidad de un usuario
También puedes realizar operaciones en nombre de usuarios específicos pasando parte o la totalidad de un token de Firebase Authentication en la opción impersonate. Como mínimo, debes especificar el ID de usuario del usuario en la reclamación sub. (Este es el mismo valor que el valor del servidor auth.uid al que puedes hacer referencia en las operaciones de GraphQL de Data Connect).
Cuando suplantas la identidad de un usuario, la operación solo se realizará correctamente si los datos del usuario que proporcionaste pasan las verificaciones de autenticación especificadas en tu definición de GraphQL.
Si llamas al SDK generado desde un extremo accesible de forma pública, es fundamental que el extremo requiera autenticación y que valides la integridad del token de autenticación antes de usarlo para suplantar la identidad de un usuario.
Cuando se usa Cloud Functions invocable, el token de autenticación se verifica automáticamente y puedes usarlo como en el siguiente ejemplo:
import { HttpsError, onCall } from "firebase-functions/https";
export const callableExample = onCall(async (req) => {
const authClaims = req.auth?.token;
if (!authClaims) {
throw new HttpsError("unauthenticated", "Unauthorized");
}
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
// ...
});
De lo contrario, usa el método verifyIdToken de Admin SDK para validar y decodificar el token de autenticación. Por ejemplo, supongamos que tu extremo se implementa como una función HTTP simple y que pasaste el token Firebase Authentication a tu extremo con el encabezado authorization, como es habitual:
import { getAuth } from "firebase-admin/auth";
import { onRequest } from "firebase-functions/https";
const auth = getAuth();
export const httpExample = onRequest(async (req, res) => {
const token = req.header("authorization")?.replace(/^bearer\s+/i, "");
if (!token) {
res.sendStatus(401);
return;
}
let authClaims;
try {
authClaims = await auth.verifyIdToken(token);
} catch {
res.sendStatus(401);
return;
}
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
// ...
});
Solo cuando realices tareas administrativas verdaderas, como la migración de datos, desde un entorno seguro y no accesible de forma pública, debes especificar un ID de usuario que no provenga de una fuente verificable:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
Ejecución con acceso sin restricciones
Si realizas una operación que requiere permisos de nivel de administrador, omite el parámetro de suplantación en la llamada:
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
Una operación llamada de esta manera tiene acceso completo a la base de datos. Si tienes consultas o mutaciones que solo se deben usar con fines administrativos, debes definirlas con la directiva @auth(level: NO_ACCESS). De esta manera, se garantiza que solo los llamadores a nivel de administrador puedan ejecutar estas operaciones.