Пакет Email Magic Link для Laravel впроваджує безпарольну автентифікацію, дозволяючи користувачам входити в систему через посилання або одноразовий код, надісланий електронною поштою. Пакет працює як самостійно, так і в інтеграції з Laravel Fortify, не додаючи жодних додаткових залежностей крім самого фреймворку.
Основні можливості
Пакет пропонує гнучкий підхід до безпарольної автентифікації з наступними функціями:
- Вхід через посилання, одноразовий код або обидва варіанти - налаштовується єдиним параметром
mode
- Посилання, захищені від сканерів - надісланий
GET запит лише відображає сторінку підтвердження; токен споживається лише явним POST запитом
- Безпечна передача до Fortify - користувачі з налаштованим TOTP перенаправляються на двофакторну перевірку перед автентифікацією, уникаючи обходу додаткового фактору захисту
- Хешовані токени в базі даних - використовується HMAC-SHA256 з ключем, одноразове споживання та блокування після перевищення спроб для кожного токена
- API для створення власних посилань та кодів - дозволяє надсилати їх через SMS, push-повідомлення або власні поштові шаблони
- Обмеження повторних надсилань - ескалаційні затримки та погодинний ліміт
- JSON відповіді для SPA та мобільних клієнтів, можливість входу через альтернативні guard'и на зразок
admin
Захист від поштових сканерів
Одна з головних проблем магічних посилань полягає в тому, що системи безпеки та поштові клієнти автоматично переходять за всіма URL-адресами в листах. Якщо клік по посиланню виконує GET запит, що споживає одноразовий токен, сканер може спалити його ще до того, як користувач побачить лист.
Email Magic Link розділяє процес на два етапи. GET запит за адресою /magic-link/verify/{token} лише відображає підписану сторінку підтвердження і нічого не змінює. Токен споживається виключно явним POST запитом з цієї сторінки, який сканер не здійснює.
Такий самий рівень захисту застосовується при зберіганні. Токени та коди ніколи не зберігаються у відкритому вигляді - зберігається лише хеш HMAC-SHA256 з ключем. Споживання використовує безгонкове умовне затвердження, відповіді на запити ідентичні незалежно від того, чи існує електронна адреса, а кожен токен має власне блокування від перебору (max_attempts_per_token, за замовчуванням 5).
Передача до двофакторної автентифікації Fortify
Якщо користувач підтвердив TOTP через Fortify, перевірка його магічного посилання не виконує вхід в систему. Замість цього він перенаправляється на двофакторну перевірку Fortify без автентифікації, тому немає шляху, який би дозволив обійти другий фактор простим кліком по посиланню.
Для SPA та мобільних клієнтів встановіть api.enabled у true, і endpoints повертатимуть JSON, який повідомляє про результат:
{ "authenticated": false, "two_factor": true, "redirect": "<challenge url>" }
Самостійне створення посилань та кодів
Facade дозволяє створювати облікові дані без їх надсилання, що корисно при доставці через SMS, push-повідомлення або власний mailable:
use EmailMagicLink\Facades\EmailMagicLink;
$link = EmailMagicLink::issueLink($user);
$link->url; // Підписаний URL підтвердження
$link->expiresAt; // Екземпляр Carbon
$link->expiresInMinutes;
$code = EmailMagicLink::issueCode($user);
$code->code;
$code->expiresAt;
Ви також можете безпосередньо впроваджувати контракт EmailMagicLink\Contracts\MagicLinkIssuer. Переприв'язування MagicLinkAuthenticator дозволяє контролювати поведінку після перевірки, а реалізація контракту CaptchaGuard додає CAPTCHA до форми запиту.
Обмеження повторних надсилань
Безпарольні процеси спонукають користувачів активно натискати кнопку повторного надсилання. Вбудований ResendGuard застосовує ескалаційні затримки (30 секунд, потім 60, потім 120) плюс ковзний ліміт у п'ять надсилань на годину. Ви можете повторно використовувати його у власних контролерах:
use EmailMagicLink\Contracts\ResendGuard;
public function resend(Request $request): Response
{
$decision = $this->guard->attempt('custom-key');
if (! $decision->allowed) {
return back()->with('retry_after', $decision->retryAfterSeconds);
}
// Надіслати лист…
}
Прострочені токени очищаються запланованою командою:
Schedule::command('email-magic-link:purge')->daily();
Встановлення та вимоги
Пакет вимагає PHP 8.4 та Laravel 13, Fortify є опціональним:
composer require pushery/email-magic-link-for-laravel
php artisan email-magic-link:install
php artisan migrate
Інструкції з встановлення та повну документацію можна знайти на GitHub.