By default, MossClient authenticates using your projectId and projectKey:
import { MossClient } from '@moss-dev/moss';
const client = new MossClient('your-project-id', 'your-project-key');
This works well for server-side code where secrets stay on the backend. For browser / frontend use, you should never embed your projectKey in client-side code. Instead, implement a custom IAuthenticator that fetches a short-lived token from your own backend.
The IAuthenticator interface
The SDK exports IAuthenticator and AuthToken types from @moss-dev/moss. Their
shapes are shown below for reference — you don’t need to redefine them in your code.
// Exported from '@moss-dev/moss' — shown here for reference
interface AuthToken {
token: string; // Bearer token to send with each request
expiresIn: number; // Token lifetime in seconds, as returned by your backend
}
interface IAuthenticator {
getAuthToken(): Promise<AuthToken>;
getAuthHeader(): Promise<string>; // returns "Bearer <token>"
}
Both methods must be implemented. The SDK calls getAuthHeader() before every request.
Recommended setup
1. Your backend — expose a token endpoint
Your backend holds the projectKey securely and uses the SDK to fetch a token, returning it directly to the frontend.
// Example: Express route on your backend
import express from 'express';
import { MossClient } from '@moss-dev/moss';
const app = express();
const moss = new MossClient('your-project-id', 'your-project-key');
// Protect this route with your own auth middleware
app.get('/api/moss-token', yourAuthMiddleware, async (req, res) => {
try {
// getAuthToken() returns { token, expiresIn } — forward it directly
res.json(await moss.getAuthToken());
} catch (err) {
res.status(500).json({ error: 'Failed to retrieve token' });
}
});
2. Your frontend — implement IAuthenticator
Since your backend forwards the Moss auth response unchanged, response.json() already matches the AuthToken shape — no manual mapping needed.
import { MossClient } from '@moss-dev/moss';
import type { IAuthenticator, AuthToken } from '@moss-dev/moss';
class MyBackendAuthenticator implements IAuthenticator {
async getAuthToken(): Promise<AuthToken> {
const response = await fetch('/api/moss-token', {
credentials: 'include', // include your session cookie / auth header
});
if (!response.ok) {
throw new Error(`Failed to fetch Moss token: HTTP ${response.status}`);
}
return response.json(); // shape matches AuthToken: { token, expiresIn }
}
async getAuthHeader(): Promise<string> {
const { token } = await this.getAuthToken();
return `Bearer ${token}`;
}
}
// Pass your authenticator to MossClient
const client = new MossClient('your-project-id', new MyBackendAuthenticator());
Token caching
The SDK automatically wraps your authenticator with an internal caching layer. Tokens are cached for expiresIn - 60 seconds, so your backend is only called when the token is about to expire — not on every SDK request. No extra setup is needed.
Make sure your backend returns the correct expiresIn value so the cache TTL is accurate.
Summary
| Use case | How to initialize |
|---|
| Server-side (Node.js) | new MossClient(projectId, projectKey) |
| Frontend — custom auth | new MossClient(projectId, new MyBackendAuthenticator()) |
Rule of thumb: your projectKey must never appear in browser-facing code. The custom authenticator pattern ensures it stays on your server while the frontend still gets authenticated access to Moss.