Platform
Authentication
Email + OTP, social login, passkey, password flows, and JWT sessions — with Row-Level Security integration.
OrbitNest Auth handles user sign-up, sign-in, email verification, and session management out of the box. It issues standard JWTs that are recognized by every module — including Row-Level Security policies in your database.
Supported flows
- Email + password — the classic flow. Sign-up always requires an OTP before the account is created, so typo'd or throw-away emails never generate a row.
- Email + OTP (passwordless) — a 4-digit code is emailed; verifying it issues a session. No password stored, no password-reset flow to worry about.
- Passkey (WebAuthn / FIDO2) — hardware-backed credentials via Credential Manager on Android and ASAuthorization on iOS. Supported for both admin users and project users; device management and revocation live in the settings page.
- Social login (OAuth) — admins can sign in or sign up with Google, GitHub, or Apple. A verified-email match auto-links the provider to an existing account, so an admin who registered with email + password can later sign in with Google with no manual linking step. Currently admin-side only.
- Password reset — request → email OTP → verify → set new password, all in a single round-trip via the SDK.
- Refresh-token rotation — every refresh invalidates the previous token; replays are detected and cause an immediate revocation of all sessions for the user (defence against stolen refresh tokens).
Social login for admins
Sign up with OTP
The recommended flow: collect email, send a 4-digit code, verify it, then optionally set a password.
// 1. Request OTP
await client.auth.signUpWithEmail({
email: 'user@example.com',
user_metadata: { name: 'Jane Doe' },
});
// User enters the 4-digit code from their email …
// 2. Verify and create the account
const { user, session } = await client.auth.verifySignup({
email: 'user@example.com',
code: '1234',
password: 'optional-password',
});Debug mode
1234. Perfect for development without blasting emails.Sessions & tokens
A successful sign-in returns an access_token (short-lived JWT) and a refresh_token. SDKs handle token refresh automatically; for manual calls, hit the refresh endpoint when a 401 comes back.
const { access_token, refresh_token } = await client.auth.refresh(refreshToken);JWT claims
OrbitNest JWTs include the user's sub (user ID), email, role, and any custom user_metadata. The signing secret can be rotated from API Keys → JWT Settings.
{
"sub": "9f2a1c7e-...",
"email": "user@example.com",
"role": "authenticated",
"iat": 1704499200,
"exp": 1704502800,
"user_metadata": { "name": "Jane Doe" }
}Multi-factor auth (TOTP)
Let users add an authenticator app (Google Authenticator, 1Password, …) as a second factor. Enroll while signed in, then confirm with the first code.
// Show data.qr_code (a data URL) or data.secret to the user
const { data } = await client.auth.enrollMfaTotp('My phone');
await client.auth.verifyMfaEnrollment(data.factor_id, '123456');
await client.auth.listMfaFactors();
await client.auth.unenrollMfa(factorId);Once a verified factor exists, signIn returns an MFA challenge instead of a session — complete it with verifyMfa:
import { isMfaChallenge } from '@orbitneststudio/js';
const { data } = await client.auth.signIn({ email, password });
if (isMfaChallenge(data)) {
// codeFromApp may be a 6-digit TOTP or a recovery code
await client.auth.verifyMfa(data.challenge_token, codeFromApp);
}Recovery codes. Confirming enrollment returns a one-time recovery_codes array — show them to the user to store safely. Any of them works in place of the authenticator code at sign-in, and you can replace the set at any time with regenerateMfaRecoveryCodes().
const { data } = await client.auth.verifyMfaEnrollment(factorId, '123456');
data.recovery_codes; // ['abcd-efgh', …] — shown once; tell the user to save them
// later — replace the whole set (also returned once)
const { data: fresh } = await client.auth.regenerateMfaRecoveryCodes();SMS OTP (phone sign-in)
Connect your own Twilio account in Settings → SMS / Twilio, then users can sign in with a code texted to their phone. The user is created on first sign-in.
await client.auth.signInWithSms('+15555550123'); // sends the code
await client.auth.verifySmsOtp('+15555550123', '123456'); // verifies + signs inRLS integration
When a user is signed in, their JWT is forwarded to Postgres. Use auth.uid() inside RLS policies to reference the current user.
CREATE POLICY "users read own rows" ON private_data
FOR SELECT USING (auth.uid() = owner_id);Admin users vs. project users
Two distinct user systems coexist:
- Admin users — access the Studio dashboard. Managed from the Admins page.
- Project users — end-users of apps built on top of OrbitNest. Managed per-project in the Authentication page.
Token isolation
Protected auth tables
Tables under the auth. schema (users, sessions, OTP, passkeys) are read-only from the client. Studio exposes them in the Authentication view with masked sensitive columns.