API reference

Authentication

Steam OpenID login, session cookies, bearer tokens, and the relay JWT.

Steam OpenID flow

GET /auth/steam?return=<origin>
  ↳ 302 to https://steamcommunity.com/openid/login?...
       (user confirms on Steam)
  ↳ 302 back to /auth/steam/callback?openid.…
GET /auth/steam/callback
  ↳ verifies signature with Steam
  ↳ upserts User row, sets rp_sess cookie
  ↳ 302 to <return>

The ?return= parameter is validated against FRONTEND_URL and ADMIN_ORIGIN. Anything else falls back to FRONTEND_URL — meaning no open-redirect surface.

Name: rp_sess.

  • httpOnly: true — JavaScript can't read it.
  • secure: true — production only.
  • sameSite: 'lax' — CSRF-safe by default.
  • Encrypted with SESSION_SECRET and salted with SESSION_SALT.

GET /me

Returns the current user:

{
  "id": "ckxxxxxxx",
  "steamId": "76561198000000000",
  "displayName": "sxrtboy",
  "avatarUrl": "https://...",
  "subscription": { "tier": "OPERATOR", "status": "ACTIVE" }
}

Returns 401 when no session.

POST /pairing/device/code

// request (session-authenticated)
{ "label": "Credentials Helper" }
// response
{ "code": "RUST-7A3B", "expiresAt": "2026-05-13T12:34:56Z" }

Max 3 active codes per user; oldest is invalidated on the 4th.

POST /pairing/device/activate

// request (NO auth — code is the auth)
{ "code": "RUST-7A3B" }
// response (token returned EXACTLY ONCE)
{ "token": "<48 bytes hex>", "userId": "ckxxxxxxx" }

POST /relay/token

Session-authenticated. Mints a short-lived JWT the relay accepts:

{ "token": "<JWT>", "exp": 1234567890 }

JWT carries sub: userId, scope: relay, exp ≤ now + 5min. The relay rejects expired tokens.

Sign-out

POST /auth/signout
  ↳ clears rp_sess
  ↳ 204

There is no token revocation list. Device tokens stay valid until you delete the device from your dashboard's Setup page. Relay JWTs are short-lived enough that revocation isn't needed.