Skip to main content

Crate umbral_auth

Crate umbral_auth 

Source
Expand description

umbral-auth — the built-in authentication plugin.

The first crate under plugins/ and the proof of the M7 plugin contract: a real built-in expressed through umbral::prelude::Plugin with no special-casing inside umbral-core. Auth is the most common plugin, so getting it right here also pressure-tests the contract for the rest.

§M9 v1 scope

  • AuthUser model: the canonical User model (username, email, password hash, is_active / is_staff / is_superuser, date_joined, last_login).
  • UserModel trait: the minimum surface a custom user model must satisfy so AuthPlugin<U> can swap in any user type. Default impls cover the optional flag methods so a minimal custom user struct only has to implement the load-bearing four.
  • argon2 password hashing via hash_password / verify_password.
  • create_user, authenticate, set_password helpers. authenticate and set_password are generic over any U: UserModel.
  • AuthPlugin registers the user model (which becomes a migration) plus the /auth routes and management commands. The type parameter defaults to AuthUser so existing apps need no changes.
  • [login_required] module: LoginRequired config, LoggedIn<U> extractor, LoginRequiredLayer middleware, and the login_required() / login_required_html() convenience constructors. A login-required gate in two shapes.

§Custom user models

// 1. Declare a custom user struct.
#[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize, umbral::orm::Model)]
pub struct TenantUser {
    pub id: i64,
    pub username: String,
    pub password_hash: String,
    pub tenant_id: i64,
    pub is_active: bool,
}

// 2. Implement UserModel (only the four required methods).
impl umbral_auth::UserModel for TenantUser {
    fn id(&self) -> i64               { self.id }
    fn username(&self) -> &str        { &self.username }
    fn password_hash(&self) -> &str   { &self.password_hash }
    fn set_password_hash(&mut self, h: String) { self.password_hash = h; }
}

// 3. Wire the plugin with your type.
App::builder()
    .plugin(AuthPlugin::<TenantUser>::default())
    .build()?

§Deferred (per docs/specs/outlines/auth-and-sessions.md)

  • Permissions, groups, the auth-backend chain.
  • The Auth<U> request extractor + #[login_required] middleware. Needs Plugin::middleware() lifted (M7 deferral).
  • Login / logout / password-reset HTTP flows. Needs the full umbral-sessions session middleware wired end-to-end.
  • Periodic session cleanup via umbral-tasks.

Re-exports§

pub use password_validation::CommonPasswordValidator;
pub use password_validation::MinLengthValidator;
pub use password_validation::NumericPasswordValidator;
pub use password_validation::PasswordContext;
pub use password_validation::PasswordPolicy;
pub use password_validation::PasswordValidator;
pub use password_validation::UserAttributeSimilarityValidator;
pub use password_validation::validate_password;
pub use bearer_auth::BearerAuthentication;
pub use bearer_auth::parse_bearer_header;
pub use extractors::CurrentIdentity;
pub use extractors::OptionalIdentity;
pub use extractors::resolve_identity;
pub use login_required::LoggedIn;
pub use login_required::LoginRequired;
pub use login_required::LoginRequiredLayer;
pub use login_required::current_session_user_id;
pub use login_required::current_session_user_pk;
pub use login_required::login_required;
pub use login_required::login_required_html;
pub use login_required::resolve_user as current_user_as;
pub use session_user::OptionalUser;
pub use session_user::SessionAuthentication;
pub use session_user::User;
pub use session_user::current_user;
pub use session_user::login;
pub use session_user::login_with_request;
pub use session_user::user_context_layer;
pub use throttle::Throttle;
pub use throttle::ThrottleConfig;
pub use throttle::login_throttle_check;
pub use throttle::login_throttle_clear;
pub use throttle::register_throttle_check;
pub use token::AuthToken;
pub use token::PlaintextToken;
pub use token::TOKEN_PREFIX;
pub use token::digest_token;

