Quick Start
Generate an auth schema and run an Axum server.
This example starts an Axum server with an in-memory SQLite database. Data resets when the process stops.
Dependencies
[dependencies]
better-auth = { version = "1.0.0-alpha.3", git = "https://github.com/better-auth-rs/better-auth-rs", branch = "master", features = ["axum", "seaorm2"] }
axum = "0.8"
tokio = { version = "1", features = ["macros", "rt-multi-thread", "net"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"Generate the schema
cargo install better-auth-cli --git https://github.com/better-auth-rs/better-auth-rs --branch master --locked
better-auth-rs generate --output src/auth_schema.rsThe generated file contains all four core entities, AppAuthSchema, and create_auth_tables. Add --plugins two-factor,api-key when your app registers those plugins. Existing output files are preserved unless you pass --force.
Start the server
Save this complete application as src/main.rs:
mod auth_schema;
use auth_schema::{AppAuthSchema, create_auth_tables};
use better_auth::{AuthConfig, BetterAuth};
use better_auth::integrations::axum::AxumIntegration;
use better_auth::plugins::{EmailPasswordPlugin, SessionManagementPlugin};
use better_auth::seaorm::{Database, SeaOrmStore};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let database = Database::connect("sqlite::memory:").await?;
create_auth_tables(&database).await?;
let config = AuthConfig::new(std::env::var("AUTH_SECRET")?)
.base_url("http://localhost:3000");
let store = SeaOrmStore::<AppAuthSchema>::new(config.clone(), database);
let auth = Arc::new(
BetterAuth::<AppAuthSchema>::new(config)
.store(store)
.plugin(EmailPasswordPlugin::new().enable_signup(true))
.plugin(SessionManagementPlugin::new())
.build()
.await?,
);
let app = axum::Router::new()
.nest("/auth", auth.clone().axum_router())
.with_state(auth);
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?;
axum::serve(listener, app).await?;
Ok(())
}Set AUTH_SECRET to a random secret of at least 32 characters. Run cargo run.
For a persistent database, run create_auth_tables once from your initial migration. The function fails if tables already exist. Use versioned application migrations for subsequent changes.
Register and sign in
COOKIE_JAR=$(mktemp)
curl --fail-with-body http://localhost:3000/auth/sign-up/email \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","password":"example-password-123","name":"Example"}'
curl --fail-with-body http://localhost:3000/auth/sign-in/email \
-c "$COOKIE_JAR" \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","password":"example-password-123"}'Sign-in sets a signed session cookie. Save the cookie in a cookie jar and send the cookie with subsequent requests:
curl --fail-with-body http://localhost:3000/auth/get-session \
-b "$COOKIE_JAR"
rm "$COOKIE_JAR"The default configuration uses cookies. To accept Bearer credentials, explicitly enable config.session.bearer as described in the session guide.
For business routes, use CurrentSession<AppAuthSchema> as shown in the Axum guide. The independent consumer tests this public schema generation flow with registration, login, protected routes, API keys, and TOTP.
Run devenv shell -- bun scripts/quick-start-check.ts to compile this document's application and execute its registration, sign-in, and session commands.