Magic link
MagicLinkPlugin sends email credentials for passwordless sign-in.
Add async-trait = "0.1" to your dependencies. This example forwards delivery to your application’s EmailProvider and installs the plugin on the auth instance.
use crate::auth_schema::AppAuthSchema;use async_trait::async_trait;use better_auth::CallbackContext;use better_auth::email::EmailProvider;use better_auth::plugins::magic_link::MagicLinkDelivery;use better_auth::plugins::{MagicLinkConfig, MagicLinkPlugin, SendMagicLink};use better_auth::sqlx::SqlxStore;use better_auth::{AuthConfig, AuthResult, BetterAuth};use std::sync::Arc;
struct Mailer(Arc<dyn EmailProvider>);
#[async_trait]impl SendMagicLink for Mailer { async fn send(&self, delivery: &MagicLinkDelivery, _: &CallbackContext) -> AuthResult<()> { self.0 .send(&delivery.email, "Sign in", "", &delivery.url.clone()) .await }}
async fn build_auth( config: AuthConfig, store: SqlxStore<AppAuthSchema>, mail: Arc<dyn EmailProvider>,) -> AuthResult<BetterAuth<AppAuthSchema>> { BetterAuth::<AppAuthSchema>::new(config) .store(store) .plugin(MagicLinkPlugin::new(MagicLinkConfig { send_magic_link: Some(Arc::new(Mailer(mail))), expires_in: 300.0, ..Default::default() })) .build() .await}Endpoints and options
Section titled “Endpoints and options”Request a link at /sign-in/magic-link. The supplied URL completes verification at /magic-link/verify and issues session cookies.
expires_in uses floating-point seconds. See delivery policies for awaited errors and passwordless configuration for numeric options.
Frontend
Section titled “Frontend”See the official magic-link guide.