Authentication
client.auth handles registration, login, token management, and session state.
Register
Section titled “Register”const result = await client.auth.register({ email: "alice@example.com", password: "hunter2secure",});
console.log(result.user.id); // "01JKX..."console.log(result.access_token); // JWTconsole.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.
Get current user
Section titled “Get current user”const user = await client.auth.me();// { id, email, created_at, updated_at, is_verified }Logout
Section titled “Logout”// Revoke current sessionawait client.auth.logout();
// Revoke all sessions ("sign out everywhere")const { sessions_revoked } = await client.auth.logoutAll();Both calls clear local tokens.
Check authentication state
Section titled “Check authentication state”if (client.auth.isAuthenticated()) { // Has an access token in memory (does not validate expiry)}Listen to auth changes
Section titled “Listen to auth changes”const unsub = client.auth.onAuthChange((session) => { if (session) { // logged in: session.accessToken, session.refreshToken } else { // logged out }});
unsub(); // stop listeningFires on: login, register, token refresh, logout.
Restore a session
Section titled “Restore a session”const at = localStorage.getItem("bb_at");const rt = localStorage.getItem("bb_rt");
if (at && rt) { client.auth.restoreSession(at, rt);}Two-factor authentication (TOTP)
Section titled “Two-factor authentication (TOTP)”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 2FAconst 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.
Magic link (passwordless)
Section titled “Magic link (passwordless)”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 itconst result = await client.auth.verifyMagicLink(tokenFromLink);console.log(result.user.id); // signed inverifyMagicLink() stores tokens exactly like a normal login.
API keys
Section titled “API keys”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 keyawait 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.
Password reset
Section titled “Password reset”// 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 linkawait client.auth.resetPassword(tokenFromLink, "newpassword123");Email verification
Section titled “Email verification”// Verify with token from linkawait client.auth.verifyEmail(tokenFromLink);
// Re-send verification email (must be logged in)await client.auth.resendVerification();Delete account
Section titled “Delete account”await client.auth.deleteAccount("currentpassword");// Revokes session and clears local tokens.Session revocation detection
Section titled “Session revocation detection”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"); }});Fallback: session watch (no WebSocket)
Section titled “Fallback: session watch (no WebSocket)”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 outstopWatch();The poll calls me() → refresh fails when session is gone → clearTokens() → onAuthChange(null). Same end result, just not instant.
API surface
Section titled “API surface”| Method | Returns | Description |
|---|---|---|
register({ email, password }) | AuthResult | Register a new user |
login({ email, password }) | LoginResult | Login — may return TotpChallenge if 2FA is enabled |
verifyTotp(totpToken, code) | AuthResult | Complete 2FA login with a TOTP code |
requestMagicLink(email) | void | Send a passwordless sign-in link |
verifyMagicLink(token) | AuthResult | Complete magic link sign-in |
logout() | void | Revoke current session |
logoutAll() | { sessions_revoked: number } | Revoke all sessions |
me() | AuthUser | Get the authenticated user |
isAuthenticated() | boolean | Returns true if a token is held |
restoreSession(at, rt, user?) | void | Load tokens (and optionally user) from external storage |
getCachedUser() | AuthUser | null | Synchronously read the last known user |
updateMe(metadata) | AuthUser | Update the authenticated user’s metadata |
onAuthChange(fn) | () => void | Subscribe to auth state changes — fires on login, logout, and server-pushed revocation events |
startSessionWatch(intervalMs?) | () => void | Fallback poll for revocation when no realtime connection is active |
forgotPassword(email) | void | Send password reset email |
resetPassword(token, password) | void | Complete password reset |
verifyEmail(token) | void | Verify email address |
resendVerification() | void | Re-send verification email |
deleteAccount(password) | void | Permanently 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) | void | Revoke an API key by ID |