Guards know your user type. Gates fail closed.
Token and session guards typed to your user model, gates and policies that deny what they do not know, and the account flows most applications rebuild — as add-ins.
What you get
AuthManager<User>withTokenGuardandSessionGuard; Argon2 hashing, and bcrypt$2y$for imported users.- Sessions in memory, the database, the cache or a cookie, with CSRF protection.
- Gates and policies; an undefined ability is denied.
- Add-ins:
accounts(registration, login with lockout, reset, verification),two-factor(TOTP),passkeys(WebAuthn), impersonation. sso: GitHub, Google, Microsoft, GitLab, Discord, X, and any OpenID Connect provider.oauth-server: authorization code with PKCE, refresh tokens, client credentials, personal access tokens, scopes.- Captcha: Turnstile, hCaptcha, reCAPTCHA. No SAML.
In the docs
src/bootstrap.rs
let auth = AuthManager::<User>::new("api")
.register(Arc::new(TokenGuard::new("api", Arc::clone(&provider))))
.register(Arc::new(SessionGuard::new("web", provider, sessions)));
app.instance(Arc::new(auth));
// src/app/policies/post_policy.rs — a gate that fails closed.
pub fn gate() -> Gate<User> {
Gate::new()
.define("posts.publish", |user: &User, post: Option<&Post>| {
post.is_some_and(|post| post.belongs_to(user.id))
})
.define_simple("posts.create", |_user: &User| true)
}
// In the controller: a denial is a 403, an undefined ability is a denial.
PostPolicy::gate().authorize("posts.publish", author.get(), Some(&post))?;
Up close
Select an image to see it full size.