El Firebase Admin SDK es un conjunto de bibliotecas de servidor que te permite interactuar con Firebase desde entornos privilegiados para realizar acciones como consultas y mutaciones en un servicio Firebase Data Connect para la administración masiva de datos y otras operaciones con privilegios elevados y credenciales suplantadas.
El Admin SDK te proporciona una API para llamar a operaciones en modos de lectura/escritura y de solo lectura. Con las operaciones de solo lectura, puedes implementar funciones administrativas que no pueden modificar los datos de tus bases de datos con la tranquilidad de que no se producirán cambios.
Configuración del SDK de Admin
Para comenzar a usar Firebase Data Connect en tu servidor, primero deberás instalar y configurar Admin SDK para Node.js.
Inicializa el SDK de Admin en tus secuencias de comandos
Para inicializar el SDK, importa las extensiones Data Connect y declara el ID y la ubicación del servicio de tu proyecto.
import { initializeApp } from 'firebase-admin/app';
import { getDataConnect } from 'firebase-admin/data-connect';
// If you'd like to use OAuth2 flows and other credentials to log in,
// visit https://firebase.google.com/docs/admin/setup#initialize-sdk
// for alternative ways to initialize the SDK.
const app = initializeApp();
const dataConnect = getDataConnect({
serviceId: 'serviceId',
location: 'us-west2'
});
Diseña consultas y mutaciones para usar con Admin SDK
El Admin SDK es útil para ejecutar operaciones de Data Connect, teniendo en cuenta las siguientes consideraciones.
Comprende el SDK y la directiva de operación @auth(level: NO_ACCESS)
Dado que Admin SDK opera con privilegios, puede ejecutar cualquiera de tus consultas y mutaciones, independientemente de los niveles de acceso establecidos con las directivas @auth, incluido el nivel NO_ACCESS.
Si, junto con tus operaciones del cliente, organizas tus consultas y mutaciones administrativas en archivos fuente .gql para importarlas en secuencias de comandos administrativas, Firebase te recomienda que marques las operaciones administrativas sin ningún nivel de acceso de autorización o, tal vez, que seas más explícito y las establezcas como NO_ACCESS. De cualquier manera, esto evita que dichas operaciones se ejecuten desde clientes o en otros contextos no privilegiados.
Usa el SDK con el emulador de Data Connect
En los entornos de prototipos y pruebas, puede ser útil realizar la creación de datos iniciales y otras operaciones en los datos locales. Admin SDK te permite simplificar tus flujos de trabajo, ya que puede ignorar la autenticación y la autorización para los flujos locales. (También puedes habilitar explícitamente el cumplimiento de la configuración de autenticación y autorización de tus operaciones con la suplantación de identidad del usuario).
Los SDKs de Firebase Admin se conectan automáticamente al emulador de Data Connect cuando se establece la variable de entorno DATA_CONNECT_EMULATOR_HOST:
export DATA_CONNECT_EMULATOR_HOST="127.0.0.1:9399"
Para obtener más información, consulte:
- La guía para la inicialización de datos en el desarrollo local
- La documentación del emulador de Data Connect
Ejecuta operaciones de administrador
El Admin SDK se proporciona para operaciones privilegiadas en tus datos críticos.
El SDK de Admin proporciona tres conjuntos de APIs:
- SDKs de Admin generados, que son SDKs con seguridad de tipos generados a partir de tus definiciones de
gqlde la misma manera en que generas SDKs de cliente. - Una interfaz general para ejecutar operaciones de GraphQL arbitrarias, en la que tu código implementa consultas y mutaciones, y las pasa al método
executeGraphqlde lectura y escritura o al métodoexecuteGraphqlReadde solo lectura. - Es una interfaz especializada para operaciones de datos masivas que, en lugar de métodos
executeGraphqlgenéricos, expone métodos específicos para operaciones de mutación:insert,insertMany,upsertyupsertMany.
Administra datos con los SDKs generados
Generas SDKs de Admin a partir de tus definiciones de gql de la misma manera en que generas SDKs de cliente.
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.
Administra datos con métodos de executeGraphql
Si necesitas ejecutar operaciones únicas para las que no definiste mutaciones o consultas de gql, puedes usar el método executeGraphql o el método executeGraphqlRead de solo lectura.
Suplantación de la identidad de un usuario no autenticado
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.
// Query to get posts, with authentication level PUBLIC
const queryGetPostsImpersonation = `
query getPosts @auth(level: PUBLIC) {
posts {
description
}
}`;
// Attempt to access data as an unauthenticated user
const optionsUnauthenticated: GraphqlOptions<undefined> = {
impersonate: {
unauthenticated: true
}
};
// executeGraphql with impersonated unauthenticated user scope
const gqlResponse = await dataConnect.executeGraphql<UserData, undefined>(queryGetPostsImpersonation, optionsUnauthenticated);
Suplantación de la identidad de un usuario
También hay casos de uso en los que deseas que tus secuencias de comandos modifiquen los datos del usuario en función de credenciales limitadas, en nombre de un usuario específico. Este enfoque respeta el principio de privilegio mínimo.
Para usar esta interfaz, recopila información de un token de autorización JWT personalizado que siga el formato de token Authentication. Consulta también la guía de tokens personalizados.
// Get the current user's data
const queryGetUserImpersonation = `
query getUser @auth(level: USER) {
user(key: {uid_expr: "auth.uid"}) {
id,
name
}
}`;
// Impersonate a user with the specified auth claims
const optionsAuthenticated: GraphqlOptions<undefined> = {
impersonate: {
authClaims: {
sub: 'QVBJcy5ndXJ1'
}
}
};
// executeGraphql with impersonated authenticated user scope
const gqlResponse = await dataConnect.executeGraphql<UserData, undefined>(queryGetUserImpersonation, optionsAuthenticated);
// gqlResponse -> { "data": { "user": { "id": "QVBJcy5ndXJ1", "name": "Fred" } } }
Usa credenciales administrativas
Si realizas una operación que requiere permisos de nivel de administrador, omite el parámetro de suplantación en la llamada:
// User can be publicly accessible, or restricted to admins
const query = "query getProfile(id: AuthID) { user(id: $id) { id name } }";
interface UserData {
user: {
id: string;
name: string;
};
}
export interface UserVariables {
id: string;
}
const options:GraphqlOptions<UserVariables> = { variables: { id: "QVBJcy5ndXJ1" } };
// executeGraphql
const gqlResponse = await dataConnect.executeGraphql<UserData, UserVariables>(query, options);
// executeGraphqlRead (similar to previous sample but only for read operations)
const gqlResponse = await dataConnect.executeGraphqlRead<UserData, UserVariables>(query, options);
// gqlResponse -> { "data": { "user": { "id": "QVBJcy5ndXJ1", "name": "Fred" } } }
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.
Realizar operaciones de datos masivas
Firebase recomienda que uses Admin SDK para las operaciones de datos masivas en bases de datos de producción.
El SDK proporciona los siguientes métodos para trabajar con datos masivos. A partir de los argumentos proporcionados, cada método construye y ejecuta una mutación de GraphQL.
// Methods of the bulk operations API
// dc is a Data Connect admin instance from getDataConnect
const resp = await dc.insert("movie" /*table name*/, data[0]);
const resp = await dc.insertMany("movie" /*table name*/, data);
const resp = await dc.upsert("movie" /*table name*/, data[0]);
const resp = await dc.upsertMany("movie" /*table name*/, data);
Notas de rendimiento para operaciones masivas
Cada solicitud al backend generará un viaje de ida y vuelta a Cloud SQL, por lo que cuanto más agrupes, mayor será la capacidad de procesamiento.
Sin embargo, cuanto mayor sea el tamaño del lote, más larga será la instrucción SQL generada. Cuando se alcance el límite de longitud de la instrucción SQL de PostgreSQL, se producirá un error.
En la práctica, experimenta para encontrar el tamaño de lote adecuado para tu carga de trabajo.
Próximos pasos
- Obtén información para inicializar tus bases de datos con datos usando Admin SDK
- Revisa la API de Admin SDK.
- Usa la CLI de Firebase y la consola de Google Cloud para otras operaciones de administración de proyectos, como administrar esquemas y conectores y administrar servicios y bases de datos.