青峰智影青峰智影
API ReferenceMirava

Authentication

Access Token, Refresh Cookie and the server-side session control plane.

Mirava panel authentication combines a short-lived Access Token, an HttpOnly Refresh Cookie and a server-side session control plane.

Auth Model

CredentialFormLifetimeStored in
Access TokenJWT15 minutesBrowser memory only
Refresh TokenOpaque random valueUp to 30 daysHttpOnly Cookie (SameSite=Strict)
new_api_has_sessionConstant 1Same as Refresh CookiePlain cookie (hint only, no credential)
  • The Access Token is sent via Authorization: Bearer <token> and kept in browser memory only.
  • For the Refresh Token, the server stores only an HMAC digest and rotates it on every refresh.
  • new_api_has_session only declares that a Refresh Cookie was once issued. It plays no part in any auth decision.

Server-Side Authority

user_sessions is the login session control plane, recording device, IP, login method, last active time, expiry and revocation state.

Session state in the database is the final authority. Redis session cache is an acceleration layer only; on a cache miss or with Redis disabled, validation falls back to the database.

  • When a user's password, status, role or security factor changes, auth_version increments and invalidates old sessions.
  • Group upgrades from a subscription only refresh the authorization cache and do not log out any device.

Secret Configuration

Env varPurpose
SESSION_SECRETDerives purpose-specific keys for Access Token, Security Proof, Refresh Token digest and AuthFlow digest
CRYPTO_SECRETCache key digests when sharing Redis across nodes

Production and multi-node deployments must configure the same high-strength random value on all nodes. Changing SESSION_SECRET invalidates all existing logins, temporary auth flows and Security Proofs.

Multi-Node Redis Topology

Multi-node deployments must share the same primary database. Login sessions, per-account active session limits and issuance window counters are all database-authoritative.

Redis setupSession propagationRate limit semantics
Shared RedisRevocation and version release propagate immediatelyQuota shared across nodes
Per-node RedisConverges after session cache TTL (at most SYNC_FREQUENCY)Counted per node
No RedisEvery check hits the databasePer-node in-memory limiter

SYNC_FREQUENCY defaults to, and falls back to, 60 seconds.

Browser API

All successful logins (password, 2FA, Passkey, OAuth, WeChat, Telegram) return the same structure:

{
  "success": true,
  "data": {
    "access_token": "...",
    "token_type": "Bearer",
    "access_expires_at": 1730000000,
    "user": {},
    "session": {
      "sid": "...",
      "current": true,
      "login_method": "password",
      "ip": "...",
      "user_agent": "...",
      "created_at": 1730000000,
      "last_active_at": 1730000000,
      "expires_at": 1732592000
    }
  }
}

Calling the API

External APIs always use an Access Token:

curl https://mirava.art/v1/models \
  -H "Authorization: Bearer sk-xxxxxxxx"

Panel requests no longer depend on Gin session and no longer require the New-Api-User header. Third-party callers should use an API token (the sk- prefix).

How is this guide?