crates.io ↗

iet-auth

core contracts official

Defines the ports for passwords, credential lookup, sessions, CSRF, profiles, and token revocation.

CoreFeaturesIntegrationsStacksTooling
Used byiet-auth-acl-timescaleiet-auth-basiciet-auth-basic-axumiet-auth-basic-timescaleiet-auth-identity-timescaleiet-auth-login-htmx-axumiet-auth-profilesiet-auth-profiles-axum+8 more
iet-authcontractsAuthentication contracts
Depends oniet-corecontractiet-configcontract

How to use it

iet-auth defines the authentication ports — Authenticate, TokenIssuer/Invalidate, session and revocation stores, password hashing — plus profile gating helpers such as profile_enabled and NoProfiles. Adapters implement these traits, and transports share the prepared mechanism through the blanket Arc<T> impls.

rust
// examples/htmx-starter/servers/web/tests/framework_auth_rest.rs
use iet_auth::{Authenticate, TokenIssuer};
use iet_core::{AppResult, Principal};

struct Stateless;
impl Authenticate<iet_auth::Secret<String>> for Stateless {
    async fn authenticate(&self, _: &iet_auth::Secret<String>) -> AppResult<Principal> {
        Ok(Principal { subject: "alice-id".into(), profile: None })
    }
}
impl TokenIssuer for Stateless {
    async fn issue(&self, _: &Principal) -> AppResult<iet_auth::Secret<String>> {
        // ... build the token for an already-verified identity
        Ok(iet_auth::Secret::new("token".into()))
    }
}
  • Secret (re-exported from iet_config) has no Display or deref; call .expose() only at the point of use, and never log it.
  • profile_enabled returns true when the principal has no profile, consults the store when it does, and false for identifiers longer than 1024 bytes.

How it works

Authentication produces a Principal; profile_enabled then gates that identity through a ProfileStore, and only a verified identity is passed to a TokenIssuer that returns a redacted Secret token.

sequenceDiagram
  participant C as "Caller"
  participant A as "Authenticate"
  participant G as "profile_enabled"
  participant S as "ProfileStore"
  participant T as "TokenIssuer"
  C->>A: "authenticate credentials"
  A-->>C: "Principal"
  C->>G: "profile_enabled principal"
  G->>S: "enabled subject and profile"
  S-->>G: "bool"
  C->>T: "issue identity"
  T-->>C: "Secret token"

Core contract

This page is the crate reference. For the framework-wide runtime and trait model, read Architecture.

What it implements

  • Defines the traits other crates implement: Csrf, TokenIssuer, SessionStore, Authenticate, Invalidate, TokenRevocations, CredentialStore, PasswordVerifier, PasswordHasher, ProfileStore.

What's inside

Modules

  • src/lib.rs

Public API

(root)

  • struct NoProfiles
  • pub fn valid_identifier(value: &str, max: usize) -> bool — Bounded, nonempty identifiers; adapters choose the capability-specific bound.
  • trait Csrf — Session-bound or nonce-bound CSRF capability. Providers must not expose the binding, must enforce expiry, and must compare signatures in constant time.
rust
pub trait Csrf: Send + Sync {
    fn issue(&self, binding: &str) -> impl Future<Output = AppResult<String>> + Send;
    fn verify(&self, binding: &str, token: &str) -> impl Future<Output = AppResult<bool>> + Send;
}
  • trait TokenIssuer
rust
pub trait TokenIssuer: Send + Sync {
    /// Caller must establish identity and verify any selected persona first.
    fn issue(&self, identity: &Principal)
    -> impl Future<Output = AppResult<Secret<String>>> + Send;
}
  • struct SessionRecord
  • trait SessionStore
rust
pub trait SessionStore: Send + Sync {
    /// Must reject collisions atomically; never replace an existing session.
    fn insert(
        &self,
        digest: [u8; 32],
        record: SessionRecord,
    ) -> impl Future<Output = AppResult<()>> + Send;
    fn find(
        &self,
        digest: &[u8; 32],
    ) -> impl Future<Output = AppResult<Option<SessionRecord>>> + Send;
    /// Idempotent durable removal. Errors must never be treated as successful logout.
    fn revoke(&self, digest: &[u8; 32]) -> impl Future<Output = AppResult<()>> + Send;
}
  • trait Authenticate
rust
pub trait Authenticate<C>: Send + Sync {
    fn authenticate(&self, credentials: &C) -> impl Future<Output = AppResult<Principal>> + Send;
}
  • trait Invalidate
rust
pub trait Invalidate<C>: Send + Sync {
    fn invalidate(&self, credentials: &C) -> impl Future<Output = AppResult<()>> + Send;
}
  • trait TokenRevocations — JWT denylist storage. Retain each digest until at least the supplied expiry. Failed writes must not be reported as successful invalidation.
rust
pub trait TokenRevocations: Send + Sync {
    fn revoked(&self, digest: &[u8; 32]) -> impl Future<Output = AppResult<bool>> + Send;
    fn revoke(
        &self,
        digest: [u8; 32],
        expires_at: std::time::SystemTime,
    ) -> impl Future<Output = AppResult<()>> + Send;
}
  • struct PasswordCredentials
  • struct PasswordAccount
  • trait CredentialStore
rust
pub trait CredentialStore: Send + Sync {
    /// Resolve an email or username according to the application's explicit rules.
    /// Return no account for unknown identifiers; never guess normalization here.
    fn account(
        &self,
        login: &str,
    ) -> impl Future<Output = AppResult<Option<PasswordAccount>>> + Send;
}
  • trait PasswordVerifier
rust
pub trait PasswordVerifier: Send + Sync {
    fn verify(
        &self,
        password: &Secret<String>,
        hash: &Secret<String>,
    ) -> impl Future<Output = AppResult<bool>> + Send;
}
  • trait PasswordHasher
rust
pub trait PasswordHasher: PasswordVerifier {
    fn hash(
        &self,
        password: &Secret<String>,
    ) -> impl Future<Output = AppResult<Secret<String>>> + Send;
}
  • trait ProfileStore — Personas are identity-owned; they are not roles and do not imply a tenant.
rust
pub trait ProfileStore: Send + Sync {
    fn enabled(&self, subject: &str, profile: &str)
    -> impl Future<Output = AppResult<bool>> + Send;
}

Impl map

  • ProfileStore for NoProfiles
  • TokenIssuer for std::sync::Arc<T>
  • Authenticate<C> for std::sync::Arc<T>
  • Invalidate<C> for std::sync::Arc<T>
  • ProfileStore for std::sync::Arc<T>

Depends on

Used by

In this repository

  • examples/htmx-starter
  • examples/skills-only-app
  • examples/skills-only-app-task-tracker

Source: crates/core/iet-auth