| Crates.io | axum-email-otp-auth |
| lib.rs | axum-email-otp-auth |
| version | 0.1.0 |
| created_at | 2025-12-12 03:11:34.734041+00 |
| updated_at | 2025-12-12 03:11:34.734041+00 |
| description | A production-ready, framework-agnostic Rust library for OTP email authentication. |
| homepage | |
| repository | https://github.com/roksprogar/axum-email-otp-auth |
| max_upload_size | |
| id | 1980943 |
| size | 114,088 |
A production-ready, framework-agnostic Rust library for OTP (One-Time Password) email authentication, with built-in support for Axum.
Passwords are a pain. Users forget them, reuse them, and they are a prime target for attackers. Storing them securely is a liability.
Axum Email OTP Auth solves this by eliminating passwords entirely:
lettre.tower-cookies).Router for quick setup.Add this to your Cargo.toml:
[dependencies]
axum-email-otp-auth = { version = "0.1.0", features = ["axum"] }
The library is configured using environment variables.
| Variable | Description | Default |
|---|---|---|
JWT_SECRET |
Secret key for signing JWTs | Required |
ACCESS_TOKEN_EXPIRE_MINUTES |
Access token lifetime | 30 |
REFRESH_TOKEN_EXPIRE_DAYS |
Refresh token lifetime | 7 |
OTP_EXPIRY_SECONDS |
OTP validity duration | 300 (5 minutes) |
ENABLE_MAGIC_LOGIN |
Enable "Magic OTP" flow (skips email, accepts 000000) |
false |
| Variable | Description | Default |
|---|---|---|
REDIS_HOST |
Redis server hostname | Required |
REDIS_PORT |
Redis server port | Required |
ENABLE_MAGIC_LOGIN is false)| Variable | Description | Default |
|---|---|---|
SMTP_HOST |
SMTP server hostname | Required |
SMTP_PORT |
SMTP server port | Required |
SMTP_USERNAME |
SMTP username | None |
SMTP_PASSWORD |
SMTP password | None |
SMTP_MAIL_FROM |
Sender email address | Required |
SMTP_MAIL_FROM_NAME |
Sender name | Required |
To simplify local development and testing, you can enable the "Magic OTP" flow. This allows you to log in as any user using the fixed OTP code 000000, without sending actual emails with the OTP.
ENABLE_MAGIC_LOGIN=true in your local .env file environment.test@example.com).000000.[!WARNING] Security Risk: Ensure this environment variable is NEVER set to
truein production environments.
Initialize the service in your main.rs:
use axum_email_otp_auth::{AuthConfig, AuthService, RedisStorage, LettreEmailSender};
use std::sync::Arc;
#[tokio::main]
async fn main() {
// 1. Load Config
let config = AuthConfig::from_env().expect("Failed to load config");
// 2. Initialize Components
let storage = Arc::new(RedisStorage::new(&config.redis_url).unwrap());
let email_sender = Arc::new(LettreEmailSender::new(&config));
// 3. Create Service
let auth_service = Arc::new(AuthService::new(config, storage, email_sender));
}
Expose the API endpoints directly in your Axum router:
use axum_email_otp_auth::axum_api::auth_router;
use axum_email_otp_auth::tower_cookies::CookieManagerLayer;
use axum::Router;
let app = Router::new()
.nest("/auth", auth_router(auth_service.clone()))
.layer(CookieManagerLayer::new());
Once mounted at /auth, the following endpoints are available:
POST /auth/request-otp
{
"email": "user@example.com"
}
POST /auth/verify-otp
{
"email": "user@example.com",
"otp": "123456"
}
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsIn...",
"expires_in": 1800
}
The secure refresh token is automatically set as an HttpOnly cookie.
POST /auth/refresh
(No body required, relies on the refresh_token cookie)
Run the test suite with:
cargo test
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.