Skip to main content

Credentials and Server Security

Understand cookie exchange, explicit principals, redaction, and server-boundary controls.

The server boundary treats Better Auth cookies and Convex JWTs as credentials. They must remain request-scoped and absent from public error fields.

Credential paths

InputBehavior
Request Better Auth cookiesFilter relevant cookies and exchange through the configured Convex site
Explicit cookie credentialExchange as a required principal
Explicit Convex authTokenSet directly on the request-scoped HTTP client
auth: 'none'Skip credential resolution

Raw Better Auth session tokens are intentionally not accepted as public bearer credentials. Bearer session handling is reserved for the package's private, marked Convex bridge.

Controls

ThreatControl
Credential forwarded to another originToken exchange rejects redirects
Oversized/malformed exchange responseBounded response reader and transport classification
Header injectionEmpty/control-character credentials rejected before fetch
Cookie confusionCookie and direct-token paths are mutually constrained
Secret leakage in payload/logcause is non-serialized; public fields are sanitized
Cross-request identity reuseOne caller and token promise per request

Public errors

Authentication and transport failures expose a stable category and safe message. Raw upstream response bodies are not copied into message, code, status, or data.

Structured Convex application errors remain server errors and preserve their application data.

Trusted client IP headers

Outside exact loopback development, configure auth.trustedClientIpHeader with a header that a trusted ingress overwrites with exactly one client IP. Auth startup and requests fail closed without that boundary. Do not trust a client-supplied forwarding chain. Public traffic must not be able to reach the Nuxt origin around the ingress unless the origin independently authenticates ingress requests; header overwrite alone cannot defend a bypassable origin.

ts
convex: {
  auth: {
    origin: process.env.SITE_URL ?? 'http://localhost:3000',
    trustedClientIpHeader: process.env.BCN_AUTH_TRUSTED_CLIENT_IP_HEADER
  }
}

Request-bound SSR hydration and serverConvex(event) use this same signed identity. Cookie-to-token exchange is deliberately not exposed as a raw public helper because it would collapse unrelated clients onto the Nitro egress IP.

Application responsibilities

  • Validate route bodies and webhook signatures.
  • Keep secrets in server or Convex environments.
  • Enforce product authorization in Convex.
  • Avoid public caching of auth routes and authenticated HTML.
  • Redact application logs and monitoring breadcrumbs.
  • Rotate compromised secrets and invalidate sessions through Better Auth.

See the broader security model.