Skip to content
Rigel docs
Open Rigel

Authentication

People sign in with Google and get a session cookie, and until personal API tokens exist, a script sends that same cookie.

Signing in#

Google is the only way to sign in. A browser starts at GET /api/v1/auth/google, which sends the person to Google. Google returns them to Rigel, Rigel creates a session and sets its cookie, and the browser lands back in the app. The flow needs a browser, so a script doesn't run it. See using it from a script.

Rigel is in early access, and only people it has let in can create an account. A Google account Rigel doesn't know is sent back to the app with sign_in_error=signup_closed in the URL, and no account is made. The other values are cancelled (the person backed out at Google), google_failed (the attempt expired; start again) and email_unverified.

Signing out is POST /api/v1/auth/sign-out. It ends the session and clears the cookie, and it succeeds even when nobody is signed in.

A signed-in browser holds a cookie named rigel_session. Its value looks like ses_01JC4M7V2S9A3B5D7F1G2H4J6K. followed by 64 hexadecimal characters. The cookie is HttpOnly, Secure and SameSite=Lax, so a page's scripts can't read it, and most cross-site requests don't carry it.

  • A session lasts 30 days from the moment of sign-in. After that, requests get 401 until you sign in again.
  • Signing out deletes the session on the server. A copy of the cookie stops working at once.
  • One person can have many sessions, one for each browser or device they signed in on. Ending one doesn't end the others.

Using it from a script#

Personal API tokens aren't built yet. Until they are, a script borrows a browser's session.

  1. Sign in at https://rigel.house.
  2. In the browser's developer tools, open the cookies for rigel.house and copy the value of rigel_session. It doesn't show in document.cookie, because it is HttpOnly.
  3. Send it as a Cookie header on every request.
curl
curl -sS https://rigel.house/api/v1/me \
  -H "Cookie: rigel_session=$RIGEL_SESSION"
TypeScript
const response = await fetch("https://rigel.house/api/v1/me", {
  headers: { Cookie: `rigel_session=${process.env.RIGEL_SESSION}` },
});
console.log(response.status, await response.json());

Call the API from a script or a server. It sends no CORS headers, so a page on another site can't call it, and a browser doesn't let a page set the Cookie header anyway.

What is public and what isn't#

These routes need no session:

RouteWhat it is
GET /api/v1/healthReturns { "ok": true }, for monitors.
GET /api/v1/openapi.jsonThe OpenAPI 3.1 document for every operation.
GET /api/v1/docsAn interactive view of that document.
GET /api/v1/socket-schema.jsonJSON Schema for the messages on the household socket.
/api/v1/auth/…The sign-in flow and sign-out.
GET /api/v1/integrations/google/callbackWhere Google sends a browser back after a member connects an outside account. It checks the session itself and always redirects. See outside accounts.

Every other route that reads or changes data needs a session, including GET /api/v1/me and every household route, files included. A request without a valid session is refused before anything else is checked.

401 and 404#

401 unauthenticated means the cookie is missing, malformed, expired, or from a session that was signed out. Sign in again and send a new cookie.

Response, 401
{
  "error": {
    "code": "unauthenticated",
    "message": "You're not signed in.",
    "details": {},
    "recovery": "Sign in, then send the request again.",
    "request_id": "req_01JC4N9D6R2T5W8Y1A4C7E0G3J"
  }
}

404 not_found on a household route means you are signed in, and the household either doesn't exist or you aren't a member of it. The two cases return the same response on purpose. Knowing a household's ID gives you nothing, and the API doesn't confirm which IDs are real. If you get a 404 for a household you expect to reach, check that the ID is right and that the cookie belongs to the account that is a member.

Response, 404
{
  "error": {
    "code": "not_found",
    "message": "That household wasn't found.",
    "details": {},
    "recovery": "Check the ID. You can only reach households you're a member of.",
    "request_id": "req_01JC4N9D8T4V7Y0A3C6E9G2K5M"
  }
}

What is planned#

These are designed but not built.

  • Personal API tokens. A person creates a token for their own scripts. Each token is for one household and is either read-only or read-write. It is shown once, stored hashed and can be revoked. Tokens can't manage tokens, members or roles, or erase anything. What a token does is recorded as the token's, not as the person's. A token is sent as Authorization: Bearer <token>.
  • Android sessions. The Android app will sign in with Google on the device and exchange the result for its own session token, sent as a bearer token. It follows the same lifetime and revocation rules as a web session.

When tokens exist, the examples on this site will switch from the Cookie header to the Authorization header. Paths, bodies and responses won't change.

Rigel is in early access, and sign-up is by invitation. Open Rigel