Auth & sessions
Authentication is built in. Real users can sign up, log in, and reset their password on day one — over secure cookies in the browser, or Bearer tokens for native and server-to-server clients. You configure the shape; the platform handles sessions, CSRF, and the security defenses.
The browser flow
Login, signup, and logout are form endpoints that set an HttpOnly session cookie. From the frontend, the SDK wraps them:
await bm.auth.signUp({ email, password, first_name });
await bm.auth.signIn({ email, password });
const me = await bm.auth.me(); // null when signed out
if (!me) location.href = '/login.html';
await bm.auth.signOut();
Or hit the endpoints directly. CSRF is required on cookie-authenticated mutations — read the auto-injected token and send it as _csrf or an X-CSRF-Token header:
const csrf = document.querySelector('meta[name="csrf-token"]').content;
await fetch('/login', {
method: 'POST',
body: new URLSearchParams({ email, password, _csrf: csrf }),
credentials: 'same-origin',
});
const me = await fetch('/api/_auth/profile', { credentials: 'same-origin' })
.then(r => r.ok ? r.json() : null); // 401 when anonymous
Configure it
The auth: block in app.yaml controls the identifier, session length, and what you collect at signup:
auth:
identifier: email # email | phone | username
session_duration: "30d"
signup_fields: first_name,last_name,company
redirect: "/dashboard"
The user table ships with sensible columns (email, name, avatar, role, verified, and more) and is extensible — add your own columns to the schema and they're collected and returned like any other field. GET /api/_auth/profile reads the current user; PATCH updates allowed fields (sensitive ones like role and password_hash are blocked).
Native and server clients
Non-browser clients exchange credentials for a Bearer token at POST /api/_auth/token, then send Authorization: Bearer <token>. Bearer requests are exempt from CSRF — there's no cookie to abuse.
Built-in defenses
- Password policy: 8+ characters with upper, lower, digit, and a special character.
- Brute-force lockout: 5 failed attempts locks an email for 15 minutes.
- The session cookie is
HttpOnly+SameSite(andSecurein production); JavaScript can't read it. - Changing a password invalidates every other session.
- CSRF tokens are HMAC-derived and valid for 24 hours; a server restart rotates the secret, so reload to get a fresh token.
OAuth and MFA
OAuth (Google, GitHub, Microsoft, or a custom provider) and TOTP-based multi-factor auth with backup codes are available — configure providers in app.yaml and enroll MFA through bm.mfa. Email verification and password reset flows are wired in.
Next: Access & roles for who can read and write each table, and Security for the full list of enforced controls.