Magic Links
Magic links provide passwordless authentication by sending a one-time login link to the user's email. This requires the Messaging wire to be loaded for email delivery.
Configuration
import { FluxKit } from "@fluxkitdev/core";
import { auth } from "@fluxkitdev/auth";
import { messaging } from "@fluxkitdev/messaging";
const app = new FluxKit({
wires: [
auth({
magicLink: {
enabled: true,
expiresIn: "15m", // Link expiration
redirectUrl: "http://localhost:5173/auth/verify", // Frontend redirect
},
}),
messaging(), // Required for sending emails
],
database: { uri: process.env.MONGODB_URI },
});
Flow
- User requests a magic link by providing their email.
- FluxKit generates a one-time token and sends a login link via email.
- User clicks the link in their email.
- Your frontend sends the token to FluxKit for verification.
- FluxKit returns a JWT if the token is valid.
Requesting a Magic Link
Programmatic
await app.auth.sendMagicLink("alice@example.com");
REST API
curl -X POST http://localhost:3000/auth/magic-link \
-H "Content-Type: application/json" \
-d '{"email": "alice@example.com"}'
Response (200):
{
"message": "Magic link sent to alice@example.com"
}
The email contains a link like:
http://localhost:5173/auth/verify?token=abc123...
Verifying a Magic Link
Programmatic
const result = await app.auth.verifyMagicLink(token);
console.log(result.user); // User object
console.log(result.token); // JWT string
REST API
curl -X POST http://localhost:3000/auth/verify-magic-link \
-H "Content-Type: application/json" \
-d '{"token": "abc123..."}'
Response (200):
{
"user": {
"_id": "65a1b2c3d4e5f6a7b8c9d0e1",
"email": "alice@example.com",
"name": "Alice Johnson"
},
"token": "eyJhbGciOiJIUzI1NiIs..."
}
Response (401):
{
"error": {
"code": "INVALID_MAGIC_LINK",
"message": "Magic link is expired or already used"
}
}
Customizing the Email
You can customize the magic link email template:
auth({
magicLink: {
enabled: true,
email: {
subject: "Sign in to My App",
template: (link) => `
<h1>Sign In</h1>
<p>Click the link below to sign in to your account:</p>
<a href="${link}">Sign In</a>
<p>This link expires in 15 minutes.</p>
`,
},
},
});
Auto-Registration
By default, if a user requests a magic link and no account exists for that email, one is created automatically. You can disable this behavior:
auth({
magicLink: {
enabled: true,
autoRegister: false, // Reject unknown emails
},
});
Environment Variables
| Variable | Default | Description |
|---|---|---|
MAGIC_LINK_EXPIRY | 15m | Token expiration time |
MAGIC_LINK_REDIRECT | /auth/verify | Frontend redirect URL |