# rustauth-plugins
Official server-side plugin modules for RustAuth.
## What It Is
`rustauth-plugins` groups Better Auth-inspired server features translated into
RustAuth's Rust plugin contracts. Use it when you want optional auth behavior
without pulling each feature into `rustauth-core`.
The deprecated upstream `oidc-provider` and MCP authorization-server plugins are
not implemented here. Use `rustauth-oauth-provider` for OAuth 2.1, OpenID
Connect provider behavior, and MCP protected-resource metadata.
## What It Provides
Current modules include access control, additional fields, admin, anonymous
users, API keys, bearer sessions, CAPTCHA hooks, custom sessions, device
authorization, email OTP, generic OAuth, Have I Been Pwned checks, JWT, last
login method, magic links, multi-session, OAuth proxy, one-tap, one-time
tokens, OpenAPI, organizations, phone number, SIWE, two-factor, and username.
Some plugins are pure helpers. Many require an RustAuth adapter because they
store users, sessions, keys, organizations, tokens, or verification state.
## Quick Start
```rust
use rustauth::RustAuth;
use rustauth_plugins::prelude::*;
let auth = RustAuth::builder()
.secret("secret-a-at-least-32-chars-long!!")
.plugin(admin(AdminOptions::default())?)
.plugin(jwt(JwtOptions::default())?)
.build()?;
# let _ = auth;
# Ok::<(), Box<dyn std::error::Error>>(())
```
Import factories from [`prelude`](./src/prelude.rs) when wiring several plugins.
Each plugin exposes one factory: `plugin_name(options)` (or `plugin_name(options)?`
when validation can fail). Dev-only presets such as `magic_link_dev_log()` and
`siwe_dev()` remain for local development.
Register plugins on [`RustAuth::builder()`](../rustauth/README.md):
- `.plugin(x)` — append one plugin (chain as needed).
- `.plugins(vec![...])` — append a batch (same as chaining `.plugin`).
When building [`RustAuthOptions`](../rustauth-core/README.md) directly,
`.plugin(x)` and `.plugins(vec![...])` both append. Use `.set_plugins(vec![...])`
to replace the full list.
```rust
use rustauth::RustAuth;
use rustauth_plugins::prelude::*;
let core = vec![
admin(AdminOptions::default())?,
bearer(BearerOptions::default()),
];
let auth = RustAuth::builder()
.secret("secret-a-at-least-32-chars-long!!")
.plugins(core)
.plugin(jwt(JwtOptions::default())?)
.build()?;
# let _ = auth;
# Ok::<(), Box<dyn std::error::Error>>(())
```
`email_otp` and `phone_number` resolve the database adapter from the auth
context at runtime; pass the adapter only to `RustAuth::builder().adapter(...)`.
Use module-specific options when a plugin needs application callbacks such as
email sending, OTP delivery, CAPTCHA verification, SIWE verification, or custom
authorization policy.
## Plugin factory conventions
1. **`foo(options)`** — single factory per plugin; always pass an options value
(`FooOptions::default()` when defaults are valid).
2. **Fallible factories** — return `Result<AuthPlugin, RustAuthError>` when options
validation can fail (`admin`, `api_key`, `captcha`, `email_otp`, `jwt`, …).
3. **Dev presets** — `magic_link_dev_log()`, `siwe_dev()`, `siwe_dev_domain()` for
local development only (not general zero-arg factories).
### Configuring options
All three styles are supported and equivalent:
| Struct literal | Full control, small configs | `email_otp(EmailOtpOptions { sender: Some(s), ..Default::default() })?` |
| Builder | Incremental or optional fields | `email_otp(EmailOtpOptions::builder().sender(s).build()?)?` |
| `Options::new(...)` | Required callbacks only | `email_otp(EmailOtpOptions::new(sender))?` |
Callback-required plugins (`email_otp`, `phone_number`, `magic_link`, `captcha`, `siwe`)
also offer `FooOptions::new(...)` or provider helpers such as
`CaptchaOptions::cloudflare_turnstile(secret)`.
Email, SMS, and magic-link senders are **async** — return `OutboundSendFuture`
(`Box::pin(async move { ... })`). RustAuth dispatches delivery in the background;
do not block handlers on SMTP/SMS. See
[docs/security-outbound-delivery.md](../../docs/security-outbound-delivery.md).
```rust