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
AuthUsermodel: the canonical User model (username, email, password hash,is_active/is_staff/is_superuser,date_joined,last_login).UserModeltrait: the minimum surface a custom user model must satisfy soAuthPlugin<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_passwordhelpers.authenticateandset_passwordare generic over anyU: UserModel.AuthPluginregisters the user model (which becomes a migration) plus the/authroutes and management commands. The type parameter defaults toAuthUserso existing apps need no changes.- [
login_required] module:LoginRequiredconfig,LoggedIn<U>extractor,LoginRequiredLayermiddleware, and thelogin_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. NeedsPlugin::middleware()lifted (M7 deferral). - Login / logout / password-reset HTTP flows. Needs the full
umbral-sessionssession middleware wired end-to-end. - Periodic session cleanup via
umbral-tasks.
Re-exports§
pub use mailer::AuthMailError;pub use mailer::AuthMailer;pub use mailer::ConsoleMailer;pub use mailer::MailKind;pub use mailer::OutgoingMail;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 challenge::AuthChallenge;pub use challenge::reset_password;pub use challenge::start_email_verification;pub use challenge::start_password_reset;pub use challenge::verify_email;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::email_action_throttle_check;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
/authHTTP surface — login, logout, me, register. - auth_
user - bearer_
auth BearerAuthentication— the bearer-token authenticator.- challenge
- Short-lived, single-use, hashed-at-rest secrets for the email-verification
and password-reset flows. One table, discriminated by
purpose. - extractors
- Axum extractors that resolve a request to an
umbral::auth::Identity. - form_
routes - POST-only form-action auth endpoints — the redirect-style counterpart to
the JSON surface in
crate::auth_routes. - login_
required - A login-required gate for umbral handlers.
- mailer
- The pluggable email seam. umbral-auth renders bodies via
umbral::templatesand hands them to whateverAuthMailerthe app wired (default: print to stderr). Keeps auth decoupled from any mail crate. - 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 / email-action rate-limiting — credential-stuffing & brute-force defense.
- token
- Opaque DB-backed bearer tokens.
Structs§
- Auth
Plugin - The built-in authentication plugin, generic over the user model.
- Auth
User - The canonical authentication user.
#[derive(Model)]snake_cases the struct name into the table nameauth_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. - Create
Superuser Command createsuperuser- interactive superuser creation, dispatched viacargo run -- createsuperuserfrom any umbral project that registersAuthPlugin.
Enums§
- Auth
Error - Errors the auth helpers can produce. Kept narrow at M9 v1 so the surface is easy to handle in one match arm.
Traits§
- User
Model - 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; returnsAuthError::InvalidCredentialsfor 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 thecreatesuperusermanagement 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_joinedis set toUtc::now();last_loginisNone;is_active = true,is_staff = false,is_superuser = false. - create_
user_ with_ flags - Insert a new user with arbitrary
is_staff/is_superuserflags. Used bycreate_user(flags = false, false) andcreate_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_passwordthat runs the CPU-bound argon2 work on tokio’s blocking pool viaspawn_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 synchash_passwordremains for non-async / CLI / test callers. - logout
- Log the current request’s user out: destroy the session row and emit a
clearing Set-Cookie on
resp. - 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_hashis 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_passwordthat runs the CPU-bound argon2 verification on tokio’s blocking pool viaspawn_blocking. Seehash_password_asyncfor the starvation rationale. Async request handlers must use this; the syncverify_passwordremains for non-async / CLI / test callers.