Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction to Torii

Torii is an authentication framework for Rust applications that gives you complete control over your users' data. Unlike hosted solutions that store user information in their cloud, Torii lets you own and manage your authentication stack while providing modern auth features.

With Torii, you get powerful authentication capabilities combined with full data sovereignty and the ability to store user data wherever you choose.

Warning: This project is in early development and is not production-ready. The API is subject to change without notice. As this project has not undergone security audits, it should not be used in production environments.

Key Features

  • Data Sovereignty: Your user data stays in your own database
  • Multiple Authentication Methods:
    • Password-based authentication
    • Social OAuth/OpenID Connect
    • Passkey/WebAuthn support
    • Magic Link authentication
  • Flexible Storage: Store user data in SQLite, PostgreSQL, or MySQL
  • Session Management: Choose between database sessions or JWT tokens
  • Type Safety: Strongly typed APIs with compile-time guarantees

Storage Support

Authentication MethodSQLitePostgreSQLMySQL
Password
OAuth2/OIDC
Passkey
Magic Link

Getting Started with Torii

This guide will get you up and running with Torii authentication in your Rust application.

Prerequisites

  • A Rust project with Cargo
  • Basic understanding of async Rust
  • Database (SQLite, PostgreSQL, or MySQL)

Installation

Add Torii to your Cargo.toml:

[dependencies]
torii = { version = "0.4.0", features = ["password", "sqlite"] }
tokio = { version = "1", features = ["full"] }

Available Features

Authentication Methods:

  • password - Email/password authentication
  • oauth - OAuth/social login
  • passkey - WebAuthn/passkey authentication
  • magic-link - Email magic link authentication

Storage Backends:

  • sqlite - SQLite storage
  • postgres - PostgreSQL storage
  • seaorm - SeaORM support (SQLite, PostgreSQL, MySQL)

Basic Setup

Here's a complete example with SQLite and password authentication:

use std::sync::Arc;
use torii::Torii;
use torii_storage_seaorm::SeaORMStorage;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize the database connection
    let storage = SeaORMStorage::connect("sqlite::memory:").await?;

    // Run migrations to set up the database schema
    storage.migrate().await?;

    // Create repository provider and Torii instance
    let repositories = Arc::new(storage.into_repository_provider());
    let torii = Arc::new(Torii::new(repositories));

    // Now torii is ready to use for authentication
    Ok(())
}

User Registration and Login

Register a User

use torii::{Torii, ToriiError};
use torii_core::RepositoryProvider;

async fn register_user(
    torii: &Torii<impl RepositoryProvider>,
    email: &str,
    password: &str
) -> Result<(), ToriiError> {
    // Register a new user
    let user = torii.register_user_with_password(email, password).await?;

    println!("User registered: {}", user.id);
    Ok(())
}

Login a User

use torii::{Torii, ToriiError};
use torii_core::RepositoryProvider;

async fn login_user(
    torii: &Torii<impl RepositoryProvider>,
    email: &str,
    password: &str
) -> Result<(), ToriiError> {
    // Authenticate user - optional user_agent and ip_address for tracking
    let (user, session) = torii.login_user_with_password(
        email,
        password,
        Some("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36".to_string()),
        Some("127.0.0.1".to_string())
    ).await?;

    // The session token can be stored in a cookie or returned to the client
    println!("User authenticated: {}", user.id);
    println!("Session token: {}", session.token);

    Ok(())
}

Verify a Session

use torii::{Torii, SessionToken, ToriiError};
use torii_core::RepositoryProvider;

async fn verify_session(
    torii: &Torii<impl RepositoryProvider>,
    session_token: &str
) -> Result<(), ToriiError> {
    // Parse the session token
    let token = SessionToken::new(session_token);

    // Verify and get session data (works for both JWT and opaque tokens)
    let session = torii.get_session(&token).await?;

    // Get the user associated with this session
    let user = torii.get_user(&session.user_id).await?
        .ok_or_else(|| ToriiError::AuthError("User not found".to_string()))?;

    println!("Session verified for user: {}", user.id);
    Ok(())
}

Session Types

Database Sessions (Default)

Sessions are stored in your database and can be revoked immediately:

use std::sync::Arc;
use torii::{Torii, SessionConfig};
use chrono::Duration;

let torii = Torii::new(repositories)
    .with_session_config(
        SessionConfig::default()
            .expires_in(Duration::days(30))
    );

JWT Sessions

Self-contained tokens that don't require database lookups:

use torii::{Torii, JwtConfig, SessionConfig};
use chrono::Duration;

// Create JWT configuration with HS256 algorithm
let jwt_config = JwtConfig::new("your-secret-key-at-least-32-chars-long!".to_string())
    .with_issuer("your-app-name")
    .with_metadata(true);

