Skip to main content

rustauth_plugins/magic_link/
mod.rs

1//! Magic link authentication plugin.
2
3mod endpoints;
4mod options;
5mod payload;
6mod response;
7mod session_response;
8mod token;
9mod user_response;
10
11pub use options::{
12    MagicLinkEmail, MagicLinkFuture, MagicLinkOptions, MagicLinkOptionsBuilder, MagicLinkRateLimit,
13    MagicLinkSendContext,
14};
15pub use token::{default_key_hasher, TokenStorage};
16
17use rustauth_core::plugin::{AuthPlugin, PluginRateLimitRule};
18
19use crate::VERSION;
20
21pub const UPSTREAM_PLUGIN_ID: &str = "magic-link";
22
23/// Development only — do not use in production.
24///
25/// Logs magic-link emails to stderr instead of sending mail.
26#[must_use]
27pub fn magic_link_dev_log() -> AuthPlugin {
28    magic_link(MagicLinkOptions::new(|email| {
29        Box::pin(async move {
30            eprintln!(
31                "[rustauth-dev] magic link for {}: {}",
32                email.email, email.url
33            );
34            Ok(())
35        })
36    }))
37}
38
39pub fn magic_link(options: MagicLinkOptions) -> AuthPlugin {
40    let rate_limit = options.rate_limit_rule();
41    AuthPlugin::new(UPSTREAM_PLUGIN_ID)
42        .with_version(VERSION)
43        .with_endpoint(endpoints::sign_in_magic_link_endpoint(options.clone()))
44        .with_endpoint(endpoints::verify_magic_link_endpoint(options))
45        .with_rate_limit(PluginRateLimitRule::new(
46            "/sign-in/magic-link",
47            rate_limit.clone(),
48        ))
49        .with_rate_limit(PluginRateLimitRule::new("/magic-link/verify", rate_limit))
50}