Skip to Content
API Service (Rust)Auth & Session Model

Auth & Session Model

Token Types

TokenLengthStorageExpiryPurpose
Session token64-char alphanumericsessions.session_token7 daysBearer auth on every request
Verification token32-char alphanumericverification_tokens.token24 hoursEmail verification link
OTP6-digit numericverification_tokens.otp24 hoursEmail verification code
Password reset token32-char alphanumericpassword_reset_tokens.token24 hoursPassword reset link

All tokens are generated via rand::thread_rng() — cryptographically secure random generation.

Auth State Lifecycle

Signup Flow

Password Requirements

Enforced in common/validation.rs:

  • Minimum 8 characters, maximum 128 characters
  • Must contain at least one uppercase letter
  • Must contain at least one lowercase letter
  • Must contain at least one digit
pub fn validate_password(password: &str) -> Result<(), ValidationError> { if password.len() < 8 || password.len() > 128 { return Err(...) } if !password.chars().any(|c| c.is_uppercase()) { return Err(...) } if !password.chars().any(|c| c.is_lowercase()) { return Err(...) } if !password.chars().any(|c| c.is_numeric()) { return Err(...) } Ok(()) }

Session Management

Session creation (auth/session.rs):

pub async fn create_session(db: &PgPool, user_id: Uuid, role: Role, ip: Option<IpNet>, user_agent: Option<String>) -> Result<Session> // Generates 64-char token // INSERT INTO sessions (user_id, session_token, expires_at=NOW()+7days, role, ip_address, user_agent)

Session validation (in auth_middleware):

SELECT s.user_id, s.role FROM sessions s WHERE s.session_token = $1 AND s.expires_at > NOW()

Session cleanup (auth/background.rs):

pub fn start_session_cleanup_task(db: PgPool) -> tokio::task::JoinHandle<()> // Runs in background Tokio task // DELETE FROM sessions WHERE expires_at < NOW() // Interval: configurable, runs indefinitely

OAuth Flow

Role Model

#[derive(sqlx::Type)] #[sqlx(type_name = "user_role", rename_all = "lowercase")] pub enum Role { User, Admin, Contributor, }

The user_role PostgreSQL enum has three variants: user, contributor, and admin.

Role propagation: admin role changes via PATCH /admin/users/{id}/role do not update active sessions. Users keep their previous session role until re-login or session expiry.

Exception: profile self-opt-in (PATCH /user/update-profile with contributor_opt_in=true) performs one-way user -> contributor escalation and synchronizes active sessions.role rows for that user.

Last updated on