Node.js and Express
@tausi-auth/node has no dependencies and needs Node 18+. TausiBackend (secret key) protects your API and manages users; TausiClient (publishable key) signs users in from Node, Electron, React Native or a CLI.
Install
@tausi-auth/node on npmRequires Node 18.17+, Bun or Deno; no dependenciesShell
npm install @tausi-auth/nodetausi.tsTypeScript
import { TausiBackend } from "@tausi-auth/node";
export const tausi = new TausiBackend({
baseUrl: process.env.TAUSI_URL ?? "https://auth.tausi.app",
secretKey: process.env.TAUSI_SECRET_KEY!,
});
await tausi.getProject(); // optional startup check that the key worksProtect your API
Your frontend sends Authorization: Bearer <sessionToken>. Check it on every request:
verifyTypeScript
const auth = await tausi.authenticateRequest(request); // any Request, Headers or Node IncomingMessage
if (!auth) return unauthorized(); // invalid, expired, revoked, banned or another project
auth.user.id; auth.user.email; auth.session.expiresAt;
// or with a token you already have:
const result = await tausi.verifySession(token);These return null for any bad token and only throw TausiError for problems on your side (wrong secret key, Tausi unreachable, 5xx). Answer those with 503, not 401, so users aren't signed out by an outage.
Express
server.tsTypeScript
import express from "express";
import { optionalAuth, requireAuth } from "@tausi-auth/node/express";
import { tausi } from "./tausi";
const app = express();
app.get("/api/me", requireAuth(tausi), (req, res) => res.json(req.auth.user)); // 401 without a valid token
app.get("/api/feed", optionalAuth(tausi), (req, res) => res.json({ personal: Boolean(req.auth) }));
app.use((err, _req, res, _next) => res.status(503).json({ error: "Authentication unavailable" }));Hono, Fastify, Bun, Deno
hono.tsTypeScript
import { Hono } from "hono";
const app = new Hono();
app.use("/api/*", async (c, next) => {
const auth = await tausi.authenticateRequest(c.req.raw);
if (!auth) return c.json({ error: "Unauthorized" }, 401);
c.set("auth", auth);
await next();
});fastify.tsTypeScript
fastify.addHook("preHandler", async (request, reply) => {
const auth = await tausi.authenticateRequest(request.raw);
if (!auth) return reply.code(401).send({ error: "Unauthorized" });
request.auth = auth;
});Manage users
adminTypeScript
const page = await tausi.users.list({ q: "asha", access: "active", page: 1, pageSize: 50 });
// each item: status ("signed_in" / "signed_out"), activeSessions, lastSignInAt, lastActiveAt, access, ...
const detail = await tausi.users.get(userId); // user, sessions (devices), signInHistory, recentAudit
await tausi.users.update(userId, { emailVerified: true, publicMetadata: { plan: "pro" }, privateMetadata: { stripeId: "cus_123" } });
await tausi.users.suspend(userId, { durationHours: 24, reason: "Chargeback" });
await tausi.users.ban(userId, { reason: "Spam" });
await tausi.users.unban(userId);
await tausi.users.bulk("revoke_sessions", [idA, idB]);
await tausi.users.revokeSessions(userId);
await tausi.users.delete(userId);Everything is in Managing users.
Sign users in (Node, Electron, React Native, CLIs)
client.tsTypeScript
import { TausiClient, randomDeviceId } from "@tausi-auth/node";
const tausi = new TausiClient({
baseUrl: "https://auth.tausi.app",
publishableKey: "pk_…",
tokenStore: { get: () => store.get("token"), set: (t) => store.set("token", t) }, // may be async (AsyncStorage, Keychain)
deviceId: savedDeviceId ?? randomDeviceId(), // persist one per install
});
await tausi.signIn({ email, password });
const token = await tausi.getToken(); // send as Authorization: Bearer
await tausi.updateUser({ username: "asha" });
// Social sign-in with PKCE
const { url, codeVerifier } = await tausi.startOAuth("google", { redirectTo: "https://app.example.com/auth/callback" });
// open url in a browser ... then, with the URL it came back to:
await tausi.handleOAuthRedirect(callbackUrl, codeVerifier);Errors
errorsTypeScript
import { isTausiError } from "@tausi-auth/node";
try { /* ... */ } catch (e) {
if (isTausiError(e)) {
e.code; // "INVALID_CREDENTIALS", "ACCOUNT_BANNED", "RATE_LIMITED", ...
e.status; // HTTP status, 0 for network errors
e.retryAfter; // seconds, for RATE_LIMITED
e.requestId; // quote it when reporting a problem
e.details; // e.g. { issues: [{ path, message }] } for VALIDATION_ERROR
}
}| See also | |
|---|---|
| All error codes | Every code with its HTTP status and meaning. |