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.5", 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 torii::ToriiBuilder;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create Torii using the builder pattern
    // This connects to SQLite and applies migrations automatically
    let torii = ToriiBuilder::new()
        .with_seaorm("sqlite::memory:")
        .await?
        .apply_migrations(true)
        .build()
        .await?;

    // 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);
    let token = session.token.as_ref().expect("freshly created session should have token");
    println!("Session token: {}", 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 torii::ToriiBuilder;
use chrono::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Opaque sessions are the default - sessions are stored in the database
    let _torii = ToriiBuilder::new()
        .with_sqlite("sqlite::memory:")
        .await?
        .with_session_expiry(Duration::days(30))
        .apply_migrations(true)
        .build()
        .await?;

    Ok(())
}

JWT Sessions

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

use torii::{ToriiBuilder, JwtConfig};
use chrono::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create JWT configuration with HS256 algorithm
    // The secret must be at least 32 bytes for security
    let jwt_config = JwtConfig::new_hs256(
        b"your-secret-key-at-least-32-chars-long!".to_vec()
    )?
        .with_issuer("your-app-name")
        .with_metadata(true);

    let torii = ToriiBuilder::new()
        .with_sqlite("sqlite::memory:")
        .await?
        .with_jwt_sessions(jwt_config)
        .with_session_expiry(Duration::hours(2))
        .apply_migrations(true)
        .build()
        .await?;

    Ok(())
}

Web Framework Integration

Axum Integration

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

[dependencies]
torii-axum = { version = "0.5.0", features = ["password", "magic-link"] }
use std::sync::Arc;
use axum::{response::Json, routing::get, Router};
use torii::ToriiBuilder;
use torii_axum::{AuthUser, CookieConfig, LinkConfig};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Set up Torii using the builder pattern
    let torii = Arc::new(
        ToriiBuilder::new()
            .with_seaorm("sqlite::memory:")
            .await?
            .apply_migrations(true)
            .build()
            .await?
    );

    // Create authentication routes with configuration
    let auth_routes = torii_axum::routes(torii.clone())
        .with_cookie_config(CookieConfig::development())
        .with_link_config(LinkConfig::new("http://localhost:3000"))
        .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
  • POST /auth/magic-link - Request magic link email
  • POST /auth/magic-link/verify - Verify magic link
  • POST /auth/password/reset/request - Request password reset
  • GET /auth/user - Get current user
  • POST /auth/logout - User logout

For complete documentation on configuration options, middleware, and all available routes, see the Axum Integration guide.

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};
use torii_core::RepositoryProvider;

async fn start_oauth_flow<R: RepositoryProvider>(
    torii: &Torii<R>,
    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)
}
// Send magic link email (requires mailer to be configured)
let token = torii.magic_link().send_link(
    "user@example.com",
    "https://example.com/auth/magic-link/verify"
).await?;

// Verify magic token (called when user clicks the link)
let (user, session) = torii.magic_link().authenticate(
    &token_from_url,
    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.