let torii = Torii::new(repositories)
    .with_jwt_sessions(jwt_config);

// Or with custom expiration
let torii = Torii::new(repositories)
    .with_session_config(
        SessionConfig::default()
            .with_jwt(jwt_config)
            .expires_in(Duration::hours(2))
    );

Web Framework Integration

Axum Integration

For quick web integration, use the torii-axum crate:

[dependencies]
torii-axum = { version = "0.4.0", features = ["password", "sqlite"] }
use std::sync::Arc;
use axum::{response::Json, routing::get, Router};
use torii::Torii;
use torii_axum::{AuthUser, CookieConfig};
use torii_storage_seaorm::SeaORMStorage;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Set up database and Torii
    let storage = SeaORMStorage::connect("sqlite::memory:").await?;
    storage.migrate().await?;
    let repositories = Arc::new(storage.into_repository_provider());
    let torii = Arc::new(Torii::new(repositories));

    // Create authentication routes with cookie configuration
    let auth_routes = torii_axum::routes(torii.clone())
        .with_cookie_config(CookieConfig::development())
        .build();

    // Build your application with auth routes
    let app = Router::new()
        .nest("/auth", auth_routes)
        .route("/protected", get(protected_handler))
        .with_state(torii);

    // Start server
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
    axum::serve(listener, app).await?;
    Ok(())
}

// Protected route handler
async fn protected_handler(user: AuthUser) -> Json<serde_json::Value> {
    Json(serde_json::json!({
        "user_id": user.id,
        "email": user.email
    }))
}

This provides automatic endpoints:

  • POST /auth/register - User registration
  • POST /auth/login - User login
  • GET /auth/user - Get current user
  • POST /auth/logout - User logout

Other Authentication Methods

OAuth Authentication

use torii::{Torii, ToriiError};

async fn start_oauth_flow(
    torii: &Torii<impl torii_core::storage::UserStorage + torii_core::storage::OAuthStorage>,
    provider: &str
) -> Result<String, ToriiError> {
    // Get the authorization URL for the provider
    let auth_url = torii.get_oauth_authorization_url(provider).await?;

    // Store the CSRF state in your session/cookies
    let csrf_state = auth_url.csrf_state;

    // Return the URL to redirect the user to
    Ok(auth_url.url)
}
// Generate magic token
let token = torii.generate_magic_token("user@example.com").await?;

// Verify magic token
let (user, session) = torii.verify_magic_token(
    &token.token,
    Some("Browser".to_string()),
    Some("127.0.0.1".to_string())
).await?;

Examples

Check out the complete examples in the repository:

Next Steps

  • Learn about Core Concepts for deeper understanding
  • Explore different authentication methods
  • Configure production storage backends
  • Add email verification and password reset functionality

Remember: Torii gives you complete control over your user data while providing modern authentication features.

Core Concepts

Torii is an authentication framework that gives you control over your users' data while providing modern authentication features. Here are the essential concepts you need to understand.

Key Components

Torii consists of four main parts:

  • Torii Instance: The main coordinator that handles all authentication
  • Storage: Where user and session data is stored (SQLite, PostgreSQL, MySQL)
  • Authentication Methods: Password, OAuth, Passkeys, Magic Links
  • Sessions: How users stay authenticated after login

Users

Users are people who can authenticate with your application. Each user has:

  • Unique ID: A stable identifier that never changes
  • Email: Their email address (required)
  • Name: Optional display name
  • Verification Status: Whether their email is verified
  • Timestamps: When they were created and last updated

Sessions

Sessions keep users authenticated after they log in. Each session has:

  • Token: A secret string that identifies the session
  • User ID: Which user the session belongs to
  • Expiration: When the session expires
  • Client Info: Optional user agent and IP address

Session Types

Torii supports two session types:

  1. Database Sessions (default): Stored in your database, can be revoked immediately
  2. JWT Sessions: Self-contained tokens, fast but cannot be revoked

Authentication Methods

Torii supports multiple ways for users to authenticate:

  • Password: Traditional email/password login
  • OAuth: Social login (Google, GitHub, etc.)
  • Passkeys: Modern biometric authentication
  • Magic Links: Email-based passwordless login

Storage

Torii can store data in multiple databases:

  • SQLite: Great for development and small applications
  • PostgreSQL: Production-ready relational database
  • MySQL: Via SeaORM integration

All storage backends support all authentication methods.

Basic Usage

Here's the typical flow:

  1. Set up storage and create a Torii instance
  2. Register users with your chosen authentication method
  3. Users log in to create sessions
  4. Validate sessions to authenticate requests
  5. Users log out to end sessions

This simple foundation supports all of Torii's authentication features.