feat: add JWT auth, configurable username, switch password auth to Basic

Add server-side JWT authentication with permission-based access control
(read/write/delete claims). Password authentication now uses HTTP Basic
auth only (replacing Bearer). Add configurable username for both server
and client (--server-username/--client-username, defaults to "keep").

JWT secret supports file-based loading via --server-jwt-secret-file for
Docker secrets. OPTIONS preflight requests bypass auth. HEAD mapped to
read permission.

Co-Authored-By: opencode <noreply@opencode.ai>
This commit is contained in:
2026-03-13 13:56:35 -03:00
parent af1e0ca570
commit e672ec751e
17 changed files with 1052 additions and 196 deletions

View File

@@ -151,6 +151,20 @@ pub struct OptionsArgs {
#[arg(help("Password hash for server authentication (requires --server)"))]
pub server_password_hash: Option<String>,
#[arg(long, env("KEEP_SERVER_USERNAME"))]
#[arg(help(
"Username for server Basic authentication (requires --server, defaults to 'keep')"
))]
pub server_username: Option<String>,
#[arg(long, env("KEEP_SERVER_JWT_SECRET"))]
#[arg(help("JWT secret for token-based authentication (requires --server)"))]
pub server_jwt_secret: Option<String>,
#[arg(long, env("KEEP_SERVER_JWT_SECRET_FILE"))]
#[arg(help("Path to file containing JWT secret (requires --server)"))]
pub server_jwt_secret_file: Option<PathBuf>,
#[cfg(feature = "client")]
#[arg(long, env("KEEP_CLIENT_URL"), help_heading("Client Options"))]
#[arg(help("Remote keep server URL for client mode"))]
@@ -161,6 +175,16 @@ pub struct OptionsArgs {
#[arg(help("Password for remote keep server authentication"))]
pub client_password: Option<String>,
#[cfg(feature = "client")]
#[arg(long, env("KEEP_CLIENT_USERNAME"), help_heading("Client Options"))]
#[arg(help("Username for remote keep server authentication (defaults to 'keep')"))]
pub client_username: Option<String>,
#[cfg(feature = "client")]
#[arg(long, env("KEEP_CLIENT_JWT"), help_heading("Client Options"))]
#[arg(help("JWT token for remote keep server authentication"))]
pub client_jwt: Option<String>,
#[arg(
long,
help("Force output even when binary data would be sent to a TTY")