Skip to content

Authentication

The session cookie the API authenticates with, and why there are no API keys yet.

Updated

The API has one way in: the session cookie the console sets when a customer signs in. There are no API keys, personal tokens or OAuth clients for the API yet.

Signing in to the console with GitHub or Google ends with Cloud setting this cookie on its own address:

PropertyValue
Namecahaves.cloud.session
Lifetime30 days from sign-in
Readable by scriptsNo, it is HttpOnly
Sent cross-siteOnly on top-level navigation, as SameSite=Lax
Sent overHTTPS only

The session is stored on Cloud's side and can be revoked there, so signing out ends it for every request at once. A request without a valid session answers:

401JSON
{ "error": "Sign in to continue." }

An account Cahaves has banned gets the same 401 on every request, whatever session it holds, and cannot sign in again.

The organization a request works in

The session names a person, and a person can own several organizations. Every customer request works in one of them, which it names in a header:

HeaderPlain text
X-Cloud-Organization: 2f6c8e0a-4b1d-4e7f-9a3c-5d7e9f1b3a5c
HeaderThe request works in
Left out, or emptyYour oldest organization
The id of one of your organizationsThat organization
Any other value, an id that is not yours includedNothing: it answers 404 with reason: "organization"
404JSON
{ "error": "That organization does not exist.", "reason": "organization" }

The reason tells this 404 from a record that does not exist. The console sends the header on every request, naming the organization its switcher shows, and on this 404 it drops its choice and asks again without the header.

Projects and everything in them, and billing, are the organization's: a record of another of your organizations answers 404 as one that does not exist would. SSH keys, git providers, notification channels and backup destinations are yours, and answer the same whichever organization the header names. Get the signed-in customer lists your organizations and names the one the request works in.

A new account has no organization until Create an organization makes one. Until then, every route that works in an organization answers:

409JSON
{ "error": "Create an organization first." }

Without an organization, /api/me, the organization routes, the catalogue of databases, applications and instance sizes, SSH keys, git providers, notification channels and deliveries, and support still answer.

What this means for these pages

Scripts cannot read the cookie, and a request sent from another site does not carry it. That rules out calling the API from a server, a CI job or the Try it panel on these pages, which answers 401 for every endpoint until Cloud offers tokens.

The reference is still the exact contract the console is built on: every field, envelope and error below is what the console sends and receives.

Signing in and out

Signing in is a browser navigation, not an API call. These routes sit on the same host as the API, outside /api:

RouteWhat it does
GET /auth/start?provider=github or provider=googleSends the browser through Cahaves' sign-in service to that provider, then back to the console signed in. The first sign-in creates the account.
GET /auth/ssoWhere the Cahaves account screen opens Cloud. It signs in from the account's existing Cahaves session without showing a screen.
GET /auth/callbackWhere the sign-in service returns the browser. Nothing calls it directly. At most 20 callbacks a minute are accepted from one address; past that it answers 429 with { "error": "Too many attempts." }.
POST /auth/logoutEnds Cloud's session and clears the cookie. It always answers 204, signed in or not. The Cahaves account session at the sign-in service stays open.

A sign-in that fails lands on the console's login screen with a code in ?error=, never with text taken from the address. The screen shows one sentence per code:

CodeSentence on the login screen
failedThat sign-in could not be completed. Start again.
providerChoose GitHub or Google to sign in.
unavailableSign-in is unavailable right now. Try again in a minute.
invalid_stateThat sign-in expired before it finished. Start again.
provider_disabledThat sign-in option is not available right now.
provider_unavailableThe provider did not finish the sign-in. If you did not cancel it, try again in a minute.
email_not_verifiedThe provider has not verified your email address. Verify it there, then start again.
missing_emailThe provider did not share an email address, and your account needs one.
email_takenAn account already uses that email address. Sign in the way you did before, or connect this provider from your Cahaves account screen first.
account_not_activeThat account cannot sign in.
registration_closedCahaves is not taking new accounts right now.
login_requiredYour Cahaves session has ended. Continue with GitHub or Google to sign in again.

Any other code reads as failed, and so does a banned account. Sign-in problems explains what to do about each.

Two kinds of session

Cahaves staff sign in through a separate route and receive a different cookie. A staff session is never honoured on a customer endpoint, and a customer session never on a staff one, whichever cookie a request carries.

The sockets

The log and terminal sockets use the same cookie. They also refuse any request whose Origin is not the console's own address. They take no organization: a socket reaches a service in any of your organizations. Log and terminal sockets has the details.