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

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.password().register(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.password().authenticate(
        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

Torii provides organized namespaces for different authentication methods:

  • torii.password(): Traditional email/password authentication
  • torii.oauth(): Social login (Google, GitHub, etc.)
  • torii.passkey(): Modern biometric authentication
  • torii.magic_link(): Email-based passwordless login

Each namespace contains focused methods for that authentication type.

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.magic_link().generate_token("user@example.com").await?;

// Verify magic token
let (user, session) = torii.magic_link().authenticate(
    &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.