On this page

Opt-in model

Auth is disabled by default. A project has no auth service until you enable it. This prevents accidental exposure of signup endpoints on projects that don’t need them.

Enable via SDK:

await miosa.projects.auth.enable(projectId, {
  allowSignups: true,
  providers: ["email"],
})

Enable via CLI:

miosa data auth enable --project proj_xxx

Enable via API:

curl -X POST https://api.miosa.ai/v1/projects/$PROJECT_ID/auth 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"allow_signups": true, "providers": ["email"]}'

Once enabled, the next sandbox or runtime instance boot for this project will have AUTH_URL and AUTH_JWT_SECRET injected automatically. No restarts of running instances — new boots pick it up.


Auth is the opt-in managed-auth experience. When enabled, MIOSA provisions a per-project auth service. The app gets two env vars:


AUTH_URL=https://auth.miosa.app/proj_xxx
AUTH_JWT_SECRET=<random 64-char hex>

The generated app uses them like this:

// Sign up a new end user
const res = await fetch(`${process.env.AUTH_URL}/signup`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ email, password }),
})
const { access_token, user } = await res.json()

// Verify a JWT in the app's own API
import jwt from "jsonwebtoken"
const claims = jwt.verify(token, process.env.AUTH_JWT_SECRET!)
const userId = claims.sub

That’s the agent-on-day-zero experience: agent writes a signup flow on day zero, never has to ask the user to configure auth.

What’s offered

FeatureStatus
Email + password signup / loginAvailable
JWT access tokensAvailable
Token verifyAvailable
Email verificationAvailable (requires email delivery configured)
Password resetAvailable (requires email delivery configured)
Refresh tokensComing soon
Magic linksComing soon
OAuth providers (Google, GitHub)Coming soon
MFA / TOTPComing soon
Passkeys / WebAuthnComing soon
Enterprise SSO (SAML, OIDC)Coming soon

Endpoints

AUTH_URL is injected into the project at boot and already points at the per-project base (.../app-auth/<type>/<id>). Append the path:

POST   {AUTH_URL}/signup                   create an end-user account → JWT
POST   {AUTH_URL}/login                    authenticate → JWT
POST   {AUTH_URL}/verify                   verify a JWT, returns the claims
POST   {AUTH_URL}/password-reset           request a reset link (sends email*)
POST   {AUTH_URL}/password-reset/confirm   complete the reset with the token
POST   {AUTH_URL}/email/confirm            confirm an email with the token

* /password-reset and /email/confirm only send mail once email delivery is configured — see below. The endpoints succeed regardless; the email is the part that needs setup.

Configuring email delivery

Password reset and email verification generate the token and call the send, but the email itself only goes out once an email provider is wired up. Until then, those endpoints return success but no email is sent (the platform logs email_not_configured and skips it — it never crashes the auth flow).

MIOSA sends transactional email through Resend. See Transactional Email for the operator setup, verification checklist, and white-label sender caveats. The app-auth sender is enabled with:

RESEND_API_KEY=re_xxxxxxxxxxxx
RESEND_FROM_APP_AUTH="Your App <noreply@yourdomain.com>"

Once set, /password-reset and /email/confirm deliver real emails. This is a one-time, platform-wide setup — there is no per-project email configuration.

Today email sends from a single platform-wide address. Per-project / custom-domain senders (so each white-label brand’s emails come from its own domain) are not available yet — it’s on the roadmap.

End users are not MIOSA users

Important distinction:

  • MIOSA platform user = the developer / platform builder. Authenticates with msk_* API keys or JWT sessions issued by MIOSA. Has access to the MIOSA dashboard.
  • End user of a generated app = the visitor to an app YOUR PLATFORM built (e.g. Dr. Smith logging into a dental clinic site). Authenticates against the per-project AUTH_URL. Has no MIOSA account.

These are completely separate auth systems. The same email can be a MIOSA platform user AND an end user of someone’s app; they’re different records, with different password hashes.

Per-project isolation

Each project gets its own user table. Users from proj_smile_dental cannot log into proj_smile_clinic. The JWT secret is per-project; you cannot use one project’s token to authenticate against another.

This makes the “user signs up to the dental clinic site” pattern safe even when the same MIOSA tenant hosts thousands of independent end-user apps.

Row-level security (Postgres pattern)

When combined with managed Postgres, the auth JWT carries the user ID (sub claim). Your runtime code uses it for row-level filtering:

const claims = jwt.verify(token, process.env.AUTH_JWT_SECRET!)

const appointments = await pool.query(
  "SELECT * FROM appointments WHERE patient_id = $1",
  [claims.sub]
)

Or use Postgres RLS policies if your Postgres has them enabled:

ALTER TABLE appointments ENABLE ROW LEVEL SECURITY;
CREATE POLICY appointment_owner ON appointments
  USING (patient_id = current_setting('jwt.claims.sub')::uuid);

Custom domains for auth

If you want the auth URLs to be branded (auth.smiledental.test instead of auth.miosa.app), add a custom domain to the project’s auth service. Same flow as Deployment Domains, different target.

Bring your own auth?

Yes. Skip the managed auth, set your own AUTH_URL and AUTH_JWT_SECRET to point at Clerk / Auth0 / your own service. MIOSA’s runtime injects whatever you set.

Python SDK

See also

Was this helpful?