feat(auth): bring opaque (RFC 9807) auth

OPAQUE (RFC 9807) implementation (using `opaque-ke` crate)

    with opaque authentfication, server will never receive the password (in the auth=password mode)
    this is a must have to create trust with users to permit end to end encryption in the future
    (we cannot know if user use the same password/passphrase for his asymetric key or his oxicloud auth,
    this is why server must never have the password)

    pass1: prepare server
This commit is contained in:
Edouard Vanbelle
2026-07-26 15:04:31 +02:00
parent d76803f602
commit 0e395ae15f
19 changed files with 1570 additions and 7 deletions
+56
View File
@@ -188,6 +188,62 @@ DATABASE_URL=postgres://postgres:postgres@localhost:5432/oxicloud
# Parallelism lanes (default: 2)
#OXICLOUD_HASH_PARALLELISM=2
# -----------------------------------------------------------------------------
# OPAQUE aPAKE (zero-knowledge password login, RFC 9807)
# -----------------------------------------------------------------------------
# OPAQUE replaces `POST /api/auth/login` with a zero-knowledge exchange:
# the passphrase never leaves the client, not on registration and not on
# login. This is the substrate for later E2EE work.
#
# Phase 0 (this build) ships the primitives only — endpoints are inert
# until `OXICLOUD_OPAQUE_MODE` is set. Leave everything commented for a
# no-op install; OIDC-only and magic-link-only deployments never need to
# touch OPAQUE at all (see the effective-mode downgrade below).
# OPAQUE mode gate. Values: off | migrate | opaque_only
# off — endpoints 404. Default. Safe for OIDC-only / magic-link-only.
# migrate — endpoints live; legacy `POST /api/auth/login` still accepted.
# opaque_only — endpoints live; legacy refused for users with an envelope.
# Effective mode is automatically downgraded to `off` when password auth
# is disabled via OXICLOUD_AUTH_METHODS (OPAQUE has nothing to shadow) —
# an audit-channel log line explains why. So enabling this without
# password in OXICLOUD_AUTH_METHODS is a no-op, not a boot error.
#OXICLOUD_OPAQUE_MODE=off
# Persistent OPAQUE server keypair (base64-encoded ServerSetup blob).
# Generated ONCE per deployment; rotating this invalidates every user's
# registration (they'd all be forced to re-register on next login). Only
# required when `OXICLOUD_OPAQUE_MODE != off` AND password auth is
# enabled — otherwise the value is ignored.
#
# Generate on first-time enable:
# # Docker (recommended for production):
# docker run --rm ghcr.io/atalayalabs/oxicloud:latest opaque-setup
# # Or from a source checkout:
# cargo run --bin opaque-setup
# Both print the base64 value on stdout (guidance on stderr, so shell
# pipelines capture cleanly). Paste the printed line into your env or
# secrets manager. NEVER regenerate — treat it like your JWT secret;
# losing it forces every user to reset their passphrase.
#OXICLOUD_OPAQUE_SERVER_SETUP=
# Client-side Argon2id key-stretching parameters (RFC 9807 KSF).
# These run on the USER'S DEVICE during OPAQUE login/registration —
# distinct from OXICLOUD_HASH_* which runs on the server for the legacy
# password path. Client-side execution means we can afford higher memory
# than the server would (each user pays once for themselves rather than
# the server paying for every concurrent login).
#
# Bumping these does NOT affect existing envelopes; they'd re-mint on
# the user's next password change.
#
# Memory cost in KiB (default: 262144 = 256 MiB)
#OXICLOUD_OPAQUE_KSF_MEMORY_KIB=262144
# Iterations (default: 3)
#OXICLOUD_OPAQUE_KSF_ITERATIONS=3
# Parallelism lanes (default: 4)
#OXICLOUD_OPAQUE_KSF_PARALLELISM=4
# -----------------------------------------------------------------------------
# RATE LIMITING & ACCOUNT LOCKOUT
# -----------------------------------------------------------------------------