Skip to content

Authentication and Security Model

SyncTV separates security into several boundaries:

  • User authentication: password, OPAQUE, WebAuthn/passkey, TOTP, recovery codes, email codes, and OAuth2.
  • User 2FA: optional per user and requires at least two local authentication methods.
  • Access tokens: issued after login completion for HTTP/gRPC business APIs.
  • Management control plane: the CLI management endpoint, separate from user tokens.
  • Provider upstream access: providers own upstream headers and credentials; the proxy does not guess client headers.
  • Cluster internal authentication: inter-node gRPC uses cluster.secret.
Authentication and 2FA boundary showing local first factors, MFA sessions, OAuth2, tokens, business APIs, and the management plane.Authentication and 2FA boundary showing local first factors, MFA sessions, OAuth2, tokens, business APIs, and the management plane.
Local login and OAuth2 are separate trust paths. When 2FA is enabled, local login must complete a second factor. OAuth2 does not count as local 2FA, but it can independently issue an accepted authentication context.
Method First factor Second factor Notes
Password/OPAQUE Yes Available only when the server returns MFA_METHOD_PASSWORD OPAQUE login is not the same as the password MFA verifier
WebAuthn/passkey Yes Yes Requires WebAuthn configuration and a bound credential
TOTP authenticator No Yes Uses SHA-1, six-digit codes, and a 30-second period; the server requires security.totp_encryption_key
TOTP recovery code No Yes Each code works once; recovery codes belong to the TOTP factor and do not count as a separate local method
Email code Yes Yes Requires SMTP and email-code delivery
OAuth2 Yes No OAuth2 does not participate in local 2FA, but 2FA-enabled users may log in with OAuth2

Before enabling 2FA, SyncTV verifies that the user has at least two usable local methods. After enabling 2FA, local single-factor login creates an MFA session instead of immediately issuing final tokens.

After 2FA is enabled, old single-factor refresh tokens should not keep rotating the session. Tokens issued after MFA or OAuth2 carry an accepted authentication context.

Semantics:

  • 2FA disabled: normal local login, MFA login, and OAuth2 tokens follow normal token rules.
  • 2FA enabled: local login must complete a second factor; refresh tokens must come from MFA or OAuth2 context.
  • 2FA disabled again: single-factor and MFA/OAuth2 contexts are accepted until token expiry or revocation.

When a local first factor succeeds and a second factor is required, SyncTV creates a short-lived MFA session instead of issuing final tokens.

Client flow:

  1. Complete the first-factor login request.
  2. If MFA is required, read the remaining available methods.
  3. If email is available, call the email-code send API immediately.
  4. If MFA_METHOD_TOTP is available, call VerifyMfaTotp.
  5. If MFA_METHOD_RECOVERY_CODE is available, call VerifyMfaRecoveryCode.
  6. Complete MFA with the session ID and second-factor proof.
  7. Store the final access and refresh tokens.

Failed password, TOTP, and recovery-code verification attempts enter their matching brute-force controls. TOTP and recovery codes share a per-user failure counter and include the client IP in enforcement.

The server generates a random 20-byte TOTP secret and returns it in an otpauth:// URI. The client renders a QR code from that URI and can show the response secret for manual entry. Setup expires after 10 minutes. The user must submit a valid TOTP code before the server confirms the credential and returns recovery codes.

The server encrypts the TOTP secret with security.totp_encryption_key and binds the ciphertext context to the user ID. Verification accepts the current 30-second time step and its adjacent steps. The server records the latest accepted step, so a code cannot be reused across login and sensitive-operation verification. Production hosts should run NTP or chrony to keep clock drift within the verification window.

Setup returns 10 recovery codes. The server stores their hashes and discards the plaintext; the client should require the user to save the codes. Regeneration invalidates all previous codes, and successful verification removes the submitted code.

Starting setup, regenerating recovery codes, and deleting TOTP require sensitive-operation verification. Removing TOTP reduces the local-method count. The user must disable 2FA first if removal would leave fewer than two local methods. Each sensitive-operation verification ID works once.

User preferences store user-level settings. two_factor_enabled is security-sensitive.

Constraints:

  • Enabling 2FA requires at least two usable local methods.
  • TOTP and its recovery codes count as one local method.
  • Removing a passkey, unbinding email, or deleting TOTP must leave at least two usable local methods while 2FA is enabled.
  • Admin-initiated preference updates must respect role hierarchy. A non-root admin cannot modify root or equally privileged users.

Management gRPC is used by the CLI and operational commands.

Production rules:

  • Prefer Unix socket transport.
  • If using TCP, set management.auth_token.
  • Do not expose management TCP publicly.
  • Inject tokens from files or secret managers.
  • Keep management.enable_reflection disabled in production.

The management token is not a user access token. Treat it as infrastructure-level secret material.

Providers decide upstream request headers. The proxy layer executes provider-supplied headers only.

Consequences:

  • Raw client Range, Accept, User-Agent, and similar headers are not automatically forwarded by the proxy.
  • If an upstream requires Range, the provider must explicitly select it.
  • If a direct URL is bound to User-Agent, client-facing headers and proxy upstream headers should match.
  • If a client cannot set required headers, use proxy mode.

See Media Providers for credential configuration and Playback and Proxy for direct, proxy, and playback-info selection.

  • Security and Secrets: Configure JWT, OPAQUE, provider credential encryption, password policy, CORS, and trusted proxies.
  • Email and OAuth2: Configure email codes, SMTP, and runtime OAuth2 provider settings.
  • WebAuthn: Configure passkey RP ID, origins, allowed origins, and challenge timeout.
  • Rate Limits: Configure HTTP, gRPC, chat, WebSocket, and authentication rate limits.