Skip to content

Architecture

┌─────────────────────────────────────────────────────┐
│ authx-axum (HTTP adapter) │
│ SessionLayer · RateLimitLayer · CSRF · Handlers │
│ RequireAuth extractor · Cookie helpers │
└──────────────────────┬──────────────────────────────┘
┌──────────────────────▼──────────────────────────────┐
│ authx-plugins (Feature plugins) │
│ EmailPassword · MagicLink · EmailOTP · TOTP │
│ PasswordReset · OAuth · ApiKey · Anonymous │
│ Username · EmailVerification · Organization │
│ Admin · OneTimeTokenStore · RedisTokenStore │
└──────────────────────┬──────────────────────────────┘
┌──────────────────────▼──────────────────────────────┐
│ authx-core (Zero-dep engine) │
│ Models · Crypto (Argon2id, AES-GCM, EdDSA) │
│ RBAC / ABAC policy engine · EventBus │
│ Identity · Brute-force tracker · Key rotation │
└──────────────────────┬──────────────────────────────┘
┌──────────────────────▼──────────────────────────────┐
│ authx-storage (Repository layer) │
│ Trait definitions (ports) · MemoryStore │
│ PostgresStore (sqlx) · AuditLogger │
│ StorageAdapter blanket impl │
└─────────────────────────────────────────────────────┘
CrateMay import
authx-corestd, serde, uuid, chrono, thiserror, crypto crates
authx-storageauthx-core + sqlx (optional, behind feature flag)
authx-pluginsauthx-core + authx-storage + tokio, rand, argon2, …
authx-axumall above + axum, tower, cookie, http
authx-dashboardall above
authx-cliall above + clap

authx-core never imports from any HTTP framework. This makes it trivially portable to Actix, any future framework, or a non-HTTP service.

Every repository is a separate trait:

pub trait UserRepository { async fn create(...); async fn find_by_id(...); … }
pub trait SessionRepository { async fn create(...); async fn invalidate(...); … }
pub trait CredentialRepository { … }
// … and so on

StorageAdapter is a supertrait alias:

pub trait StorageAdapter:
UserRepository + SessionRepository + CredentialRepository +
OrgRepository + ApiKeyRepository + OAuthAccountRepository +
InviteRepository + AuditLogRepository
{}
// Any T implementing all traits gets StorageAdapter automatically
impl<T: UserRepository + SessionRepository + …> StorageAdapter for T {}

This means you can pass any conforming store to any plugin without a type parameter explosion.

Both UserRepository and SessionRepository define a create method. When a plugin uses both, Rust requires Fully Qualified Syntax (UFCS):

// ✅ Correct — unambiguous
UserRepository::create(&self.storage, create_user).await?;
SessionRepository::create(&self.storage, create_session).await?;
// ❌ Ambiguous — won't compile
self.storage.create(create_user).await?;

All authx plugins follow this convention.

EventBus is a tokio::sync::broadcast channel. Plugins emit typed AuthEvent variants; subscribers (like AuditLogger) react asynchronously:

self.events.emit(AuthEvent::SignIn { user: user.clone(), session: session.clone() });

The bus is cloneable and cheaply shareable. Missing events on a lagged subscriber is logged as a warning — it never panics.