---
title: "Admin SDK (server)"
description: "Abrova Auth for your server, with the Firebase Admin SDK's names: setCustomUserClaims, getUser and revokeRefreshTokens. The @abrova/auth-admin package for Node.js, or the same calls as plain HTTPS requests from any language."
product: auth
platform: "Node.js"
language: en
url: https://abrova.ir/en/docs/auth/admin-sdk
updated: 2026-11-05
---

# Admin SDK (server)

Abrova Auth for your server, with the Firebase Admin SDK's names: setCustomUserClaims, getUser and revokeRefreshTokens. The @abrova/auth-admin package for Node.js, or the same calls as plain HTTPS requests from any language.

> **For your server only**
>
> The Admin SDK manages your app's users from your own server: their [custom claims](https://abrova.ir/docs/auth/custom-claims), their account details and their sessions. It uses the project's **server secret**, so it never runs in an app or a browser. Apps sign users in with the [Abrova Auth SDKs](https://abrova.ir/docs/auth/quick-start).

## Step 1: Installation

The package comes from Abrova Center. Point the `@abrova` scope at the Abrova registry in your project's `.npmrc`:

```bash
npm install @abrova/auth-admin
```

It needs Node.js 18 or later and has no dependencies.

## Step 2: Initialization

Set three environment variables on your server. You find them in the Console under **Project settings**:

| Variable | Value |
| --- | --- |
| `ABROVA_PROJECT_ID` | The project id. |
| `ABROVA_API_KEY` | The public API key (ab_live_...). |
| `ABROVA_SERVER_SECRET` | The server secret (ab_srv_...). Server only. |

```ts
import { initAdmin } from '@abrova/auth-admin';

const auth = initAdmin();
```

You can also pass them in code: `initAdmin({ projectId, apiKey, serverSecret })`.

## setCustomUserClaims

Replaces all of a user's custom claims. `null` or `{}` removes them. See [Custom claims](https://abrova.ir/docs/auth/custom-claims) for what a claim can hold.

```ts
await auth.setCustomUserClaims(userId, { plan: 'pro', teams: ['red'] });
```

## getUser

Returns the user, with Firebase's `UserRecord` names:

```ts
const user = await auth.getUser(userId);
```

| Field | What it is |
| --- | --- |
| `uid` | The user id (ru_...). |
| `email, emailVerified` | The e-mail address, when the user has one, and whether it is confirmed. |
| `phoneNumber` | The phone number of a Telegram sign-in, or null. |
| `displayName` | The name from Apple or Google sign-in, or null. |
| `disabled` | True when the user is disabled in the Console. |
| `providerData` | The linked sign-in methods, for example [{ providerId: "google" }]. Empty for an anonymous user. |
| `metadata` | creationTime, lastSignInTime and lastRefreshTime (the last session renewal). |
| `customClaims` | The custom claims, {} when none. |
| `tokensValidAfterTime` | The last time all of the user's sessions were ended, or null. |
| `anonymous` | True for an anonymous user. |

## revokeRefreshTokens

Ends every session of the user, on every device: no renewal works any more, so the user signs in again. Access tokens already issued keep working until they expire, at most one hour later.

```ts
await auth.revokeRefreshTokens(userId);
```

## Errors

Every error is an `AbrovaAuthAdminError` with a `code` and the HTTP `status`:

| Code | HTTP | Meaning |
| --- | --- | --- |
| `INVALID_CLAIMS` | 400 | The claims break a rule. The message names the first problem, for example "claims.sub: not an allowed name". |
| `USER_NOT_FOUND` | 404 | No such user in this project. |
| `UNAUTHENTICATED` | 401 | Wrong API key or server secret, a key of another project, or an address your project's IP allow-list does not allow. |
| `RATE_LIMITED` | 429 | Too many calls in a minute. Wait and try again. |
| `NETWORK` | - | Abrova Auth could not be reached. |

## Without Node.js: the REST API

Every call is one HTTPS request to `https://auth-users.abrova.ir` with two headers, `x-api-key` and `x-server-secret`:

| Call | Request |
| --- | --- |
| `setCustomUserClaims` | PUT /v1/projects/{projectId}/users/{userId}/custom-claims with the body { "claims": { ... } } |
| `getUser` | GET /v1/projects/{projectId}/users/{userId} |
| `revokeRefreshTokens` | POST /v1/projects/{projectId}/users/{userId}/revoke-refresh-tokens |

```php
// PHP (Laravel)
Http::withHeaders([
    'x-api-key' => env('ABROVA_API_KEY'),
    'x-server-secret' => env('ABROVA_SERVER_SECRET'),
])->put("https://auth-users.abrova.ir/v1/projects/{$projectId}/users/{$userId}/custom-claims", [
    'claims' => ['plan' => 'pro'],
]);
```

Errors come back as JSON with the same `code` and a `message`.
