snowfinch
Authentication and sessions for Rust tower/axum servers.
Snowfinch provides a small set of interfaces for session-based authentication
without prescribing an application database or user model. The core middleware
is built on Tower, while the optional axum
feature adds extractors, response integration, and router conveniences.
Architecture
Applications provide three pieces:
- a
Uservalue containing a stable ID and permissionScope; - a
Backendwhich loads users and authenticates credentials; - a
Storewhich persists compact session records.
Stores retain only a session ID, expiry, and user ID. When a request carries a
valid session cookie, ProvideAuthenticationLayer loads that compact record,
rejects it if expired, and asks the backend for the current user. The resulting
Session and a cheaply cloned Authentication handle are inserted into the
request extensions.
This separation keeps large user values out of the session store and ensures that restored sessions use current user data and permissions.
Example
use Infallible;
use ;
scope!
;
// Without an explicit store, the layer uses NoopStore. Configure a custom
// Store or call with_memory_store() when sessions should survive requests.
let _layer = new.with_backend;
Backend and store methods use return-position impl Future, so implementations
do not need to name, box, or erase their futures. The authentication layer shares
backend and store values through Arc, therefore neither implementation needs
to be Clone.
Login and logout
Request handlers obtain the Authentication handle from request extensions,
or as an Axum extractor when the axum feature is enabled.
Authentication::authenticate validates credentials, Authentication::login
creates and persists a session, and Authentication::logout revokes it.
A returned Session can be added to an Axum response. Its response-parts
implementation writes the secure, HTTP-only session cookie.
Authorization
The authorization module provides Tower middleware for rejecting requests
without an acceptable authenticated session:
RequireAuthenticatedaccepts any authenticated user;RequireScoperequires a complete permission scope;AuthorizeFnadapts a closure;RequireAuthorizationLayeraccepts a customAuthorizeimplementation.
Extension traits are provided for tower::ServiceBuilder, and for Axum routers
and method routers when the axum feature is enabled.
Permission scopes
The scope! macro defines a compact, u64-backed permission type. Generated
scopes support compound scopes, lookup by name, iteration, set operations, raw u64
conversion, and optional Serde and SQLx integration. Unknown raw bits are
ignored when constructing or decoding a scope.
Passwords
Password is a packed 64-byte salted SHA-256 value containing a 32-byte hash
followed by a 32-byte salt. Plaintext comparisons recompute the hash and compare
the packed representation in constant time. With sqlx, passwords are encoded
directly as binary blobs.
Feature flags
The default feature set enables memory-store and session-local.
axumenables extractors, response integration, and router extensions.memory-storeenables the Moka-backedstore::MemoryStore.serdeenables serialization forPasswordand generated scopes.session-localexposes the current session throughsession::currentandsession::try_current.sqlxenables database encoding and decoding forPasswordand generated scopes.
license
snowfinch is licensed under the MIT License. See LICENSE for details.
contributing
Contributions are welcome.
Please follow the existing code style and conventions used throughout the project. If you're proposing a new feature or API, opening an issue first is often the easiest way to discuss the design.