Skip to content
Blog

Backend Verification

Every authenticated Tribe session produces a userToken, a standard JWT signed with your site’s secret key. Because the signature is cryptographic, your backend can verify a user’s identity by checking it alone, no database lookup or network call back to Tribe required.

  1. User logs in via the SDK on the frontend
  2. The SDK returns a userToken (JWT) alongside the session
  3. Your frontend sends the userToken to your backend (for example, in an Authorization header)
  4. Your backend verifies the JWT with your site’s TRIBE_KEY
  1. Go to the Tribe dashboard
  2. Open your site’s Settings
  3. Copy the TRIBE_KEY

This is a secret. Store it as an environment variable and keep it out of version control.

On the frontend:

import { Tribe } from "@tribecloud/sdk";
const token = tribe.getUserToken();
// Send this to your backend

The token refreshes automatically when you call getSession(), so it stays current as long as the user has an active session.

{
sub: string; // User ID
email: string | null; // null for wallet/OAuth/Google users
pseudonymousId?: string; // Stable hash for non-email users
authMethod?: string; // "email" | "wallet" | "google" | "github" | etc.
role: string | null; // User's role (set via tribe.setRole())
siteId: string; // Your site ID
iat: number; // Issued at (unix timestamp)
exp: number; // Expires at (1 hour after iat)
}
import { createHmac } from "crypto";
function verifyUserToken(userToken: string, tribeKey: string) {
const [header, payload, signature] = userToken.split(".");
const expected = createHmac("sha256", tribeKey)
.update(`${header}.${payload}`)
.digest("base64url");
if (signature !== expected) throw new Error("Invalid token");
const data = JSON.parse(Buffer.from(payload, "base64url").toString());
if (data.exp < Math.floor(Date.now() / 1000)) throw new Error("Token expired");
return data; // { sub, email, role, siteId, iat, exp }
}
// Usage in an Express route
app.get("/api/profile", (req, res) => {
const token = req.headers.authorization?.replace("Bearer ", "");
try {
const user = verifyUserToken(token, process.env.TRIBE_KEY);
res.json({ userId: user.sub, email: user.email, role: user.role });
} catch (err) {
res.status(401).json({ error: "Unauthorized" });
}
});

If you’d rather not write the verification by hand, any standard JWT library that supports HS256 works fine. Popular choices include jose or jsonwebtoken for Node.js and PyJWT for Python.

  • Rotating the TRIBE_KEY in the dashboard invalidates every outstanding user token immediately. Plan for a brief re-authentication window if you rotate keys.
  • For users who signed in via wallet or social login, the email field will be null. Use sub (the user ID) or pseudonymousId as a stable identifier instead.
  • The userToken is separate from the session token that the SDK uses internally to talk to Tribe’s servers. They serve different purposes and shouldn’t be confused.