webx_core/security/mod.rs
1//! Authentication/security extension points.
2//!
3//! Ports shared by application code and the HTTP host:
4//!
5//! * [`ITokenIssuer`] — mint a token from [`TokenClaims`] (login).
6//! * [`ISessionStore`] — revoke / query revoked tokens (logout, forced sign-out);
7//! the authentication middleware consults it after verifying a token.
8//! * [`IPasswordHasher`] — hash/verify passwords as PHC strings (Argon2id by
9//! default).
10//!
11//! Two dependency-free primitives for the security-adjacent code every
12//! application writes at least once:
13//!
14//! * [`constant_time_eq`] — compare secrets without leaking where they differ.
15//! * [`OneTimeSecret`] — a TTL-bound secret consumed exactly once (installation
16//! token, invite link, password reset), with a [`OneTimeSecretState`] for
17//! telling 401 from 410.
18//!
19//! # How the framework uses these ports
20//!
21//! The ports exist so business crates write "call the port" code, never crypto
22//! or session-plumbing code:
23//!
24//! * **Login** — a handler injects `Arc<dyn ITokenIssuer>`, calls
25//! [`ITokenIssuer::issue`], and returns `IssuedToken::token`. The password is
26//! checked with `Arc<dyn IPasswordHasher>` (`hash` on registration, `verify` on
27//! login, `needs_rehash` to upgrade old hashes).
28//! * **Authenticated requests** — the authentication middleware verifies the
29//! token, then (when an `ISessionStore` is registered) asks
30//! [`ISessionStore::is_revoked`] about the token's `jti`; revoked → 401.
31//! * **Logout** — the handler calls [`ISessionStore::revoke`] with the `jti` it
32//! stored (or received) at login; no wait for `exp` is needed.
33//!
34//! The traits are dependency-free so they can be implemented anywhere; the
35//! implementations that need third-party crates live in `rust-webx-host`
36//! (`JwtTokenIssuer`, `Argon2PasswordHasher`), while the ones that need nothing
37//! live here ([`InMemorySessionStore`]).
38
39mod once;
40mod password;
41mod session;
42mod tokens;
43
44pub use once::{constant_time_eq, OneTimeSecret, OneTimeSecretState};
45pub use password::IPasswordHasher;
46pub use session::{ISessionStore, InMemorySessionStore};
47pub use tokens::{ITokenIssuer, IssuedToken, TokenClaims};