@authforgesf/client
v0.3.0
Published
TypeScript SDK for AuthForge — auth, users, roles, sessions with auto refresh and typed errors
Maintainers
Readme
@authforgesf/client
TypeScript SDK for AuthForge — self-hosted identity provider. Wraps every gateway endpoint with auto token refresh, typed errors, and pluggable storage.
Designed to run server-side (Node.js / edge runtimes). It also runs in browsers technically, but see the security note below before doing so.
⚠️ Security: the API key is a backend-only secret
The SDK attaches your app X-Api-Key to every request. That key is an app-wide, server-side secret — anyone who obtains it can impersonate your entire app against AuthForge.
- Run the SDK server-side, or behind a backend-for-frontend (BFF) that holds the key and proxies calls. Never ship the API key to a browser bundle or a public client.
- If you instantiate
AuthForgeClientin a browser environment, the SDK logs a loudconsole.warn. You can acknowledge and silence it withnew AuthForgeClient({ ..., allowBrowser: true })— but only do so if you have deliberately scoped a key for that use.
Installation
pnpm add @authforgesf/client
npm install @authforgesf/client
yarn add @authforgesf/clientQuick start
import { AuthForgeClient, InMemoryStorage } from '@authforgesf/client';
// Run this server-side — apiKey is a backend-only secret (see Security note above).
const auth = new AuthForgeClient({
baseUrl: process.env.AUTHFORGE_API_URL!, // e.g. https://your-api.railway.app
apiKey: process.env.AUTHFORGE_API_KEY!, // af_<key> from AuthForge UI — keep server-side
storage: new InMemoryStorage(), // default — recommended for browsers too
});
// Register
await auth.register({
email: '[email protected]',
password: 'secret',
firstName: 'Alice',
lastName: 'Smith',
});
// Login
await auth.login({ email: '[email protected]', password: 'secret' });
// Verify (protected route — auto-refreshes on 401)
const session = await auth.verify();
// → { user: { id, email, firstName, ... }, roles: [...] }Custom storage
InMemoryStorage (the default) is the safest option for browsers — tokens live only for the page session and are never written to disk where XSS can read them. Prefer it unless you have a specific reason not to.
If you persist tokens in cookies, set them Secure; HttpOnly; SameSite=Strict (write them from your server, not JS, so HttpOnly is possible). Avoid localStorage/sessionStorage for tokens — they are fully readable by any script on the page (XSS) and offer no Secure/SameSite/HttpOnly protection.
import type { TokenStorage } from '@authforgesf/client';
// Cookie example — set Secure; SameSite=Strict (and HttpOnly when written server-side).
const cookieStorage: TokenStorage = {
getAccessToken: () => readCookie('af_access'),
getRefreshToken: () => readCookie('af_refresh'),
setTokens: (a, r) => {
// e.g. `af_access=${a}; Secure; SameSite=Strict; Path=/`
writeCookie('af_access', a);
writeCookie('af_refresh', r);
},
clearTokens: () => { clearCookie('af_access'); clearCookie('af_refresh'); },
};
const auth = new AuthForgeClient({ baseUrl, apiKey, storage: cookieStorage });API reference
Auth
| Method | Description |
|---|---|
| sendVerification(email) | Send email verification code |
| register(dto) | Register user + persist tokens |
| login({ email, password }) | Email/password login + persist tokens |
| socialLogin({ provider, token }) | Google or GitHub token exchange |
| sendMagicLink({ email }) | Send passwordless link |
| verifyMagicLink(token) | Consume magic link token |
| refresh() | Force token refresh (deduped) |
| logout() | Revoke refresh token + clear storage |
| verify() | Verify access token → user + roles |
| forgotPassword({ email }) | Send password reset email |
| resetPassword({ token, password }) | Consume reset token |
Users
| Method | Description |
|---|---|
| getUser(userId) | Get user profile |
| updateUser(userId, dto) | Update profile fields |
| deleteUser(userId) | Delete user |
Token helpers
| Method | Description |
|---|---|
| getAccessToken() | Read access token from storage |
| getRefreshToken() | Read refresh token from storage |
| setTokens(tokens) | Persist tokens manually |
| clearTokens() | Clear all stored tokens |
Error handling
import {
AuthForgeError,
InvalidCredentialsError,
UserBannedError,
TokenExpiredError,
} from '@authforgesf/client';
try {
await auth.login({ email, password });
} catch (e) {
if (e instanceof InvalidCredentialsError) {
// wrong email or password
} else if (e instanceof UserBannedError) {
// account is banned
} else if (e instanceof AuthForgeError) {
console.error(e.status, e.message);
}
}AuthForge setup
- Deploy AuthForge (see main repo)
- Admin UI → New App → copy the API key (shown once)
- Add
AUTHFORGE_API_URLandAUTHFORGE_API_KEYto your app env - Done — no auth logic needed in your SaaS
License
MIT © Laurent Schall-Fonteilles