Modules§

auth_routes
Built-in /auth HTTP surface — login, logout, me, register.
auth_user
bearer_auth
BearerAuthentication — the bearer-token authenticator.
extractors
Axum extractors that resolve a request to an umbral::auth::Identity.
login_required
A login-required gate for umbral handlers.
password_validation
Password-strength validation.
session_user
AuthUser-aware session helpers — moved from umbral-sessions so sessions can stay free of any user-model dependency.
throttle
Login / register rate-limiting — credential-stuffing & brute-force defense.
token
Opaque DB-backed bearer tokens.

Structs§

AuthPlugin
The built-in authentication plugin, generic over the user model.
AuthUser
The canonical authentication user. #[derive(Model)] snake_cases the struct name into the table name auth_user; the M3 derive doesn’t yet accept #[umbral(table = ...)] so the snake_case round-trip is the only way to get a plugin-prefixed table name until the attribute lands.
CreateSuperuserCommand
createsuperuser - interactive superuser creation, dispatched via cargo run -- createsuperuser from any umbral project that registers AuthPlugin.

Enums§

AuthError
Errors the auth helpers can produce. Kept narrow at M9 v1 so the surface is easy to handle in one match arm.

Traits§

UserModel
The minimum surface a user model must expose so AuthPlugin<U> can operate on it generically.

Functions§

authenticate
Verify a username + plaintext password against the user table for user model U. Returns the user on success; returns AuthError::InvalidCredentials for both “no such user” and “wrong password” (the same shape, so a caller can’t enumerate accounts).
create_superuser
Create a superuser - is_staff = true, is_superuser = true, is_active = true. Used by the createsuperuser management command and available directly for tests / seed scripts.
create_user
Create a new active user with the given username, email, and plaintext password. The password is hashed before insert; the plaintext never touches the database. date_joined is set to Utc::now(); last_login is None; is_active = true, is_staff = false, is_superuser = false.
create_user_with_flags
Insert a new user with arbitrary is_staff / is_superuser flags. Used by create_user (flags = false, false) and create_superuser (flags = true, true); exposed publicly so custom seed paths can pick a specific shape (e.g. a staff-but- not-superuser editor account).
hash_password
Hash a plaintext password with argon2’s framework-chosen parameters. Returns the PHC-encoded string ready to store in the password_hash column. The hash is self-describing so future parameter upgrades stay transparent: a verified hash with old parameters can be re-hashed on next login.
hash_password_async
Async wrapper around hash_password that runs the CPU-bound argon2 work on tokio’s blocking pool via spawn_blocking. argon2id with the framework parameters takes ~100ms of CPU; calling it directly from a request handler pins an async worker thread for that whole time, so a login/registration burst starves the runtime and HTTP/1.1 connections hang. Offloading keeps the async workers free to drive other tasks. Async request handlers must use this; the sync hash_password remains for non-async / CLI / test callers.
logout
Pure forwarding alias for umbral_sessions::logout. Re-exported so handlers that import umbral_auth::login also reach for umbral_auth::logout without flipping crates. Sessions still owns the implementation; it’s user-agnostic. End a session. Reads the session token from the request headers, destroys the row, and sets a Set-Cookie header on the response that immediately expires the client-side cookie.
set_password
Replace a user’s password with a fresh hash of the given plaintext. Writes through to the database using U::TABLE. user.password_hash is updated in place on success so the caller can keep using the same value.
verify_password
Verify a plaintext password against an argon2 PHC-encoded hash. Returns Ok(true) on match, Ok(false) on mismatch, and an error only when the hash itself is malformed. Callers that just want a bool can use .unwrap_or(false).
verify_password_async
Async wrapper around verify_password that runs the CPU-bound argon2 verification on tokio’s blocking pool via spawn_blocking. See hash_password_async for the starvation rationale. Async request handlers must use this; the sync verify_password remains for non-async / CLI / test callers.