Skip to content
BunBase BunBase BunBase Docs Alpha v0.1.0

Authentication

client.auth handles registration, login, token management, and session state.

const result = await client.auth.register({
email: "alice@example.com",
password: "hunter2secure",
});
console.log(result.user.id); // "01JKX..."
console.log(result.access_token); // JWT
console.log(result.expires_in); // 900 (seconds)

Tokens are stored automatically. Subsequent requests will be authenticated.

import { BunBaseError } from "@bunbase/js";
import type { LoginResult } from "@bunbase/js";
const result: LoginResult = await client.auth.login({
email: "alice@example.com",
password: "hunter2secure",
});
if ("totp_required" in result) {
// Account has 2FA enabled — show TOTP input to the user
const { totp_token } = result; // pass to verifyTotp()
} else {
console.log(result.user.id); // signed in
}

login() returns LoginResult, which is either an AuthResult (success) or a TotpChallenge (when 2FA is enabled). Tokens are only stored after a successful AuthResult.

const user = await client.auth.me();
// { id, email, created_at, updated_at, is_verified }
// Revoke current session
await client.auth.logout();
// Revoke all sessions ("sign out everywhere")
const { sessions_revoked } = await client.auth.logoutAll();

Both calls clear local tokens.

if (client.auth.isAuthenticated()) {
// Has an access token in memory (does not validate expiry)
}
const unsub = client.auth.onAuthChange((session) => {
if (session) {
// logged in: session.accessToken, session.refreshToken
} else {
// logged out
}
});
unsub(); // stop listening

Fires on: login, register, token refresh, logout.

const at = localStorage.getItem("bb_at");
const rt = localStorage.getItem("bb_rt");
if (at && rt) {
client.auth.restoreSession(at, rt);
}

When login() returns a TotpChallenge, prompt the user for the 6-digit code from their authenticator app, then call verifyTotp() with the token from the challenge.

// Step 1 — login detects 2FA
const challenge = await client.auth.login({ email, password });
if ("totp_required" in challenge) {
// Step 2 — user enters code from authenticator app
const result = await client.auth.verifyTotp(
challenge.totp_token, // short-lived token from login response
"123456", // 6-digit code from authenticator app
);
console.log(result.user.id); // signed in
}

TOTP setup and enable/disable are managed via the REST API (/auth/2fa/*) or through the Studio admin panel.

Send a sign-in link to the user’s email. No password needed.

// Step 1 — send the link (always resolves, never reveals if email exists)
await client.auth.requestMagicLink("alice@example.com");
// Step 2 — the email link contains ?token=... — verify it
const result = await client.auth.verifyMagicLink(tokenFromLink);
console.log(result.user.id); // signed in

verifyMagicLink() stores tokens exactly like a normal login.

API keys let server-side scripts authenticate without user credentials. Keys never expire and bypass the token refresh flow.

// Create a key — returns the raw key string once (store it securely)
const { key, id, name } = await client.auth.createApiKey("my-script");
// key: "bb_..."
// List existing keys (raw key is never returned again)
const keys = await client.auth.listApiKeys();
// [{ id, name, created_at }, ...]
// Revoke a key
await client.auth.revokeApiKey(id);

To use a key in the SDK, pass it at construction time:

const serverClient = new BunBaseClient({
url: "https://your-bunbase.example.com",
apiKey: "bb_...",
});

All requests will use X-Api-Key instead of Authorization: Bearer.

// Step 1 — send reset email (always resolves, never reveals if email exists)
await client.auth.forgotPassword("alice@example.com");
// Step 2 — complete reset with token from email link
await client.auth.resetPassword(tokenFromLink, "newpassword123");
// Verify with token from link
await client.auth.verifyEmail(tokenFromLink);
// Re-send verification email (must be logged in)
await client.auth.resendVerification();
await client.auth.deleteAccount("currentpassword");
// Revokes session and clears local tokens.

When a session is revoked (admin logout, password change, account deletion), the server pushes an auth event over the WebSocket connection immediately. The SDK handles this automatically — tokens are cleared and onAuthChange(null) fires on all listeners with no extra code required.

When a realtime connection is active, revocations arrive instantly. No polling is needed.

client.auth.onAuthChange((session) => {
if (!session) {
// Fires immediately when the server pushes session_revoked,
// sessions_purged, account_deleted, or password_changed.
router.push("/login");
}
});

If your app doesn’t use a realtime connection (e.g. server-side rendering, API-only clients), use startSessionWatch() to poll instead:

// Detects revocations within intervalMs (default 30 s)
const stopWatch = client.auth.startSessionWatch(30_000);
// Stop when the user signs out
stopWatch();

The poll calls me() → refresh fails when session is gone → clearTokens()onAuthChange(null). Same end result, just not instant.

MethodReturnsDescription
register({ email, password })AuthResultRegister a new user
login({ email, password })LoginResultLogin — may return TotpChallenge if 2FA is enabled
verifyTotp(totpToken, code)AuthResultComplete 2FA login with a TOTP code
requestMagicLink(email)voidSend a passwordless sign-in link
verifyMagicLink(token)AuthResultComplete magic link sign-in
logout()voidRevoke current session
logoutAll(){ sessions_revoked: number }Revoke all sessions
me()AuthUserGet the authenticated user
isAuthenticated()booleanReturns true if a token is held
restoreSession(at, rt, user?)voidLoad tokens (and optionally user) from external storage
getCachedUser()AuthUser | nullSynchronously read the last known user
updateMe(metadata)AuthUserUpdate the authenticated user’s metadata
onAuthChange(fn)() => voidSubscribe to auth state changes — fires on login, logout, and server-pushed revocation events
startSessionWatch(intervalMs?)() => voidFallback poll for revocation when no realtime connection is active
forgotPassword(email)voidSend password reset email
resetPassword(token, password)voidComplete password reset
verifyEmail(token)voidVerify email address
resendVerification()voidRe-send verification email
deleteAccount(password)voidPermanently delete account
listApiKeys()ApiKey[]List all API keys for the current user
createApiKey(name)ApiKey & { key: string }Create an API key (raw key returned once)
revokeApiKey(id)voidRevoke an API key by ID