Skip to content

Auth and sessions

Private apps are admitted at the edge. An unauthenticated browser is redirected to auth.opencloud.ai, where a one-time email link or configured password approves or creates the central browser session and returns directly to the original app URL. Email-link access creates the session in the browser that requested the email, not the window that opens the message.

Do not build a second sign-in form inside a private app.

Agent-created accounts

MCP start_onboarding creates a provisional identity and retained project request for a new email. organisation_setup_required has no app or credential. The owner confirms the project-aware email within 24 hours, then explicitly sets up their company or accepts its invitation. Each account is assigned to one company; signing in or changing email never creates or transfers that assignment.

If the email already exists, OpenCloud sends an approval request and withholds both the project and agent credential until the user confirms it. A GET of the email link only renders the review page. The explicit confirmation navigation must carry a short-lived, preview-bound HttpOnly cookie, so mail-security link prefetchers cannot approve the request.

After the user chooses the explicit confirmation action, OpenCloud establishes the normal HttpOnly session, consumes the one-time secret, and redirects the same browser directly to the non-secret owner launch page. That page waits for company setup when needed and opens the project after deployment. Company setup opens in a separate tab; return to the retained request and ask the coding agent to complete onboarding. The agent never receives the browser session. The CLI keeps account and app credentials in its protected OS credential backend.

The regular access page defaults to email-link access. Submit an email address, keep that window open, then open the 15-minute message and explicitly confirm. The email-opened window reports that confirmation is complete and can be closed. A short-lived, path-scoped HttpOnly browser claim lets the initiating window detect approval, create its own session, and continue to the requested OpenCloud page automatically. The email token never becomes a session in the mail window, and another browser cannot claim the initiating window's request.

The page can instead reveal a password field. A confirmed identity with a configured password signs in immediately. An unknown address creates an unconfirmed identity when registration is enabled and sends the same scanner-safe confirmation email. It also starts a provisional browser session that expires at the 24-hour confirmation deadline. There is no separate registration mode.

Each successful sign-in creates an independent browser session. Signing in on another browser or device does not end existing sessions; signing out ends only the session in that browser. A confirmed browser session has a fixed, non-sliding 30-day lifetime at both the OpenCloud broker and the underlying Auth session. Its one-hour access token refreshes during the final minute and each successful refresh rotates the server-held refresh token.

If Auth definitively rejects a refresh token before that deadline, OpenCloud revokes the unusable broker session and treats the browser as signed out. A public app continues anonymously, a private app redirects to Login, and the Login page renders normally. Timeouts and Auth service failures remain errors; they are not mistaken for a signed-out user.

Existing link-only users can sign in with an email link and set a password in global Preferences.

Passwords

Passwords must contain 8 to 72 characters. The central Auth service stores the password verifier; OpenCloud's application database does not store plaintext passwords or password hashes. A signed-in user can set or replace a password in global Preferences. The form includes matching guidance beneath both password fields. Changing a password does not disable email-link access, so the confirmed email remains an alternate sign-in and recovery path.

While a password registration remains unconfirmed, the user can create and work on their own apps but cannot approve connected clients, perform owner-only actions, or use private apps granted by another owner. If the deadline passes before confirmation, OpenCloud revokes provisional grants and browser sessions and pauses every app owned by the unverified user. HTTP runtime traffic, Functions, and cron stop. The app address shows a verification-required page with a resend action, while data, files, deployments, secrets, and backups remain preserved. Submitting the verification form resumes all affected apps and active cron schedules.

Render the current user

js
const user = await opencloud.auth.currentUser();

if (!user) {
  signInLink.href = opencloud.auth.signInUrl();
  renderSignedOut();
} else {
  renderIdentity(user.displayName ?? user.email ?? user.id);
}

The SDK keeps token and expiry state private and refreshes through the HttpOnly broker cookie. Never decode JWTs, copy access tokens into application state, or persist token material.

Public apps

A public app may have either an authenticated or anonymous visitor. Use auth.currentUser() to adapt the UI. Data reads use the current user when present and can follow deliberately public RLS; data and file writes still require a user. Point a protected action at auth.signInUrl() rather than constructing the central Auth URL or passing a return target yourself.

Private authorization

Private app access is separate from identity. A valid OpenCloud account receives HTTP 403 when it has not been granted access to that app. The platform applies this edge check before serving the frontend or runtime APIs.

Signed-in platform administrators are the explicit exception: they may open any active deployed app with their own identity for safety, abuse, or security review. Review access does not add an app membership or grant owner or builder control. Runtime interactions still follow the app's row-level security, Files, Function, integration, and AI policies, and secret values remain unavailable.

Programmatic private-app access

The verified current owner can create an app access token from the app's Access screen, the owner API, or full MCP. Store the one-time oc_app_... value in a secret manager. A client can then call any current or future authenticated runtime route with only that Bearer credential; the edge injects infrastructure credentials internally:

bash
printf 'Authorization: Bearer %s\n' "$OPENCLOUD_APP_TOKEN" | \
  curl --fail-with-body --header @- \
    "$APP_URL/rest/v1/items?select=id,title"

The token acts as the owner for PostgREST RLS, database RPCs, Functions, managed Files, Realtime, and platform-owned runtime endpoints. It is bound to one deployed app, is revalidated on every new request, and cannot manage apps, deployments, secrets, backups, or any other control-plane resource. Use POST /_opencloud/api/session when a client library specifically needs a short-lived JWT and semantic same-origin runtime paths; the response has no refresh token or infrastructure key.

The platform also exposes a short-lived owner-approval request endpoint for app-scoped clients. Public CLI v3.10.3 exposes it as app access-token request; owner sessions may also list, create, and revoke tokens with the adjacent app access-token commands. CLI creation uses a one-time reveal link and never prints the runtime secret.

Session failures

  • null in a public app is normal.
  • null after a private app rendered indicates an expired or unavailable brokered session; show retry/sign-in UI.
  • OpenCloudError with code AUTH_REQUIRED means an authenticated SDK operation cannot proceed.
  • Never bypass the high-level SDK or fall back to anonymous raw requests for a user-private mutation.

Self-hosted infrastructure for agent-built applications.