Auth Management (Server-Side)
Administer the end users of your project’s auth apps from your backend, using the Server SDK.
This page covers server-side user administration. For client-side user
authentication (login, register, profile), see the
Client SDK. Creating an auth app, changing its settings
and rotating its signing keys are not in the SDK — they live in the Dashboard
and the ghayma auth commands.
import { Ghayma } from "@ghayma/sdk";
const ghayma = new Ghayma({ apiKey: process.env.GHAYMA_API_KEY });These calls need the auth capability, which the Application purpose
grants. A key restricted to specific auth apps
answers 404 for every other app in the project.
Verifying User Tokens
This SDK does not verify user tokens. @ghayma/sdk acts on your auth
apps with a project API key, not on your end-users’ sessions.
Access tokens are RS256-signed JWTs, so your backend verifies them locally against the app’s published signing key (JWKS) with any standard JWT library — no API call per request:
import { verifyAccessToken } from "@/lib/auth";
const claims = await verifyAccessToken(token); // throws if invalid or expired
console.log(claims.sub); // user id
console.log(claims.email);
console.log(claims.app_metadata); // roles / plan / tenant, if you set themThe lib/auth.ts helper, plus ready-made Express and Next.js
middleware, is in
Auth Integration → JWT Verification.
List Users
Page through the users registered in your auth app.
const { users, total, page, per_page } = await ghayma.auth.listUsers("my-app", {
page: 1,
per_page: 50,
});
for (const user of users) {
console.log(user.id, user.email, user.name, user.provider);
}Options:
| Name | Type | Default | Description |
|---|---|---|---|
page | number? | 1 | Page number |
per_page | number? | 20 | Results per page, 1–100 |
The first argument is the auth app — its slug (my-app) or its UUID.
App Metadata (Roles)
Set developer-owned data on a user — roles, plan, tenant id. Unlike the
user-editable metadata, app_metadata can only be written from here
(or the Dashboard), and it is embedded in the user’s JWT as the
app_metadata claim, so your backend can authorize from the verified token
with no extra lookups.
// Replace semantics — send the full object; {} clears it. Max 8KB.
await ghayma.auth.updateUserAppMetadata("my-app", "user-id", {
roles: ["admin"],
plan: "pro",
});Then on your server, after verifying the JWT:
const roles = (claims.app_metadata?.roles as string[]) ?? [];
if (!roles.includes("admin")) throw new Error("forbidden");Notes:
- Requires the admin or owner role on the project — read/write
collaborators get
403. - Changes reach the user’s tokens at their next refresh (up to the JWT expiry, 15 min by default). If a role change can’t wait, disabling the user ends their sessions; once re-enabled they sign in again with the new roles. A backend that verifies tokens itself still accepts an older token until it expires — see Ending every session.
- Every change is audit-logged.
Generate Password Reset Link
Mint a password-reset link for a user — for apps that send reset emails through their own transport and templates instead of Ghayma’s. This is the full-control alternative to the custom reset page (where Ghayma still sends the email).
const { link, expires_at } = await ghayma.auth.generatePasswordResetLink(
"my-app",
"[email protected]"
);
// Put `link` in your own email template and send it.The link points at your configured reset page (reset_url) when set, or the
hosted form otherwise, and behaves exactly like an emailed link: single-use,
expires in 1 hour, and minting invalidates any previously issued reset link
for that user.
Handle the link like a password:
- Send it to the user’s verified email address — never over chat, SMS, or URLs you don’t control, and never log it.
- Requires the admin or owner role on the project (
403otherwise), and is strictly rate-limited per app (429). - Every mint is recorded in the audit log (without the link itself).
Reset a User’s 2FA
The support hammer for a locked-out user (lost phone and recovery codes): clears their entire 2FA enrolment so they can sign in again — with a password, Google or GitHub — and re-enrol. It is also the way out for a user asked for a code they never set up after a Google or GitHub sign-in took over their account. Requires the admin or owner role; audited.
await ghayma.auth.resetUser2FA("my-app", "user-id");Disable / Enable User
// Disable (block login)
await ghayma.auth.disableUser("my-app", "user-id");
// Re-enable
await ghayma.auth.enableUser("my-app", "user-id");Disabling ends every session of the user at once, and a disabled user cannot sign in. Re-enabling lets them sign in again; nothing from before the disable comes back.
Delete User
await ghayma.auth.deleteUser("my-app", "user-id");This permanently deletes the user account. The user will need to re-register.
Auth App Details
Read-only. Everything that changes an app — create, configure, rotate keys,
delete — is in the Dashboard and the ghayma auth commands.
List Auth Apps
const apps = await ghayma.auth.listApps();With a project API key this lists the apps of the key’s own project — and only
those. A restricted key still sees the whole list; it just answers 404 when
you act on an app outside its restriction. With an account token the call lists
your account’s auth apps instead.
Get Auth App
const app = await ghayma.auth.getApp("my-app");Get Statistics
const stats = await ghayma.auth.getStats("my-app");
console.log(stats.total_users); // 1542
console.log(stats.logins_today); // 87