← Files FirebaseARCHIVED FILE
reference/sdk_admin_node.md
4.1 KB · Sep 30, 2026 · 23:02 UTC
# Admin Node SDK
Consult this file when writing server-side code (e.g., Cloud Functions) that
needs elevated privileges or needs to impersonate specific users.
### Best Practices for Agents
- **Understand Operation Storage**: SQL Connect queries and mutations are stored
on the server like Cloud Functions. Clients do not submit the raw operations.
Therefore, **whenever you update operations, you must regenerate the SDK and
redeploy services** that use it.
- **Follow Least Privilege**: Admin SDKs have unrestricted access by default.
Always use impersonation when possible to limit access.
- **Impersonation**: Use the `impersonate` parameter to run operations as a
specific user or as an unauthenticated user.
- **Impersonation Variables**: If you call an operation with optional variables
and want to pass impersonation options but without variables, you **MUST**
pass `undefined` as the first argument (variables) to clearly indicate no
variables are being provided.
- **Admin Operations**: If you create operations intended only for
administration, define them with `@auth(level: NO_ACCESS)`. This ensures they
can only be called via the Admin SDK with unrestricted access.
- **Resilient Enum Handling**: JavaScript/TypeScript does not enforce exhaustive
checks on enums. Always add a `default` branch to `switch` statements or an
`else` branch to handle unknown values gracefully when schemas evolve.
### Configuration in `connector.yaml`
To generate an Admin SDK, add the `adminNodeSdk` block to your `connector.yaml`:
```yaml
connectorId: my-connector
generate:
adminNodeSdk:
outputDir: "./admin-sdk"
package: "@dataconnect/admin-generated"
packageJsonDir: "." # Directory containing package.json
```
### Generation
Run the generation command:
```bash
npx -y firebase-tools@latest dataconnect:sdk:generate
```
### Usage Examples
#### 1. Impersonating an Unauthenticated User
Unauthenticated users can only run operations marked as `PUBLIC`.
```typescript
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 } }
);
```
#### 2. Impersonating a Specific User (Cloud Functions)
When using callable Cloud Functions, the authentication token is automatically
verified.
```typescript
import { HttpsError, onCall } from "firebase-functions/https";
import { getMyFavoriteSongs } from "@dataconnect/admin-generated";
export const callableExample = onCall(async (req) => {
const authClaims = req.auth?.token;
if (!authClaims) {
throw new HttpsError("unauthenticated", "Unauthorized");
}
const favoriteSongs = await getMyFavoriteSongs(
adminDc,
undefined,
{ impersonate: { authClaims } }
);
return favoriteSongs;
});
```
#### 3. Impersonating a Specific User (Plain HTTP)
For non-callable endpoints, you must verify the token yourself.
```typescript
import { getAuth } from "firebase-admin/auth";
import { onRequest } from "firebase-functions/https";
import { getMyFavoriteSongs } from "@dataconnect/admin-generated";
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(
adminDc,
undefined,
{ impersonate: { authClaims } }
);
res.send(favoriteSongs);
});
```
#### 4. Running with Unrestricted Access
Omit the `impersonate` parameter to run with full admin access. Only do this for
true administrative tasks.
```typescript
import { upsertSong } from "@dataconnect/admin-generated";
await upsertSong(adminDc, {
title: "New Song",
genre: "Rock"
});
```
SHA-256: 6ee20ef0d81234b6cbcc5cbbf62c8e755a66a04fd7f547a0dabd13d79ef8acdb