Magic Links allow users to log in by simply clicking a link sent to their email address. This reduces friction for users who forget their passwords and improves security by eliminating weak user-chosen passwords.
The Magic Link flow is designed to work seamlessly between the decoupled Frontend and Backend:
User enters their email on the Nuxt login page and clicks "Login".
AdonisJS validates the email exists in the database.
The email job is pushed to the Redis Queue via BullMQ. The API responds immediately with a success message—no waiting for email delivery.
The background worker processes the job and sends an email containing a cryptographically signed URL.
User clicks the magic link in their email. The request hits the Backend API verification endpoint.
AdonisJS verifies the signature and expiration. If valid, it creates a JWT access token and redirects to the frontend with the token.
The frontend receives the token, stores it, and redirects the user to the dashboard.
| Method | Endpoint | Description |
|---|---|---|
POST | /users/login/magic-link | Request a magic link email |
GET | /users/login/magic-link/:email/verify | Verify the magic link (signed URL) |
The magic link implementation includes several security measures:
Signed URLs
Short Expiration
Device Tracking
No Email Enumeration
The login page provides a tabbed interface where users can choose between:
When using magic links:
The magic link email includes:
http://localhost:8025.| Error | Cause | User Experience |
|---|---|---|
| Link expired | User waited too long to click | Error message, prompted to request new link |
| Invalid signature | Link was modified or corrupted | Error message on login page |
| User not found | Email doesn't exist | Redirected to signup page |
You can easily customize the magic link behavior:
resources/views/emails/