Le Firebase Admin SDK est un ensemble de bibliothèques de serveur qui vous permet d'interagir avec Firebase à partir d'environnements privilégiés pour effectuer des actions telles que des requêtes et des mutations sur un Firebase Data Connect service pour la gestion groupée des données et d'autres opérations avec des droits élevés et des identifiants empruntés.
Le Admin SDK vous fournit une API pour appeler des opérations en mode lecture/écriture et en mode lecture seule. Avec les opérations en lecture seule, vous avez l'assurance d'implémenter des fonctions administratives qui ne peuvent pas modifier les données de vos bases de données.
Configuration du SDK Admin
Pour commencer à utiliser le avec Firebase Data Connect sur votre serveur, vous devez d'abord installer et configurer le Admin SDK pour Node.js.
Initialiser le SDK Admin dans vos scripts
Pour initialiser le SDK, importez les extensions Data Connect et déclarez l'ID et l'emplacement de votre service de projet.
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'
});
Concevoir des requêtes et des mutations à utiliser avec le Admin SDK
Le Admin SDK est utile pour exécuter des opérations Data Connect, compte tenu des considérations suivantes.
Comprendre le SDK et la directive d'opération @auth(level: NO_ACCESS)
Étant donné que le Admin SDK fonctionne avec des droits d’accès, il peut exécuter n’importe laquelle de vos
requêtes et mutations, quels que soient les niveaux d’accès définis à l’aide de @auth directives, y compris le niveau NO_ACCESS.
Si, en plus de vos opérations client, vous organisez vos requêtes et mutations administratives dans des fichiers sources .gql à importer dans des scripts administratifs, Firebase vous recommande de marquer les opérations administratives sans aucun niveau d'accès d'autorisation, ou peut-être d'être plus explicite et de les définir sur NO_ACCESS. Dans tous les cas, cela empêche l'exécution de ces opérations à partir de clients ou dans d'autres contextes non privilégiés.
Utiliser le SDK avec l'émulateur Data Connect
Dans les environnements de prototype et de test, il peut être utile d'effectuer l'amorçage des données et d'autres opérations sur les données locales. Le Admin SDK vous permet de simplifier vos workflows, car il peut ignorer l'authentification et l'autorisation pour les flux locaux. (Vous pouvez également choisir explicitement de respecter la configuration d'authentification et d'autorisation de vos opérations avec l'emprunt d'identité de l'utilisateur.)
Les SDK Admin Firebase se connectent automatiquement à l'Data Connect
émulateur lorsque la variable d'environnement DATA_CONNECT_EMULATOR_HOST est définie :
export DATA_CONNECT_EMULATOR_HOST="127.0.0.1:9399"
Pour en savoir plus, consultez les pages suivantes :
- Le guide sur l'amorçage des données dans le développement local
- La documentation de l'émulateur Data Connect.
Exécuter des opérations d'administration
Le Admin SDK est fourni pour les opérations privilégiées sur vos données critiques.
Le SDK Admin fournit trois ensembles d'API :
- Les SDK Admin générés, qui sont des SDK de type sécurisé générés à partir de vos définitions
gqlde la même manière que vous générez des SDK client. - Une interface générale pour exécuter des opérations GraphQL arbitraires, dans laquelle votre
code implémente des requêtes et des mutations, et les transmet à la méthode en lecture/écriture
executeGraphqlou à la méthode en lecture seuleexecuteGraphqlRead. - Une interface spécialisée pour les opérations de données groupées, qui, au lieu des
méthodes
executeGraphqlgénériques, expose des méthodes dédiées aux opérations de mutation :insert,insertMany,upsertetupsertMany.
Gérer les données avec les SDK générés
Vous générez des SDK Admin
à partir de vos définitions gql de la même manière que vous générez des SDK client.
Le SDK Admin généré contient des interfaces et des fonctions qui correspondent à vos définitions gql, que vous pouvez utiliser pour effectuer des opérations sur votre base de données. Supposons, par exemple, que vous ayez généré un SDK pour une base de données de chansons, ainsi qu'une requête, 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 } }
);
Vous pouvez également spécifier une configuration de connecteur :
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 } }
);
Emprunter l'identité d'un utilisateur non authentifié
Les SDK Admin sont conçus pour être exécutés à partir d'environnements de confiance et disposent donc d'un accès illimité à vos bases de données.
Lorsque vous exécutez des opérations publiques avec le SDK Admin, vous devez éviter de les exécuter avec des droits d'administrateur complets (en suivant le principe du moindre privilège). Vous devez plutôt exécuter l'opération en tant qu'utilisateur emprunté (voir la section suivante) ou en tant qu'utilisateur non authentifié emprunté.
Les utilisateurs non authentifiés ne peuvent exécuter que les opérations marquées comme PUBLIC.
Dans l'exemple ci-dessus, la requête getSongs est exécutée en tant qu'utilisateur non authentifié.
Emprunter l'identité d'un utilisateur
Vous pouvez également effectuer des opérations au nom d'utilisateurs spécifiques en transmettant une partie ou
la totalité d'un jeton Firebase Authentication dans l'option impersonate. Vous
devez au minimum spécifier l'ID utilisateur de l'utilisateur dans la revendication sub. (Il s'agit de la même valeur que la
auth.uid valeur de serveur
à laquelle vous pouvez faire référence dans les opérations GraphQL Data Connect.)
Lorsque vous empruntez l'identité d'un utilisateur, l'opération ne réussit que si les données utilisateur que vous avez fournies réussissent les vérifications d'authentification spécifiées dans votre définition GraphQL.
Si vous appelez le SDK généré à partir d'un point de terminaison accessible au public, il est essentiel que le point de terminaison nécessite une authentification et que vous validiez l'intégrité du jeton d'authentification avant de l'utiliser pour emprunter l'identité d'un utilisateur.
Lorsque vous utilisez des Cloud Functions appelables, le jeton d'authentification est automatiquement vérifié et vous pouvez l'utiliser comme dans l'exemple suivant :
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 } }
);
// ...
});
Sinon, utilisez la Admin SDK du verifyIdToken pour valider et décoder
le jeton d'authentification. Supposons, par exemple, que votre point de terminaison soit implémenté en tant que
fonction HTTP simple et que vous ayez transmis le Firebase Authentication jeton
à votre point de terminaison à l'aide de l'en-tête authorization, comme c'est la norme :
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 } }
);
// ...
});
Vous ne devez spécifier un ID utilisateur qui ne provient pas d'une source vérifiable que lorsque vous effectuez de véritables tâches administratives, telles que la migration de données, à partir d'un environnement sécurisé et non accessible au public :
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
Exécution avec un accès illimité
Si vous effectuez une opération qui nécessite des autorisations de niveau administrateur, omettez le paramètre d'emprunt d'identité de l'appel :
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
Une opération appelée de cette manière dispose d'un accès complet à la base de données. Si vous avez des requêtes ou des mutations destinées à être utilisées uniquement à des fins d'administration, vous devez les définir avec la directive @auth(level: NO_ACCESS). Cela garantit que seuls les appelants de niveau administrateur peuvent exécuter ces opérations.
Gérer les données avec les méthodes executeGraphql
Si vous devez exécuter des opérations ponctuelles pour lesquelles vous n'avez pas défini de gql
mutations ou de requêtes, vous pouvez utiliser la méthode executeGraphql ou la méthode
executeGraphqlRead en lecture seule.
Emprunter l'identité d'un utilisateur non authentifié
Lorsque vous exécutez des opérations publiques avec le SDK Admin, vous devez éviter de les exécuter avec des droits d'administrateur complets (en suivant le principe du moindre privilège). Vous devez plutôt exécuter l'opération en tant qu'utilisateur emprunté
(voir la section suivante) ou en tant qu'utilisateur non authentifié
emprunté. Les utilisateurs non authentifiés ne peuvent exécuter que les opérations marquées comme 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);
Emprunter l'identité d'un utilisateur
Il existe également des cas d'utilisation dans lesquels vous souhaitez que vos scripts modifient les données utilisateur en fonction d'identifiants limités, au nom d'un utilisateur spécifique. Cette approche respecte le principe du moindre privilège.
Pour utiliser cette interface, collectez des informations à partir d'un jeton d'authentification JWT personnalisé qui suit le Authentication format de jeton. Consultez également le guide sur les jetons personnalisés.
// 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" } } }
Utiliser des identifiants d'administrateur
Si vous effectuez une opération qui nécessite des autorisations de niveau administrateur, omettez le paramètre d'emprunt d'identité de l'appel :
// 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" } } }
Une opération appelée de cette manière dispose d'un accès complet à la base de données. Si vous avez des requêtes ou des mutations destinées à être utilisées uniquement à des fins d'administration, vous devez les définir avec la directive @auth(level: NO_ACCESS). Cela garantit que seuls les appelants de niveau administrateur peuvent exécuter ces opérations.
Effectuer des opérations de données groupées
Firebase vous recommande d'utiliser le Admin SDK pour les opérations de données groupées sur les bases de données de production.
Le SDK fournit les méthodes suivantes pour travailler avec des données groupées. À partir des arguments fournis, chaque méthode construit et exécute une mutation 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);
Remarques concernant les performances pour les opérations groupées
Chaque requête adressée au backend entraîne un aller-retour vers Cloud SQL. Par conséquent, plus vous regroupez les requêtes, plus le débit est élevé.
Toutefois, plus la taille du lot est importante, plus l'instruction SQL générée est longue. Lorsque la limite de longueur de l'instruction SQL PostgreSQL est atteinte, une erreur se produit.
En pratique, faites des tests pour trouver la taille de lot appropriée pour votre charge de travail.
Étape suivante
- Découvrez comment amorcer vos bases de données avec des données à l'aide du Admin SDK
- Consultez l'API du Admin SDK.
- Utilisez la Firebase CLI et la Google Cloud console pour d'autres opérations de gestion de projet, telles que la gestion des schémas et des connecteurs et la gestion des services et des bases de données.